From fd46c0a93c1a4fa302d118533f40d255e2c56ae3 Mon Sep 17 00:00:00 2001 From: Ximin Luo Date: Wed, 28 Sep 2016 21:53:48 +0200 Subject: [PATCH] New upstream version 4.03.0 --- .depend | 1802 +- .gitattributes | 127 + .gitignore | 2660 +- .gitmodules | 3 + .ignore | 11 - .merlin | 7 +- .travis-ci.sh | 142 +- .travis.yml | 29 +- CONTRIBUTING.md | 292 + Changes | 1118 +- INSTALL | 356 - INSTALL.adoc | 366 + LICENSE | 2 +- Makefile | 287 +- Makefile.nt | 405 +- Makefile.shared | 244 + README | 130 - README.adoc | 139 + README.win32 | 453 - README.win32.adoc | 329 + VERSION | 2 +- appveyor.yml | 56 + appveyor_build.sh | 34 + asmcomp/.ignore | 7 - asmcomp/CSEgen.ml | 123 +- asmcomp/CSEgen.mli | 25 +- asmcomp/amd64/CSE.ml | 25 +- asmcomp/amd64/NOTES.md | 21 + asmcomp/amd64/arch.ml | 31 +- asmcomp/amd64/emit.mlp | 1347 +- asmcomp/amd64/emit_nt.mlp | 795 - asmcomp/amd64/proc.ml | 54 +- asmcomp/amd64/reload.ml | 28 +- asmcomp/amd64/scheduling.ml | 25 +- asmcomp/amd64/selection.ml | 43 +- asmcomp/arm/CSE.ml | 25 +- asmcomp/arm/NOTES.md | 20 + asmcomp/arm/arch.ml | 45 +- asmcomp/arm/emit.mlp | 63 +- asmcomp/arm/proc.ml | 148 +- asmcomp/arm/reload.ml | 25 +- asmcomp/arm/scheduling.ml | 27 +- asmcomp/arm/selection.ml | 53 +- asmcomp/arm64/CSE.ml | 25 +- asmcomp/arm64/NOTES.md | 12 + asmcomp/arm64/arch.ml | 29 +- asmcomp/arm64/emit.mlp | 51 +- asmcomp/arm64/proc.ml | 43 +- asmcomp/arm64/reload.ml | 25 +- asmcomp/arm64/scheduling.ml | 25 +- asmcomp/arm64/selection.ml | 48 +- asmcomp/asmgen.ml | 238 +- asmcomp/asmgen.mli | 46 +- asmcomp/asmlibrarian.ml | 33 +- asmcomp/asmlibrarian.mli | 25 +- asmcomp/asmlink.ml | 91 +- asmcomp/asmlink.mli | 25 +- asmcomp/asmpackager.ml | 122 +- asmcomp/asmpackager.mli | 33 +- asmcomp/branch_relaxation.ml | 27 +- asmcomp/branch_relaxation.mli | 27 +- asmcomp/branch_relaxation_intf.ml | 27 +- asmcomp/build_export_info.ml | 551 + asmcomp/build_export_info.mli | 25 + asmcomp/clambda.ml | 56 +- asmcomp/clambda.mli | 44 +- asmcomp/closure.ml | 281 +- asmcomp/closure.mli | 25 +- asmcomp/closure_offsets.ml | 138 + asmcomp/closure_offsets.mli | 44 + asmcomp/cmm.ml | 88 +- asmcomp/cmm.mli | 81 +- asmcomp/cmmgen.ml | 1506 +- asmcomp/cmmgen.mli | 31 +- asmcomp/cmx_format.mli | 35 +- asmcomp/codegen.ml | 95 - asmcomp/codegen.mli | 27 - asmcomp/coloring.ml | 25 +- asmcomp/coloring.mli | 25 +- asmcomp/comballoc.ml | 25 +- asmcomp/comballoc.mli | 25 +- asmcomp/compilenv.ml | 235 +- asmcomp/compilenv.mli | 109 +- asmcomp/deadcode.ml | 25 +- asmcomp/deadcode.mli | 25 +- asmcomp/debuginfo.ml | 56 - asmcomp/debuginfo.mli | 32 - asmcomp/emit.mli | 25 +- asmcomp/emitaux.ml | 56 +- asmcomp/emitaux.mli | 38 +- asmcomp/export_info.ml | 354 + asmcomp/export_info.mli | 148 + asmcomp/export_info_for_pack.ml | 138 + asmcomp/export_info_for_pack.mli | 34 + asmcomp/flambda_to_clambda.ml | 711 + asmcomp/flambda_to_clambda.mli | 38 + asmcomp/i386/CSE.ml | 25 +- asmcomp/i386/NOTES.md | 22 + asmcomp/i386/arch.ml | 25 +- asmcomp/i386/emit.mlp | 1532 +- asmcomp/i386/emit_nt.mlp | 893 - asmcomp/i386/proc.ml | 49 +- asmcomp/i386/reload.ml | 25 +- asmcomp/i386/scheduling.ml | 25 +- asmcomp/i386/selection.ml | 45 +- asmcomp/import_approx.ml | 175 + asmcomp/import_approx.mli | 34 + asmcomp/interf.ml | 25 +- asmcomp/interf.mli | 25 +- asmcomp/linearize.ml | 25 +- asmcomp/linearize.mli | 25 +- asmcomp/liveness.ml | 25 +- asmcomp/liveness.mli | 25 +- asmcomp/mach.ml | 27 +- asmcomp/mach.mli | 27 +- asmcomp/power/CSE.ml | 25 +- asmcomp/power/NOTES.md | 26 + asmcomp/power/arch.ml | 59 +- asmcomp/power/emit.mlp | 1003 +- asmcomp/power/proc.ml | 253 +- asmcomp/power/reload.ml | 25 +- asmcomp/power/scheduling.ml | 25 +- asmcomp/power/selection.ml | 31 +- asmcomp/printclambda.ml | 44 +- asmcomp/printclambda.mli | 25 +- asmcomp/printcmm.ml | 41 +- asmcomp/printcmm.mli | 25 +- asmcomp/printlinear.ml | 25 +- asmcomp/printlinear.mli | 25 +- asmcomp/printmach.ml | 35 +- asmcomp/printmach.mli | 25 +- asmcomp/proc.mli | 40 +- asmcomp/reg.ml | 27 +- asmcomp/reg.mli | 27 +- asmcomp/reload.mli | 25 +- asmcomp/reloadgen.ml | 34 +- asmcomp/reloadgen.mli | 25 +- asmcomp/s390x/CSE.ml | 42 + asmcomp/s390x/NOTES.md | 16 + asmcomp/s390x/arch.ml | 89 + asmcomp/s390x/emit.mlp | 773 + asmcomp/s390x/proc.ml | 213 + asmcomp/s390x/reload.ml | 50 + asmcomp/s390x/scheduling.ml | 63 + asmcomp/s390x/selection.ml | 117 + asmcomp/schedgen.ml | 27 +- asmcomp/schedgen.mli | 25 +- asmcomp/scheduling.mli | 25 +- asmcomp/selectgen.ml | 131 +- asmcomp/selectgen.mli | 27 +- asmcomp/selection.mli | 25 +- asmcomp/sparc/CSE.ml | 25 +- asmcomp/sparc/NOTES.md | 17 + asmcomp/sparc/arch.ml | 25 +- asmcomp/sparc/emit.mlp | 57 +- asmcomp/sparc/proc.ml | 76 +- asmcomp/sparc/reload.ml | 25 +- asmcomp/sparc/scheduling.ml | 25 +- asmcomp/sparc/selection.ml | 33 +- asmcomp/spill.ml | 33 +- asmcomp/spill.mli | 25 +- asmcomp/split.ml | 25 +- asmcomp/split.mli | 25 +- asmcomp/strmatch.ml | 31 +- asmcomp/strmatch.mli | 25 +- asmcomp/un_anf.ml | 757 + asmcomp/un_anf.mli | 22 + asmcomp/x86_ast.mli | 219 + asmcomp/x86_dsl.ml | 198 + asmcomp/x86_dsl.mli | 191 + asmcomp/x86_gas.ml | 311 + asmcomp/x86_gas.mli | 18 + asmcomp/x86_masm.ml | 261 + asmcomp/x86_masm.mli | 18 + asmcomp/x86_proc.ml | 275 + asmcomp/x86_proc.mli | 91 + asmrun/.depend | 1389 +- asmrun/.ignore | 40 - asmrun/Makefile | 135 +- asmrun/Makefile.nt | 39 +- asmrun/amd64.S | 90 +- asmrun/amd64nt.asm | 26 +- asmrun/arm.S | 63 +- asmrun/arm64.S | 49 +- asmrun/backtrace.c | 385 - asmrun/backtrace_prim.c | 232 + asmrun/clambda_checks.c | 86 + asmrun/fail.c | 30 +- asmrun/i386.S | 28 +- asmrun/i386nt.asm | 26 +- asmrun/natdynlink.c | 28 +- asmrun/power-elf.S | 480 - asmrun/power-rhapsody.S | 510 - asmrun/power.S | 697 + asmrun/roots.c | 316 +- asmrun/s390x.S | 358 + asmrun/signals_asm.c | 49 +- asmrun/signals_osdep.h | 43 +- asmrun/sparc.S | 26 +- asmrun/stack.h | 66 +- asmrun/startup.c | 111 +- boot/.ignore | 6 - boot/ocamlc | Bin 1746238 -> 2072761 bytes boot/ocamldep | Bin 557017 -> 696193 bytes boot/ocamllex | Bin 256452 -> 267698 bytes bytecomp/.ignore | 2 - bytecomp/bytegen.ml | 102 +- bytecomp/bytegen.mli | 25 +- bytecomp/bytelibrarian.ml | 25 +- bytecomp/bytelibrarian.mli | 25 +- bytecomp/bytelink.ml | 38 +- bytecomp/bytelink.mli | 25 +- bytecomp/bytepackager.ml | 32 +- bytecomp/bytepackager.mli | 25 +- bytecomp/bytesections.ml | 25 +- bytecomp/bytesections.mli | 25 +- bytecomp/cmo_format.mli | 25 +- bytecomp/debuginfo.ml | 81 + bytecomp/debuginfo.mli | 38 + bytecomp/dll.ml | 25 +- bytecomp/dll.mli | 25 +- bytecomp/emitcode.ml | 31 +- bytecomp/emitcode.mli | 30 +- bytecomp/instruct.ml | 25 +- bytecomp/instruct.mli | 25 +- bytecomp/lambda.ml | 173 +- bytecomp/lambda.mli | 97 +- bytecomp/matching.ml | 459 +- bytecomp/matching.mli | 25 +- bytecomp/meta.ml | 30 +- bytecomp/meta.mli | 30 +- bytecomp/printinstr.ml | 25 +- bytecomp/printinstr.mli | 25 +- bytecomp/printlambda.ml | 221 +- bytecomp/printlambda.mli | 27 +- bytecomp/runtimedef.mli | 25 +- bytecomp/simplif.ml | 174 +- bytecomp/simplif.mli | 34 +- bytecomp/switch.ml | 81 +- bytecomp/switch.mli | 25 +- bytecomp/symtable.ml | 25 +- bytecomp/symtable.mli | 25 +- bytecomp/translattribute.ml | 255 + bytecomp/translattribute.mli | 60 + bytecomp/translclass.ml | 162 +- bytecomp/translclass.mli | 25 +- bytecomp/translcore.ml | 599 +- bytecomp/translcore.mli | 36 +- bytecomp/translmod.ml | 792 +- bytecomp/translmod.mli | 34 +- bytecomp/translobj.ml | 69 +- bytecomp/translobj.mli | 27 +- bytecomp/typeopt.ml | 78 +- bytecomp/typeopt.mli | 39 +- byterun/.depend | 1061 +- byterun/.ignore | 16 - byterun/Makefile | 51 +- byterun/Makefile.common | 64 +- byterun/Makefile.nt | 51 +- byterun/alloc.c | 42 +- byterun/array.c | 57 +- byterun/backtrace.c | 487 +- byterun/backtrace_prim.c | 456 + byterun/callback.c | 26 +- byterun/caml/address_class.h | 29 +- byterun/caml/alloc.h | 40 +- byterun/caml/backtrace.h | 129 +- byterun/caml/backtrace_prim.h | 69 + byterun/caml/callback.h | 26 +- byterun/caml/compact.h | 26 +- byterun/caml/compare.h | 26 +- byterun/caml/compatibility.h | 30 +- byterun/caml/config.h | 89 +- byterun/caml/custom.h | 30 +- byterun/caml/debugger.h | 54 +- byterun/caml/dynlink.h | 26 +- byterun/caml/exec.h | 30 +- byterun/caml/fail.h | 99 +- byterun/caml/finalise.h | 26 +- byterun/caml/fix_code.h | 28 +- byterun/caml/freelist.h | 36 +- byterun/caml/gc.h | 26 +- byterun/caml/gc_ctrl.h | 42 +- byterun/caml/globroots.h | 26 +- byterun/caml/hash.h | 39 +- byterun/caml/instrtrace.h | 27 +- byterun/caml/instruct.h | 26 +- byterun/caml/int64_emul.h | 140 +- byterun/caml/int64_format.h | 30 +- byterun/caml/int64_native.h | 46 +- byterun/caml/interp.h | 26 +- byterun/caml/intext.h | 64 +- byterun/caml/io.h | 33 +- byterun/caml/major_gc.h | 64 +- byterun/caml/md5.h | 32 +- byterun/caml/memory.h | 130 +- byterun/caml/minor_gc.h | 119 +- byterun/caml/misc.h | 176 +- byterun/caml/mlvalues.h | 47 +- byterun/caml/osdeps.h | 42 +- byterun/caml/prims.h | 26 +- byterun/caml/printexc.h | 28 +- byterun/caml/reverse.h | 26 +- byterun/caml/roots.h | 32 +- byterun/caml/signals.h | 32 +- byterun/caml/signals_machdep.h | 36 +- byterun/caml/stacks.h | 26 +- byterun/caml/startup.h | 31 +- byterun/caml/startup_aux.h | 29 + byterun/caml/sys.h | 26 +- byterun/caml/ui.h | 26 +- byterun/caml/weak.h | 93 +- byterun/compact.c | 115 +- byterun/compare.c | 32 +- byterun/custom.c | 33 +- byterun/debugger.c | 29 +- byterun/dynlink.c | 28 +- byterun/extern.c | 303 +- byterun/fail.c | 26 +- byterun/finalise.c | 80 +- byterun/fix_code.c | 40 +- byterun/floats.c | 300 +- byterun/freelist.c | 275 +- byterun/gc_ctrl.c | 249 +- byterun/globroots.c | 36 +- byterun/hash.c | 70 +- byterun/instrtrace.c | 45 +- byterun/intern.c | 462 +- byterun/interp.c | 35 +- byterun/ints.c | 299 +- byterun/io.c | 155 +- byterun/lexing.c | 26 +- byterun/main.c | 47 +- byterun/major_gc.c | 783 +- byterun/md5.c | 52 +- byterun/memory.c | 230 +- byterun/meta.c | 71 +- byterun/minor_gc.c | 392 +- byterun/misc.c | 144 +- byterun/obj.c | 61 +- byterun/parsing.c | 26 +- byterun/printexc.c | 26 +- byterun/roots.c | 49 +- byterun/signals.c | 72 +- byterun/signals_byt.c | 29 +- byterun/stacks.c | 26 +- byterun/startup.c | 150 +- byterun/startup_aux.c | 97 + byterun/str.c | 78 +- byterun/sys.c | 134 +- byterun/terminfo.c | 26 +- byterun/unix.c | 75 +- byterun/weak.c | 347 +- byterun/win32.c | 132 +- compilerlibs/.gitignore | 7 + config/.ignore | 3 - config/Makefile-templ | 30 +- config/Makefile.mingw | 55 +- config/Makefile.mingw64 | 55 +- config/Makefile.msvc | 64 +- config/Makefile.msvc64 | 65 +- config/auto-aux/.ignore | 1 - config/auto-aux/align.c | 26 +- config/auto-aux/ansi.c | 30 +- config/auto-aux/async_io.c | 26 +- config/auto-aux/bytecopy.c | 32 - config/auto-aux/cckind.c | 30 + config/auto-aux/dblalign.c | 36 +- config/auto-aux/divmod.c | 45 - config/auto-aux/elf.c | 26 +- config/auto-aux/endian.c | 35 +- config/auto-aux/expm1.c | 24 - config/auto-aux/getgroups.c | 26 +- config/auto-aux/gethostbyaddr.c | 30 +- config/auto-aux/gethostbyname.c | 30 +- config/auto-aux/hasgot | 30 +- config/auto-aux/hasgot2 | 30 +- config/auto-aux/ia32sse2.c | 26 +- config/auto-aux/initgroups.c | 26 +- config/auto-aux/int64align.c | 42 +- config/auto-aux/longlong.c | 41 - config/auto-aux/mmap-huge.c | 51 + config/auto-aux/nanosecond_stat.c | 26 +- config/auto-aux/runtest | 26 +- config/auto-aux/schar.c | 21 - config/auto-aux/schar2.c | 21 - config/auto-aux/searchpath | 26 +- config/auto-aux/setgroups.c | 26 +- config/auto-aux/sighandler.c | 21 - config/auto-aux/signals.c | 26 +- config/auto-aux/sizes.c | 33 +- config/auto-aux/solaris-ld | 26 +- config/auto-aux/stackov.c | 66 - config/auto-aux/tryassemble | 26 +- config/auto-aux/trycompile | 26 +- config/m-nt.h | 30 +- config/m-templ.h | 26 +- config/s-nt.h | 30 +- config/s-templ.h | 26 +- configure | 398 +- debugger/.ignore | 7 - debugger/Makefile | 25 +- debugger/Makefile.nt | 25 +- debugger/Makefile.shared | 36 +- debugger/breakpoints.ml | 27 +- debugger/breakpoints.mli | 27 +- debugger/checkpoints.ml | 27 +- debugger/checkpoints.mli | 27 +- debugger/command_line.ml | 96 +- debugger/command_line.mli | 27 +- debugger/debugcom.ml | 37 +- debugger/debugcom.mli | 30 +- debugger/debugger_config.ml | 27 +- debugger/debugger_config.mli | 27 +- debugger/eval.ml | 27 +- debugger/eval.mli | 27 +- debugger/events.ml | 27 +- debugger/events.mli | 27 +- debugger/exec.ml | 27 +- debugger/exec.mli | 27 +- debugger/frames.ml | 27 +- debugger/frames.mli | 27 +- debugger/history.ml | 27 +- debugger/history.mli | 27 +- debugger/input_handling.ml | 27 +- debugger/input_handling.mli | 27 +- debugger/int64ops.ml | 25 +- debugger/int64ops.mli | 25 +- debugger/lexer.mli | 29 +- debugger/lexer.mll | 33 +- debugger/loadprinter.ml | 30 +- debugger/loadprinter.mli | 25 +- debugger/main.ml | 27 +- debugger/parameters.ml | 27 +- debugger/parameters.mli | 27 +- debugger/parser.mly | 27 +- debugger/parser_aux.mli | 27 +- debugger/pattern_matching.ml | 27 +- debugger/pattern_matching.mli | 27 +- debugger/pos.ml | 25 +- debugger/pos.mli | 25 +- debugger/primitives.ml | 27 +- debugger/primitives.mli | 27 +- debugger/printval.ml | 27 +- debugger/printval.mli | 27 +- debugger/program_loading.ml | 27 +- debugger/program_loading.mli | 27 +- debugger/program_management.ml | 27 +- debugger/program_management.mli | 27 +- debugger/question.ml | 25 +- debugger/question.mli | 25 +- debugger/show_information.ml | 27 +- debugger/show_information.mli | 27 +- debugger/show_source.ml | 27 +- debugger/show_source.mli | 27 +- debugger/source.ml | 27 +- debugger/source.mli | 27 +- debugger/symbols.ml | 27 +- debugger/symbols.mli | 27 +- debugger/time_travel.ml | 29 +- debugger/time_travel.mli | 27 +- debugger/trap_barrier.ml | 27 +- debugger/trap_barrier.mli | 27 +- debugger/unix_tools.ml | 27 +- debugger/unix_tools.mli | 27 +- driver/compenv.ml | 512 +- driver/compenv.mli | 29 +- driver/compile.ml | 49 +- driver/compile.mli | 25 +- driver/compmisc.ml | 31 +- driver/compmisc.mli | 27 +- driver/errors.ml | 25 +- driver/errors.mli | 25 +- driver/main.ml | 83 +- driver/main.mli | 25 +- driver/main_args.ml | 397 +- driver/main_args.mli | 78 +- driver/ocamlcomp.sh.in | 25 +- driver/optcompile.ml | 89 +- driver/optcompile.mli | 34 +- driver/opterrors.ml | 25 +- driver/opterrors.mli | 25 +- driver/optmain.ml | 163 +- driver/optmain.mli | 25 +- driver/pparse.ml | 49 +- driver/pparse.mli | 47 +- emacs/.ignore | 2 - emacs/Makefile | 24 +- emacs/caml-compat.el | 24 +- emacs/caml-emacs.el | 24 +- emacs/caml-font-old.el | 24 +- emacs/caml-font.el | 68 +- emacs/caml-help.el | 27 +- emacs/caml-hilit.el | 24 +- emacs/caml-types.el | 24 +- emacs/caml-xemacs.el | 24 +- emacs/caml.el | 24 +- emacs/camldebug.el | 24 +- emacs/inf-caml.el | 24 +- emacs/ocamltags.in | 24 +- lex/.ignore | 6 - lex/Makefile | 25 +- lex/Makefile.nt | 34 +- lex/common.ml | 27 +- lex/common.mli | 25 +- lex/compact.ml | 25 +- lex/compact.mli | 25 +- lex/cset.ml | 27 +- lex/cset.mli | 27 +- lex/lexer.mli | 25 +- lex/lexer.mll | 30 +- lex/lexgen.ml | 28 +- lex/lexgen.mli | 25 +- lex/main.ml | 25 +- lex/output.ml | 25 +- lex/output.mli | 25 +- lex/outputbis.ml | 25 +- lex/outputbis.mli | 25 +- lex/parser.mly | 25 +- lex/syntax.ml | 25 +- lex/syntax.mli | 25 +- lex/table.ml | 25 +- lex/table.mli | 25 +- man/Makefile | 25 +- man/ocaml.m | 55 +- man/ocamlc.m | 71 +- man/ocamlcp.m | 25 +- man/ocamldebug.m | 41 +- man/ocamldep.m | 73 +- man/ocamldoc.m | 25 +- man/ocamllex.m | 25 +- man/ocamlmktop.m | 25 +- man/ocamlopt.m | 25 +- man/ocamlprof.m | 25 +- man/ocamlrun.m | 45 +- man/ocamlyacc.m | 25 +- middle_end/alias_analysis.ml | 167 + middle_end/alias_analysis.mli | 63 + middle_end/allocated_const.ml | 85 + middle_end/allocated_const.mli | 36 + middle_end/augment_specialised_args.ml | 755 + middle_end/augment_specialised_args.mli | 65 + middle_end/backend_intf.mli | 47 + middle_end/base_types/closure_element.ml | 25 + middle_end/base_types/closure_element.mli | 32 + middle_end/base_types/closure_id.ml | 19 + middle_end/base_types/closure_id.mli | 27 + middle_end/base_types/compilation_unit.ml | 73 + middle_end/base_types/compilation_unit.mli | 33 + middle_end/base_types/export_id.ml | 28 + middle_end/base_types/export_id.mli | 28 + middle_end/base_types/id_types.ml | 92 + middle_end/base_types/id_types.mli | 56 + middle_end/base_types/linkage_name.ml | 29 + middle_end/base_types/linkage_name.mli | 22 + middle_end/base_types/mutable_variable.ml | 91 + middle_end/base_types/mutable_variable.mli | 37 + middle_end/base_types/set_of_closures_id.ml | 27 + middle_end/base_types/set_of_closures_id.mli | 25 + .../base_types/set_of_closures_origin.ml | 21 + .../base_types/set_of_closures_origin.mli | 21 + middle_end/base_types/static_exception.ml | 22 + middle_end/base_types/static_exception.mli | 26 + middle_end/base_types/symbol.ml | 79 + middle_end/base_types/symbol.mli | 43 + middle_end/base_types/tag.ml | 32 + middle_end/base_types/tag.mli | 27 + middle_end/base_types/var_within_closure.ml | 19 + middle_end/base_types/var_within_closure.mli | 24 + middle_end/base_types/variable.ml | 124 + middle_end/base_types/variable.mli | 62 + middle_end/closure_conversion.ml | 672 + middle_end/closure_conversion.mli | 53 + middle_end/closure_conversion_aux.ml | 192 + middle_end/closure_conversion_aux.mli | 100 + middle_end/effect_analysis.ml | 59 + middle_end/effect_analysis.mli | 27 + middle_end/extract_projections.ml | 189 + middle_end/extract_projections.mli | 33 + middle_end/find_recursive_functions.ml | 31 + middle_end/find_recursive_functions.mli | 37 + middle_end/flambda.ml | 1173 + middle_end/flambda.mli | 649 + middle_end/flambda_invariants.ml | 822 + middle_end/flambda_invariants.mli | 29 + middle_end/flambda_iterators.ml | 834 + middle_end/flambda_iterators.mli | 227 + middle_end/flambda_utils.ml | 836 + middle_end/flambda_utils.mli | 216 + middle_end/freshening.ml | 444 + middle_end/freshening.mli | 165 + middle_end/inconstant_idents.ml | 494 + middle_end/inconstant_idents.mli | 36 + middle_end/initialize_symbol_to_let_symbol.ml | 56 + .../initialize_symbol_to_let_symbol.mli | 21 + middle_end/inline_and_simplify.ml | 1595 ++ middle_end/inline_and_simplify.mli | 38 + middle_end/inline_and_simplify_aux.ml | 680 + middle_end/inline_and_simplify_aux.mli | 344 + middle_end/inlining_cost.ml | 684 + middle_end/inlining_cost.mli | 141 + middle_end/inlining_decision.ml | 662 + middle_end/inlining_decision.mli | 43 + middle_end/inlining_decision_intf.mli | 49 + middle_end/inlining_stats.ml | 257 + middle_end/inlining_stats.mli | 46 + middle_end/inlining_stats_types.ml | 281 + middle_end/inlining_stats_types.mli | 88 + middle_end/inlining_transforms.ml | 380 + middle_end/inlining_transforms.mli | 102 + middle_end/invariant_params.ml | 414 + middle_end/invariant_params.mli | 57 + middle_end/lift_code.ml | 165 + middle_end/lift_code.mli | 43 + middle_end/lift_constants.ml | 1033 + middle_end/lift_constants.mli | 65 + middle_end/lift_let_to_initialize_symbol.ml | 294 + middle_end/lift_let_to_initialize_symbol.mli | 38 + middle_end/middle_end.ml | 183 + middle_end/middle_end.mli | 30 + middle_end/pass_wrapper.ml | 34 + middle_end/pass_wrapper.mli | 25 + middle_end/projection.ml | 169 + middle_end/projection.mli | 80 + middle_end/ref_to_variables.ml | 195 + middle_end/ref_to_variables.mli | 23 + middle_end/remove_free_vars_equal_to_args.ml | 104 + middle_end/remove_free_vars_equal_to_args.mli | 20 + middle_end/remove_unused_arguments.ml | 231 + middle_end/remove_unused_arguments.mli | 39 + middle_end/remove_unused_closure_vars.ml | 124 + middle_end/remove_unused_closure_vars.mli | 26 + .../remove_unused_program_constructs.ml | 108 + .../remove_unused_program_constructs.mli | 24 + middle_end/semantics_of_primitives.ml | 144 + middle_end/semantics_of_primitives.mli | 65 + middle_end/share_constants.ml | 129 + middle_end/share_constants.mli | 22 + middle_end/simple_value_approx.ml | 719 + middle_end/simple_value_approx.mli | 401 + middle_end/simplify_boxed_integer_ops.ml | 110 + middle_end/simplify_boxed_integer_ops.mli | 28 + .../simplify_boxed_integer_ops_intf.mli | 45 + middle_end/simplify_common.ml | 66 + middle_end/simplify_common.mli | 73 + middle_end/simplify_primitives.ml | 217 + middle_end/simplify_primitives.mli | 28 + middle_end/unbox_closures.ml | 87 + middle_end/unbox_closures.mli | 32 + middle_end/unbox_free_vars_of_closures.ml | 175 + middle_end/unbox_free_vars_of_closures.mli | 26 + middle_end/unbox_specialised_args.ml | 103 + middle_end/unbox_specialised_args.mli | 49 + ocamlbuild/.depend | 207 - ocamlbuild/AUTHORS | 2 - ocamlbuild/ChangeLog | 3621 --- ocamlbuild/FAQ | 35 - ocamlbuild/Makefile | 213 - ocamlbuild/TODO | 38 - ocamlbuild/_tags | 22 - ocamlbuild/bool.ml | 39 - ocamlbuild/bool.mli | 35 - ocamlbuild/command.ml | 422 - ocamlbuild/command.mli | 51 - ocamlbuild/configuration.ml | 95 - ocamlbuild/configuration.mli | 44 - ocamlbuild/const.ml | 11 - ocamlbuild/digest_cache.ml | 42 - ocamlbuild/digest_cache.mli | 18 - ocamlbuild/discard_printf.ml | 16 - ocamlbuild/discard_printf.mli | 20 - ocamlbuild/display.ml | 393 - ocamlbuild/display.mli | 34 - ocamlbuild/examples/example1/hello.ml | 17 - ocamlbuild/examples/example2/greet.ml | 18 - ocamlbuild/examples/example2/hello.ml | 26 - ocamlbuild/examples/example3/epoch.ml | 18 - ocamlbuild/examples/example3/make.sh | 44 - ocamlbuild/exit_codes.ml | 27 - ocamlbuild/exit_codes.mli | 27 - ocamlbuild/fda.ml | 82 - ocamlbuild/fda.mli | 19 - ocamlbuild/findlib.ml | 198 - ocamlbuild/findlib.mli | 16 - ocamlbuild/flags.ml | 78 - ocamlbuild/flags.mli | 40 - ocamlbuild/glob.ml | 413 - ocamlbuild/glob.mli | 24 - ocamlbuild/glob_ast.ml | 32 - ocamlbuild/glob_ast.mli | 26 - ocamlbuild/glob_lexer.mli | 28 - ocamlbuild/glob_lexer.mll | 117 - ocamlbuild/hooks.ml | 27 - ocamlbuild/hooks.mli | 24 - ocamlbuild/hygiene.ml | 176 - ocamlbuild/hygiene.mli | 47 - ocamlbuild/lexers.mli | 48 - ocamlbuild/lexers.mll | 191 - ocamlbuild/loc.ml | 35 - ocamlbuild/loc.mli | 7 - ocamlbuild/log.ml | 80 - ocamlbuild/log.mli | 44 - ocamlbuild/main.ml | 356 - ocamlbuild/main.mli | 15 - ocamlbuild/man/ocamlbuild.1 | 268 - ocamlbuild/misc/opentracer.ml | 102 - ocamlbuild/my_std.ml | 431 - ocamlbuild/my_std.mli | 67 - ocamlbuild/my_unix.ml | 146 - ocamlbuild/my_unix.mli | 74 - ocamlbuild/ocaml_arch.ml | 136 - ocamlbuild/ocaml_arch.mli | 17 - ocamlbuild/ocaml_compiler.ml | 432 - ocamlbuild/ocaml_compiler.mli | 96 - ocamlbuild/ocaml_dependencies.ml | 262 - ocamlbuild/ocaml_dependencies.mli | 44 - ocamlbuild/ocaml_specific.ml | 792 - ocamlbuild/ocaml_specific.mli | 17 - ocamlbuild/ocaml_tools.ml | 163 - ocamlbuild/ocaml_tools.mli | 34 - ocamlbuild/ocaml_utils.ml | 178 - ocamlbuild/ocaml_utils.mli | 46 - ocamlbuild/ocamlbuild.ml | 16 - ocamlbuild/ocamlbuild.mli | 15 - ocamlbuild/ocamlbuild.mltop | 3 - ocamlbuild/ocamlbuild.odocl | 41 - ocamlbuild/ocamlbuild_executor.ml | 350 - ocamlbuild/ocamlbuild_executor.mli | 55 - ocamlbuild/ocamlbuild_pack.mlpack | 43 - ocamlbuild/ocamlbuild_plugin.ml | 63 - ocamlbuild/ocamlbuild_plugin.mli | 17 - ocamlbuild/ocamlbuild_unix_plugin.ml | 95 - ocamlbuild/ocamlbuild_unix_plugin.mli | 15 - ocamlbuild/ocamlbuild_where.ml | 19 - ocamlbuild/ocamlbuild_where.mli | 18 - ocamlbuild/ocamlbuildlib.mllib | 4 - ocamlbuild/ocamlbuildlight.ml | 15 - ocamlbuild/ocamlbuildlight.mli | 15 - ocamlbuild/ocamlbuildlightlib.mllib | 2 - ocamlbuild/options.ml | 373 - ocamlbuild/options.mli | 34 - ocamlbuild/param_tags.ml | 62 - ocamlbuild/param_tags.mli | 50 - ocamlbuild/pathname.ml | 159 - ocamlbuild/pathname.mli | 17 - ocamlbuild/plugin.ml | 262 - ocamlbuild/plugin.mli | 18 - ocamlbuild/ppcache.ml | 91 - ocamlbuild/ppcache.mli | 15 - ocamlbuild/report.ml | 62 - ocamlbuild/report.mli | 19 - ocamlbuild/resource.ml | 400 - ocamlbuild/resource.mli | 77 - ocamlbuild/rule.ml | 338 - ocamlbuild/rule.mli | 85 - ocamlbuild/shell.ml | 88 - ocamlbuild/shell.mli | 31 - ocamlbuild/signatures.mli | 797 - ocamlbuild/slurp.ml | 188 - ocamlbuild/slurp.mli | 49 - ocamlbuild/solver.ml | 132 - ocamlbuild/solver.mli | 24 - ocamlbuild/start.sh | 120 - ocamlbuild/tags.ml | 44 - ocamlbuild/tags.mli | 16 - ocamlbuild/testsuite/README | 13 - ocamlbuild/testsuite/external.ml | 22 - ocamlbuild/testsuite/external_test_header.ml | 7 - ocamlbuild/testsuite/findlibonly.ml | 42 - .../testsuite/findlibonly_test_header.ml | 9 - ocamlbuild/testsuite/internal.ml | 324 - ocamlbuild/testsuite/internal_test_header.ml | 10 - ocamlbuild/testsuite/ocamlbuild_test.ml | 536 - ocamlbuild/tools.ml | 46 - ocamlbuild/tools.mli | 19 - ocamldoc/.depend | 31 +- ocamldoc/.ignore | 16 - ocamldoc/Makefile | 72 +- ocamldoc/Makefile.nt | 54 +- ocamldoc/generators/odoc_literate.ml | 34 +- ocamldoc/generators/odoc_todo.ml | 25 +- ocamldoc/ocamldoc.hva | 25 +- ocamldoc/odoc.ml | 27 +- ocamldoc/odoc_analyse.ml | 44 +- ocamldoc/odoc_analyse.mli | 25 +- ocamldoc/odoc_args.ml | 72 +- ocamldoc/odoc_args.mli | 25 +- ocamldoc/odoc_ast.ml | 164 +- ocamldoc/odoc_ast.mli | 25 +- ocamldoc/odoc_class.ml | 31 +- ocamldoc/odoc_comments.ml | 61 +- ocamldoc/odoc_comments.mli | 25 +- ocamldoc/odoc_comments_global.ml | 25 +- ocamldoc/odoc_comments_global.mli | 25 +- ocamldoc/odoc_config.ml | 25 +- ocamldoc/odoc_config.mli | 25 +- ocamldoc/odoc_control.ml | 25 +- ocamldoc/odoc_cross.ml | 42 +- ocamldoc/odoc_cross.mli | 25 +- ocamldoc/odoc_dag2html.ml | 43 +- ocamldoc/odoc_dag2html.mli | 25 +- ocamldoc/odoc_dep.ml | 97 +- ocamldoc/odoc_dot.ml | 25 +- ocamldoc/odoc_env.ml | 31 +- ocamldoc/odoc_env.mli | 25 +- ocamldoc/odoc_exception.ml | 27 +- ocamldoc/odoc_extension.ml | 28 +- ocamldoc/odoc_gen.ml | 25 +- ocamldoc/odoc_gen.mli | 25 +- ocamldoc/odoc_global.ml | 25 +- ocamldoc/odoc_global.mli | 25 +- ocamldoc/odoc_html.ml | 118 +- ocamldoc/odoc_info.ml | 26 +- ocamldoc/odoc_info.mli | 59 +- ocamldoc/odoc_inherit.ml | 25 +- ocamldoc/odoc_latex.ml | 53 +- ocamldoc/odoc_latex_style.ml | 25 +- ocamldoc/odoc_lexer.mll | 59 +- ocamldoc/odoc_man.ml | 101 +- ocamldoc/odoc_merge.ml | 25 +- ocamldoc/odoc_merge.mli | 25 +- ocamldoc/odoc_messages.ml | 39 +- ocamldoc/odoc_misc.ml | 41 +- ocamldoc/odoc_misc.mli | 36 +- ocamldoc/odoc_module.ml | 27 +- ocamldoc/odoc_name.ml | 26 +- ocamldoc/odoc_name.mli | 25 +- ocamldoc/odoc_ocamlhtml.mll | 31 +- ocamldoc/odoc_parameter.ml | 25 +- ocamldoc/odoc_parser.mly | 24 +- ocamldoc/odoc_print.ml | 31 +- ocamldoc/odoc_print.mli | 25 +- ocamldoc/odoc_scan.ml | 25 +- ocamldoc/odoc_search.ml | 39 +- ocamldoc/odoc_search.mli | 25 +- ocamldoc/odoc_see_lexer.mll | 24 +- ocamldoc/odoc_sig.ml | 184 +- ocamldoc/odoc_sig.mli | 25 +- ocamldoc/odoc_str.ml | 100 +- ocamldoc/odoc_str.mli | 27 +- ocamldoc/odoc_test.ml | 25 +- ocamldoc/odoc_texi.ml | 41 +- ocamldoc/odoc_text.ml | 25 +- ocamldoc/odoc_text.mli | 25 +- ocamldoc/odoc_text_lexer.mll | 44 +- ocamldoc/odoc_text_parser.mly | 26 +- ocamldoc/odoc_to_text.ml | 100 +- ocamldoc/odoc_type.ml | 45 +- ocamldoc/odoc_types.ml | 25 +- ocamldoc/odoc_types.mli | 25 +- ocamldoc/odoc_value.ml | 39 +- ocamldoc/remove_DEBUG | 24 +- ocamldoc/runocamldoc | 23 - otherlibs/Makefile | 26 +- otherlibs/Makefile.nt | 32 +- otherlibs/Makefile.shared | 54 +- otherlibs/bigarray/.depend | 34 +- otherlibs/bigarray/Makefile | 26 +- otherlibs/bigarray/Makefile.nt | 26 +- otherlibs/bigarray/bigarray.h | 26 +- otherlibs/bigarray/bigarray.ml | 57 +- otherlibs/bigarray/bigarray.mli | 52 +- otherlibs/bigarray/bigarray_stubs.c | 135 +- otherlibs/bigarray/libbigarray.clib | 1 - otherlibs/bigarray/libbigarraywin32.clib | 1 - otherlibs/bigarray/mmap_unix.c | 26 +- otherlibs/bigarray/mmap_win32.c | 26 +- otherlibs/dynlink/.ignore | 1 - otherlibs/dynlink/Makefile | 52 +- otherlibs/dynlink/Makefile.nt | 26 +- otherlibs/dynlink/dynlink.ml | 36 +- otherlibs/dynlink/dynlink.mli | 26 +- otherlibs/dynlink/dynlinkaux.mlpack | 5 - otherlibs/dynlink/extract_crc.ml | 28 +- otherlibs/dynlink/natdynlink.ml | 26 +- otherlibs/graph/.depend | 38 +- otherlibs/graph/Makefile | 26 +- otherlibs/graph/color.c | 26 +- otherlibs/graph/draw.c | 26 +- otherlibs/graph/dump_img.c | 26 +- otherlibs/graph/events.c | 26 +- otherlibs/graph/fill.c | 26 +- otherlibs/graph/graphics.ml | 26 +- otherlibs/graph/graphics.mli | 26 +- otherlibs/graph/graphics.mllib | 1 - otherlibs/graph/graphicsX11.ml | 26 +- otherlibs/graph/graphicsX11.mli | 26 +- otherlibs/graph/image.c | 26 +- otherlibs/graph/image.h | 26 +- otherlibs/graph/libgraph.h | 32 +- otherlibs/graph/libgraphics.clib | 3 - otherlibs/graph/make_img.c | 26 +- otherlibs/graph/open.c | 26 +- otherlibs/graph/point_col.c | 26 +- otherlibs/graph/sound.c | 26 +- otherlibs/graph/subwindow.c | 26 +- otherlibs/graph/text.c | 26 +- otherlibs/num/.depend | 18 +- otherlibs/num/Makefile | 28 +- otherlibs/num/Makefile.nt | 28 +- otherlibs/num/arith_flags.ml | 26 +- otherlibs/num/arith_flags.mli | 26 +- otherlibs/num/arith_status.ml | 26 +- otherlibs/num/arith_status.mli | 31 +- otherlibs/num/big_int.ml | 103 +- otherlibs/num/big_int.mli | 78 +- otherlibs/num/bng.c | 28 +- otherlibs/num/bng.h | 28 +- otherlibs/num/bng_amd64.c | 28 +- otherlibs/num/bng_arm64.c | 26 +- otherlibs/num/bng_digit.c | 28 +- otherlibs/num/bng_ia32.c | 28 +- otherlibs/num/bng_ppc.c | 30 +- otherlibs/num/bng_sparc.c | 28 +- otherlibs/num/int_misc.ml | 26 +- otherlibs/num/int_misc.mli | 26 +- otherlibs/num/libnums.clib | 1 - otherlibs/num/nat.h | 28 +- otherlibs/num/nat.ml | 141 +- otherlibs/num/nat.mli | 68 +- otherlibs/num/nat_stubs.c | 45 +- otherlibs/num/num.ml | 34 +- otherlibs/num/num.mli | 26 +- otherlibs/num/nums.mllib | 1 - otherlibs/num/ratio.ml | 75 +- otherlibs/num/ratio.mli | 26 +- otherlibs/str/.depend | 7 +- otherlibs/str/Makefile | 26 +- otherlibs/str/Makefile.nt | 26 +- otherlibs/str/libstr.clib | 1 - otherlibs/str/str.ml | 55 +- otherlibs/str/str.mli | 34 +- otherlibs/str/strstubs.c | 197 +- otherlibs/systhreads/.depend | 18 +- otherlibs/systhreads/.ignore | 1 - otherlibs/systhreads/Makefile | 40 +- otherlibs/systhreads/Makefile.nt | 58 +- otherlibs/systhreads/condition.ml | 26 +- otherlibs/systhreads/condition.mli | 26 +- otherlibs/systhreads/event.ml | 30 +- otherlibs/systhreads/event.mli | 26 +- otherlibs/systhreads/libthreads.clib | 1 - otherlibs/systhreads/mutex.ml | 26 +- otherlibs/systhreads/mutex.mli | 26 +- otherlibs/systhreads/st_posix.h | 50 +- otherlibs/systhreads/st_stubs.c | 91 +- otherlibs/systhreads/st_win32.h | 40 +- otherlibs/systhreads/thread.ml | 30 +- otherlibs/systhreads/thread.mli | 26 +- otherlibs/systhreads/threadUnix.ml | 26 +- otherlibs/systhreads/threadUnix.mli | 26 +- otherlibs/systhreads/threads.h | 26 +- otherlibs/systhreads/threads.mllib | 1 - otherlibs/threads/.depend | 12 +- otherlibs/threads/.ignore | 3 - otherlibs/threads/Makefile | 39 +- otherlibs/threads/condition.ml | 26 +- otherlibs/threads/condition.mli | 26 +- otherlibs/threads/event.ml | 26 +- otherlibs/threads/event.mli | 26 +- otherlibs/threads/libvmthreads.clib | 1 - otherlibs/threads/marshal.ml | 26 +- otherlibs/threads/mutex.ml | 26 +- otherlibs/threads/mutex.mli | 26 +- otherlibs/threads/pervasives.ml | 114 +- otherlibs/threads/scheduler.c | 28 +- otherlibs/threads/thread.ml | 32 +- otherlibs/threads/thread.mli | 28 +- otherlibs/threads/threadUnix.ml | 26 +- otherlibs/threads/threadUnix.mli | 26 +- otherlibs/threads/threads.mllib | 1 - otherlibs/threads/unix.ml | 30 +- otherlibs/threads/unix.mllib | 1 - otherlibs/unix/.depend | 540 +- otherlibs/unix/Makefile | 26 +- otherlibs/unix/accept.c | 26 +- otherlibs/unix/access.c | 27 +- otherlibs/unix/addrofstr.c | 37 +- otherlibs/unix/alarm.c | 26 +- otherlibs/unix/bind.c | 26 +- otherlibs/unix/chdir.c | 27 +- otherlibs/unix/chmod.c | 27 +- otherlibs/unix/chown.c | 27 +- otherlibs/unix/chroot.c | 27 +- otherlibs/unix/close.c | 26 +- otherlibs/unix/closedir.c | 26 +- otherlibs/unix/connect.c | 26 +- otherlibs/unix/cst2constr.c | 26 +- otherlibs/unix/cst2constr.h | 26 +- otherlibs/unix/cstringv.c | 32 +- otherlibs/unix/dup.c | 26 +- otherlibs/unix/dup2.c | 26 +- otherlibs/unix/envir.c | 26 +- otherlibs/unix/errmsg.c | 26 +- otherlibs/unix/execv.c | 31 +- otherlibs/unix/execve.c | 33 +- otherlibs/unix/execvp.c | 35 +- otherlibs/unix/exit.c | 26 +- otherlibs/unix/fchmod.c | 26 +- otherlibs/unix/fchown.c | 26 +- otherlibs/unix/fcntl.c | 26 +- otherlibs/unix/fork.c | 26 +- otherlibs/unix/ftruncate.c | 26 +- otherlibs/unix/getaddrinfo.c | 29 +- otherlibs/unix/getcwd.c | 26 +- otherlibs/unix/getegid.c | 26 +- otherlibs/unix/geteuid.c | 26 +- otherlibs/unix/getgid.c | 26 +- otherlibs/unix/getgr.c | 27 +- otherlibs/unix/getgroups.c | 26 +- otherlibs/unix/gethost.c | 44 +- otherlibs/unix/gethostname.c | 26 +- otherlibs/unix/getlogin.c | 26 +- otherlibs/unix/getnameinfo.c | 26 +- otherlibs/unix/getpeername.c | 26 +- otherlibs/unix/getpid.c | 26 +- otherlibs/unix/getppid.c | 26 +- otherlibs/unix/getproto.c | 27 +- otherlibs/unix/getpw.c | 27 +- otherlibs/unix/getserv.c | 29 +- otherlibs/unix/getsockname.c | 26 +- otherlibs/unix/gettimeofday.c | 26 +- otherlibs/unix/getuid.c | 26 +- otherlibs/unix/gmtime.c | 26 +- otherlibs/unix/initgroups.c | 29 +- otherlibs/unix/isatty.c | 26 +- otherlibs/unix/itimer.c | 26 +- otherlibs/unix/kill.c | 26 +- otherlibs/unix/libunix.clib | 16 - otherlibs/unix/link.c | 28 +- otherlibs/unix/listen.c | 26 +- otherlibs/unix/lockf.c | 26 +- otherlibs/unix/lseek.c | 26 +- otherlibs/unix/mkdir.c | 27 +- otherlibs/unix/mkfifo.c | 28 +- otherlibs/unix/nanosecond_stat.h | 26 +- otherlibs/unix/nice.c | 26 +- otherlibs/unix/open.c | 27 +- otherlibs/unix/opendir.c | 27 +- otherlibs/unix/pipe.c | 26 +- otherlibs/unix/putenv.c | 32 +- otherlibs/unix/read.c | 26 +- otherlibs/unix/readdir.c | 26 +- otherlibs/unix/readlink.c | 27 +- otherlibs/unix/rename.c | 28 +- otherlibs/unix/rewinddir.c | 26 +- otherlibs/unix/rmdir.c | 27 +- otherlibs/unix/select.c | 26 +- otherlibs/unix/sendrecv.c | 26 +- otherlibs/unix/setgid.c | 26 +- otherlibs/unix/setgroups.c | 26 +- otherlibs/unix/setsid.c | 26 +- otherlibs/unix/setuid.c | 26 +- otherlibs/unix/shutdown.c | 26 +- otherlibs/unix/signals.c | 26 +- otherlibs/unix/sleep.c | 79 +- otherlibs/unix/socket.c | 26 +- otherlibs/unix/socketaddr.c | 40 +- otherlibs/unix/socketaddr.h | 26 +- otherlibs/unix/socketpair.c | 26 +- otherlibs/unix/sockopt.c | 26 +- otherlibs/unix/stat.c | 39 +- otherlibs/unix/strofaddr.c | 26 +- otherlibs/unix/symlink.c | 46 +- otherlibs/unix/termios.c | 26 +- otherlibs/unix/time.c | 26 +- otherlibs/unix/times.c | 26 +- otherlibs/unix/truncate.c | 28 +- otherlibs/unix/umask.c | 26 +- otherlibs/unix/unix.ml | 67 +- otherlibs/unix/unix.mli | 354 +- otherlibs/unix/unix.mllib | 1 - otherlibs/unix/unixLabels.ml | 26 +- otherlibs/unix/unixLabels.mli | 39 +- otherlibs/unix/unixsupport.c | 31 +- otherlibs/unix/unixsupport.h | 40 +- otherlibs/unix/unlink.c | 27 +- otherlibs/unix/utimes.c | 93 +- otherlibs/unix/wait.c | 26 +- otherlibs/unix/write.c | 26 +- otherlibs/win32graph/.ignore | 2 - otherlibs/win32graph/Makefile.nt | 29 +- otherlibs/win32graph/dib.c | 61 +- otherlibs/win32graph/draw.c | 47 +- otherlibs/win32graph/events.c | 26 +- otherlibs/win32graph/libgraph.h | 26 +- otherlibs/win32graph/libgraphics.clib | 1 - otherlibs/win32graph/open.c | 44 +- otherlibs/win32unix/.ignore | 29 - otherlibs/win32unix/Makefile | 74 +- otherlibs/win32unix/Makefile.common | 63 + otherlibs/win32unix/Makefile.nt | 74 +- otherlibs/win32unix/accept.c | 42 +- otherlibs/win32unix/bind.c | 26 +- otherlibs/win32unix/channels.c | 26 +- otherlibs/win32unix/close.c | 26 +- otherlibs/win32unix/close_on.c | 26 +- otherlibs/win32unix/connect.c | 26 +- otherlibs/win32unix/createprocess.c | 34 +- otherlibs/win32unix/dup.c | 26 +- otherlibs/win32unix/dup2.c | 26 +- otherlibs/win32unix/errmsg.c | 26 +- otherlibs/win32unix/getpeername.c | 26 +- otherlibs/win32unix/getpid.c | 26 +- otherlibs/win32unix/getsockname.c | 26 +- otherlibs/win32unix/gettimeofday.c | 28 +- otherlibs/win32unix/libunix.clib | 17 - otherlibs/win32unix/link.c | 28 +- otherlibs/win32unix/listen.c | 26 +- otherlibs/win32unix/lockf.c | 29 +- otherlibs/win32unix/lseek.c | 26 +- otherlibs/win32unix/mkdir.c | 27 +- otherlibs/win32unix/nonblock.c | 26 +- otherlibs/win32unix/open.c | 27 +- otherlibs/win32unix/pipe.c | 26 +- otherlibs/win32unix/read.c | 26 +- otherlibs/win32unix/readlink.c | 105 + otherlibs/win32unix/rename.c | 28 +- otherlibs/win32unix/select.c | 155 +- otherlibs/win32unix/sendrecv.c | 26 +- otherlibs/win32unix/shutdown.c | 26 +- otherlibs/win32unix/sleep.c | 28 +- otherlibs/win32unix/socket.c | 42 +- otherlibs/win32unix/socketaddr.h | 26 +- otherlibs/win32unix/sockopt.c | 26 +- otherlibs/win32unix/startup.c | 26 +- otherlibs/win32unix/stat.c | 331 +- otherlibs/win32unix/symlink.c | 103 + otherlibs/win32unix/system.c | 27 +- otherlibs/win32unix/times.c | 26 +- otherlibs/win32unix/unix.ml | 62 +- otherlibs/win32unix/unixsupport.c | 73 +- otherlibs/win32unix/unixsupport.h | 67 +- otherlibs/win32unix/windbug.c | 26 +- otherlibs/win32unix/windbug.h | 26 +- otherlibs/win32unix/windir.c | 36 +- otherlibs/win32unix/winlist.c | 26 +- otherlibs/win32unix/winlist.h | 26 +- otherlibs/win32unix/winwait.c | 26 +- otherlibs/win32unix/winworker.c | 26 +- otherlibs/win32unix/winworker.h | 26 +- otherlibs/win32unix/write.c | 26 +- parsing/.ignore | 9 - parsing/ast_helper.ml | 48 +- parsing/ast_helper.mli | 116 +- parsing/ast_invariants.ml | 166 + parsing/ast_invariants.mli | 18 + parsing/ast_iterator.ml | 591 + parsing/ast_iterator.mli | 72 + parsing/ast_mapper.ml | 205 +- parsing/ast_mapper.mli | 37 +- parsing/asttypes.mli | 31 +- parsing/attr_helper.ml | 54 + parsing/attr_helper.mli | 36 + parsing/builtin_attributes.ml | 190 + parsing/builtin_attributes.mli | 47 + parsing/docstrings.ml | 44 +- parsing/docstrings.mli | 26 +- parsing/lexer.mli | 28 +- parsing/lexer.mll | 190 +- parsing/location.ml | 117 +- parsing/location.mli | 41 +- parsing/longident.ml | 25 +- parsing/longident.mli | 25 +- parsing/parse.ml | 25 +- parsing/parse.mli | 25 +- parsing/parser.mly | 1069 +- parsing/parsetree.mli | 119 +- parsing/pprintast.ml | 479 +- parsing/pprintast.mli | 42 +- parsing/printast.ml | 90 +- parsing/printast.mli | 25 +- parsing/syntaxerr.ml | 55 +- parsing/syntaxerr.mli | 26 +- stdlib/.depend | 134 +- stdlib/.ignore | 8 - stdlib/Compflags | 26 +- stdlib/Makefile | 65 +- stdlib/Makefile.nt | 34 +- stdlib/Makefile.shared | 84 +- stdlib/StdlibModules | 27 +- stdlib/arg.ml | 215 +- stdlib/arg.mli | 31 +- stdlib/array.ml | 100 +- stdlib/array.mli | 90 +- stdlib/arrayLabels.ml | 26 +- stdlib/arrayLabels.mli | 54 +- stdlib/buffer.ml | 58 +- stdlib/buffer.mli | 56 +- stdlib/bytes.ml | 100 +- stdlib/bytes.mli | 79 +- stdlib/bytesLabels.ml | 26 +- stdlib/bytesLabels.mli | 30 +- stdlib/callback.ml | 26 +- stdlib/callback.mli | 26 +- stdlib/camlinternalFormat.ml | 363 +- stdlib/camlinternalFormat.mli | 20 +- stdlib/camlinternalFormatBasics.ml | 33 +- stdlib/camlinternalFormatBasics.mli | 18 +- stdlib/camlinternalLazy.ml | 37 +- stdlib/camlinternalLazy.mli | 36 +- stdlib/camlinternalMod.ml | 52 +- stdlib/camlinternalMod.mli | 26 +- stdlib/camlinternalOO.ml | 151 +- stdlib/camlinternalOO.mli | 28 +- stdlib/char.ml | 46 +- stdlib/char.mli | 56 +- stdlib/complex.ml | 26 +- stdlib/complex.mli | 26 +- stdlib/digest.ml | 27 +- stdlib/digest.mli | 30 +- stdlib/ephemeron.ml | 616 + stdlib/ephemeron.mli | 368 + stdlib/filename.ml | 40 +- stdlib/filename.mli | 38 +- stdlib/format.ml | 820 +- stdlib/format.mli | 702 +- stdlib/gc.ml | 104 +- stdlib/gc.mli | 81 +- stdlib/genlex.ml | 26 +- stdlib/genlex.mli | 26 +- stdlib/hashtbl.ml | 52 +- stdlib/hashtbl.mli | 60 +- stdlib/header.c | 28 +- stdlib/headernt.c | 30 +- stdlib/int32.ml | 43 +- stdlib/int32.mli | 46 +- stdlib/int64.ml | 43 +- stdlib/int64.mli | 46 +- stdlib/lazy.ml | 50 +- stdlib/lazy.mli | 53 +- stdlib/lexing.ml | 43 +- stdlib/lexing.mli | 28 +- stdlib/list.ml | 47 +- stdlib/list.mli | 60 +- stdlib/listLabels.ml | 26 +- stdlib/listLabels.mli | 54 +- stdlib/map.ml | 68 +- stdlib/map.mli | 50 +- stdlib/marshal.ml | 26 +- stdlib/marshal.mli | 26 +- stdlib/moreLabels.ml | 26 +- stdlib/moreLabels.mli | 33 +- stdlib/nativeint.ml | 35 +- stdlib/nativeint.mli | 38 +- stdlib/obj.ml | 90 +- stdlib/obj.mli | 104 +- stdlib/oo.ml | 26 +- stdlib/oo.mli | 26 +- stdlib/parsing.ml | 44 +- stdlib/parsing.mli | 28 +- stdlib/pervasives.ml | 123 +- stdlib/pervasives.mli | 145 +- stdlib/printexc.ml | 38 +- stdlib/printexc.mli | 26 +- stdlib/printf.ml | 28 +- stdlib/printf.mli | 46 +- stdlib/queue.ml | 219 +- stdlib/queue.mli | 26 +- stdlib/random.ml | 138 +- stdlib/random.mli | 34 +- stdlib/scanf.ml | 899 +- stdlib/scanf.mli | 214 +- stdlib/set.ml | 53 +- stdlib/set.mli | 40 +- stdlib/sort.ml | 26 +- stdlib/sort.mli | 26 +- stdlib/stack.ml | 46 +- stdlib/stack.mli | 34 +- stdlib/stdLabels.ml | 26 +- stdlib/stdLabels.mli | 26 +- stdlib/std_exit.ml | 26 +- stdlib/stdlib.mllib | 48 - stdlib/stream.ml | 169 +- stdlib/stream.mli | 26 +- stdlib/string.ml | 57 +- stdlib/string.mli | 91 +- stdlib/stringLabels.ml | 26 +- stdlib/stringLabels.mli | 30 +- stdlib/sys.mli | 104 +- stdlib/sys.mlp | 56 +- stdlib/uchar.ml | 55 + stdlib/uchar.mli | 90 + stdlib/weak.ml | 117 +- stdlib/weak.mli | 62 +- testsuite/.ignore | 1 - testsuite/Makefile | 115 +- testsuite/external/.ignore | 152 - testsuite/external/Makefile | 1747 -- testsuite/external/Patcher.sh | 31 - testsuite/external/TODO.txt | 26 - testsuite/external/boomerang-0.2.patch | 11 - testsuite/external/camlimages-4.0.1.patch | 11 - testsuite/external/camlp5-6.06.patch | 2243 -- testsuite/external/camlp5-6.08.patch | 1127 - testsuite/external/camlp5-6.10.patch | 10 - testsuite/external/camlp5-git.patch | 12 - testsuite/external/camlpdf-0.5.patch | 25 - testsuite/external/camlzip-1.04.patch | 45 - testsuite/external/coq-8.3pl4.patch | 59 - testsuite/external/coq-8.4pl1.patch | 11 - testsuite/external/coq-8.4pl2.patch | 11 - testsuite/external/core-109.37.00.patch | 20 - testsuite/external/core-suite-108.00.01.patch | 213 - testsuite/external/extlib-1.5.2.patch | 10 - .../external/frama-c-Nitrogen-20111001.patch | 126 - .../external/frama-c-Oxygen-20120901.patch | 185 - testsuite/external/hevea-1.10.patch | 22 - testsuite/external/kaputt-1.2.patch | 37 - testsuite/external/lablgtk-2.14.2.patch | 11 - testsuite/external/lablgtk-2.16.0.patch | 22 - testsuite/external/lablgtkextras-1.1.patch | 22 - testsuite/external/lablgtkextras-1.3.patch | 11 - testsuite/external/lwt-2.4.0.patch | 24 - testsuite/external/menhir-20120123.patch | 11 - testsuite/external/mldonkey-3.1.2.patch | 31 - testsuite/external/oasis-common.patch | 55 - testsuite/external/obrowser-1.1.1.patch | 1385 -- .../external/ocaml-bitstring-2.0.3.patch | 11 - .../external/ocaml-mysql-1.0.4.patch.disabled | 15 - testsuite/external/ocamlnet-3.5.1.patch | 52 - testsuite/external/ocsigen-bundle-2.2.2.patch | 47 - testsuite/external/omake-0.9.8.6.patch | 11 - testsuite/external/sks-1.1.3.patch | 20 - testsuite/external/vsyml-2010-04-06.patch | 20 - testsuite/external/xml-light-2.2.patch | 19 - testsuite/interactive/lib-gc/Makefile | 25 +- testsuite/interactive/lib-gc/alloc.ml | 25 +- testsuite/interactive/lib-graph-2/Makefile | 25 +- .../interactive/lib-graph-2/graph_test.ml | 25 +- testsuite/interactive/lib-graph-3/Makefile | 25 +- testsuite/interactive/lib-graph-3/sorts.ml | 25 +- testsuite/interactive/lib-graph/Makefile | 25 +- .../interactive/lib-graph/graph_example.ml | 25 +- testsuite/interactive/lib-signals/Makefile | 25 +- testsuite/interactive/lib-signals/signals.ml | 25 +- testsuite/lib/Makefile | 25 +- testsuite/lib/testing.ml | 25 +- testsuite/lib/testing.mli | 25 +- testsuite/makefiles/Makefile.common | 89 +- testsuite/makefiles/Makefile.dlambda | 35 + testsuite/makefiles/Makefile.dparsetree | 30 + testsuite/makefiles/Makefile.okbad | 25 +- testsuite/makefiles/Makefile.one | 59 +- testsuite/makefiles/Makefile.several | 49 +- testsuite/makefiles/Makefile.toplevel | 25 +- testsuite/makefiles/summarize.awk | 169 +- testsuite/tests/array-functions/Makefile | 18 + testsuite/tests/array-functions/test.ml | 182 + .../tests/array-functions/test.reference | 1 + testsuite/tests/asmcomp/.ignore | 7 - testsuite/tests/asmcomp/Makefile | 101 +- testsuite/tests/asmcomp/alpha.S | 25 +- testsuite/tests/asmcomp/amd64.S | 25 +- testsuite/tests/asmcomp/arith.cmm | 30 +- testsuite/tests/asmcomp/arm.S | 25 +- testsuite/tests/asmcomp/arm64.S | 25 +- testsuite/tests/asmcomp/bind_tuples.ml | 40 + testsuite/tests/asmcomp/checkbound.cmm | 25 +- testsuite/tests/asmcomp/fib.cmm | 25 +- testsuite/tests/asmcomp/i386.S | 25 +- testsuite/tests/asmcomp/ia64.S | 25 +- testsuite/tests/asmcomp/integr.cmm | 25 +- testsuite/tests/asmcomp/is_in_static_data.c | 5 + testsuite/tests/asmcomp/is_static.ml | 34 + testsuite/tests/asmcomp/is_static_flambda.ml | 93 + testsuite/tests/asmcomp/lexcmm.mli | 25 +- testsuite/tests/asmcomp/lexcmm.mll | 29 +- testsuite/tests/asmcomp/main.c | 52 +- testsuite/tests/asmcomp/main.ml | 27 +- testsuite/tests/asmcomp/mainarith.c | 90 +- testsuite/tests/asmcomp/mips.s | 25 +- testsuite/tests/asmcomp/optargs.ml | 25 +- testsuite/tests/asmcomp/parsecmm.mly | 56 +- testsuite/tests/asmcomp/parsecmmaux.ml | 25 +- testsuite/tests/asmcomp/parsecmmaux.mli | 25 +- testsuite/tests/asmcomp/power-aix.S | 150 - testsuite/tests/asmcomp/power-elf.S | 129 - testsuite/tests/asmcomp/power-rhapsody.S | 127 - testsuite/tests/asmcomp/power.S | 197 + testsuite/tests/asmcomp/quicksort.cmm | 27 +- testsuite/tests/asmcomp/quicksort2.cmm | 29 +- testsuite/tests/asmcomp/register_typing.ml | 20 + testsuite/tests/asmcomp/s390x.S | 64 + testsuite/tests/asmcomp/soli.cmm | 31 +- testsuite/tests/asmcomp/sparc.S | 25 +- testsuite/tests/asmcomp/staticalloc.ml | 25 +- testsuite/tests/asmcomp/tagged-fib.cmm | 25 +- testsuite/tests/asmcomp/tagged-integr.cmm | 33 +- testsuite/tests/asmcomp/tagged-quicksort.cmm | 29 +- testsuite/tests/asmcomp/tagged-tak.cmm | 25 +- testsuite/tests/asmcomp/tak.cmm | 25 +- testsuite/tests/asmcomp/unrolling_flambda.ml | 7 + testsuite/tests/ast-invariants/Makefile | 27 + testsuite/tests/ast-invariants/test.ml | 85 + testsuite/tests/ast-invariants/test.reference | 0 testsuite/tests/backtrace/Makefile | 69 +- .../tests/backtrace/backtrace..reference | 2 +- .../tests/backtrace/backtrace.b.reference | 18 +- .../tests/backtrace/backtrace.c.reference | 4 +- .../tests/backtrace/backtrace.d.reference | 16 +- testsuite/tests/backtrace/backtrace.ml | 11 - testsuite/tests/backtrace/backtrace2.ml | 11 - .../tests/backtrace/backtrace2.reference | 40 +- testsuite/tests/backtrace/backtrace3.ml | 39 + .../tests/backtrace/backtrace3.reference | 27 + .../tests/backtrace/backtrace_deprecated.ml | 11 - .../backtrace/backtrace_deprecated.reference | 40 +- testsuite/tests/backtrace/backtrace_slots.ml | 11 - .../tests/backtrace/backtrace_slots.reference | 40 +- .../backtrace/backtraces_and_finalizers.ml | 1 + testsuite/tests/backtrace/pr6920_why_at.ml | 9 + .../tests/backtrace/pr6920_why_at.reference | 4 + .../tests/backtrace/pr6920_why_swallow.ml | 11 + .../backtrace/pr6920_why_swallow.reference | 4 + testsuite/tests/backtrace/raw_backtrace.ml | 11 - .../tests/backtrace/raw_backtrace.reference | 40 +- testsuite/tests/basic-float/Makefile | 27 +- testsuite/tests/basic-float/float_array.ml | 8 + testsuite/tests/basic-float/float_record.ml | 25 +- testsuite/tests/basic-float/float_record.mli | 25 +- testsuite/tests/basic-float/tfloat_record.ml | 39 +- .../tests/basic-float/tfloat_record.reference | 45 + testsuite/tests/basic-io-2/Makefile | 25 +- testsuite/tests/basic-io-2/io.ml | 25 +- .../tests/basic-io-2/test-file-short-lines | 6 +- testsuite/tests/basic-io/Makefile | 25 +- testsuite/tests/basic-io/wc.ml | 11 - testsuite/tests/basic-io/wc.reference | 2 +- testsuite/tests/basic-manyargs/Makefile | 25 +- testsuite/tests/basic-manyargs/manyargs.ml | 25 +- testsuite/tests/basic-manyargs/manyargsprim.c | 25 +- testsuite/tests/basic-modules/Makefile | 27 +- testsuite/tests/basic-modules/main.ml | 16 + testsuite/tests/basic-modules/main.mli | 0 testsuite/tests/basic-modules/offset.ml | 15 + testsuite/tests/basic-modules/pr6726.ml | 33 + testsuite/tests/basic-more/Makefile | 25 +- testsuite/tests/basic-more/bounds.ml | 25 +- testsuite/tests/basic-more/function_in_ref.ml | 9 + .../basic-more/function_in_ref.reference | 2 + testsuite/tests/basic-more/if_in_if.ml | 44 + testsuite/tests/basic-more/if_in_if.reference | 2 + testsuite/tests/basic-more/morematch.ml | 55 +- testsuite/tests/basic-more/opaque_prim.ml | 6 + .../tests/basic-more/opaque_prim.reference | 2 + testsuite/tests/basic-more/pr2719.ml | 15 + testsuite/tests/basic-more/pr6216.ml | 15 + .../tests/basic-more/sequential_and_or.ml | 137 + .../basic-more/sequential_and_or.reference | 74 + testsuite/tests/basic-more/testrandom.ml | 25 +- .../tests/basic-more/top_level_patterns.ml | 8 + .../basic-more/top_level_patterns.reference | 2 + testsuite/tests/basic-more/tprintf.ml | 25 +- testsuite/tests/basic-multdef/Makefile | 25 +- testsuite/tests/basic-multdef/multdef.ml | 25 +- testsuite/tests/basic-multdef/multdef.mli | 25 +- testsuite/tests/basic-multdef/usemultdef.ml | 25 +- testsuite/tests/basic-private/Makefile | 25 +- testsuite/tests/basic-private/length.ml | 25 +- testsuite/tests/basic-private/length.mli | 25 +- testsuite/tests/basic-private/tlength.ml | 25 +- testsuite/tests/basic/Makefile | 25 +- testsuite/tests/basic/arrays.ml | 28 +- testsuite/tests/basic/bigints.ml | 25 +- testsuite/tests/basic/boxedints.ml | 25 +- testsuite/tests/basic/constprop.ml | 80 +- testsuite/tests/basic/constprop.mlp | 32 +- testsuite/tests/basic/divint.ml | 106 +- testsuite/tests/basic/equality.ml | 25 +- testsuite/tests/basic/float.ml | 25 +- .../tests/basic/float_physical_equality.ml | 10 + .../basic/float_physical_equality.reference | 0 testsuite/tests/basic/includestruct.ml | 25 +- testsuite/tests/basic/maps.ml | 38 +- testsuite/tests/basic/maps.reference | 6 +- testsuite/tests/basic/min_int.ml | 10 + testsuite/tests/basic/min_int.reference | 1 + testsuite/tests/basic/patmatch.ml | 1513 +- testsuite/tests/basic/patmatch.reference | 5 + testsuite/tests/basic/recvalues.ml | 25 +- testsuite/tests/basic/sets.ml | 25 +- testsuite/tests/basic/stringmatch.ml | 15 + testsuite/tests/basic/tailcalls.ml | 25 +- testsuite/tests/callback/Makefile | 32 +- testsuite/tests/callback/callbackprim.c | 25 +- testsuite/tests/callback/tcallback.ml | 31 +- testsuite/tests/embedded/.ignore | 1 - testsuite/tests/embedded/Makefile | 29 +- testsuite/tests/embedded/cmcaml.ml | 25 +- testsuite/tests/exotic-syntax/Makefile | 25 +- testsuite/tests/exotic-syntax/exotic.ml | 32 +- .../tests/extension-constructor/Makefile | 18 + testsuite/tests/extension-constructor/test.ml | 36 + .../extension-constructor/test.reference | 1 + testsuite/tests/float-unboxing/Makefile | 12 + .../float_subst_boxed_number.ml | 65 + .../ignored_scan_counters.ml | 2 +- .../formats-transition/invalid_formats.ml | 67 - .../invalid_formats.ml.reference | 24 - .../legacy_incompatible_flags.ml.reference | 8 + testsuite/tests/formatting/Makefile | 5 + testsuite/tests/formatting/margins.ml | 7 + .../tests/formatting/margins.ml.reference | 14 + testsuite/tests/gc-roots/Makefile | 25 +- testsuite/tests/gc-roots/globroots.ml | 25 +- testsuite/tests/int64-unboxing/Makefile | 24 + testsuite/tests/int64-unboxing/stubs.c | 25 + testsuite/tests/int64-unboxing/test.ml | 40 + testsuite/tests/int64-unboxing/test.reference | 0 testsuite/tests/letrec/Makefile | 25 +- testsuite/tests/letrec/backreferences.ml | 25 +- testsuite/tests/letrec/class_1.ml | 25 +- testsuite/tests/letrec/class_2.ml | 25 +- testsuite/tests/letrec/evaluation_order_1.ml | 25 +- testsuite/tests/letrec/evaluation_order_2.ml | 36 +- .../tests/letrec/evaluation_order_2.reference | 6 +- testsuite/tests/letrec/evaluation_order_3.ml | 25 +- testsuite/tests/letrec/float_block_1.ml | 35 +- .../tests/letrec/float_block_1.reference | 4 +- testsuite/tests/letrec/float_block_2.ml | 25 +- testsuite/tests/letrec/lists.ml | 25 +- .../tests/letrec/mixing_value_closures_1.ml | 25 +- .../tests/letrec/mixing_value_closures_2.ml | 25 +- testsuite/tests/letrec/mutual_functions.ml | 25 +- testsuite/tests/letrec/record_with.ml | 25 +- testsuite/tests/lib-arg/Makefile | 20 + testsuite/tests/lib-arg/testarg.ml | 123 + testsuite/tests/lib-arg/testarg.reference | 0 testsuite/tests/lib-bigarray-2/Makefile | 27 +- testsuite/tests/lib-bigarray-2/bigarrfml.ml | 27 +- testsuite/tests/lib-bigarray-2/bigarrfstub.c | 25 +- testsuite/tests/lib-bigarray/Makefile | 25 +- testsuite/tests/lib-bigarray/bigarrays.ml | 155 +- .../tests/lib-bigarray/bigarrays.reference | 12 +- testsuite/tests/lib-bigarray/fftba.ml | 25 +- testsuite/tests/lib-bigarray/pr5115.ml | 25 +- testsuite/tests/lib-digest/Makefile | 25 +- testsuite/tests/lib-digest/md5.ml | 25 +- testsuite/tests/lib-dynlink-bytecode/.ignore | 6 - testsuite/tests/lib-dynlink-bytecode/Makefile | 31 +- testsuite/tests/lib-dynlink-bytecode/main.ml | 25 +- testsuite/tests/lib-dynlink-bytecode/plug1.ml | 25 +- testsuite/tests/lib-dynlink-bytecode/plug2.ml | 25 +- .../tests/lib-dynlink-bytecode/registry.ml | 25 +- testsuite/tests/lib-dynlink-bytecode/stub1.c | 30 +- testsuite/tests/lib-dynlink-bytecode/stub2.c | 29 +- testsuite/tests/lib-dynlink-csharp/Makefile | 77 +- .../lib-dynlink-csharp/bytecode.reference | 1 - testsuite/tests/lib-dynlink-csharp/entry.c | 27 +- testsuite/tests/lib-dynlink-csharp/main.ml | 26 +- .../tests/lib-dynlink-csharp/native.reference | 1 - testsuite/tests/lib-dynlink-csharp/plugin.ml | 25 +- testsuite/tests/lib-dynlink-native/.ignore | 7 - testsuite/tests/lib-dynlink-native/Makefile | 47 +- testsuite/tests/lib-dynlink-native/a.ml | 25 +- testsuite/tests/lib-dynlink-native/api.ml | 25 +- testsuite/tests/lib-dynlink-native/b.ml | 25 +- testsuite/tests/lib-dynlink-native/bug.ml | 25 +- testsuite/tests/lib-dynlink-native/c.ml | 25 +- .../tests/lib-dynlink-native/factorial.c | 25 +- testsuite/tests/lib-dynlink-native/main.ml | 25 +- .../tests/lib-dynlink-native/pack_client.ml | 25 +- testsuite/tests/lib-dynlink-native/packed1.ml | 25 +- .../lib-dynlink-native/packed1_client.ml | 25 +- testsuite/tests/lib-dynlink-native/plugin.ml | 25 +- testsuite/tests/lib-dynlink-native/plugin.mli | 25 +- testsuite/tests/lib-dynlink-native/plugin2.ml | 25 +- testsuite/tests/lib-dynlink-native/plugin4.ml | 25 +- .../tests/lib-dynlink-native/plugin_ext.ml | 25 +- .../lib-dynlink-native/plugin_high_arity.ml | 25 +- .../tests/lib-dynlink-native/plugin_ref.ml | 25 +- .../tests/lib-dynlink-native/plugin_simple.ml | 25 +- .../tests/lib-dynlink-native/plugin_thread.ml | 25 +- testsuite/tests/lib-dynlink-native/sub/api.ml | 25 +- .../tests/lib-dynlink-native/sub/api.mli | 25 +- .../tests/lib-dynlink-native/sub/plugin.ml | 25 +- .../tests/lib-dynlink-native/sub/plugin3.ml | 25 +- testsuite/tests/lib-format/Makefile | 25 +- testsuite/tests/lib-format/tformat.ml | 30 + testsuite/tests/lib-format/tformat.reference | 60 +- testsuite/tests/lib-hashtbl/Makefile | 25 +- testsuite/tests/lib-hashtbl/hfun.ml | 25 +- testsuite/tests/lib-hashtbl/htbl.ml | 129 +- testsuite/tests/lib-hashtbl/htbl.reference | 32 + testsuite/tests/lib-marshal/Makefile | 25 +- testsuite/tests/lib-marshal/intext.ml | 31 +- testsuite/tests/lib-marshal/intextaux.c | 25 +- testsuite/tests/lib-num-2/Makefile | 25 +- testsuite/tests/lib-num/Makefile | 25 +- testsuite/tests/lib-num/end_test.ml | 25 +- testsuite/tests/lib-num/end_test.reference | 4 + testsuite/tests/lib-num/test.ml | 26 +- testsuite/tests/lib-num/test_big_ints.ml | 114 +- testsuite/tests/lib-num/test_io.ml | 25 +- testsuite/tests/lib-num/test_nats.ml | 25 +- testsuite/tests/lib-num/test_nums.ml | 25 +- testsuite/tests/lib-num/test_ratios.ml | 44 +- testsuite/tests/lib-printf/Makefile | 25 +- testsuite/tests/lib-printf/pr6938.ml | 42 + testsuite/tests/lib-printf/pr6938.reference | 31 + testsuite/tests/lib-printf/tprintf.ml | 30 + testsuite/tests/lib-printf/tprintf.reference | 60 +- testsuite/tests/lib-queue/Makefile | 18 + testsuite/tests/lib-queue/test.ml | 153 + testsuite/tests/lib-queue/test.reference | 1 + testsuite/tests/lib-random/Makefile | 25 +- testsuite/tests/lib-scanf-2/Makefile | 25 +- testsuite/tests/lib-scanf-2/tscanf2_io.ml | 25 +- testsuite/tests/lib-scanf-2/tscanf2_master.ml | 25 +- testsuite/tests/lib-scanf-2/tscanf2_slave.ml | 25 +- testsuite/tests/lib-scanf/.ignore | 1 - testsuite/tests/lib-scanf/Makefile | 25 +- testsuite/tests/lib-scanf/tscanf.ml | 60 +- testsuite/tests/lib-set/Makefile | 25 +- testsuite/tests/lib-set/testmap.ml | 77 +- testsuite/tests/lib-set/testset.ml | 65 +- testsuite/tests/lib-stack/Makefile | 18 + testsuite/tests/lib-stack/test.ml | 130 + testsuite/tests/lib-stack/test.reference | 1 + testsuite/tests/lib-str/Makefile | 25 +- testsuite/tests/lib-str/t01.ml | 266 +- testsuite/tests/lib-str/t01.reference | 2 + testsuite/tests/lib-stream/Makefile | 25 +- .../tests/lib-stream/count_concat_bug.ml | 25 +- testsuite/tests/lib-string/Makefile | 22 + testsuite/tests/lib-string/test_string.ml | 38 + .../tests/lib-string/test_string.reference | 0 testsuite/tests/lib-systhreads/Makefile | 25 +- testsuite/tests/lib-systhreads/testfork.ml | 25 +- .../tests/lib-systhreads/testfork.precheck | 31 +- testsuite/tests/lib-threads/.ignore | 1 - testsuite/tests/lib-threads/Makefile | 35 +- testsuite/tests/lib-threads/bank.ml | 42 + testsuite/tests/lib-threads/bank.reference | 2 + testsuite/tests/lib-threads/beat.ml | 34 + testsuite/tests/lib-threads/beat.reference | 1 + testsuite/tests/lib-threads/bufchan.ml | 66 + .../{test8.reference => bufchan.reference} | 0 testsuite/tests/lib-threads/close.ml | 25 +- testsuite/tests/lib-threads/fileio.ml | 132 + testsuite/tests/lib-threads/fileio.reference | 22 + testsuite/tests/lib-threads/pr4466.ml | 85 + testsuite/tests/lib-threads/pr4466.reference | 6 + testsuite/tests/lib-threads/pr5325.ml | 72 + testsuite/tests/lib-threads/pr5325.reference | 1 + testsuite/tests/lib-threads/prodcons.ml | 77 + .../tests/lib-threads/prodcons.reference | 1 + testsuite/tests/lib-threads/prodcons2.ml | 48 + .../tests/lib-threads/prodcons2.reference | 1 + testsuite/tests/lib-threads/sieve.ml | 82 +- testsuite/tests/lib-threads/sieve.reference | 45 - testsuite/tests/lib-threads/sigint.c | 37 + testsuite/tests/lib-threads/signal.checker | 16 + testsuite/tests/lib-threads/signal.ml | 28 + testsuite/tests/lib-threads/signal.precheck | 1 + testsuite/tests/lib-threads/signal.runner | 19 + testsuite/tests/lib-threads/signal2.checker | 16 + testsuite/tests/lib-threads/signal2.ml | 26 + testsuite/tests/lib-threads/signal2.precheck | 16 + testsuite/tests/lib-threads/signal2.runner | 21 + testsuite/tests/lib-threads/sockets.ml | 52 + testsuite/tests/lib-threads/sockets.reference | 2 + testsuite/tests/lib-threads/socketsbuf.ml | 54 + .../tests/lib-threads/socketsbuf.reference | 2 + testsuite/tests/lib-threads/swapchan.checker | 16 + testsuite/tests/lib-threads/swapchan.ml | 41 + .../{test9.reference => swapchan.reference} | 0 .../tests/lib-threads/test-file-short-lines | 10 - testsuite/tests/lib-threads/test1.checker | 13 - testsuite/tests/lib-threads/test1.ml | 75 - testsuite/tests/lib-threads/test1.reference | 20002 ---------------- testsuite/tests/lib-threads/test2.checker | 13 - testsuite/tests/lib-threads/test2.ml | 27 - testsuite/tests/lib-threads/test3.checker | 13 - testsuite/tests/lib-threads/test3.ml | 20 - testsuite/tests/lib-threads/test3.precheck | 13 - testsuite/tests/lib-threads/test3.runner | 16 - testsuite/tests/lib-threads/test4.checker | 13 - testsuite/tests/lib-threads/test4.data | 3 - testsuite/tests/lib-threads/test4.ml | 33 - testsuite/tests/lib-threads/test4.reference | 4 - testsuite/tests/lib-threads/test4.runner | 13 - testsuite/tests/lib-threads/test5.checker | 13 - testsuite/tests/lib-threads/test5.ml | 31 - testsuite/tests/lib-threads/test5.precheck | 13 - testsuite/tests/lib-threads/test5.reference | 4 - testsuite/tests/lib-threads/test5.runner | 16 - testsuite/tests/lib-threads/test6.checker | 13 - testsuite/tests/lib-threads/test6.ml | 27 - testsuite/tests/lib-threads/test6.precheck | 13 - testsuite/tests/lib-threads/test6.reference | 2 - testsuite/tests/lib-threads/test6.runner | 16 - testsuite/tests/lib-threads/test7.checker | 14 - testsuite/tests/lib-threads/test7.ml | 38 - testsuite/tests/lib-threads/test7.precheck | 13 - testsuite/tests/lib-threads/test7.runner | 16 - testsuite/tests/lib-threads/test8.ml | 63 - testsuite/tests/lib-threads/test8.precheck | 13 - testsuite/tests/lib-threads/test9.checker | 13 - testsuite/tests/lib-threads/test9.ml | 38 - testsuite/tests/lib-threads/test9.precheck | 13 - testsuite/tests/lib-threads/testA.checker | 13 - testsuite/tests/lib-threads/testA.ml | 38 - testsuite/tests/lib-threads/testexit.checker | 13 - testsuite/tests/lib-threads/testexit.ml | 33 - .../tests/lib-threads/testexit.reference | 27 - testsuite/tests/lib-threads/testio.ml | 132 - testsuite/tests/lib-threads/testio.reference | 24 - testsuite/tests/lib-threads/testsieve.ml | 54 - .../tests/lib-threads/testsieve.reference | 100 - .../tests/lib-threads/testsignal.checker | 13 - testsuite/tests/lib-threads/testsignal.ml | 25 - .../tests/lib-threads/testsignal.precheck | 13 - testsuite/tests/lib-threads/testsignal.runner | 16 - .../tests/lib-threads/testsignal2.checker | 13 - testsuite/tests/lib-threads/testsignal2.ml | 23 - .../tests/lib-threads/testsignal2.precheck | 13 - .../tests/lib-threads/testsignal2.runner | 18 - testsuite/tests/lib-threads/testsocket.ml | 48 - .../tests/lib-threads/testsocket.precheck | 23 - .../tests/lib-threads/testsocket.reference | 3 - testsuite/tests/lib-threads/tls.checker | 16 + testsuite/tests/lib-threads/tls.ml | 41 + .../{testA.reference => tls.reference} | 0 testsuite/tests/lib-threads/token1.ml | 48 - testsuite/tests/lib-threads/token2.ml | 51 - testsuite/tests/lib-threads/torture.data | 3 - testsuite/tests/lib-threads/torture.ml | 63 +- testsuite/tests/lib-threads/torture.reference | 5 +- testsuite/tests/lib-threads/torture.runner | 13 - testsuite/tests/lib-uchar/Makefile | 18 + testsuite/tests/lib-uchar/test.ml | 111 + testsuite/tests/lib-uchar/test.reference | 1 + testsuite/tests/link-test/Makefile | 36 + testsuite/tests/link-test/aliases.ml | 1 + testsuite/tests/link-test/submodule.ml | 2 + testsuite/tests/link-test/test.ml | 1 + testsuite/tests/link-test/test.reference | 1 + .../tests/match-exception-warnings/Makefile | 25 +- testsuite/tests/match-exception/Makefile | 25 +- testsuite/tests/match-exception/allocation.ml | 3 +- .../match-exception/exception_propagation.ml | 2 +- .../tests/match-exception/match_failure.ml | 4 +- .../tests/match-exception/nested_handlers.ml | 10 +- testsuite/tests/match-exception/streams.ml | 4 +- testsuite/tests/misc-kb/Makefile | 25 +- testsuite/tests/misc-kb/equations.ml | 25 +- testsuite/tests/misc-kb/equations.mli | 25 +- testsuite/tests/misc-kb/kb.ml | 25 +- testsuite/tests/misc-kb/kb.mli | 25 +- testsuite/tests/misc-kb/kbmain.ml | 27 +- testsuite/tests/misc-kb/kbmain.reference | 5187 ---- testsuite/tests/misc-kb/orderings.ml | 25 +- testsuite/tests/misc-kb/orderings.mli | 25 +- testsuite/tests/misc-kb/terms.ml | 25 +- testsuite/tests/misc-kb/terms.mli | 25 +- testsuite/tests/misc-unsafe/Makefile | 25 +- testsuite/tests/misc-unsafe/almabench.ml | 5 +- testsuite/tests/misc-unsafe/fft.ml | 27 +- testsuite/tests/misc-unsafe/fft.reference | 1 - testsuite/tests/misc-unsafe/quicksort.ml | 29 +- testsuite/tests/misc-unsafe/soli.ml | 25 +- testsuite/tests/misc/Makefile | 25 +- testsuite/tests/misc/bdd.ml | 29 +- testsuite/tests/misc/boyer.ml | 46 +- testsuite/tests/misc/ephetest.ml | 180 + testsuite/tests/misc/ephetest.reference | 29 + testsuite/tests/misc/ephetest2.ml | 161 + testsuite/tests/misc/ephetest2.reference | 5 + testsuite/tests/misc/ephetest3.ml | 133 + testsuite/tests/misc/ephetest3.reference | 18 + testsuite/tests/misc/fib.ml | 27 +- testsuite/tests/misc/fib.reference | 2 +- testsuite/tests/misc/hamming.ml | 25 +- testsuite/tests/misc/nucleic.ml | 26 +- testsuite/tests/misc/pr7168.ml | 77 + testsuite/tests/misc/pr7168.reference | 1 + testsuite/tests/misc/sieve.ml | 25 +- testsuite/tests/misc/sorts.ml | 58 +- testsuite/tests/misc/sorts.reference | 192 +- testsuite/tests/misc/takc.ml | 27 +- testsuite/tests/misc/takc.reference | 2 +- testsuite/tests/misc/taku.ml | 27 +- testsuite/tests/misc/taku.reference | 2 +- testsuite/tests/misc/weaklifetime2.ml | 69 + testsuite/tests/misc/weaklifetime2.reference | 2 + testsuite/tests/no-alias-deps/Makefile | 37 + .../tests/no-alias-deps/aliases.cmo.reference | 12 + testsuite/tests/no-alias-deps/aliases.ml | 5 + .../tests/no-alias-deps/aliases.ml.reference | 5 + testsuite/tests/no-alias-deps/b.cmi.pre | 1 + testsuite/tests/no-alias-deps/c.mli | 1 + testsuite/tests/no-alias-deps/d.mli | 1 + testsuite/tests/opaque/Makefile | 75 + testsuite/tests/opaque/fst/opaque_impl.ml | 2 + testsuite/tests/opaque/fst/opaque_intf.ml | 2 + testsuite/tests/opaque/fst/regular.ml | 2 + testsuite/tests/opaque/intf/opaque_impl.mli | 2 + testsuite/tests/opaque/intf/opaque_intf.mli | 2 + testsuite/tests/opaque/intf/regular.mli | 2 + testsuite/tests/opaque/snd/opaque_impl.ml | 2 + testsuite/tests/opaque/snd/opaque_intf.ml | 2 + testsuite/tests/opaque/snd/regular.ml | 2 + testsuite/tests/opaque/test.ml | 9 + testsuite/tests/parsing/Makefile | 19 + testsuite/tests/parsing/attributes.ml | 34 + .../tests/parsing/attributes.ml.reference | 153 + testsuite/tests/parsing/docstrings.ml | 16 + .../tests/parsing/docstrings.ml.reference | 146 + testsuite/tests/parsing/extensions.ml | 18 + .../tests/parsing/extensions.ml.reference | 326 + .../parsing/int_and_float_with_modifier.ml | 14 + .../int_and_float_with_modifier.ml.reference | 86 + testsuite/tests/parsing/pr6865.ml | 3 + testsuite/tests/parsing/pr6865.ml.reference | 52 + testsuite/tests/parsing/shortcut_ext_attr.ml | 113 + .../parsing/shortcut_ext_attr.ml.reference | 962 + testsuite/tests/ppx-attributes/Makefile | 18 + testsuite/tests/ppx-attributes/warning.ml | 47 + .../tests/ppx-attributes/warning.reference | 0 testsuite/tests/prim-revapply/Makefile | 25 +- testsuite/tests/prim-revapply/apply.ml | 25 +- testsuite/tests/prim-revapply/revapply.ml | 25 +- testsuite/tests/regression/pr3612/Makefile | 21 + .../tests/regression/pr3612/custom_finalize.c | 65 + testsuite/tests/regression/pr3612/pr3612.ml | 36 + .../tests/regression/pr3612/pr3612.reference | 1 + .../tests/regression/pr5080-notes/Makefile | 25 +- .../pr5080-notes/pr5080_notes_ok.ml | 25 +- testsuite/tests/regression/pr5233/Makefile | 25 +- testsuite/tests/regression/pr5233/pr5233.ml | 50 +- testsuite/tests/regression/pr5757/Makefile | 25 +- testsuite/tests/regression/pr5757/pr5757.ml | 25 +- testsuite/tests/regression/pr6024/Makefile | 25 +- testsuite/tests/regression/pr6024/pr6024.ml | 25 +- testsuite/tests/regression/pr7042/Makefile | 20 + testsuite/tests/regression/pr7042/pr7042.ml | 19 + .../tests/regression/pr7042/pr7042.reference | 1 + testsuite/tests/required-external/Makefile | 18 + testsuite/tests/required-external/file.ml | 7 + testsuite/tests/required-external/main.ml | 2 + .../tests/required-external/main.reference | 1 + testsuite/tests/runtime-errors/.ignore | 1 - testsuite/tests/runtime-errors/Makefile | 64 +- .../stackoverflow.bytecode.checker | 25 +- .../tests/runtime-errors/stackoverflow.ml | 25 +- .../stackoverflow.native.checker | 25 +- .../runtime-errors/syserror.bytecode.checker | 25 +- testsuite/tests/runtime-errors/syserror.ml | 25 +- .../runtime-errors/syserror.native.checker | 25 +- testsuite/tests/tool-debugger/basic/.ignore | 1 - testsuite/tests/tool-debugger/basic/Makefile | 25 +- .../tool-debugger/find-artifacts/.ignore | 2 - .../tool-debugger/find-artifacts/Makefile | 25 +- .../tool-debugger/no_debug_event/.ignore | 4 - .../tool-debugger/no_debug_event/Makefile | 25 +- testsuite/tests/tool-lexyacc/.ignore | 3 - testsuite/tests/tool-lexyacc/Makefile | 25 +- testsuite/tests/tool-lexyacc/gram_aux.ml | 25 +- testsuite/tests/tool-lexyacc/grammar.mly | 25 +- testsuite/tests/tool-lexyacc/input | 25 +- testsuite/tests/tool-lexyacc/lexgen.ml | 25 +- testsuite/tests/tool-lexyacc/main.ml | 25 +- testsuite/tests/tool-lexyacc/output.ml | 25 +- testsuite/tests/tool-lexyacc/scan_aux.ml | 25 +- testsuite/tests/tool-lexyacc/scanner.mll | 25 +- testsuite/tests/tool-lexyacc/syntax.ml | 25 +- testsuite/tests/tool-ocaml/Makefile | 25 +- testsuite/tests/tool-ocaml/t000.ml | 4 +- testsuite/tests/tool-ocaml/t010-const0.ml | 6 +- testsuite/tests/tool-ocaml/t010-const1.ml | 6 +- testsuite/tests/tool-ocaml/t010-const2.ml | 6 +- testsuite/tests/tool-ocaml/t010-const3.ml | 6 +- testsuite/tests/tool-ocaml/t011-constint.ml | 4 +- testsuite/tests/tool-ocaml/t020.ml | 8 +- testsuite/tests/tool-ocaml/t021-pushconst1.ml | 8 +- testsuite/tests/tool-ocaml/t021-pushconst2.ml | 8 +- testsuite/tests/tool-ocaml/t021-pushconst3.ml | 8 +- .../tests/tool-ocaml/t022-pushconstint.ml | 6 +- testsuite/tests/tool-ocaml/t040-makeblock1.ml | 6 +- testsuite/tests/tool-ocaml/t040-makeblock2.ml | 8 +- testsuite/tests/tool-ocaml/t040-makeblock3.ml | 10 +- testsuite/tests/tool-ocaml/t041-makeblock.ml | 12 +- testsuite/tests/tool-ocaml/t050-getglobal.ml | 4 +- .../tests/tool-ocaml/t050-pushgetglobal.ml | 6 +- .../tests/tool-ocaml/t051-getglobalfield.ml | 6 +- .../tool-ocaml/t051-pushgetglobalfield.ml | 8 +- testsuite/tests/tool-ocaml/t060-raise.ml | 6 +- testsuite/tests/tool-ocaml/t070-branch.ml | 12 +- testsuite/tests/tool-ocaml/t070-branchif.ml | 12 +- .../tests/tool-ocaml/t070-branchifnot.ml | 10 +- testsuite/tests/tool-ocaml/t071-boolnot.ml | 12 +- testsuite/tests/tool-ocaml/t080-eq.ml | 16 +- testsuite/tests/tool-ocaml/t080-geint.ml | 16 +- testsuite/tests/tool-ocaml/t080-gtint.ml | 14 +- testsuite/tests/tool-ocaml/t080-leint.ml | 16 +- testsuite/tests/tool-ocaml/t080-ltint.ml | 14 +- testsuite/tests/tool-ocaml/t080-neq.ml | 14 +- testsuite/tests/tool-ocaml/t090-acc0.ml | 16 +- testsuite/tests/tool-ocaml/t090-acc1.ml | 18 +- testsuite/tests/tool-ocaml/t090-acc2.ml | 20 +- testsuite/tests/tool-ocaml/t090-acc3.ml | 22 +- testsuite/tests/tool-ocaml/t090-acc4.ml | 24 +- testsuite/tests/tool-ocaml/t090-acc5.ml | 26 +- testsuite/tests/tool-ocaml/t090-acc6.ml | 28 +- testsuite/tests/tool-ocaml/t090-acc7.ml | 30 +- testsuite/tests/tool-ocaml/t091-acc.ml | 30 +- testsuite/tests/tool-ocaml/t092-pushacc.ml | 26 +- testsuite/tests/tool-ocaml/t092-pushacc0.ml | 12 +- testsuite/tests/tool-ocaml/t092-pushacc1.ml | 14 +- testsuite/tests/tool-ocaml/t092-pushacc2.ml | 16 +- testsuite/tests/tool-ocaml/t092-pushacc3.ml | 18 +- testsuite/tests/tool-ocaml/t092-pushacc4.ml | 20 +- testsuite/tests/tool-ocaml/t092-pushacc5.ml | 22 +- testsuite/tests/tool-ocaml/t092-pushacc6.ml | 24 +- testsuite/tests/tool-ocaml/t092-pushacc7.ml | 26 +- testsuite/tests/tool-ocaml/t093-pushacc.ml | 26 +- testsuite/tests/tool-ocaml/t100-pushtrap.ml | 10 +- testsuite/tests/tool-ocaml/t101-poptrap.ml | 12 +- testsuite/tests/tool-ocaml/t110-addint.ml | 20 +- testsuite/tests/tool-ocaml/t110-andint.ml | 16 +- testsuite/tests/tool-ocaml/t110-asrint-1.ml | 14 +- testsuite/tests/tool-ocaml/t110-asrint-2.ml | 18 +- testsuite/tests/tool-ocaml/t110-divint-1.ml | 18 +- testsuite/tests/tool-ocaml/t110-divint-2.ml | 18 +- testsuite/tests/tool-ocaml/t110-divint-3.ml | 26 +- testsuite/tests/tool-ocaml/t110-lslint.ml | 16 +- testsuite/tests/tool-ocaml/t110-lsrint.ml | 16 +- testsuite/tests/tool-ocaml/t110-modint-1.ml | 16 +- testsuite/tests/tool-ocaml/t110-modint-2.ml | 26 +- testsuite/tests/tool-ocaml/t110-mulint.ml | 16 +- testsuite/tests/tool-ocaml/t110-negint.ml | 16 +- testsuite/tests/tool-ocaml/t110-offsetint.ml | 12 +- testsuite/tests/tool-ocaml/t110-orint.ml | 14 +- testsuite/tests/tool-ocaml/t110-subint.ml | 20 +- testsuite/tests/tool-ocaml/t110-xorint.ml | 14 +- .../tests/tool-ocaml/t120-getstringchar.ml | 14 +- .../tests/tool-ocaml/t121-setstringchar.ml | 22 +- .../tests/tool-ocaml/t130-getvectitem.ml | 20 +- testsuite/tests/tool-ocaml/t130-vectlength.ml | 18 +- .../tests/tool-ocaml/t131-setvectitem.ml | 30 +- testsuite/tests/tool-ocaml/t140-switch-1.ml | 18 +- testsuite/tests/tool-ocaml/t140-switch-2.ml | 18 +- testsuite/tests/tool-ocaml/t140-switch-3.ml | 18 +- testsuite/tests/tool-ocaml/t140-switch-4.ml | 16 +- testsuite/tests/tool-ocaml/t141-switch-5.ml | 16 +- testsuite/tests/tool-ocaml/t141-switch-6.ml | 16 +- testsuite/tests/tool-ocaml/t141-switch-7.ml | 16 +- testsuite/tests/tool-ocaml/t142-switch-8.ml | 16 +- testsuite/tests/tool-ocaml/t142-switch-9.ml | 14 +- testsuite/tests/tool-ocaml/t142-switch-A.ml | 14 +- testsuite/tests/tool-ocaml/t150-push-1.ml | 16 +- testsuite/tests/tool-ocaml/t150-push-2.ml | 32 +- testsuite/tests/tool-ocaml/t160-closure.ml | 8 +- testsuite/tests/tool-ocaml/t161-apply1.ml | 30 +- testsuite/tests/tool-ocaml/t162-return.ml | 14 +- testsuite/tests/tool-ocaml/t163.ml | 16 +- testsuite/tests/tool-ocaml/t164-apply2.ml | 18 +- testsuite/tests/tool-ocaml/t164-apply3.ml | 20 +- testsuite/tests/tool-ocaml/t165-apply.ml | 22 +- testsuite/tests/tool-ocaml/t170-envacc2.ml | 30 +- testsuite/tests/tool-ocaml/t170-envacc3.ml | 38 +- testsuite/tests/tool-ocaml/t170-envacc4.ml | 42 +- testsuite/tests/tool-ocaml/t171-envacc.ml | 48 +- .../tests/tool-ocaml/t172-pushenvacc1.ml | 24 +- .../tests/tool-ocaml/t172-pushenvacc2.ml | 26 +- .../tests/tool-ocaml/t172-pushenvacc3.ml | 34 +- .../tests/tool-ocaml/t172-pushenvacc4.ml | 40 +- testsuite/tests/tool-ocaml/t173-pushenvacc.ml | 44 +- testsuite/tests/tool-ocaml/t180-appterm1.ml | 22 +- testsuite/tests/tool-ocaml/t180-appterm2.ml | 26 +- testsuite/tests/tool-ocaml/t180-appterm3.ml | 28 +- testsuite/tests/tool-ocaml/t181-appterm.ml | 30 +- .../tests/tool-ocaml/t190-makefloatblock-1.ml | 8 +- .../tests/tool-ocaml/t190-makefloatblock-2.ml | 10 +- .../tests/tool-ocaml/t190-makefloatblock-3.ml | 12 +- testsuite/tests/tool-ocaml/t191-vectlength.ml | 16 +- .../tests/tool-ocaml/t192-getfloatfield-1.ml | 8 +- .../tests/tool-ocaml/t192-getfloatfield-2.ml | 8 +- .../tests/tool-ocaml/t193-setfloatfield-1.ml | 12 +- .../tests/tool-ocaml/t193-setfloatfield-2.ml | 12 +- testsuite/tests/tool-ocaml/t200-getfield0.ml | 12 +- testsuite/tests/tool-ocaml/t200-getfield1.ml | 12 +- testsuite/tests/tool-ocaml/t200-getfield2.ml | 12 +- testsuite/tests/tool-ocaml/t200-getfield3.ml | 12 +- testsuite/tests/tool-ocaml/t201-getfield.ml | 12 +- testsuite/tests/tool-ocaml/t210-setfield0.ml | 20 +- testsuite/tests/tool-ocaml/t210-setfield1.ml | 20 +- testsuite/tests/tool-ocaml/t210-setfield2.ml | 20 +- testsuite/tests/tool-ocaml/t210-setfield3.ml | 20 +- testsuite/tests/tool-ocaml/t211-setfield.ml | 16 +- testsuite/tests/tool-ocaml/t220-assign.ml | 18 +- .../tests/tool-ocaml/t230-check_signals.ml | 26 +- testsuite/tests/tool-ocaml/t240-c_call1.ml | 16 +- testsuite/tests/tool-ocaml/t240-c_call2.ml | 14 +- testsuite/tests/tool-ocaml/t240-c_call3.ml | 10 +- testsuite/tests/tool-ocaml/t240-c_call4.ml | 18 +- testsuite/tests/tool-ocaml/t240-c_call5.ml | 26 +- .../tests/tool-ocaml/t250-closurerec-1.ml | 8 +- .../tests/tool-ocaml/t250-closurerec-2.ml | 16 +- .../tool-ocaml/t251-pushoffsetclosure0.ml | 24 +- .../tool-ocaml/t251-pushoffsetclosure2.ml | 18 +- .../tool-ocaml/t251-pushoffsetclosurem2.ml | 18 +- .../tool-ocaml/t252-pushoffsetclosure.ml | 20 +- .../tests/tool-ocaml/t253-offsetclosure0.ml | 20 +- .../tests/tool-ocaml/t253-offsetclosure2.ml | 18 +- .../tests/tool-ocaml/t253-offsetclosurem2.ml | 18 +- .../tests/tool-ocaml/t254-offsetclosure.ml | 18 +- testsuite/tests/tool-ocaml/t260-offsetref.ml | 18 +- .../tests/tool-ocaml/t270-push_retaddr.ml | 22 +- testsuite/tests/tool-ocaml/t300-getmethod.ml | 7086 +++--- testsuite/tests/tool-ocaml/t301-object.ml | 4 +- testsuite/tests/tool-ocaml/t310-alloc-1.ml | 1686 +- testsuite/tests/tool-ocaml/t310-alloc-2.ml | 2616 +- testsuite/tests/tool-ocaml/t320-gc-1.ml | 1686 +- testsuite/tests/tool-ocaml/t320-gc-2.ml | 1686 +- testsuite/tests/tool-ocaml/t320-gc-3.ml | 1686 +- testsuite/tests/tool-ocaml/t330-compact-1.ml | 8 +- testsuite/tests/tool-ocaml/t330-compact-2.ml | 720 +- testsuite/tests/tool-ocaml/t330-compact-3.ml | 1686 +- testsuite/tests/tool-ocaml/t330-compact-4.ml | 1686 +- testsuite/tests/tool-ocaml/t340-weak.ml | 2527 -- testsuite/tests/tool-ocaml/t350-heapcheck.ml | 2529 -- testsuite/tests/tool-ocaml/t360-stacks-1.ml | 30 +- testsuite/tests/tool-ocaml/t360-stacks-2.ml | 40 +- testsuite/tests/tool-ocamldep-modalias/A.ml | 1 + testsuite/tests/tool-ocamldep-modalias/B.ml | 2 + testsuite/tests/tool-ocamldep-modalias/C.ml | 2 + testsuite/tests/tool-ocamldep-modalias/D.ml | 1 + .../tests/tool-ocamldep-modalias/Makefile | 73 + .../tool-ocamldep-modalias/Makefile.build | 43 + .../tool-ocamldep-modalias/Makefile.build2 | 38 + .../depend.mk.reference | 11 + .../depend.mk2.reference | 8 + .../depend.mod.reference | 6 + .../depend.mod2.reference | 4 + .../depend.mod3.reference | 4 + .../tests/tool-ocamldep-modalias/lib.mli | 8 + .../tests/tool-ocamldep-modalias/lib_impl.ml | 8 + .../tests/tool-ocamldep-modalias/main.ml | 3 + testsuite/tests/tool-ocamldoc-2/Makefile | 53 + testsuite/tests/tool-ocamldoc-2/test.mli | 30 + .../tests/tool-ocamldoc-2/test.reference | 74 + testsuite/tests/tool-ocamldoc/.ignore | 4 - testsuite/tests/tool-ocamldoc/Makefile | 25 +- testsuite/tests/tool-ocamldoc/t03.ml | 7 +- testsuite/tests/tool-toplevel/Makefile | 25 +- testsuite/tests/translprim/Makefile | 4 + testsuite/tests/translprim/array_spec.ml | 62 + .../tests/translprim/array_spec.ml.reference | 88 + .../tests/translprim/comparison_table.ml | 239 + .../translprim/comparison_table.ml.reference | 381 + testsuite/tests/translprim/module_coercion.ml | 37 + .../translprim/module_coercion.ml.reference | 104 + testsuite/tests/translprim/ref_spec.ml | 54 + .../tests/translprim/ref_spec.ml.reference | 50 + .../typing-extension-constructor/Makefile | 18 + .../typing-extension-constructor/test.ml | 14 + .../test.ml.reference | 12 + testsuite/tests/typing-extensions/Makefile | 1 - testsuite/tests/typing-extensions/cast.ml | 5 +- .../tests/typing-extensions/cast.ml.reference | 2 +- .../tests/typing-extensions/extensions.ml | 23 +- .../typing-extensions/extensions.ml.reference | 14 +- .../tests/typing-extensions/open_types.ml | 8 + .../typing-extensions/open_types.ml.reference | 17 +- testsuite/tests/typing-fstclassmod/Makefile | 25 +- .../tests/typing-fstclassmod/fstclassmod.ml | 6 +- testsuite/tests/typing-gadts/Makefile | 25 +- testsuite/tests/typing-gadts/didier.ml | 19 +- .../tests/typing-gadts/didier.ml.reference | 34 + .../tests/typing-gadts/dynamic_frisch.ml | 1 - .../dynamic_frisch.ml.principal.reference | 6 +- .../typing-gadts/dynamic_frisch.ml.reference | 6 +- testsuite/tests/typing-gadts/omega07.ml | 3 +- .../omega07.ml.principal.reference | 10 +- .../tests/typing-gadts/omega07.ml.reference | 10 +- testsuite/tests/typing-gadts/pr5332.ml | 4 +- .../tests/typing-gadts/pr5332.ml.reference | 17 +- testsuite/tests/typing-gadts/pr5689.ml | 2 +- testsuite/tests/typing-gadts/pr5906.ml | 3 +- .../tests/typing-gadts/pr5906.ml.reference | 4 +- .../tests/typing-gadts/pr5948.ml.reference | 3 +- .../pr6158.ml.principal.reference | 6 +- .../tests/typing-gadts/pr6158.ml.reference | 10 +- testsuite/tests/typing-gadts/pr6163.ml | 1 + .../pr6163.ml.principal.reference | 16 +- .../tests/typing-gadts/pr6163.ml.reference | 16 +- .../pr6174.ml.principal.reference | 4 +- .../tests/typing-gadts/pr6174.ml.reference | 4 +- testsuite/tests/typing-gadts/pr6690.ml | 9 +- .../pr6690.ml.principal.reference | 18 +- .../tests/typing-gadts/pr6690.ml.reference | 32 +- testsuite/tests/typing-gadts/pr6980.ml | 11 + .../tests/typing-gadts/pr6980.ml.reference | 14 + testsuite/tests/typing-gadts/pr6993_bad.ml | 12 + .../typing-gadts/pr6993_bad.ml.reference | 13 + testsuite/tests/typing-gadts/pr7016.ml | 9 + .../tests/typing-gadts/pr7016.ml.reference | 13 + testsuite/tests/typing-gadts/pr7160.ml | 5 + .../tests/typing-gadts/pr7160.ml.reference | 12 + testsuite/tests/typing-gadts/pr7214.ml | 8 + .../tests/typing-gadts/pr7214.ml.reference | 9 + testsuite/tests/typing-gadts/pr7222.ml | 10 + .../pr7222.ml.principal.reference | 15 + .../tests/typing-gadts/pr7222.ml.reference | 15 + testsuite/tests/typing-gadts/pr7230.ml | 4 + .../tests/typing-gadts/pr7230.ml.reference | 4 + testsuite/tests/typing-gadts/pr7234.ml | 7 + .../pr7234.ml.principal.reference | 19 + .../tests/typing-gadts/pr7234.ml.reference | 19 + testsuite/tests/typing-gadts/test.ml | 51 +- .../typing-gadts/test.ml.principal.reference | 77 +- .../tests/typing-gadts/test.ml.reference | 77 +- testsuite/tests/typing-gadts/yallop_bugs.ml | 2 +- .../yallop_bugs.ml.principal.reference | 2 +- .../typing-gadts/yallop_bugs.ml.reference | 2 +- testsuite/tests/typing-immediate/Makefile | 18 + testsuite/tests/typing-immediate/immediate.ml | 86 + .../typing-immediate/immediate.ml.reference | 71 + .../tests/typing-implicit_unpack/Makefile | 25 +- .../implicit_unpack.ml.reference | 2 + testsuite/tests/typing-labels/Makefile | 25 +- testsuite/tests/typing-misc-bugs/Makefile | 25 +- .../typing-misc-bugs/core_array_reduced_ok.ml | 94 + .../tests/typing-misc-bugs/pr6946_bad.ml | 2 + testsuite/tests/typing-misc/Makefile | 25 +- testsuite/tests/typing-misc/pr6939.ml | 4 + .../tests/typing-misc/pr6939.ml.reference | 18 + testsuite/tests/typing-misc/pr7103.ml | 14 + .../tests/typing-misc/pr7103.ml.reference | 25 + testsuite/tests/typing-misc/printing.ml | 7 + .../tests/typing-misc/printing.ml.reference | 9 + testsuite/tests/typing-missing-cmi/Makefile | 17 + testsuite/tests/typing-missing-cmi/a.ml | 1 + testsuite/tests/typing-missing-cmi/b.ml | 1 + testsuite/tests/typing-missing-cmi/main.ml | 1 + .../typing-missing-cmi/main.ml.reference | 5 + .../tests/typing-missing-cmi/subdir/m.ml | 2 + testsuite/tests/typing-modules-bugs/Makefile | 25 +- .../tests/typing-modules-bugs/pr51_ok.ml | 18 + .../tests/typing-modules-bugs/pr5663_ok.ml | 7 + .../tests/typing-modules-bugs/pr6513_ok.ml | 9 +- .../tests/typing-modules-bugs/pr6651_ok.ml | 13 + .../tests/typing-modules-bugs/pr6752_ok.ml | 43 + .../typing-modules-bugs/pr6899_first_bad.ml | 3 + .../tests/typing-modules-bugs/pr6899_ok.ml | 6 + .../typing-modules-bugs/pr6899_second_bad.ml | 5 + .../tests/typing-modules-bugs/pr6944_ok.ml | 4 + .../tests/typing-modules-bugs/pr6954_ok.ml | 11 + .../tests/typing-modules-bugs/pr6981_ok.ml | 10 + .../tests/typing-modules-bugs/pr6982_ok.ml | 26 + .../tests/typing-modules-bugs/pr6985_ok.ml | 7 + .../tests/typing-modules-bugs/pr6992_bad.ml | 15 + .../tests/typing-modules-bugs/pr7036_ok.ml | 21 + .../tests/typing-modules-bugs/pr7082_ok.ml | 7 + .../tests/typing-modules-bugs/pr7152_ok.ml | 72 + .../tests/typing-modules-bugs/pr7182_ok.ml | 3 + testsuite/tests/typing-modules/Makefile | 30 +- testsuite/tests/typing-modules/Test.ml | 1 + .../Test.ml.principal.reference | 6 +- .../tests/typing-modules/Test.ml.reference | 6 +- .../tests/typing-modules/aliases.ml.reference | 45 +- testsuite/tests/typing-modules/b.ml.reference | 5 + .../tests/typing-modules/b2.ml.reference | 5 + testsuite/tests/typing-modules/d.ml.reference | 5 + .../typing-modules/generative.ml.reference | 2 +- testsuite/tests/typing-modules/pr7207.ml | 2 + .../tests/typing-modules/pr7207.ml.reference | 7 + testsuite/tests/typing-modules/printing.ml | 14 + .../typing-modules/printing.ml.reference | 10 + testsuite/tests/typing-objects-bugs/Makefile | 25 +- testsuite/tests/typing-objects/Exemples.ml | 4 +- .../Exemples.ml.principal.reference | 4 +- .../typing-objects/Exemples.ml.reference | 4 +- testsuite/tests/typing-objects/Makefile | 25 +- testsuite/tests/typing-objects/Tests.ml | 30 +- .../Tests.ml.principal.reference | 6 +- .../tests/typing-objects/Tests.ml.reference | 13 +- testsuite/tests/typing-objects/pr5545.ml | 22 + .../pr5545.ml.principal.reference | 6 + .../tests/typing-objects/pr5545.ml.reference | 6 + testsuite/tests/typing-objects/pr5619_bad.ml | 3 +- .../pr5619_bad.ml.principal.reference | 6 +- .../typing-objects/pr5619_bad.ml.reference | 6 +- .../pr6123_bad.ml.principal.reference | 4 +- .../typing-objects/pr6123_bad.ml.reference | 4 +- testsuite/tests/typing-objects/pr6907_bad.ml | 7 + .../typing-objects/pr6907_bad.ml.reference | 10 + testsuite/tests/typing-poly-bugs/Makefile | 25 +- .../tests/typing-poly-bugs/pr5673_bad.ml | 4 +- testsuite/tests/typing-poly-bugs/pr5673_ok.ml | 4 +- testsuite/tests/typing-poly/Makefile | 25 +- testsuite/tests/typing-poly/poly.ml | 28 +- .../typing-poly/poly.ml.principal.reference | 35 +- testsuite/tests/typing-poly/poly.ml.reference | 29 +- .../tests/typing-polyvariants-bugs-2/Makefile | 25 +- .../tests/typing-polyvariants-bugs/Makefile | 25 +- .../typing-polyvariants-bugs/pr7199_ok.ml | 13 + testsuite/tests/typing-private-bugs/Makefile | 25 +- testsuite/tests/typing-private/Makefile | 25 +- testsuite/tests/typing-recmod/Makefile | 25 +- testsuite/tests/typing-recordarg/Makefile | 18 + testsuite/tests/typing-recordarg/recordarg.ml | 92 + .../typing-recordarg/recordarg.ml.reference | 67 + testsuite/tests/typing-rectypes-bugs/Makefile | 25 +- testsuite/tests/typing-safe-linking/Makefile | 15 + testsuite/tests/typing-safe-linking/a.ml | 5 + testsuite/tests/typing-safe-linking/b_bad.ml | 4 + testsuite/tests/typing-short-paths/Makefile | 25 +- .../short-paths.ml.reference | 6 +- testsuite/tests/typing-signatures/Makefile | 25 +- .../tests/typing-signatures/els.ml.reference | 2 +- testsuite/tests/typing-signatures/pr6672.ml | 3 + .../typing-signatures/pr6672.ml.reference | 10 + testsuite/tests/typing-sigsubst/Makefile | 25 +- testsuite/tests/typing-typeparam/Makefile | 25 +- .../typing-typeparam/newtype.ml.reference | 4 +- testsuite/tests/typing-unboxed/Makefile | 18 + testsuite/tests/typing-unboxed/test.ml | 126 + .../tests/typing-unboxed/test.ml.reference | 191 + testsuite/tests/typing-warnings/Makefile | 25 +- .../ambiguous_guarded_disjunction.ml | 203 + ...ambiguous_guarded_disjunction.ml.reference | 139 + .../tests/typing-warnings/application.ml | 2 + .../typing-warnings/application.ml.reference | 13 + testsuite/tests/typing-warnings/coercions.ml | 19 +- .../coercions.ml.principal.reference | 11 + .../typing-warnings/coercions.ml.reference | 7 + .../tests/typing-warnings/exhaustiveness.ml | 109 + .../exhaustiveness.ml.reference | 122 + testsuite/tests/typing-warnings/pr6872.ml | 1 - .../pr6872.ml.principal.reference | 2 +- .../tests/typing-warnings/pr6872.ml.reference | 2 +- testsuite/tests/typing-warnings/pr7085.ml | 23 + .../tests/typing-warnings/pr7085.ml.reference | 20 + testsuite/tests/typing-warnings/pr7115.ml | 20 + .../tests/typing-warnings/pr7115.ml.reference | 22 + testsuite/tests/typing-warnings/records.ml | 2 +- .../tests/unboxed-primitive-args/Makefile | 40 + testsuite/tests/unboxed-primitive-args/README | 26 + .../tests/unboxed-primitive-args/common.ml | 301 + .../tests/unboxed-primitive-args/common.mli | 44 + .../tests/unboxed-primitive-args/gen_test.ml | 243 + .../unboxed-primitive-args/main.reference | 0 .../unboxed-primitive-args/test_common.c | 37 + .../unboxed-primitive-args/test_common.h | 44 + testsuite/tests/unwind/Makefile | 39 + testsuite/tests/unwind/README | 9 + testsuite/tests/unwind/driver.ml | 3 + testsuite/tests/unwind/mylib.ml | 20 + testsuite/tests/unwind/mylib.mli | 10 + testsuite/tests/unwind/stack_walker.c | 59 + testsuite/tests/utils/Makefile | 27 +- testsuite/tests/utils/edit_distance.ml | 3 +- .../test_strongly_connected_components.ml | 29 + ...st_strongly_connected_components.reference | 2 + testsuite/tests/warnings/Makefile | 57 +- testsuite/tests/warnings/deprecated_module.ml | 9 + .../tests/warnings/deprecated_module.mli | 13 + .../warnings/deprecated_module.reference | 4 + .../tests/warnings/deprecated_module_use.ml | 6 + .../warnings/deprecated_module_use.reference | 14 + .../tests/warnings/module_without_cmx.mli | 2 + testsuite/tests/warnings/w01.ml | 11 - testsuite/tests/warnings/w01.reference | 12 +- testsuite/tests/warnings/w06.ml | 6 + testsuite/tests/warnings/w06.reference | 4 + testsuite/tests/warnings/w45.ml | 16 + testsuite/tests/warnings/w45.reference | 7 + testsuite/tests/warnings/w47_inline.ml | 15 + testsuite/tests/warnings/w47_inline.reference | 15 + testsuite/tests/warnings/w51.ml | 5 + testsuite/tests/warnings/w51.reference | 2 + testsuite/tests/warnings/w51_bis.ml | 5 + testsuite/tests/warnings/w51_bis.reference | 2 + testsuite/tests/warnings/w53.ml | 31 + testsuite/tests/warnings/w53.reference | 26 + testsuite/tests/warnings/w54.ml | 9 + testsuite/tests/warnings/w54.reference | 8 + .../w55.opt_backend.clambda.opt_reference | 12 + .../w55.opt_backend.flambda.opt_reference | 6 + testsuite/tests/warnings/w55.opt_backend.ml | 21 + .../tests/warnings/w55.opt_backend.reference | 0 testsuite/tests/warnings/w58.opt.ml | 2 + .../tests/warnings/w58.opt.opt_reference | 2 + testsuite/tests/warnings/w58.opt.reference | 0 testsuite/typing | 16 + tools/.depend | 81 +- tools/.ignore | 27 - tools/Makefile | 27 +- tools/Makefile.nt | 36 +- tools/Makefile.shared | 180 +- tools/addlabels.ml | 27 +- tools/check-typo | 166 +- tools/checkstack.c | 25 +- tools/ci-build | 98 +- tools/cleanup-header | 25 +- tools/cmpbyt.ml | 87 + tools/cmt2annot.ml | 250 +- tools/cvt_emit.mll | 25 +- tools/depend.ml | 305 +- tools/depend.mli | 43 +- tools/dumpobj.ml | 121 +- tools/eqparsetree.ml | 9 +- tools/gdb-macros | 321 + tools/lexer299.mll | 25 +- tools/lexer301.mll | 25 +- tools/make-opcodes | 25 +- tools/make-package-macosx | 30 +- tools/make-version-header.sh | 26 +- tools/msvs-promote-path | 51 + tools/objinfo.ml | 51 +- tools/objinfo_helper.c | 29 +- tools/ocaml-instr-graph | 116 + tools/ocaml-instr-report | 162 + tools/ocaml-objcopy-macosx | 25 +- tools/ocaml299to3.ml | 25 +- tools/ocamlcp.ml | 37 +- tools/ocamldep.ml | 244 +- tools/ocamlmklib.ml | 50 +- tools/ocamlmktop.ml | 25 +- tools/ocamlmktop.tpl | 25 +- tools/ocamloptp.ml | 68 +- tools/ocamlprof.ml | 28 +- tools/ocamlsize | 31 +- tools/primreq.ml | 25 +- tools/profiling.ml | 28 +- tools/profiling.mli | 28 +- tools/read_cmt.ml | 25 +- tools/scrapelabels.ml | 25 +- tools/setignore | 44 - tools/stripdebug.ml | 57 + tools/tast_iter.ml | 390 - tools/tast_iter.mli | 82 - tools/untypeast.ml | 636 - tools/untypeast.mli | 20 - toplevel/expunge.ml | 29 +- toplevel/genprintval.ml | 124 +- toplevel/genprintval.mli | 25 +- toplevel/opttopdirs.ml | 89 +- toplevel/opttopdirs.mli | 26 +- toplevel/opttoploop.ml | 326 +- toplevel/opttoploop.mli | 48 +- toplevel/opttopmain.ml | 101 +- toplevel/opttopmain.mli | 25 +- toplevel/opttopstart.ml | 25 +- toplevel/topdirs.ml | 348 +- toplevel/topdirs.mli | 25 +- toplevel/toplevellib.mllib | 21 - toplevel/toploop.ml | 199 +- toplevel/toploop.mli | 45 +- toplevel/topmain.ml | 33 +- toplevel/topmain.mli | 25 +- toplevel/topstart.ml | 25 +- toplevel/trace.ml | 28 +- toplevel/trace.mli | 25 +- typing/annot.mli | 25 +- typing/btype.ml | 198 +- typing/btype.mli | 46 +- typing/cmi_format.ml | 30 +- typing/cmi_format.mli | 32 +- typing/cmt_format.ml | 110 +- typing/cmt_format.mli | 25 +- typing/ctype.ml | 607 +- typing/ctype.mli | 44 +- typing/datarepr.ml | 137 +- typing/datarepr.mli | 41 +- typing/env.ml | 675 +- typing/env.mli | 76 +- typing/envaux.ml | 27 +- typing/envaux.mli | 27 +- typing/ident.ml | 52 +- typing/ident.mli | 34 +- typing/includeclass.ml | 25 +- typing/includeclass.mli | 25 +- typing/includecore.ml | 183 +- typing/includecore.mli | 26 +- typing/includemod.ml | 41 +- typing/includemod.mli | 25 +- typing/mtype.ml | 65 +- typing/mtype.mli | 25 +- typing/oprint.ml | 95 +- typing/oprint.mli | 25 +- typing/outcometree.mli | 38 +- typing/parmatch.ml | 695 +- typing/parmatch.mli | 40 +- typing/path.ml | 57 +- typing/path.mli | 36 +- typing/predef.ml | 80 +- typing/predef.mli | 34 +- typing/primitive.ml | 250 +- typing/primitive.mli | 74 +- typing/printtyp.ml | 240 +- typing/printtyp.mli | 35 +- typing/printtyped.ml | 340 +- typing/printtyped.mli | 25 +- typing/stypes.ml | 25 +- typing/stypes.mli | 25 +- typing/subst.ml | 108 +- typing/subst.mli | 26 +- typing/tast_mapper.ml | 679 + typing/tast_mapper.mli | 67 + typing/typeclass.ml | 163 +- typing/typeclass.mli | 27 +- typing/typecore.ml | 1047 +- typing/typecore.mli | 52 +- typing/typedecl.ml | 486 +- typing/typedecl.mli | 32 +- typing/typedtree.ml | 95 +- typing/typedtree.mli | 189 +- typing/typedtreeIter.ml | 47 +- typing/typedtreeIter.mli | 34 +- typing/typedtreeMap.ml | 99 +- typing/typedtreeMap.mli | 31 +- typing/typemod.ml | 468 +- typing/typemod.mli | 28 +- typing/types.ml | 135 +- typing/types.mli | 305 +- typing/typetexp.ml | 294 +- typing/typetexp.mli | 43 +- typing/untypeast.ml | 800 + typing/untypeast.mli | 78 + utils/.ignore | 1 - utils/arg_helper.ml | 130 + utils/arg_helper.mli | 63 + utils/ccomp.ml | 94 +- utils/ccomp.mli | 25 +- utils/clflags.ml | 265 +- utils/clflags.mli | 126 +- utils/config.mlbuild | 151 - utils/config.mli | 33 +- utils/config.mlp | 74 +- utils/consistbl.ml | 25 +- utils/consistbl.mli | 25 +- utils/identifiable.ml | 223 + utils/identifiable.mli | 95 + utils/misc.ml | 341 +- utils/misc.mli | 180 +- utils/numbers.ml | 48 + utils/numbers.mli | 26 + utils/strongly_connected_components.ml | 199 + utils/strongly_connected_components.mli | 38 + utils/tbl.ml | 25 +- utils/tbl.mli | 25 +- utils/terminfo.ml | 25 +- utils/terminfo.mli | 25 +- utils/timings.ml | 148 + utils/timings.mli | 63 + utils/warnings.ml | 159 +- utils/warnings.mli | 39 +- yacc/.ignore | 4 - yacc/Makefile | 25 +- yacc/Makefile.nt | 25 +- yacc/closure.c | 31 +- yacc/defs.h | 69 +- yacc/error.c | 25 +- yacc/lalr.c | 25 +- yacc/lr0.c | 27 +- yacc/main.c | 25 +- yacc/mkpar.c | 25 +- yacc/output.c | 25 +- yacc/reader.c | 30 +- yacc/skeleton.c | 25 +- yacc/symtab.c | 25 +- yacc/verbose.c | 25 +- yacc/warshall.c | 25 +- 2468 files changed, 114814 insertions(+), 109574 deletions(-) create mode 100644 .gitattributes create mode 100644 .gitmodules delete mode 100644 .ignore mode change 100644 => 100755 .travis-ci.sh create mode 100644 CONTRIBUTING.md delete mode 100644 INSTALL create mode 100644 INSTALL.adoc create mode 100644 Makefile.shared delete mode 100644 README create mode 100644 README.adoc delete mode 100644 README.win32 create mode 100644 README.win32.adoc create mode 100644 appveyor.yml create mode 100644 appveyor_build.sh delete mode 100644 asmcomp/.ignore create mode 100644 asmcomp/amd64/NOTES.md delete mode 100644 asmcomp/amd64/emit_nt.mlp create mode 100644 asmcomp/arm/NOTES.md create mode 100644 asmcomp/arm64/NOTES.md create mode 100644 asmcomp/build_export_info.ml create mode 100644 asmcomp/build_export_info.mli create mode 100644 asmcomp/closure_offsets.ml create mode 100644 asmcomp/closure_offsets.mli delete mode 100644 asmcomp/codegen.ml delete mode 100644 asmcomp/codegen.mli delete mode 100644 asmcomp/debuginfo.ml delete mode 100644 asmcomp/debuginfo.mli create mode 100644 asmcomp/export_info.ml create mode 100644 asmcomp/export_info.mli create mode 100644 asmcomp/export_info_for_pack.ml create mode 100644 asmcomp/export_info_for_pack.mli create mode 100644 asmcomp/flambda_to_clambda.ml create mode 100644 asmcomp/flambda_to_clambda.mli create mode 100644 asmcomp/i386/NOTES.md delete mode 100644 asmcomp/i386/emit_nt.mlp create mode 100644 asmcomp/import_approx.ml create mode 100644 asmcomp/import_approx.mli create mode 100644 asmcomp/power/NOTES.md create mode 100644 asmcomp/s390x/CSE.ml create mode 100644 asmcomp/s390x/NOTES.md create mode 100644 asmcomp/s390x/arch.ml create mode 100644 asmcomp/s390x/emit.mlp create mode 100644 asmcomp/s390x/proc.ml create mode 100644 asmcomp/s390x/reload.ml create mode 100644 asmcomp/s390x/scheduling.ml create mode 100644 asmcomp/s390x/selection.ml create mode 100644 asmcomp/sparc/NOTES.md create mode 100644 asmcomp/un_anf.ml create mode 100644 asmcomp/un_anf.mli create mode 100644 asmcomp/x86_ast.mli create mode 100644 asmcomp/x86_dsl.ml create mode 100644 asmcomp/x86_dsl.mli create mode 100644 asmcomp/x86_gas.ml create mode 100644 asmcomp/x86_gas.mli create mode 100644 asmcomp/x86_masm.ml create mode 100644 asmcomp/x86_masm.mli create mode 100644 asmcomp/x86_proc.ml create mode 100644 asmcomp/x86_proc.mli delete mode 100644 asmrun/.ignore delete mode 100644 asmrun/backtrace.c create mode 100644 asmrun/backtrace_prim.c create mode 100644 asmrun/clambda_checks.c delete mode 100644 asmrun/power-elf.S delete mode 100644 asmrun/power-rhapsody.S create mode 100644 asmrun/power.S create mode 100644 asmrun/s390x.S delete mode 100644 boot/.ignore delete mode 100644 bytecomp/.ignore create mode 100644 bytecomp/debuginfo.ml create mode 100644 bytecomp/debuginfo.mli create mode 100644 bytecomp/translattribute.ml create mode 100644 bytecomp/translattribute.mli delete mode 100644 byterun/.ignore mode change 100755 => 100644 byterun/Makefile.common create mode 100644 byterun/backtrace_prim.c create mode 100644 byterun/caml/backtrace_prim.h create mode 100644 byterun/caml/startup_aux.h create mode 100644 byterun/startup_aux.c create mode 100644 compilerlibs/.gitignore delete mode 100644 config/.ignore delete mode 100644 config/auto-aux/.ignore delete mode 100644 config/auto-aux/bytecopy.c create mode 100644 config/auto-aux/cckind.c delete mode 100644 config/auto-aux/divmod.c delete mode 100644 config/auto-aux/expm1.c delete mode 100644 config/auto-aux/longlong.c create mode 100644 config/auto-aux/mmap-huge.c delete mode 100644 config/auto-aux/schar.c delete mode 100644 config/auto-aux/schar2.c delete mode 100644 config/auto-aux/sighandler.c delete mode 100644 config/auto-aux/stackov.c delete mode 100644 debugger/.ignore delete mode 100644 emacs/.ignore delete mode 100644 lex/.ignore create mode 100644 middle_end/alias_analysis.ml create mode 100644 middle_end/alias_analysis.mli create mode 100644 middle_end/allocated_const.ml create mode 100644 middle_end/allocated_const.mli create mode 100644 middle_end/augment_specialised_args.ml create mode 100644 middle_end/augment_specialised_args.mli create mode 100644 middle_end/backend_intf.mli create mode 100644 middle_end/base_types/closure_element.ml create mode 100644 middle_end/base_types/closure_element.mli create mode 100644 middle_end/base_types/closure_id.ml create mode 100644 middle_end/base_types/closure_id.mli create mode 100644 middle_end/base_types/compilation_unit.ml create mode 100644 middle_end/base_types/compilation_unit.mli create mode 100644 middle_end/base_types/export_id.ml create mode 100644 middle_end/base_types/export_id.mli create mode 100644 middle_end/base_types/id_types.ml create mode 100644 middle_end/base_types/id_types.mli create mode 100644 middle_end/base_types/linkage_name.ml create mode 100644 middle_end/base_types/linkage_name.mli create mode 100644 middle_end/base_types/mutable_variable.ml create mode 100644 middle_end/base_types/mutable_variable.mli create mode 100644 middle_end/base_types/set_of_closures_id.ml create mode 100644 middle_end/base_types/set_of_closures_id.mli create mode 100644 middle_end/base_types/set_of_closures_origin.ml create mode 100644 middle_end/base_types/set_of_closures_origin.mli create mode 100644 middle_end/base_types/static_exception.ml create mode 100644 middle_end/base_types/static_exception.mli create mode 100644 middle_end/base_types/symbol.ml create mode 100644 middle_end/base_types/symbol.mli create mode 100644 middle_end/base_types/tag.ml create mode 100644 middle_end/base_types/tag.mli create mode 100644 middle_end/base_types/var_within_closure.ml create mode 100644 middle_end/base_types/var_within_closure.mli create mode 100644 middle_end/base_types/variable.ml create mode 100644 middle_end/base_types/variable.mli create mode 100644 middle_end/closure_conversion.ml create mode 100644 middle_end/closure_conversion.mli create mode 100644 middle_end/closure_conversion_aux.ml create mode 100644 middle_end/closure_conversion_aux.mli create mode 100644 middle_end/effect_analysis.ml create mode 100644 middle_end/effect_analysis.mli create mode 100644 middle_end/extract_projections.ml create mode 100644 middle_end/extract_projections.mli create mode 100644 middle_end/find_recursive_functions.ml create mode 100644 middle_end/find_recursive_functions.mli create mode 100644 middle_end/flambda.ml create mode 100644 middle_end/flambda.mli create mode 100644 middle_end/flambda_invariants.ml create mode 100644 middle_end/flambda_invariants.mli create mode 100644 middle_end/flambda_iterators.ml create mode 100644 middle_end/flambda_iterators.mli create mode 100644 middle_end/flambda_utils.ml create mode 100644 middle_end/flambda_utils.mli create mode 100644 middle_end/freshening.ml create mode 100644 middle_end/freshening.mli create mode 100644 middle_end/inconstant_idents.ml create mode 100644 middle_end/inconstant_idents.mli create mode 100644 middle_end/initialize_symbol_to_let_symbol.ml create mode 100644 middle_end/initialize_symbol_to_let_symbol.mli create mode 100644 middle_end/inline_and_simplify.ml create mode 100644 middle_end/inline_and_simplify.mli create mode 100644 middle_end/inline_and_simplify_aux.ml create mode 100644 middle_end/inline_and_simplify_aux.mli create mode 100644 middle_end/inlining_cost.ml create mode 100644 middle_end/inlining_cost.mli create mode 100644 middle_end/inlining_decision.ml create mode 100644 middle_end/inlining_decision.mli create mode 100644 middle_end/inlining_decision_intf.mli create mode 100644 middle_end/inlining_stats.ml create mode 100644 middle_end/inlining_stats.mli create mode 100644 middle_end/inlining_stats_types.ml create mode 100644 middle_end/inlining_stats_types.mli create mode 100644 middle_end/inlining_transforms.ml create mode 100644 middle_end/inlining_transforms.mli create mode 100644 middle_end/invariant_params.ml create mode 100644 middle_end/invariant_params.mli create mode 100644 middle_end/lift_code.ml create mode 100644 middle_end/lift_code.mli create mode 100644 middle_end/lift_constants.ml create mode 100644 middle_end/lift_constants.mli create mode 100644 middle_end/lift_let_to_initialize_symbol.ml create mode 100644 middle_end/lift_let_to_initialize_symbol.mli create mode 100644 middle_end/middle_end.ml create mode 100644 middle_end/middle_end.mli create mode 100644 middle_end/pass_wrapper.ml create mode 100644 middle_end/pass_wrapper.mli create mode 100644 middle_end/projection.ml create mode 100644 middle_end/projection.mli create mode 100644 middle_end/ref_to_variables.ml create mode 100644 middle_end/ref_to_variables.mli create mode 100644 middle_end/remove_free_vars_equal_to_args.ml create mode 100644 middle_end/remove_free_vars_equal_to_args.mli create mode 100644 middle_end/remove_unused_arguments.ml create mode 100644 middle_end/remove_unused_arguments.mli create mode 100644 middle_end/remove_unused_closure_vars.ml create mode 100644 middle_end/remove_unused_closure_vars.mli create mode 100644 middle_end/remove_unused_program_constructs.ml create mode 100644 middle_end/remove_unused_program_constructs.mli create mode 100644 middle_end/semantics_of_primitives.ml create mode 100644 middle_end/semantics_of_primitives.mli create mode 100644 middle_end/share_constants.ml create mode 100644 middle_end/share_constants.mli create mode 100644 middle_end/simple_value_approx.ml create mode 100644 middle_end/simple_value_approx.mli create mode 100644 middle_end/simplify_boxed_integer_ops.ml create mode 100644 middle_end/simplify_boxed_integer_ops.mli create mode 100644 middle_end/simplify_boxed_integer_ops_intf.mli create mode 100644 middle_end/simplify_common.ml create mode 100644 middle_end/simplify_common.mli create mode 100644 middle_end/simplify_primitives.ml create mode 100644 middle_end/simplify_primitives.mli create mode 100644 middle_end/unbox_closures.ml create mode 100644 middle_end/unbox_closures.mli create mode 100644 middle_end/unbox_free_vars_of_closures.ml create mode 100644 middle_end/unbox_free_vars_of_closures.mli create mode 100644 middle_end/unbox_specialised_args.ml create mode 100644 middle_end/unbox_specialised_args.mli delete mode 100644 ocamlbuild/.depend delete mode 100644 ocamlbuild/AUTHORS delete mode 100644 ocamlbuild/ChangeLog delete mode 100644 ocamlbuild/FAQ delete mode 100644 ocamlbuild/Makefile delete mode 100644 ocamlbuild/TODO delete mode 100644 ocamlbuild/_tags delete mode 100644 ocamlbuild/bool.ml delete mode 100644 ocamlbuild/bool.mli delete mode 100644 ocamlbuild/command.ml delete mode 100644 ocamlbuild/command.mli delete mode 100644 ocamlbuild/configuration.ml delete mode 100644 ocamlbuild/configuration.mli delete mode 100644 ocamlbuild/const.ml delete mode 100644 ocamlbuild/digest_cache.ml delete mode 100644 ocamlbuild/digest_cache.mli delete mode 100644 ocamlbuild/discard_printf.ml delete mode 100644 ocamlbuild/discard_printf.mli delete mode 100644 ocamlbuild/display.ml delete mode 100644 ocamlbuild/display.mli delete mode 100644 ocamlbuild/examples/example1/hello.ml delete mode 100644 ocamlbuild/examples/example2/greet.ml delete mode 100644 ocamlbuild/examples/example2/hello.ml delete mode 100644 ocamlbuild/examples/example3/epoch.ml delete mode 100755 ocamlbuild/examples/example3/make.sh delete mode 100644 ocamlbuild/exit_codes.ml delete mode 100644 ocamlbuild/exit_codes.mli delete mode 100644 ocamlbuild/fda.ml delete mode 100644 ocamlbuild/fda.mli delete mode 100644 ocamlbuild/findlib.ml delete mode 100644 ocamlbuild/findlib.mli delete mode 100644 ocamlbuild/flags.ml delete mode 100644 ocamlbuild/flags.mli delete mode 100644 ocamlbuild/glob.ml delete mode 100644 ocamlbuild/glob.mli delete mode 100644 ocamlbuild/glob_ast.ml delete mode 100644 ocamlbuild/glob_ast.mli delete mode 100644 ocamlbuild/glob_lexer.mli delete mode 100644 ocamlbuild/glob_lexer.mll delete mode 100644 ocamlbuild/hooks.ml delete mode 100644 ocamlbuild/hooks.mli delete mode 100644 ocamlbuild/hygiene.ml delete mode 100644 ocamlbuild/hygiene.mli delete mode 100644 ocamlbuild/lexers.mli delete mode 100644 ocamlbuild/lexers.mll delete mode 100644 ocamlbuild/loc.ml delete mode 100644 ocamlbuild/loc.mli delete mode 100644 ocamlbuild/log.ml delete mode 100644 ocamlbuild/log.mli delete mode 100644 ocamlbuild/main.ml delete mode 100644 ocamlbuild/main.mli delete mode 100644 ocamlbuild/man/ocamlbuild.1 delete mode 100644 ocamlbuild/misc/opentracer.ml delete mode 100644 ocamlbuild/my_std.ml delete mode 100644 ocamlbuild/my_std.mli delete mode 100644 ocamlbuild/my_unix.ml delete mode 100644 ocamlbuild/my_unix.mli delete mode 100644 ocamlbuild/ocaml_arch.ml delete mode 100644 ocamlbuild/ocaml_arch.mli delete mode 100644 ocamlbuild/ocaml_compiler.ml delete mode 100644 ocamlbuild/ocaml_compiler.mli delete mode 100644 ocamlbuild/ocaml_dependencies.ml delete mode 100644 ocamlbuild/ocaml_dependencies.mli delete mode 100644 ocamlbuild/ocaml_specific.ml delete mode 100644 ocamlbuild/ocaml_specific.mli delete mode 100644 ocamlbuild/ocaml_tools.ml delete mode 100644 ocamlbuild/ocaml_tools.mli delete mode 100644 ocamlbuild/ocaml_utils.ml delete mode 100644 ocamlbuild/ocaml_utils.mli delete mode 100644 ocamlbuild/ocamlbuild.ml delete mode 100644 ocamlbuild/ocamlbuild.mli delete mode 100644 ocamlbuild/ocamlbuild.mltop delete mode 100644 ocamlbuild/ocamlbuild.odocl delete mode 100644 ocamlbuild/ocamlbuild_executor.ml delete mode 100644 ocamlbuild/ocamlbuild_executor.mli delete mode 100644 ocamlbuild/ocamlbuild_pack.mlpack delete mode 100644 ocamlbuild/ocamlbuild_plugin.ml delete mode 100644 ocamlbuild/ocamlbuild_plugin.mli delete mode 100644 ocamlbuild/ocamlbuild_unix_plugin.ml delete mode 100644 ocamlbuild/ocamlbuild_unix_plugin.mli delete mode 100644 ocamlbuild/ocamlbuild_where.ml delete mode 100644 ocamlbuild/ocamlbuild_where.mli delete mode 100644 ocamlbuild/ocamlbuildlib.mllib delete mode 100644 ocamlbuild/ocamlbuildlight.ml delete mode 100644 ocamlbuild/ocamlbuildlight.mli delete mode 100644 ocamlbuild/ocamlbuildlightlib.mllib delete mode 100644 ocamlbuild/options.ml delete mode 100644 ocamlbuild/options.mli delete mode 100644 ocamlbuild/param_tags.ml delete mode 100644 ocamlbuild/param_tags.mli delete mode 100644 ocamlbuild/pathname.ml delete mode 100644 ocamlbuild/pathname.mli delete mode 100644 ocamlbuild/plugin.ml delete mode 100644 ocamlbuild/plugin.mli delete mode 100644 ocamlbuild/ppcache.ml delete mode 100644 ocamlbuild/ppcache.mli delete mode 100644 ocamlbuild/report.ml delete mode 100644 ocamlbuild/report.mli delete mode 100644 ocamlbuild/resource.ml delete mode 100644 ocamlbuild/resource.mli delete mode 100644 ocamlbuild/rule.ml delete mode 100644 ocamlbuild/rule.mli delete mode 100644 ocamlbuild/shell.ml delete mode 100644 ocamlbuild/shell.mli delete mode 100644 ocamlbuild/signatures.mli delete mode 100644 ocamlbuild/slurp.ml delete mode 100644 ocamlbuild/slurp.mli delete mode 100644 ocamlbuild/solver.ml delete mode 100644 ocamlbuild/solver.mli delete mode 100755 ocamlbuild/start.sh delete mode 100644 ocamlbuild/tags.ml delete mode 100644 ocamlbuild/tags.mli delete mode 100644 ocamlbuild/testsuite/README delete mode 100644 ocamlbuild/testsuite/external.ml delete mode 100644 ocamlbuild/testsuite/external_test_header.ml delete mode 100644 ocamlbuild/testsuite/findlibonly.ml delete mode 100644 ocamlbuild/testsuite/findlibonly_test_header.ml delete mode 100644 ocamlbuild/testsuite/internal.ml delete mode 100644 ocamlbuild/testsuite/internal_test_header.ml delete mode 100644 ocamlbuild/testsuite/ocamlbuild_test.ml delete mode 100644 ocamlbuild/tools.ml delete mode 100644 ocamlbuild/tools.mli delete mode 100644 ocamldoc/.ignore delete mode 100644 ocamldoc/runocamldoc delete mode 100644 otherlibs/bigarray/libbigarray.clib delete mode 100644 otherlibs/bigarray/libbigarraywin32.clib delete mode 100644 otherlibs/dynlink/.ignore delete mode 100644 otherlibs/dynlink/dynlinkaux.mlpack delete mode 100644 otherlibs/graph/graphics.mllib delete mode 100644 otherlibs/graph/libgraphics.clib delete mode 100644 otherlibs/num/libnums.clib delete mode 100644 otherlibs/num/nums.mllib delete mode 100644 otherlibs/str/libstr.clib delete mode 100644 otherlibs/systhreads/.ignore delete mode 100644 otherlibs/systhreads/libthreads.clib delete mode 100644 otherlibs/systhreads/threads.mllib delete mode 100644 otherlibs/threads/.ignore delete mode 100644 otherlibs/threads/libvmthreads.clib delete mode 100644 otherlibs/threads/threads.mllib delete mode 100644 otherlibs/threads/unix.mllib delete mode 100644 otherlibs/unix/libunix.clib delete mode 100644 otherlibs/unix/unix.mllib delete mode 100644 otherlibs/win32graph/.ignore delete mode 100644 otherlibs/win32graph/libgraphics.clib delete mode 100644 otherlibs/win32unix/.ignore create mode 100644 otherlibs/win32unix/Makefile.common delete mode 100644 otherlibs/win32unix/libunix.clib create mode 100644 otherlibs/win32unix/readlink.c create mode 100644 otherlibs/win32unix/symlink.c delete mode 100644 parsing/.ignore create mode 100644 parsing/ast_invariants.ml create mode 100644 parsing/ast_invariants.mli create mode 100755 parsing/ast_iterator.ml create mode 100755 parsing/ast_iterator.mli create mode 100644 parsing/attr_helper.ml create mode 100644 parsing/attr_helper.mli create mode 100755 parsing/builtin_attributes.ml create mode 100755 parsing/builtin_attributes.mli delete mode 100644 stdlib/.ignore create mode 100644 stdlib/ephemeron.ml create mode 100644 stdlib/ephemeron.mli delete mode 100644 stdlib/stdlib.mllib create mode 100644 stdlib/uchar.ml create mode 100644 stdlib/uchar.mli delete mode 100644 testsuite/.ignore delete mode 100644 testsuite/external/.ignore delete mode 100644 testsuite/external/Makefile delete mode 100755 testsuite/external/Patcher.sh delete mode 100644 testsuite/external/TODO.txt delete mode 100644 testsuite/external/boomerang-0.2.patch delete mode 100644 testsuite/external/camlimages-4.0.1.patch delete mode 100644 testsuite/external/camlp5-6.06.patch delete mode 100644 testsuite/external/camlp5-6.08.patch delete mode 100644 testsuite/external/camlp5-6.10.patch delete mode 100644 testsuite/external/camlp5-git.patch delete mode 100644 testsuite/external/camlpdf-0.5.patch delete mode 100644 testsuite/external/camlzip-1.04.patch delete mode 100644 testsuite/external/coq-8.3pl4.patch delete mode 100644 testsuite/external/coq-8.4pl1.patch delete mode 100644 testsuite/external/coq-8.4pl2.patch delete mode 100644 testsuite/external/core-109.37.00.patch delete mode 100644 testsuite/external/core-suite-108.00.01.patch delete mode 100644 testsuite/external/extlib-1.5.2.patch delete mode 100644 testsuite/external/frama-c-Nitrogen-20111001.patch delete mode 100644 testsuite/external/frama-c-Oxygen-20120901.patch delete mode 100644 testsuite/external/hevea-1.10.patch delete mode 100644 testsuite/external/kaputt-1.2.patch delete mode 100644 testsuite/external/lablgtk-2.14.2.patch delete mode 100644 testsuite/external/lablgtk-2.16.0.patch delete mode 100644 testsuite/external/lablgtkextras-1.1.patch delete mode 100644 testsuite/external/lablgtkextras-1.3.patch delete mode 100644 testsuite/external/lwt-2.4.0.patch delete mode 100644 testsuite/external/menhir-20120123.patch delete mode 100644 testsuite/external/mldonkey-3.1.2.patch delete mode 100644 testsuite/external/oasis-common.patch delete mode 100644 testsuite/external/obrowser-1.1.1.patch delete mode 100644 testsuite/external/ocaml-bitstring-2.0.3.patch delete mode 100644 testsuite/external/ocaml-mysql-1.0.4.patch.disabled delete mode 100644 testsuite/external/ocamlnet-3.5.1.patch delete mode 100644 testsuite/external/ocsigen-bundle-2.2.2.patch delete mode 100644 testsuite/external/omake-0.9.8.6.patch delete mode 100644 testsuite/external/sks-1.1.3.patch delete mode 100644 testsuite/external/vsyml-2010-04-06.patch delete mode 100644 testsuite/external/xml-light-2.2.patch create mode 100644 testsuite/makefiles/Makefile.dlambda create mode 100644 testsuite/makefiles/Makefile.dparsetree create mode 100644 testsuite/tests/array-functions/Makefile create mode 100644 testsuite/tests/array-functions/test.ml create mode 100644 testsuite/tests/array-functions/test.reference delete mode 100644 testsuite/tests/asmcomp/.ignore create mode 100755 testsuite/tests/asmcomp/bind_tuples.ml create mode 100644 testsuite/tests/asmcomp/is_in_static_data.c create mode 100644 testsuite/tests/asmcomp/is_static.ml create mode 100644 testsuite/tests/asmcomp/is_static_flambda.ml delete mode 100644 testsuite/tests/asmcomp/power-aix.S delete mode 100644 testsuite/tests/asmcomp/power-elf.S delete mode 100644 testsuite/tests/asmcomp/power-rhapsody.S create mode 100644 testsuite/tests/asmcomp/power.S create mode 100644 testsuite/tests/asmcomp/register_typing.ml create mode 100644 testsuite/tests/asmcomp/s390x.S create mode 100644 testsuite/tests/asmcomp/unrolling_flambda.ml create mode 100644 testsuite/tests/ast-invariants/Makefile create mode 100644 testsuite/tests/ast-invariants/test.ml create mode 100644 testsuite/tests/ast-invariants/test.reference create mode 100644 testsuite/tests/backtrace/backtrace3.ml create mode 100644 testsuite/tests/backtrace/backtrace3.reference create mode 100644 testsuite/tests/backtrace/pr6920_why_at.ml create mode 100644 testsuite/tests/backtrace/pr6920_why_at.reference create mode 100644 testsuite/tests/backtrace/pr6920_why_swallow.ml create mode 100644 testsuite/tests/backtrace/pr6920_why_swallow.reference create mode 100644 testsuite/tests/basic-float/float_array.ml create mode 100644 testsuite/tests/basic-modules/main.mli create mode 100644 testsuite/tests/basic-modules/pr6726.ml create mode 100644 testsuite/tests/basic-more/function_in_ref.ml create mode 100644 testsuite/tests/basic-more/function_in_ref.reference create mode 100644 testsuite/tests/basic-more/if_in_if.ml create mode 100644 testsuite/tests/basic-more/if_in_if.reference create mode 100644 testsuite/tests/basic-more/opaque_prim.ml create mode 100644 testsuite/tests/basic-more/opaque_prim.reference create mode 100644 testsuite/tests/basic-more/sequential_and_or.ml create mode 100644 testsuite/tests/basic-more/sequential_and_or.reference create mode 100644 testsuite/tests/basic-more/top_level_patterns.ml create mode 100644 testsuite/tests/basic-more/top_level_patterns.reference create mode 100644 testsuite/tests/basic/float_physical_equality.ml create mode 100644 testsuite/tests/basic/float_physical_equality.reference create mode 100644 testsuite/tests/basic/min_int.ml create mode 100644 testsuite/tests/basic/min_int.reference delete mode 100644 testsuite/tests/embedded/.ignore create mode 100644 testsuite/tests/extension-constructor/Makefile create mode 100644 testsuite/tests/extension-constructor/test.ml create mode 100644 testsuite/tests/extension-constructor/test.reference delete mode 100644 testsuite/tests/formats-transition/invalid_formats.ml delete mode 100644 testsuite/tests/formats-transition/invalid_formats.ml.reference create mode 100644 testsuite/tests/formats-transition/legacy_incompatible_flags.ml.reference create mode 100644 testsuite/tests/formatting/Makefile create mode 100644 testsuite/tests/formatting/margins.ml create mode 100644 testsuite/tests/formatting/margins.ml.reference create mode 100644 testsuite/tests/int64-unboxing/Makefile create mode 100644 testsuite/tests/int64-unboxing/stubs.c create mode 100644 testsuite/tests/int64-unboxing/test.ml create mode 100644 testsuite/tests/int64-unboxing/test.reference create mode 100644 testsuite/tests/lib-arg/Makefile create mode 100644 testsuite/tests/lib-arg/testarg.ml create mode 100644 testsuite/tests/lib-arg/testarg.reference delete mode 100644 testsuite/tests/lib-dynlink-bytecode/.ignore delete mode 100644 testsuite/tests/lib-dynlink-native/.ignore create mode 100644 testsuite/tests/lib-printf/pr6938.ml create mode 100644 testsuite/tests/lib-printf/pr6938.reference create mode 100644 testsuite/tests/lib-queue/Makefile create mode 100644 testsuite/tests/lib-queue/test.ml create mode 100644 testsuite/tests/lib-queue/test.reference delete mode 100644 testsuite/tests/lib-scanf/.ignore create mode 100644 testsuite/tests/lib-stack/Makefile create mode 100644 testsuite/tests/lib-stack/test.ml create mode 100644 testsuite/tests/lib-stack/test.reference create mode 100644 testsuite/tests/lib-string/Makefile create mode 100644 testsuite/tests/lib-string/test_string.ml create mode 100644 testsuite/tests/lib-string/test_string.reference delete mode 100644 testsuite/tests/lib-threads/.ignore create mode 100644 testsuite/tests/lib-threads/bank.ml create mode 100644 testsuite/tests/lib-threads/bank.reference create mode 100644 testsuite/tests/lib-threads/beat.ml create mode 100644 testsuite/tests/lib-threads/beat.reference create mode 100644 testsuite/tests/lib-threads/bufchan.ml rename testsuite/tests/lib-threads/{test8.reference => bufchan.reference} (100%) create mode 100644 testsuite/tests/lib-threads/fileio.ml create mode 100644 testsuite/tests/lib-threads/fileio.reference create mode 100644 testsuite/tests/lib-threads/pr4466.ml create mode 100644 testsuite/tests/lib-threads/pr4466.reference create mode 100644 testsuite/tests/lib-threads/pr5325.ml create mode 100644 testsuite/tests/lib-threads/pr5325.reference create mode 100644 testsuite/tests/lib-threads/prodcons.ml create mode 100644 testsuite/tests/lib-threads/prodcons.reference create mode 100644 testsuite/tests/lib-threads/prodcons2.ml create mode 100644 testsuite/tests/lib-threads/prodcons2.reference create mode 100644 testsuite/tests/lib-threads/sigint.c create mode 100644 testsuite/tests/lib-threads/signal.checker create mode 100644 testsuite/tests/lib-threads/signal.ml create mode 100644 testsuite/tests/lib-threads/signal.precheck create mode 100644 testsuite/tests/lib-threads/signal.runner create mode 100644 testsuite/tests/lib-threads/signal2.checker create mode 100644 testsuite/tests/lib-threads/signal2.ml create mode 100644 testsuite/tests/lib-threads/signal2.precheck create mode 100644 testsuite/tests/lib-threads/signal2.runner create mode 100644 testsuite/tests/lib-threads/sockets.ml create mode 100644 testsuite/tests/lib-threads/sockets.reference create mode 100644 testsuite/tests/lib-threads/socketsbuf.ml create mode 100644 testsuite/tests/lib-threads/socketsbuf.reference create mode 100644 testsuite/tests/lib-threads/swapchan.checker create mode 100644 testsuite/tests/lib-threads/swapchan.ml rename testsuite/tests/lib-threads/{test9.reference => swapchan.reference} (100%) delete mode 100644 testsuite/tests/lib-threads/test-file-short-lines delete mode 100644 testsuite/tests/lib-threads/test1.checker delete mode 100644 testsuite/tests/lib-threads/test1.ml delete mode 100644 testsuite/tests/lib-threads/test1.reference delete mode 100644 testsuite/tests/lib-threads/test2.checker delete mode 100644 testsuite/tests/lib-threads/test2.ml delete mode 100644 testsuite/tests/lib-threads/test3.checker delete mode 100644 testsuite/tests/lib-threads/test3.ml delete mode 100644 testsuite/tests/lib-threads/test3.precheck delete mode 100644 testsuite/tests/lib-threads/test3.runner delete mode 100644 testsuite/tests/lib-threads/test4.checker delete mode 100644 testsuite/tests/lib-threads/test4.data delete mode 100644 testsuite/tests/lib-threads/test4.ml delete mode 100644 testsuite/tests/lib-threads/test4.reference delete mode 100644 testsuite/tests/lib-threads/test4.runner delete mode 100644 testsuite/tests/lib-threads/test5.checker delete mode 100644 testsuite/tests/lib-threads/test5.ml delete mode 100644 testsuite/tests/lib-threads/test5.precheck delete mode 100644 testsuite/tests/lib-threads/test5.reference delete mode 100644 testsuite/tests/lib-threads/test5.runner delete mode 100644 testsuite/tests/lib-threads/test6.checker delete mode 100644 testsuite/tests/lib-threads/test6.ml delete mode 100644 testsuite/tests/lib-threads/test6.precheck delete mode 100644 testsuite/tests/lib-threads/test6.reference delete mode 100644 testsuite/tests/lib-threads/test6.runner delete mode 100644 testsuite/tests/lib-threads/test7.checker delete mode 100644 testsuite/tests/lib-threads/test7.ml delete mode 100644 testsuite/tests/lib-threads/test7.precheck delete mode 100644 testsuite/tests/lib-threads/test7.runner delete mode 100644 testsuite/tests/lib-threads/test8.ml delete mode 100644 testsuite/tests/lib-threads/test8.precheck delete mode 100644 testsuite/tests/lib-threads/test9.checker delete mode 100644 testsuite/tests/lib-threads/test9.ml delete mode 100644 testsuite/tests/lib-threads/test9.precheck delete mode 100644 testsuite/tests/lib-threads/testA.checker delete mode 100644 testsuite/tests/lib-threads/testA.ml delete mode 100644 testsuite/tests/lib-threads/testexit.checker delete mode 100644 testsuite/tests/lib-threads/testexit.ml delete mode 100644 testsuite/tests/lib-threads/testexit.reference delete mode 100644 testsuite/tests/lib-threads/testio.ml delete mode 100644 testsuite/tests/lib-threads/testio.reference delete mode 100644 testsuite/tests/lib-threads/testsieve.ml delete mode 100644 testsuite/tests/lib-threads/testsieve.reference delete mode 100644 testsuite/tests/lib-threads/testsignal.checker delete mode 100644 testsuite/tests/lib-threads/testsignal.ml delete mode 100644 testsuite/tests/lib-threads/testsignal.precheck delete mode 100644 testsuite/tests/lib-threads/testsignal.runner delete mode 100644 testsuite/tests/lib-threads/testsignal2.checker delete mode 100644 testsuite/tests/lib-threads/testsignal2.ml delete mode 100644 testsuite/tests/lib-threads/testsignal2.precheck delete mode 100644 testsuite/tests/lib-threads/testsignal2.runner delete mode 100644 testsuite/tests/lib-threads/testsocket.ml delete mode 100644 testsuite/tests/lib-threads/testsocket.precheck delete mode 100644 testsuite/tests/lib-threads/testsocket.reference create mode 100644 testsuite/tests/lib-threads/tls.checker create mode 100644 testsuite/tests/lib-threads/tls.ml rename testsuite/tests/lib-threads/{testA.reference => tls.reference} (100%) delete mode 100644 testsuite/tests/lib-threads/token1.ml delete mode 100644 testsuite/tests/lib-threads/token2.ml delete mode 100644 testsuite/tests/lib-threads/torture.data delete mode 100644 testsuite/tests/lib-threads/torture.runner create mode 100644 testsuite/tests/lib-uchar/Makefile create mode 100644 testsuite/tests/lib-uchar/test.ml create mode 100644 testsuite/tests/lib-uchar/test.reference create mode 100644 testsuite/tests/link-test/Makefile create mode 100644 testsuite/tests/link-test/aliases.ml create mode 100644 testsuite/tests/link-test/submodule.ml create mode 100644 testsuite/tests/link-test/test.ml create mode 100644 testsuite/tests/link-test/test.reference create mode 100644 testsuite/tests/misc/ephetest.ml create mode 100644 testsuite/tests/misc/ephetest.reference create mode 100644 testsuite/tests/misc/ephetest2.ml create mode 100644 testsuite/tests/misc/ephetest2.reference create mode 100644 testsuite/tests/misc/ephetest3.ml create mode 100644 testsuite/tests/misc/ephetest3.reference create mode 100644 testsuite/tests/misc/pr7168.ml create mode 100644 testsuite/tests/misc/pr7168.reference create mode 100644 testsuite/tests/misc/weaklifetime2.ml create mode 100644 testsuite/tests/misc/weaklifetime2.reference create mode 100644 testsuite/tests/no-alias-deps/Makefile create mode 100644 testsuite/tests/no-alias-deps/aliases.cmo.reference create mode 100644 testsuite/tests/no-alias-deps/aliases.ml create mode 100644 testsuite/tests/no-alias-deps/aliases.ml.reference create mode 100644 testsuite/tests/no-alias-deps/b.cmi.pre create mode 100644 testsuite/tests/no-alias-deps/c.mli create mode 100644 testsuite/tests/no-alias-deps/d.mli create mode 100644 testsuite/tests/opaque/Makefile create mode 100644 testsuite/tests/opaque/fst/opaque_impl.ml create mode 100644 testsuite/tests/opaque/fst/opaque_intf.ml create mode 100644 testsuite/tests/opaque/fst/regular.ml create mode 100644 testsuite/tests/opaque/intf/opaque_impl.mli create mode 100644 testsuite/tests/opaque/intf/opaque_intf.mli create mode 100644 testsuite/tests/opaque/intf/regular.mli create mode 100644 testsuite/tests/opaque/snd/opaque_impl.ml create mode 100644 testsuite/tests/opaque/snd/opaque_intf.ml create mode 100644 testsuite/tests/opaque/snd/regular.ml create mode 100644 testsuite/tests/opaque/test.ml create mode 100644 testsuite/tests/parsing/Makefile create mode 100644 testsuite/tests/parsing/attributes.ml create mode 100644 testsuite/tests/parsing/attributes.ml.reference create mode 100644 testsuite/tests/parsing/docstrings.ml create mode 100644 testsuite/tests/parsing/docstrings.ml.reference create mode 100644 testsuite/tests/parsing/extensions.ml create mode 100644 testsuite/tests/parsing/extensions.ml.reference create mode 100644 testsuite/tests/parsing/int_and_float_with_modifier.ml create mode 100644 testsuite/tests/parsing/int_and_float_with_modifier.ml.reference create mode 100644 testsuite/tests/parsing/pr6865.ml create mode 100644 testsuite/tests/parsing/pr6865.ml.reference create mode 100644 testsuite/tests/parsing/shortcut_ext_attr.ml create mode 100644 testsuite/tests/parsing/shortcut_ext_attr.ml.reference create mode 100644 testsuite/tests/ppx-attributes/Makefile create mode 100644 testsuite/tests/ppx-attributes/warning.ml create mode 100644 testsuite/tests/ppx-attributes/warning.reference create mode 100644 testsuite/tests/regression/pr3612/Makefile create mode 100644 testsuite/tests/regression/pr3612/custom_finalize.c create mode 100644 testsuite/tests/regression/pr3612/pr3612.ml create mode 100644 testsuite/tests/regression/pr3612/pr3612.reference create mode 100644 testsuite/tests/regression/pr7042/Makefile create mode 100644 testsuite/tests/regression/pr7042/pr7042.ml create mode 100644 testsuite/tests/regression/pr7042/pr7042.reference create mode 100644 testsuite/tests/required-external/Makefile create mode 100644 testsuite/tests/required-external/file.ml create mode 100644 testsuite/tests/required-external/main.ml create mode 100644 testsuite/tests/required-external/main.reference delete mode 100644 testsuite/tests/runtime-errors/.ignore delete mode 100644 testsuite/tests/tool-debugger/basic/.ignore delete mode 100644 testsuite/tests/tool-debugger/find-artifacts/.ignore delete mode 100644 testsuite/tests/tool-debugger/no_debug_event/.ignore delete mode 100644 testsuite/tests/tool-lexyacc/.ignore create mode 100644 testsuite/tests/tool-ocamldep-modalias/A.ml create mode 100644 testsuite/tests/tool-ocamldep-modalias/B.ml create mode 100644 testsuite/tests/tool-ocamldep-modalias/C.ml create mode 100644 testsuite/tests/tool-ocamldep-modalias/D.ml create mode 100644 testsuite/tests/tool-ocamldep-modalias/Makefile create mode 100644 testsuite/tests/tool-ocamldep-modalias/Makefile.build create mode 100644 testsuite/tests/tool-ocamldep-modalias/Makefile.build2 create mode 100644 testsuite/tests/tool-ocamldep-modalias/depend.mk.reference create mode 100644 testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference create mode 100644 testsuite/tests/tool-ocamldep-modalias/depend.mod.reference create mode 100644 testsuite/tests/tool-ocamldep-modalias/depend.mod2.reference create mode 100644 testsuite/tests/tool-ocamldep-modalias/depend.mod3.reference create mode 100644 testsuite/tests/tool-ocamldep-modalias/lib.mli create mode 100644 testsuite/tests/tool-ocamldep-modalias/lib_impl.ml create mode 100644 testsuite/tests/tool-ocamldep-modalias/main.ml create mode 100644 testsuite/tests/tool-ocamldoc-2/Makefile create mode 100644 testsuite/tests/tool-ocamldoc-2/test.mli create mode 100644 testsuite/tests/tool-ocamldoc-2/test.reference delete mode 100644 testsuite/tests/tool-ocamldoc/.ignore create mode 100644 testsuite/tests/translprim/Makefile create mode 100644 testsuite/tests/translprim/array_spec.ml create mode 100644 testsuite/tests/translprim/array_spec.ml.reference create mode 100644 testsuite/tests/translprim/comparison_table.ml create mode 100644 testsuite/tests/translprim/comparison_table.ml.reference create mode 100644 testsuite/tests/translprim/module_coercion.ml create mode 100644 testsuite/tests/translprim/module_coercion.ml.reference create mode 100644 testsuite/tests/translprim/ref_spec.ml create mode 100644 testsuite/tests/translprim/ref_spec.ml.reference create mode 100644 testsuite/tests/typing-extension-constructor/Makefile create mode 100644 testsuite/tests/typing-extension-constructor/test.ml create mode 100644 testsuite/tests/typing-extension-constructor/test.ml.reference create mode 100644 testsuite/tests/typing-gadts/didier.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr6980.ml create mode 100644 testsuite/tests/typing-gadts/pr6980.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr6993_bad.ml create mode 100644 testsuite/tests/typing-gadts/pr6993_bad.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7016.ml create mode 100644 testsuite/tests/typing-gadts/pr7016.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7160.ml create mode 100644 testsuite/tests/typing-gadts/pr7160.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7214.ml create mode 100644 testsuite/tests/typing-gadts/pr7214.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7222.ml create mode 100644 testsuite/tests/typing-gadts/pr7222.ml.principal.reference create mode 100644 testsuite/tests/typing-gadts/pr7222.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7230.ml create mode 100644 testsuite/tests/typing-gadts/pr7230.ml.reference create mode 100644 testsuite/tests/typing-gadts/pr7234.ml create mode 100644 testsuite/tests/typing-gadts/pr7234.ml.principal.reference create mode 100644 testsuite/tests/typing-gadts/pr7234.ml.reference create mode 100644 testsuite/tests/typing-immediate/Makefile create mode 100644 testsuite/tests/typing-immediate/immediate.ml create mode 100644 testsuite/tests/typing-immediate/immediate.ml.reference create mode 100644 testsuite/tests/typing-misc-bugs/core_array_reduced_ok.ml create mode 100644 testsuite/tests/typing-misc-bugs/pr6946_bad.ml create mode 100755 testsuite/tests/typing-misc/pr6939.ml create mode 100644 testsuite/tests/typing-misc/pr6939.ml.reference create mode 100644 testsuite/tests/typing-misc/pr7103.ml create mode 100644 testsuite/tests/typing-misc/pr7103.ml.reference create mode 100644 testsuite/tests/typing-misc/printing.ml create mode 100644 testsuite/tests/typing-misc/printing.ml.reference create mode 100644 testsuite/tests/typing-missing-cmi/Makefile create mode 100644 testsuite/tests/typing-missing-cmi/a.ml create mode 100644 testsuite/tests/typing-missing-cmi/b.ml create mode 100644 testsuite/tests/typing-missing-cmi/main.ml create mode 100644 testsuite/tests/typing-missing-cmi/main.ml.reference create mode 100644 testsuite/tests/typing-missing-cmi/subdir/m.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr51_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr5663_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6651_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6752_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6899_first_bad.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6899_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6899_second_bad.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6944_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6954_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6981_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6982_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6985_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr6992_bad.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr7036_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr7082_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr7152_ok.ml create mode 100644 testsuite/tests/typing-modules-bugs/pr7182_ok.ml create mode 100644 testsuite/tests/typing-modules/b.ml.reference create mode 100644 testsuite/tests/typing-modules/b2.ml.reference create mode 100644 testsuite/tests/typing-modules/d.ml.reference create mode 100644 testsuite/tests/typing-modules/pr7207.ml create mode 100644 testsuite/tests/typing-modules/pr7207.ml.reference create mode 100644 testsuite/tests/typing-modules/printing.ml create mode 100644 testsuite/tests/typing-modules/printing.ml.reference create mode 100644 testsuite/tests/typing-objects/pr5545.ml create mode 100644 testsuite/tests/typing-objects/pr5545.ml.principal.reference create mode 100644 testsuite/tests/typing-objects/pr5545.ml.reference create mode 100644 testsuite/tests/typing-objects/pr6907_bad.ml create mode 100644 testsuite/tests/typing-objects/pr6907_bad.ml.reference create mode 100644 testsuite/tests/typing-polyvariants-bugs/pr7199_ok.ml create mode 100644 testsuite/tests/typing-recordarg/Makefile create mode 100644 testsuite/tests/typing-recordarg/recordarg.ml create mode 100644 testsuite/tests/typing-recordarg/recordarg.ml.reference create mode 100644 testsuite/tests/typing-safe-linking/Makefile create mode 100644 testsuite/tests/typing-safe-linking/a.ml create mode 100644 testsuite/tests/typing-safe-linking/b_bad.ml create mode 100644 testsuite/tests/typing-signatures/pr6672.ml create mode 100644 testsuite/tests/typing-signatures/pr6672.ml.reference create mode 100644 testsuite/tests/typing-unboxed/Makefile create mode 100644 testsuite/tests/typing-unboxed/test.ml create mode 100644 testsuite/tests/typing-unboxed/test.ml.reference create mode 100644 testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml create mode 100644 testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference create mode 100644 testsuite/tests/typing-warnings/application.ml create mode 100644 testsuite/tests/typing-warnings/application.ml.reference create mode 100644 testsuite/tests/typing-warnings/exhaustiveness.ml create mode 100644 testsuite/tests/typing-warnings/exhaustiveness.ml.reference create mode 100644 testsuite/tests/typing-warnings/pr7085.ml create mode 100644 testsuite/tests/typing-warnings/pr7085.ml.reference create mode 100755 testsuite/tests/typing-warnings/pr7115.ml create mode 100644 testsuite/tests/typing-warnings/pr7115.ml.reference create mode 100644 testsuite/tests/unboxed-primitive-args/Makefile create mode 100644 testsuite/tests/unboxed-primitive-args/README create mode 100644 testsuite/tests/unboxed-primitive-args/common.ml create mode 100644 testsuite/tests/unboxed-primitive-args/common.mli create mode 100644 testsuite/tests/unboxed-primitive-args/gen_test.ml create mode 100644 testsuite/tests/unboxed-primitive-args/main.reference create mode 100644 testsuite/tests/unboxed-primitive-args/test_common.c create mode 100644 testsuite/tests/unboxed-primitive-args/test_common.h create mode 100644 testsuite/tests/unwind/Makefile create mode 100644 testsuite/tests/unwind/README create mode 100644 testsuite/tests/unwind/driver.ml create mode 100644 testsuite/tests/unwind/mylib.ml create mode 100644 testsuite/tests/unwind/mylib.mli create mode 100644 testsuite/tests/unwind/stack_walker.c create mode 100644 testsuite/tests/utils/test_strongly_connected_components.ml create mode 100644 testsuite/tests/utils/test_strongly_connected_components.reference create mode 100755 testsuite/tests/warnings/deprecated_module.ml create mode 100755 testsuite/tests/warnings/deprecated_module.mli create mode 100644 testsuite/tests/warnings/deprecated_module.reference create mode 100755 testsuite/tests/warnings/deprecated_module_use.ml create mode 100644 testsuite/tests/warnings/deprecated_module_use.reference create mode 100644 testsuite/tests/warnings/module_without_cmx.mli create mode 100644 testsuite/tests/warnings/w06.ml create mode 100644 testsuite/tests/warnings/w06.reference create mode 100755 testsuite/tests/warnings/w45.ml create mode 100644 testsuite/tests/warnings/w45.reference create mode 100644 testsuite/tests/warnings/w47_inline.ml create mode 100644 testsuite/tests/warnings/w47_inline.reference create mode 100644 testsuite/tests/warnings/w51.ml create mode 100644 testsuite/tests/warnings/w51.reference create mode 100644 testsuite/tests/warnings/w51_bis.ml create mode 100644 testsuite/tests/warnings/w51_bis.reference create mode 100644 testsuite/tests/warnings/w53.ml create mode 100644 testsuite/tests/warnings/w53.reference create mode 100644 testsuite/tests/warnings/w54.ml create mode 100644 testsuite/tests/warnings/w54.reference create mode 100644 testsuite/tests/warnings/w55.opt_backend.clambda.opt_reference create mode 100644 testsuite/tests/warnings/w55.opt_backend.flambda.opt_reference create mode 100644 testsuite/tests/warnings/w55.opt_backend.ml create mode 100644 testsuite/tests/warnings/w55.opt_backend.reference create mode 100644 testsuite/tests/warnings/w58.opt.ml create mode 100644 testsuite/tests/warnings/w58.opt.opt_reference create mode 100644 testsuite/tests/warnings/w58.opt.reference delete mode 100644 tools/.ignore create mode 100644 tools/cmpbyt.ml create mode 100644 tools/gdb-macros create mode 100755 tools/msvs-promote-path create mode 100755 tools/ocaml-instr-graph create mode 100755 tools/ocaml-instr-report delete mode 100755 tools/setignore create mode 100644 tools/stripdebug.ml delete mode 100644 tools/tast_iter.ml delete mode 100644 tools/tast_iter.mli delete mode 100644 tools/untypeast.ml delete mode 100644 tools/untypeast.mli delete mode 100644 toplevel/toplevellib.mllib create mode 100644 typing/tast_mapper.ml create mode 100644 typing/tast_mapper.mli create mode 100644 typing/untypeast.ml create mode 100644 typing/untypeast.mli delete mode 100644 utils/.ignore create mode 100644 utils/arg_helper.ml create mode 100644 utils/arg_helper.mli delete mode 100644 utils/config.mlbuild create mode 100644 utils/identifiable.ml create mode 100644 utils/identifiable.mli create mode 100644 utils/numbers.ml create mode 100644 utils/numbers.mli create mode 100644 utils/strongly_connected_components.ml create mode 100644 utils/strongly_connected_components.mli create mode 100644 utils/timings.ml create mode 100644 utils/timings.mli delete mode 100644 yacc/.ignore diff --git a/.depend b/.depend index 86652727..43f0a1c6 100644 --- a/.depend +++ b/.depend @@ -1,33 +1,58 @@ +utils/arg_helper.cmi : utils/ccomp.cmi : -utils/clflags.cmi : +utils/clflags.cmi : utils/misc.cmi utils/config.cmi : utils/consistbl.cmi : +utils/identifiable.cmi : utils/misc.cmi : +utils/numbers.cmi : utils/identifiable.cmi +utils/strongly_connected_components.cmi : utils/identifiable.cmi utils/tbl.cmi : utils/terminfo.cmi : +utils/timings.cmi : utils/warnings.cmi : +utils/arg_helper.cmo : utils/misc.cmi utils/arg_helper.cmi +utils/arg_helper.cmx : utils/misc.cmx utils/arg_helper.cmi utils/ccomp.cmo : utils/misc.cmi utils/config.cmi utils/clflags.cmi \ utils/ccomp.cmi utils/ccomp.cmx : utils/misc.cmx utils/config.cmx utils/clflags.cmx \ utils/ccomp.cmi -utils/clflags.cmo : utils/config.cmi utils/clflags.cmi -utils/clflags.cmx : utils/config.cmx utils/clflags.cmi +utils/clflags.cmo : utils/numbers.cmi utils/misc.cmi utils/config.cmi \ + utils/arg_helper.cmi utils/clflags.cmi +utils/clflags.cmx : utils/numbers.cmx utils/misc.cmx utils/config.cmx \ + utils/arg_helper.cmx utils/clflags.cmi utils/config.cmo : utils/config.cmi utils/config.cmx : utils/config.cmi utils/consistbl.cmo : utils/consistbl.cmi utils/consistbl.cmx : utils/consistbl.cmi +utils/identifiable.cmo : utils/misc.cmi utils/identifiable.cmi +utils/identifiable.cmx : utils/misc.cmx utils/identifiable.cmi utils/misc.cmo : utils/misc.cmi utils/misc.cmx : utils/misc.cmi +utils/numbers.cmo : utils/identifiable.cmi utils/numbers.cmi +utils/numbers.cmx : utils/identifiable.cmx utils/numbers.cmi +utils/strongly_connected_components.cmo : utils/numbers.cmi utils/misc.cmi \ + utils/identifiable.cmi utils/strongly_connected_components.cmi +utils/strongly_connected_components.cmx : utils/numbers.cmx utils/misc.cmx \ + utils/identifiable.cmx utils/strongly_connected_components.cmi utils/tbl.cmo : utils/tbl.cmi utils/tbl.cmx : utils/tbl.cmi utils/terminfo.cmo : utils/terminfo.cmi utils/terminfo.cmx : utils/terminfo.cmi -utils/warnings.cmo : utils/warnings.cmi -utils/warnings.cmx : utils/warnings.cmi +utils/timings.cmo : utils/timings.cmi +utils/timings.cmx : utils/timings.cmi +utils/warnings.cmo : utils/misc.cmi utils/warnings.cmi +utils/warnings.cmx : utils/misc.cmx utils/warnings.cmi parsing/ast_helper.cmi : parsing/parsetree.cmi parsing/longident.cmi \ parsing/location.cmi parsing/docstrings.cmi parsing/asttypes.cmi +parsing/ast_invariants.cmi : parsing/parsetree.cmi +parsing/ast_iterator.cmi : parsing/parsetree.cmi parsing/location.cmi parsing/ast_mapper.cmi : parsing/parsetree.cmi parsing/location.cmi parsing/asttypes.cmi : parsing/location.cmi +parsing/attr_helper.cmi : parsing/parsetree.cmi parsing/location.cmi \ + parsing/asttypes.cmi +parsing/builtin_attributes.cmi : parsing/parsetree.cmi parsing/location.cmi \ + parsing/ast_iterator.cmi parsing/docstrings.cmi : parsing/parsetree.cmi parsing/location.cmi parsing/lexer.cmi : parsing/parser.cmi parsing/location.cmi parsing/location.cmi : utils/warnings.cmi @@ -47,6 +72,16 @@ parsing/ast_helper.cmo : parsing/parsetree.cmi parsing/longident.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_invariants.cmo : parsing/syntaxerr.cmi parsing/parsetree.cmi \ + parsing/longident.cmi parsing/builtin_attributes.cmi parsing/asttypes.cmi \ + parsing/ast_iterator.cmi parsing/ast_invariants.cmi +parsing/ast_invariants.cmx : parsing/syntaxerr.cmx parsing/parsetree.cmi \ + parsing/longident.cmx parsing/builtin_attributes.cmx parsing/asttypes.cmi \ + parsing/ast_iterator.cmx parsing/ast_invariants.cmi +parsing/ast_iterator.cmo : parsing/parsetree.cmi parsing/location.cmi \ + parsing/ast_iterator.cmi +parsing/ast_iterator.cmx : parsing/parsetree.cmi parsing/location.cmx \ + parsing/ast_iterator.cmi parsing/ast_mapper.cmo : parsing/parsetree.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi utils/config.cmi \ utils/clflags.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ @@ -55,18 +90,28 @@ parsing/ast_mapper.cmx : parsing/parsetree.cmi utils/misc.cmx \ parsing/longident.cmx parsing/location.cmx utils/config.cmx \ utils/clflags.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ parsing/ast_mapper.cmi +parsing/attr_helper.cmo : parsing/parsetree.cmi parsing/location.cmi \ + parsing/asttypes.cmi parsing/attr_helper.cmi +parsing/attr_helper.cmx : parsing/parsetree.cmi parsing/location.cmx \ + parsing/asttypes.cmi parsing/attr_helper.cmi +parsing/builtin_attributes.cmo : utils/warnings.cmi parsing/parsetree.cmi \ + parsing/location.cmi parsing/asttypes.cmi parsing/ast_iterator.cmi \ + parsing/builtin_attributes.cmi +parsing/builtin_attributes.cmx : utils/warnings.cmx parsing/parsetree.cmi \ + parsing/location.cmx parsing/asttypes.cmi parsing/ast_iterator.cmx \ + parsing/builtin_attributes.cmi parsing/docstrings.cmo : utils/warnings.cmi parsing/parsetree.cmi \ - parsing/location.cmi parsing/asttypes.cmi parsing/docstrings.cmi + parsing/location.cmi parsing/docstrings.cmi parsing/docstrings.cmx : utils/warnings.cmx parsing/parsetree.cmi \ - parsing/location.cmx parsing/asttypes.cmi parsing/docstrings.cmi + parsing/location.cmx parsing/docstrings.cmi parsing/lexer.cmo : utils/warnings.cmi parsing/parser.cmi utils/misc.cmi \ parsing/location.cmi parsing/docstrings.cmi parsing/lexer.cmi parsing/lexer.cmx : utils/warnings.cmx parsing/parser.cmx utils/misc.cmx \ parsing/location.cmx parsing/docstrings.cmx parsing/lexer.cmi -parsing/location.cmo : utils/warnings.cmi utils/terminfo.cmi \ - parsing/location.cmi -parsing/location.cmx : utils/warnings.cmx utils/terminfo.cmx \ - parsing/location.cmi +parsing/location.cmo : utils/warnings.cmi utils/terminfo.cmi utils/misc.cmi \ + utils/clflags.cmi parsing/location.cmi +parsing/location.cmx : utils/warnings.cmx utils/terminfo.cmx utils/misc.cmx \ + utils/clflags.cmx parsing/location.cmi parsing/longident.cmo : utils/misc.cmi parsing/longident.cmi parsing/longident.cmx : utils/misc.cmx parsing/longident.cmi parsing/parse.cmo : parsing/syntaxerr.cmi parsing/parser.cmi \ @@ -104,13 +149,12 @@ typing/cmt_format.cmi : typing/types.cmi typing/typedtree.cmi \ parsing/location.cmi typing/env.cmi typing/cmi_format.cmi typing/ctype.cmi : typing/types.cmi typing/path.cmi parsing/longident.cmi \ typing/ident.cmi typing/env.cmi parsing/asttypes.cmi -typing/datarepr.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi \ - parsing/asttypes.cmi +typing/datarepr.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi typing/env.cmi : utils/warnings.cmi typing/types.cmi typing/subst.cmi \ typing/path.cmi parsing/longident.cmi parsing/location.cmi \ typing/ident.cmi utils/consistbl.cmi parsing/asttypes.cmi typing/envaux.cmi : typing/subst.cmi typing/path.cmi typing/env.cmi -typing/ident.cmi : +typing/ident.cmi : utils/identifiable.cmi typing/includeclass.cmi : typing/types.cmi typing/env.cmi typing/ctype.cmi typing/includecore.cmi : typing/types.cmi typing/typedtree.cmi \ typing/ident.cmi typing/env.cmi @@ -126,14 +170,17 @@ typing/parmatch.cmi : typing/types.cmi typing/typedtree.cmi \ typing/env.cmi parsing/asttypes.cmi typing/path.cmi : typing/ident.cmi typing/predef.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi -typing/primitive.cmi : +typing/primitive.cmi : parsing/parsetree.cmi typing/outcometree.cmi \ + parsing/location.cmi typing/printtyp.cmi : typing/types.cmi typing/path.cmi \ typing/outcometree.cmi parsing/longident.cmi typing/ident.cmi \ - typing/env.cmi + typing/env.cmi parsing/asttypes.cmi typing/printtyped.cmi : typing/typedtree.cmi typing/stypes.cmi : typing/typedtree.cmi parsing/location.cmi \ typing/annot.cmi typing/subst.cmi : typing/types.cmi typing/path.cmi typing/ident.cmi +typing/tast_mapper.cmi : typing/typedtree.cmi typing/env.cmi \ + parsing/asttypes.cmi typing/typeclass.cmi : typing/types.cmi typing/typedtree.cmi \ parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ typing/ident.cmi typing/env.cmi typing/ctype.cmi parsing/asttypes.cmi @@ -158,29 +205,32 @@ typing/types.cmi : typing/primitive.cmi typing/path.cmi \ typing/ident.cmi parsing/asttypes.cmi typing/typetexp.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ - typing/env.cmi parsing/asttypes.cmi parsing/ast_mapper.cmi + typing/env.cmi parsing/asttypes.cmi +typing/untypeast.cmi : typing/typedtree.cmi typing/path.cmi \ + parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \ + parsing/asttypes.cmi typing/btype.cmo : typing/types.cmi typing/path.cmi utils/misc.cmi \ - typing/ident.cmi typing/btype.cmi + typing/ident.cmi parsing/asttypes.cmi typing/btype.cmi typing/btype.cmx : typing/types.cmx typing/path.cmx utils/misc.cmx \ - typing/ident.cmx typing/btype.cmi + typing/ident.cmx parsing/asttypes.cmi typing/btype.cmi typing/cmi_format.cmo : typing/types.cmi parsing/location.cmi \ utils/config.cmi typing/cmi_format.cmi typing/cmi_format.cmx : typing/types.cmx parsing/location.cmx \ utils/config.cmx typing/cmi_format.cmi -typing/cmt_format.cmo : typing/types.cmi typing/typedtreeMap.cmi \ - typing/typedtree.cmi utils/misc.cmi parsing/location.cmi \ +typing/cmt_format.cmo : typing/types.cmi typing/typedtree.cmi \ + typing/tast_mapper.cmi utils/misc.cmi parsing/location.cmi \ parsing/lexer.cmi typing/env.cmi utils/config.cmi typing/cmi_format.cmi \ utils/clflags.cmi typing/cmt_format.cmi -typing/cmt_format.cmx : typing/types.cmx typing/typedtreeMap.cmx \ - typing/typedtree.cmx utils/misc.cmx parsing/location.cmx \ +typing/cmt_format.cmx : typing/types.cmx typing/typedtree.cmx \ + typing/tast_mapper.cmx utils/misc.cmx parsing/location.cmx \ parsing/lexer.cmx typing/env.cmx utils/config.cmx typing/cmi_format.cmx \ utils/clflags.cmx typing/cmt_format.cmi -typing/ctype.cmo : typing/types.cmi typing/subst.cmi typing/path.cmi \ - utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ +typing/ctype.cmo : typing/types.cmi typing/subst.cmi typing/predef.cmi \ + typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ typing/ident.cmi typing/env.cmi utils/clflags.cmi typing/btype.cmi \ parsing/asttypes.cmi typing/ctype.cmi -typing/ctype.cmx : typing/types.cmx typing/subst.cmx typing/path.cmx \ - utils/misc.cmx parsing/longident.cmx parsing/location.cmx \ +typing/ctype.cmx : typing/types.cmx typing/subst.cmx typing/predef.cmx \ + typing/path.cmx utils/misc.cmx parsing/longident.cmx parsing/location.cmx \ typing/ident.cmx typing/env.cmx utils/clflags.cmx typing/btype.cmx \ parsing/asttypes.cmi typing/ctype.cmi typing/datarepr.cmo : typing/types.cmi typing/path.cmi parsing/location.cmi \ @@ -193,33 +243,33 @@ typing/env.cmo : utils/warnings.cmi typing/types.cmi utils/tbl.cmi \ typing/subst.cmi typing/predef.cmi typing/path.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ typing/datarepr.cmi utils/consistbl.cmi utils/config.cmi \ - typing/cmi_format.cmi utils/clflags.cmi typing/btype.cmi \ - parsing/asttypes.cmi typing/env.cmi + typing/cmi_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ + typing/btype.cmi parsing/asttypes.cmi typing/env.cmi typing/env.cmx : utils/warnings.cmx typing/types.cmx utils/tbl.cmx \ typing/subst.cmx typing/predef.cmx typing/path.cmx utils/misc.cmx \ parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ typing/datarepr.cmx utils/consistbl.cmx utils/config.cmx \ - typing/cmi_format.cmx utils/clflags.cmx typing/btype.cmx \ - parsing/asttypes.cmi typing/env.cmi + typing/cmi_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ + typing/btype.cmx parsing/asttypes.cmi typing/env.cmi typing/envaux.cmo : typing/types.cmi typing/subst.cmi typing/printtyp.cmi \ typing/path.cmi utils/misc.cmi typing/ident.cmi typing/env.cmi \ parsing/asttypes.cmi typing/envaux.cmi typing/envaux.cmx : typing/types.cmx typing/subst.cmx typing/printtyp.cmx \ typing/path.cmx utils/misc.cmx typing/ident.cmx typing/env.cmx \ parsing/asttypes.cmi typing/envaux.cmi -typing/ident.cmo : typing/ident.cmi -typing/ident.cmx : typing/ident.cmi +typing/ident.cmo : utils/identifiable.cmi typing/ident.cmi +typing/ident.cmx : utils/identifiable.cmx typing/ident.cmi typing/includeclass.cmo : typing/types.cmi typing/printtyp.cmi \ typing/ctype.cmi typing/includeclass.cmi typing/includeclass.cmx : typing/types.cmx typing/printtyp.cmx \ typing/ctype.cmx typing/includeclass.cmi typing/includecore.cmo : typing/types.cmi typing/typedtree.cmi \ - typing/predef.cmi typing/path.cmi utils/misc.cmi typing/ident.cmi \ - typing/env.cmi typing/ctype.cmi typing/btype.cmi parsing/asttypes.cmi \ + typing/path.cmi utils/misc.cmi typing/ident.cmi typing/env.cmi \ + typing/ctype.cmi typing/btype.cmi parsing/asttypes.cmi \ typing/includecore.cmi typing/includecore.cmx : typing/types.cmx typing/typedtree.cmx \ - typing/predef.cmx typing/path.cmx utils/misc.cmx typing/ident.cmx \ - typing/env.cmx typing/ctype.cmx typing/btype.cmx parsing/asttypes.cmi \ + typing/path.cmx utils/misc.cmx typing/ident.cmx typing/env.cmx \ + typing/ctype.cmx typing/btype.cmx parsing/asttypes.cmi \ typing/includecore.cmi typing/includemod.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \ typing/subst.cmi typing/printtyp.cmi typing/primitive.cmi typing/path.cmi \ @@ -245,38 +295,44 @@ typing/oprint.cmo : typing/outcometree.cmi parsing/asttypes.cmi \ typing/oprint.cmi typing/oprint.cmx : typing/outcometree.cmi parsing/asttypes.cmi \ typing/oprint.cmi -typing/parmatch.cmo : utils/warnings.cmi typing/types.cmi \ - typing/typedtree.cmi typing/subst.cmi typing/predef.cmi typing/path.cmi \ - parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ - typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ - typing/parmatch.cmi -typing/parmatch.cmx : utils/warnings.cmx typing/types.cmx \ - typing/typedtree.cmx typing/subst.cmx typing/predef.cmx typing/path.cmx \ - parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ - typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ - typing/parmatch.cmi +typing/parmatch.cmo : utils/warnings.cmi typing/untypeast.cmi \ + typing/types.cmi typing/typedtreeIter.cmi typing/typedtree.cmi \ + typing/subst.cmi typing/predef.cmi typing/path.cmi parsing/parsetree.cmi \ + utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ + typing/ident.cmi typing/env.cmi typing/ctype.cmi typing/btype.cmi \ + parsing/asttypes.cmi parsing/ast_helper.cmi typing/parmatch.cmi +typing/parmatch.cmx : utils/warnings.cmx typing/untypeast.cmx \ + typing/types.cmx typing/typedtreeIter.cmx typing/typedtree.cmx \ + typing/subst.cmx typing/predef.cmx typing/path.cmx parsing/parsetree.cmi \ + utils/misc.cmx parsing/longident.cmx parsing/location.cmx \ + typing/ident.cmx typing/env.cmx typing/ctype.cmx typing/btype.cmx \ + parsing/asttypes.cmi parsing/ast_helper.cmx typing/parmatch.cmi typing/path.cmo : typing/ident.cmi typing/path.cmi typing/path.cmx : typing/ident.cmx typing/path.cmi -typing/predef.cmo : typing/types.cmi typing/path.cmi parsing/location.cmi \ - typing/ident.cmi typing/btype.cmi parsing/asttypes.cmi typing/predef.cmi -typing/predef.cmx : typing/types.cmx typing/path.cmx parsing/location.cmx \ - typing/ident.cmx typing/btype.cmx parsing/asttypes.cmi typing/predef.cmi -typing/primitive.cmo : utils/misc.cmi typing/primitive.cmi -typing/primitive.cmx : utils/misc.cmx typing/primitive.cmi +typing/predef.cmo : typing/types.cmi typing/path.cmi parsing/parsetree.cmi \ + parsing/location.cmi typing/ident.cmi typing/btype.cmi \ + parsing/asttypes.cmi typing/predef.cmi +typing/predef.cmx : typing/types.cmx typing/path.cmx parsing/parsetree.cmi \ + parsing/location.cmx typing/ident.cmx typing/btype.cmx \ + parsing/asttypes.cmi typing/predef.cmi +typing/primitive.cmo : utils/warnings.cmi parsing/parsetree.cmi \ + typing/outcometree.cmi utils/misc.cmi parsing/location.cmi \ + parsing/attr_helper.cmi typing/primitive.cmi +typing/primitive.cmx : utils/warnings.cmx parsing/parsetree.cmi \ + typing/outcometree.cmi utils/misc.cmx parsing/location.cmx \ + parsing/attr_helper.cmx typing/primitive.cmi typing/printtyp.cmo : typing/types.cmi typing/primitive.cmi \ - typing/predef.cmi typing/path.cmi typing/outcometree.cmi \ - typing/oprint.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ - utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ - typing/printtyp.cmi + typing/predef.cmi typing/path.cmi parsing/parsetree.cmi \ + typing/outcometree.cmi typing/oprint.cmi utils/misc.cmi \ + parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ + typing/env.cmi typing/ctype.cmi utils/clflags.cmi typing/btype.cmi \ + parsing/asttypes.cmi typing/printtyp.cmi typing/printtyp.cmx : typing/types.cmx typing/primitive.cmx \ - typing/predef.cmx typing/path.cmx typing/outcometree.cmi \ - typing/oprint.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ - utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ - typing/printtyp.cmi + typing/predef.cmx typing/path.cmx parsing/parsetree.cmi \ + typing/outcometree.cmi typing/oprint.cmx utils/misc.cmx \ + parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ + typing/env.cmx typing/ctype.cmx utils/clflags.cmx typing/btype.cmx \ + parsing/asttypes.cmi typing/printtyp.cmi typing/printtyped.cmo : typing/typedtree.cmi parsing/printast.cmi \ typing/path.cmi utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ typing/ident.cmi parsing/asttypes.cmi typing/printtyped.cmi @@ -293,58 +349,64 @@ typing/subst.cmo : typing/types.cmi utils/tbl.cmi typing/path.cmi \ typing/subst.cmx : typing/types.cmx utils/tbl.cmx typing/path.cmx \ utils/misc.cmx parsing/location.cmx typing/ident.cmx utils/clflags.cmx \ typing/btype.cmx parsing/ast_mapper.cmx typing/subst.cmi +typing/tast_mapper.cmo : typing/typedtree.cmi typing/env.cmi \ + parsing/asttypes.cmi typing/tast_mapper.cmi +typing/tast_mapper.cmx : typing/typedtree.cmx typing/env.cmx \ + parsing/asttypes.cmi typing/tast_mapper.cmi typing/typeclass.cmo : utils/warnings.cmi typing/typetexp.cmi \ typing/types.cmi typing/typedtree.cmi typing/typedecl.cmi \ - typing/typecore.cmi parsing/syntaxerr.cmi typing/subst.cmi \ - typing/stypes.cmi typing/printtyp.cmi typing/predef.cmi typing/path.cmi \ + typing/typecore.cmi typing/subst.cmi typing/stypes.cmi \ + typing/printtyp.cmi typing/predef.cmi typing/path.cmi \ parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ parsing/location.cmi typing/includeclass.cmi typing/ident.cmi \ typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi utils/clflags.cmi \ - typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ - typing/typeclass.cmi + parsing/builtin_attributes.cmi typing/btype.cmi parsing/asttypes.cmi \ + parsing/ast_helper.cmi typing/typeclass.cmi typing/typeclass.cmx : utils/warnings.cmx typing/typetexp.cmx \ typing/types.cmx typing/typedtree.cmx typing/typedecl.cmx \ - typing/typecore.cmx parsing/syntaxerr.cmx typing/subst.cmx \ - typing/stypes.cmx typing/printtyp.cmx typing/predef.cmx typing/path.cmx \ + typing/typecore.cmx typing/subst.cmx typing/stypes.cmx \ + typing/printtyp.cmx typing/predef.cmx typing/path.cmx \ parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ parsing/location.cmx typing/includeclass.cmx typing/ident.cmx \ typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx utils/clflags.cmx \ - typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ - typing/typeclass.cmi + parsing/builtin_attributes.cmx typing/btype.cmx parsing/asttypes.cmi \ + parsing/ast_helper.cmx typing/typeclass.cmi typing/typecore.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi typing/typedtree.cmi parsing/syntaxerr.cmi \ - typing/subst.cmi typing/stypes.cmi typing/printtyp.cmi \ - typing/primitive.cmi typing/predef.cmi typing/path.cmi \ - parsing/parsetree.cmi typing/parmatch.cmi typing/oprint.cmi \ - utils/misc.cmi parsing/longident.cmi parsing/location.cmi \ - typing/ident.cmi typing/env.cmi typing/ctype.cmi typing/cmt_format.cmi \ - utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi typing/annot.cmi typing/typecore.cmi + typing/types.cmi typing/typedtree.cmi typing/subst.cmi typing/stypes.cmi \ + typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \ + typing/path.cmi parsing/parsetree.cmi typing/parmatch.cmi \ + typing/oprint.cmi utils/misc.cmi parsing/longident.cmi \ + parsing/location.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \ + typing/cmt_format.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ + typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ + typing/annot.cmi typing/typecore.cmi typing/typecore.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx typing/typedtree.cmx parsing/syntaxerr.cmx \ - typing/subst.cmx typing/stypes.cmx typing/printtyp.cmx \ - typing/primitive.cmx typing/predef.cmx typing/path.cmx \ - parsing/parsetree.cmi typing/parmatch.cmx typing/oprint.cmx \ - utils/misc.cmx parsing/longident.cmx parsing/location.cmx \ - typing/ident.cmx typing/env.cmx typing/ctype.cmx typing/cmt_format.cmx \ - utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx typing/annot.cmi typing/typecore.cmi + typing/types.cmx typing/typedtree.cmx typing/subst.cmx typing/stypes.cmx \ + typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \ + typing/path.cmx parsing/parsetree.cmi typing/parmatch.cmx \ + typing/oprint.cmx utils/misc.cmx parsing/longident.cmx \ + parsing/location.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \ + typing/cmt_format.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ + typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ + typing/annot.cmi typing/typecore.cmi typing/typedecl.cmo : utils/warnings.cmi typing/typetexp.cmi \ - typing/types.cmi typing/typedtree.cmi parsing/syntaxerr.cmi \ - typing/subst.cmi typing/printtyp.cmi typing/primitive.cmi \ - typing/predef.cmi typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \ + typing/types.cmi typing/typedtree.cmi typing/subst.cmi \ + typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \ + typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi typing/includecore.cmi \ typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/config.cmi \ - utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_helper.cmi typing/typedecl.cmi + utils/clflags.cmi typing/btype.cmi parsing/attr_helper.cmi \ + parsing/asttypes.cmi parsing/ast_iterator.cmi parsing/ast_helper.cmi \ + typing/typedecl.cmi typing/typedecl.cmx : utils/warnings.cmx typing/typetexp.cmx \ - typing/types.cmx typing/typedtree.cmx parsing/syntaxerr.cmx \ - typing/subst.cmx typing/printtyp.cmx typing/primitive.cmx \ - typing/predef.cmx typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \ + typing/types.cmx typing/typedtree.cmx typing/subst.cmx \ + typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \ + typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \ parsing/longident.cmx parsing/location.cmx typing/includecore.cmx \ typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/config.cmx \ - utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_helper.cmx typing/typedecl.cmi + utils/clflags.cmx typing/btype.cmx parsing/attr_helper.cmx \ + parsing/asttypes.cmi parsing/ast_iterator.cmx parsing/ast_helper.cmx \ + typing/typedecl.cmi typing/typedtree.cmo : typing/types.cmi typing/primitive.cmi typing/path.cmi \ parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi \ @@ -368,8 +430,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 typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_mapper.cmi typing/annot.cmi typing/typemod.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 \ @@ -377,8 +440,9 @@ 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 typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_mapper.cmx typing/annot.cmi typing/typemod.cmi + utils/clflags.cmx parsing/builtin_attributes.cmx typing/btype.cmx \ + parsing/asttypes.cmi parsing/ast_iterator.cmx typing/annot.cmi \ + typing/typemod.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 @@ -386,23 +450,34 @@ typing/types.cmx : typing/primitive.cmx typing/path.cmx \ parsing/parsetree.cmi parsing/longident.cmx parsing/location.cmx \ typing/ident.cmx parsing/asttypes.cmi typing/types.cmi typing/typetexp.cmo : utils/warnings.cmi typing/types.cmi \ - typing/typedtree.cmi utils/tbl.cmi parsing/syntaxerr.cmi \ - typing/printtyp.cmi typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \ + typing/typedtree.cmi utils/tbl.cmi typing/printtyp.cmi typing/predef.cmi \ + typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \ parsing/longident.cmi parsing/location.cmi typing/env.cmi \ - typing/ctype.cmi utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ - parsing/ast_mapper.cmi parsing/ast_helper.cmi typing/typetexp.cmi + typing/ctype.cmi utils/clflags.cmi parsing/builtin_attributes.cmi \ + typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \ + typing/typetexp.cmi typing/typetexp.cmx : utils/warnings.cmx typing/types.cmx \ - typing/typedtree.cmx utils/tbl.cmx parsing/syntaxerr.cmx \ - typing/printtyp.cmx typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \ + typing/typedtree.cmx utils/tbl.cmx typing/printtyp.cmx typing/predef.cmx \ + typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \ parsing/longident.cmx parsing/location.cmx typing/env.cmx \ - typing/ctype.cmx utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ - parsing/ast_mapper.cmx parsing/ast_helper.cmx typing/typetexp.cmi + typing/ctype.cmx utils/clflags.cmx parsing/builtin_attributes.cmx \ + typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \ + typing/typetexp.cmi +typing/untypeast.cmo : typing/typedtree.cmi typing/path.cmi \ + parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ + parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi \ + parsing/ast_helper.cmi typing/untypeast.cmi +typing/untypeast.cmx : typing/typedtree.cmx typing/path.cmx \ + parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ + parsing/location.cmx typing/ident.cmx typing/env.cmx parsing/asttypes.cmi \ + parsing/ast_helper.cmx typing/untypeast.cmi bytecomp/bytegen.cmi : bytecomp/lambda.cmi bytecomp/instruct.cmi bytecomp/bytelibrarian.cmi : bytecomp/bytelink.cmi : bytecomp/symtable.cmi bytecomp/cmo_format.cmi bytecomp/bytepackager.cmi : typing/ident.cmi typing/env.cmi bytecomp/bytesections.cmi : bytecomp/cmo_format.cmi : bytecomp/lambda.cmi typing/ident.cmi +bytecomp/debuginfo.cmi : parsing/location.cmi bytecomp/lambda.cmi bytecomp/dll.cmi : bytecomp/emitcode.cmi : bytecomp/instruct.cmi bytecomp/cmo_format.cmi bytecomp/instruct.cmi : typing/types.cmi typing/subst.cmi \ @@ -411,24 +486,26 @@ bytecomp/lambda.cmi : typing/types.cmi typing/primitive.cmi typing/path.cmi \ parsing/location.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi bytecomp/matching.cmi : typing/typedtree.cmi parsing/location.cmi \ bytecomp/lambda.cmi typing/ident.cmi -bytecomp/meta.cmi : +bytecomp/meta.cmi : bytecomp/instruct.cmi bytecomp/printinstr.cmi : bytecomp/instruct.cmi bytecomp/printlambda.cmi : bytecomp/lambda.cmi bytecomp/runtimedef.cmi : -bytecomp/simplif.cmi : bytecomp/lambda.cmi +bytecomp/simplif.cmi : bytecomp/lambda.cmi typing/ident.cmi bytecomp/switch.cmi : bytecomp/symtable.cmi : utils/misc.cmi typing/ident.cmi \ bytecomp/cmo_format.cmi +bytecomp/translattribute.cmi : typing/typedtree.cmi parsing/parsetree.cmi \ + parsing/location.cmi bytecomp/lambda.cmi bytecomp/translclass.cmi : typing/typedtree.cmi parsing/location.cmi \ bytecomp/lambda.cmi typing/ident.cmi parsing/asttypes.cmi -bytecomp/translcore.cmi : typing/typedtree.cmi typing/primitive.cmi \ - typing/path.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ - parsing/asttypes.cmi +bytecomp/translcore.cmi : typing/types.cmi typing/typedtree.cmi \ + typing/primitive.cmi typing/path.cmi parsing/location.cmi \ + bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi parsing/asttypes.cmi bytecomp/translmod.cmi : typing/typedtree.cmi typing/primitive.cmi \ parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi bytecomp/translobj.cmi : bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi -bytecomp/typeopt.cmi : typing/typedtree.cmi typing/path.cmi \ - bytecomp/lambda.cmi +bytecomp/typeopt.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \ + bytecomp/lambda.cmi typing/env.cmi bytecomp/bytegen.cmo : typing/types.cmi bytecomp/switch.cmi typing/subst.cmi \ typing/primitive.cmi utils/misc.cmi bytecomp/matching.cmi \ bytecomp/lambda.cmi bytecomp/instruct.cmi typing/ident.cmi \ @@ -445,13 +522,13 @@ bytecomp/bytelibrarian.cmx : utils/misc.cmx parsing/location.cmx \ bytecomp/bytelink.cmx bytecomp/bytelibrarian.cmi bytecomp/bytelink.cmo : utils/warnings.cmi bytecomp/symtable.cmi \ bytecomp/opcodes.cmo utils/misc.cmi parsing/location.cmi \ - bytecomp/instruct.cmi typing/ident.cmi bytecomp/dll.cmi \ + bytecomp/lambda.cmi bytecomp/instruct.cmi bytecomp/dll.cmi \ utils/consistbl.cmi utils/config.cmi bytecomp/cmo_format.cmi \ utils/clflags.cmi utils/ccomp.cmi bytecomp/bytesections.cmi \ bytecomp/bytelink.cmi bytecomp/bytelink.cmx : utils/warnings.cmx bytecomp/symtable.cmx \ bytecomp/opcodes.cmx utils/misc.cmx parsing/location.cmx \ - bytecomp/instruct.cmx typing/ident.cmx bytecomp/dll.cmx \ + bytecomp/lambda.cmx bytecomp/instruct.cmx bytecomp/dll.cmx \ utils/consistbl.cmx utils/config.cmx bytecomp/cmo_format.cmi \ utils/clflags.cmx utils/ccomp.cmx bytecomp/bytesections.cmx \ bytecomp/bytelink.cmi @@ -469,6 +546,10 @@ bytecomp/bytepackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \ bytecomp/bytegen.cmx bytecomp/bytepackager.cmi bytecomp/bytesections.cmo : utils/config.cmi bytecomp/bytesections.cmi bytecomp/bytesections.cmx : utils/config.cmx bytecomp/bytesections.cmi +bytecomp/debuginfo.cmo : parsing/location.cmi bytecomp/lambda.cmi \ + bytecomp/debuginfo.cmi +bytecomp/debuginfo.cmx : parsing/location.cmx bytecomp/lambda.cmx \ + bytecomp/debuginfo.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/emitcode.cmo : bytecomp/translmod.cmi typing/primitive.cmi \ @@ -507,8 +588,8 @@ bytecomp/matching.cmx : typing/types.cmx bytecomp/typeopt.cmx \ parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ bytecomp/matching.cmi -bytecomp/meta.cmo : bytecomp/meta.cmi -bytecomp/meta.cmx : bytecomp/meta.cmi +bytecomp/meta.cmo : bytecomp/instruct.cmi bytecomp/meta.cmi +bytecomp/meta.cmx : bytecomp/instruct.cmx bytecomp/meta.cmi bytecomp/opcodes.cmo : bytecomp/opcodes.cmx : bytecomp/printinstr.cmo : bytecomp/printlambda.cmi parsing/location.cmi \ @@ -525,12 +606,14 @@ bytecomp/printlambda.cmx : typing/types.cmx typing/primitive.cmx \ parsing/asttypes.cmi bytecomp/printlambda.cmi bytecomp/runtimedef.cmo : bytecomp/runtimedef.cmi bytecomp/runtimedef.cmx : bytecomp/runtimedef.cmi -bytecomp/simplif.cmo : utils/tbl.cmi typing/stypes.cmi utils/misc.cmi \ - bytecomp/lambda.cmi typing/ident.cmi utils/clflags.cmi \ - parsing/asttypes.cmi typing/annot.cmi bytecomp/simplif.cmi -bytecomp/simplif.cmx : utils/tbl.cmx typing/stypes.cmx utils/misc.cmx \ - bytecomp/lambda.cmx typing/ident.cmx utils/clflags.cmx \ - parsing/asttypes.cmi typing/annot.cmi bytecomp/simplif.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 \ + bytecomp/simplif.cmi +bytecomp/simplif.cmx : utils/warnings.cmx utils/tbl.cmx typing/stypes.cmx \ + utils/misc.cmx parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ + utils/clflags.cmx parsing/asttypes.cmi typing/annot.cmi \ + bytecomp/simplif.cmi bytecomp/switch.cmo : bytecomp/switch.cmi bytecomp/switch.cmx : bytecomp/switch.cmi bytecomp/symtable.cmo : utils/tbl.cmi bytecomp/runtimedef.cmi \ @@ -543,6 +626,14 @@ 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/translattribute.cmo : utils/warnings.cmi typing/typedtree.cmi \ + parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \ + parsing/location.cmi bytecomp/lambda.cmi utils/config.cmi \ + bytecomp/translattribute.cmi +bytecomp/translattribute.cmx : utils/warnings.cmx typing/typedtree.cmx \ + parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \ + parsing/location.cmx bytecomp/lambda.cmx utils/config.cmx \ + bytecomp/translattribute.cmi bytecomp/translclass.cmo : typing/types.cmi bytecomp/typeopt.cmi \ typing/typedtree.cmi bytecomp/translobj.cmi bytecomp/translcore.cmi \ typing/path.cmi bytecomp/matching.cmi parsing/location.cmi \ @@ -554,38 +645,40 @@ bytecomp/translclass.cmx : typing/types.cmx bytecomp/typeopt.cmx \ bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx utils/clflags.cmx \ typing/btype.cmx parsing/asttypes.cmi bytecomp/translclass.cmi bytecomp/translcore.cmo : typing/types.cmi bytecomp/typeopt.cmi \ - typing/typedtree.cmi bytecomp/translobj.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 + 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 \ + 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 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 + 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 \ + 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 bytecomp/translmod.cmo : typing/types.cmi typing/typedtree.cmi \ bytecomp/translobj.cmi bytecomp/translcore.cmi bytecomp/translclass.cmi \ - typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \ - typing/path.cmi typing/mtype.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ - typing/ctype.cmi parsing/asttypes.cmi bytecomp/translmod.cmi + bytecomp/translattribute.cmi typing/printtyp.cmi typing/primitive.cmi \ + typing/predef.cmi typing/path.cmi typing/mtype.cmi utils/misc.cmi \ + parsing/longident.cmi parsing/location.cmi bytecomp/lambda.cmi \ + typing/ident.cmi typing/env.cmi typing/ctype.cmi utils/clflags.cmi \ + parsing/asttypes.cmi bytecomp/translmod.cmi bytecomp/translmod.cmx : typing/types.cmx typing/typedtree.cmx \ bytecomp/translobj.cmx bytecomp/translcore.cmx bytecomp/translclass.cmx \ - typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \ - typing/path.cmx typing/mtype.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ - typing/ctype.cmx parsing/asttypes.cmi bytecomp/translmod.cmi + bytecomp/translattribute.cmx typing/printtyp.cmx typing/primitive.cmx \ + typing/predef.cmx typing/path.cmx typing/mtype.cmx utils/misc.cmx \ + parsing/longident.cmx parsing/location.cmx bytecomp/lambda.cmx \ + typing/ident.cmx typing/env.cmx typing/ctype.cmx utils/clflags.cmx \ + parsing/asttypes.cmi bytecomp/translmod.cmi bytecomp/translobj.cmo : typing/primitive.cmi utils/misc.cmi \ parsing/longident.cmi bytecomp/lambda.cmi typing/ident.cmi typing/env.cmi \ - utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ + utils/config.cmi utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ bytecomp/translobj.cmi bytecomp/translobj.cmx : typing/primitive.cmx utils/misc.cmx \ parsing/longident.cmx bytecomp/lambda.cmx typing/ident.cmx typing/env.cmx \ - utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ + utils/config.cmx utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ bytecomp/translobj.cmi bytecomp/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \ typing/predef.cmi typing/path.cmi bytecomp/lambda.cmi typing/ident.cmi \ @@ -594,34 +687,56 @@ bytecomp/typeopt.cmx : typing/types.cmx typing/typedtree.cmx \ typing/predef.cmx typing/path.cmx bytecomp/lambda.cmx typing/ident.cmx \ typing/env.cmx typing/ctype.cmx bytecomp/typeopt.cmi asmcomp/CSEgen.cmi : asmcomp/mach.cmi -asmcomp/asmgen.cmi : bytecomp/lambda.cmi asmcomp/cmm.cmi +asmcomp/asmgen.cmi : utils/timings.cmi bytecomp/lambda.cmi \ + middle_end/flambda.cmi asmcomp/cmm.cmi middle_end/backend_intf.cmi asmcomp/asmlibrarian.cmi : asmcomp/asmlink.cmi : asmcomp/cmx_format.cmi -asmcomp/asmpackager.cmi : typing/env.cmi +asmcomp/asmpackager.cmi : typing/env.cmi middle_end/backend_intf.cmi asmcomp/branch_relaxation.cmi : asmcomp/linearize.cmi \ asmcomp/branch_relaxation_intf.cmo +asmcomp/build_export_info.cmi : middle_end/flambda.cmi \ + asmcomp/export_info.cmi middle_end/backend_intf.cmi asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \ - asmcomp/debuginfo.cmi parsing/asttypes.cmi + bytecomp/debuginfo.cmi parsing/asttypes.cmi asmcomp/closure.cmi : bytecomp/lambda.cmi asmcomp/clambda.cmi -asmcomp/cmm.cmi : bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi +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.cmi : bytecomp/lambda.cmi typing/ident.cmi \ + bytecomp/debuginfo.cmi asmcomp/cmmgen.cmi : asmcomp/cmx_format.cmi asmcomp/cmm.cmi \ asmcomp/clambda.cmi -asmcomp/cmx_format.cmi : asmcomp/clambda.cmi -asmcomp/codegen.cmi : asmcomp/cmm.cmi +asmcomp/cmx_format.cmi : asmcomp/export_info.cmi asmcomp/clambda.cmi asmcomp/coloring.cmi : asmcomp/comballoc.cmi : asmcomp/mach.cmi -asmcomp/compilenv.cmi : typing/ident.cmi asmcomp/cmx_format.cmi \ - asmcomp/clambda.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 \ + middle_end/flambda.cmi asmcomp/export_info.cmi \ + middle_end/base_types/compilation_unit.cmi asmcomp/cmx_format.cmi \ + middle_end/base_types/closure_id.cmi asmcomp/clambda.cmi asmcomp/deadcode.cmi : asmcomp/mach.cmi -asmcomp/debuginfo.cmi : parsing/location.cmi bytecomp/lambda.cmi asmcomp/emit.cmi : asmcomp/linearize.cmi asmcomp/cmm.cmi -asmcomp/emitaux.cmi : asmcomp/debuginfo.cmi +asmcomp/emitaux.cmi : bytecomp/debuginfo.cmi +asmcomp/export_info.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 \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ + middle_end/base_types/export_id.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi +asmcomp/export_info_for_pack.cmi : asmcomp/export_info.cmi \ + middle_end/base_types/compilation_unit.cmi +asmcomp/flambda_to_clambda.cmi : middle_end/base_types/symbol.cmi \ + middle_end/flambda.cmi asmcomp/export_info.cmi asmcomp/clambda.cmi +asmcomp/import_approx.cmi : middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi asmcomp/interf.cmi : asmcomp/mach.cmi asmcomp/linearize.cmi : asmcomp/reg.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \ - asmcomp/debuginfo.cmi + bytecomp/debuginfo.cmi asmcomp/liveness.cmi : asmcomp/mach.cmi -asmcomp/mach.cmi : asmcomp/reg.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \ - asmcomp/cmm.cmi asmcomp/arch.cmo +asmcomp/mach.cmi : asmcomp/reg.cmi bytecomp/lambda.cmi \ + bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/printclambda.cmi : asmcomp/clambda.cmi asmcomp/printcmm.cmi : asmcomp/cmm.cmi asmcomp/printlinear.cmi : asmcomp/linearize.cmi @@ -633,65 +748,85 @@ asmcomp/reloadgen.cmi : asmcomp/reg.cmi asmcomp/mach.cmi asmcomp/schedgen.cmi : asmcomp/mach.cmi asmcomp/linearize.cmi asmcomp/scheduling.cmi : asmcomp/linearize.cmi asmcomp/selectgen.cmi : utils/tbl.cmi asmcomp/reg.cmi asmcomp/mach.cmi \ - typing/ident.cmi asmcomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo + typing/ident.cmi bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/selection.cmi : asmcomp/mach.cmi asmcomp/cmm.cmi asmcomp/spill.cmi : asmcomp/mach.cmi asmcomp/split.cmi : asmcomp/mach.cmi asmcomp/strmatch.cmi : asmcomp/cmm.cmi +asmcomp/un_anf.cmi : asmcomp/clambda.cmi +asmcomp/x86_ast.cmi : +asmcomp/x86_dsl.cmi : asmcomp/x86_ast.cmi +asmcomp/x86_gas.cmi : asmcomp/x86_ast.cmi +asmcomp/x86_masm.cmi : asmcomp/x86_ast.cmi +asmcomp/x86_proc.cmi : asmcomp/x86_ast.cmi asmcomp/CSE.cmo : asmcomp/mach.cmi asmcomp/CSEgen.cmi asmcomp/arch.cmo asmcomp/CSE.cmx : asmcomp/mach.cmx asmcomp/CSEgen.cmx asmcomp/arch.cmx asmcomp/CSEgen.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ - asmcomp/CSEgen.cmi + asmcomp/cmm.cmi asmcomp/CSEgen.cmi asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ - asmcomp/CSEgen.cmi -asmcomp/arch.cmo : -asmcomp/arch.cmx : -asmcomp/asmgen.cmo : bytecomp/translmod.cmi asmcomp/split.cmi \ + asmcomp/cmm.cmx asmcomp/CSEgen.cmi +asmcomp/arch.cmo : utils/clflags.cmi +asmcomp/arch.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 \ asmcomp/reload.cmi asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/printmach.cmi \ asmcomp/printlinear.cmi asmcomp/printcmm.cmi asmcomp/printclambda.cmi \ typing/primitive.cmi utils/misc.cmi asmcomp/mach.cmi parsing/location.cmi \ - asmcomp/liveness.cmi asmcomp/linearize.cmi asmcomp/interf.cmi \ - asmcomp/emitaux.cmi asmcomp/emit.cmi asmcomp/deadcode.cmi \ - utils/config.cmi asmcomp/compilenv.cmi asmcomp/comballoc.cmi \ - asmcomp/coloring.cmi asmcomp/cmmgen.cmi asmcomp/cmm.cmi \ - asmcomp/closure.cmi utils/clflags.cmi asmcomp/CSE.cmo asmcomp/asmgen.cmi -asmcomp/asmgen.cmx : bytecomp/translmod.cmx asmcomp/split.cmx \ + asmcomp/liveness.cmi middle_end/base_types/linkage_name.cmi \ + asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/interf.cmi \ + asmcomp/flambda_to_clambda.cmi middle_end/flambda.cmi asmcomp/emitaux.cmi \ + asmcomp/emit.cmi asmcomp/deadcode.cmi utils/config.cmi \ + asmcomp/compilenv.cmi asmcomp/comballoc.cmi asmcomp/coloring.cmi \ + asmcomp/cmmgen.cmi asmcomp/cmm.cmi asmcomp/closure.cmi utils/clflags.cmi \ + asmcomp/clambda.cmi asmcomp/CSE.cmo asmcomp/build_export_info.cmi \ + asmcomp/asmgen.cmi +asmcomp/asmgen.cmx : asmcomp/un_anf.cmx bytecomp/translmod.cmx \ + utils/timings.cmx middle_end/base_types/symbol.cmx asmcomp/split.cmx \ asmcomp/spill.cmx asmcomp/selection.cmx asmcomp/scheduling.cmx \ asmcomp/reload.cmx asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/printmach.cmx \ asmcomp/printlinear.cmx asmcomp/printcmm.cmx asmcomp/printclambda.cmx \ typing/primitive.cmx utils/misc.cmx asmcomp/mach.cmx parsing/location.cmx \ - asmcomp/liveness.cmx asmcomp/linearize.cmx asmcomp/interf.cmx \ - asmcomp/emitaux.cmx asmcomp/emit.cmx asmcomp/deadcode.cmx \ - utils/config.cmx asmcomp/compilenv.cmx asmcomp/comballoc.cmx \ - asmcomp/coloring.cmx asmcomp/cmmgen.cmx asmcomp/cmm.cmx \ - asmcomp/closure.cmx utils/clflags.cmx asmcomp/CSE.cmx asmcomp/asmgen.cmi + asmcomp/liveness.cmx middle_end/base_types/linkage_name.cmx \ + asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/interf.cmx \ + asmcomp/flambda_to_clambda.cmx middle_end/flambda.cmx asmcomp/emitaux.cmx \ + asmcomp/emit.cmx asmcomp/deadcode.cmx utils/config.cmx \ + asmcomp/compilenv.cmx asmcomp/comballoc.cmx asmcomp/coloring.cmx \ + asmcomp/cmmgen.cmx asmcomp/cmm.cmx asmcomp/closure.cmx utils/clflags.cmx \ + asmcomp/clambda.cmx asmcomp/CSE.cmx asmcomp/build_export_info.cmx \ + asmcomp/asmgen.cmi asmcomp/asmlibrarian.cmo : utils/misc.cmi parsing/location.cmi \ - utils/config.cmi asmcomp/compilenv.cmi asmcomp/cmx_format.cmi \ - utils/clflags.cmi asmcomp/clambda.cmi utils/ccomp.cmi asmcomp/asmlink.cmi \ - asmcomp/asmlibrarian.cmi + asmcomp/export_info.cmi utils/config.cmi asmcomp/compilenv.cmi \ + asmcomp/cmx_format.cmi utils/clflags.cmi asmcomp/clambda.cmi \ + utils/ccomp.cmi asmcomp/asmlink.cmi asmcomp/asmlibrarian.cmi asmcomp/asmlibrarian.cmx : utils/misc.cmx parsing/location.cmx \ - utils/config.cmx asmcomp/compilenv.cmx asmcomp/cmx_format.cmi \ - utils/clflags.cmx asmcomp/clambda.cmx utils/ccomp.cmx asmcomp/asmlink.cmx \ - asmcomp/asmlibrarian.cmi -asmcomp/asmlink.cmo : bytecomp/runtimedef.cmi asmcomp/proc.cmi \ + asmcomp/export_info.cmx utils/config.cmx asmcomp/compilenv.cmx \ + asmcomp/cmx_format.cmi utils/clflags.cmx asmcomp/clambda.cmx \ + utils/ccomp.cmx asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmi +asmcomp/asmlink.cmo : utils/timings.cmi bytecomp/runtimedef.cmi \ utils/misc.cmi parsing/location.cmi asmcomp/emitaux.cmi asmcomp/emit.cmi \ utils/consistbl.cmi utils/config.cmi asmcomp/compilenv.cmi \ asmcomp/cmx_format.cmi asmcomp/cmmgen.cmi utils/clflags.cmi \ utils/ccomp.cmi asmcomp/asmgen.cmi asmcomp/asmlink.cmi -asmcomp/asmlink.cmx : bytecomp/runtimedef.cmx asmcomp/proc.cmx \ +asmcomp/asmlink.cmx : utils/timings.cmx bytecomp/runtimedef.cmx \ utils/misc.cmx parsing/location.cmx asmcomp/emitaux.cmx asmcomp/emit.cmx \ utils/consistbl.cmx utils/config.cmx asmcomp/compilenv.cmx \ asmcomp/cmx_format.cmi asmcomp/cmmgen.cmx utils/clflags.cmx \ utils/ccomp.cmx asmcomp/asmgen.cmx asmcomp/asmlink.cmi asmcomp/asmpackager.cmo : typing/typemod.cmi bytecomp/translmod.cmi \ - utils/misc.cmi parsing/location.cmi typing/ident.cmi typing/env.cmi \ - utils/config.cmi asmcomp/compilenv.cmi asmcomp/cmx_format.cmi \ + utils/timings.cmi utils/misc.cmi middle_end/middle_end.cmi \ + parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ + asmcomp/export_info_for_pack.cmi asmcomp/export_info.cmi typing/env.cmi \ + utils/config.cmi asmcomp/compilenv.cmi \ + middle_end/base_types/compilation_unit.cmi asmcomp/cmx_format.cmi \ utils/clflags.cmi utils/ccomp.cmi asmcomp/asmlink.cmi asmcomp/asmgen.cmi \ asmcomp/asmpackager.cmi asmcomp/asmpackager.cmx : typing/typemod.cmx bytecomp/translmod.cmx \ - utils/misc.cmx parsing/location.cmx typing/ident.cmx typing/env.cmx \ - utils/config.cmx asmcomp/compilenv.cmx asmcomp/cmx_format.cmi \ + utils/timings.cmx utils/misc.cmx middle_end/middle_end.cmx \ + parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ + asmcomp/export_info_for_pack.cmx asmcomp/export_info.cmx typing/env.cmx \ + utils/config.cmx asmcomp/compilenv.cmx \ + middle_end/base_types/compilation_unit.cmx asmcomp/cmx_format.cmi \ utils/clflags.cmx utils/ccomp.cmx asmcomp/asmlink.cmx asmcomp/asmgen.cmx \ asmcomp/asmpackager.cmi asmcomp/branch_relaxation.cmo : utils/misc.cmi asmcomp/mach.cmi \ @@ -702,89 +837,197 @@ asmcomp/branch_relaxation.cmx : utils/misc.cmx asmcomp/mach.cmx \ asmcomp/branch_relaxation.cmi asmcomp/branch_relaxation_intf.cmo : asmcomp/linearize.cmi asmcomp/arch.cmo asmcomp/branch_relaxation_intf.cmx : asmcomp/linearize.cmx asmcomp/arch.cmx +asmcomp/build_export_info.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 \ + middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ + middle_end/invariant_params.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi asmcomp/compilenv.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/backend_intf.cmi middle_end/allocated_const.cmi \ + asmcomp/build_export_info.cmi +asmcomp/build_export_info.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 \ + middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ + middle_end/invariant_params.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx asmcomp/compilenv.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/backend_intf.cmi middle_end/allocated_const.cmx \ + asmcomp/build_export_info.cmi asmcomp/clambda.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - asmcomp/debuginfo.cmi parsing/asttypes.cmi asmcomp/clambda.cmi + bytecomp/debuginfo.cmi parsing/asttypes.cmi asmcomp/clambda.cmi asmcomp/clambda.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - asmcomp/debuginfo.cmx parsing/asttypes.cmi asmcomp/clambda.cmi -asmcomp/closure.cmo : utils/tbl.cmi bytecomp/switch.cmi typing/primitive.cmi \ - utils/misc.cmi parsing/location.cmi bytecomp/lambda.cmi typing/ident.cmi \ - asmcomp/debuginfo.cmi asmcomp/compilenv.cmi utils/clflags.cmi \ + bytecomp/debuginfo.cmx parsing/asttypes.cmi asmcomp/clambda.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/debuginfo.cmi asmcomp/compilenv.cmi utils/clflags.cmi \ asmcomp/clambda.cmi parsing/asttypes.cmi asmcomp/arch.cmo \ asmcomp/closure.cmi -asmcomp/closure.cmx : utils/tbl.cmx bytecomp/switch.cmx typing/primitive.cmx \ - utils/misc.cmx parsing/location.cmx bytecomp/lambda.cmx typing/ident.cmx \ - asmcomp/debuginfo.cmx asmcomp/compilenv.cmx utils/clflags.cmx \ +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/debuginfo.cmx asmcomp/compilenv.cmx utils/clflags.cmx \ asmcomp/clambda.cmx parsing/asttypes.cmi asmcomp/arch.cmx \ asmcomp/closure.cmi -asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi asmcomp/debuginfo.cmi \ - asmcomp/arch.cmo asmcomp/cmm.cmi -asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx asmcomp/debuginfo.cmx \ - asmcomp/arch.cmx asmcomp/cmm.cmi -asmcomp/cmmgen.cmo : typing/types.cmi bytecomp/switch.cmi \ - asmcomp/strmatch.cmi asmcomp/proc.cmi typing/primitive.cmi utils/misc.cmi \ - bytecomp/lambda.cmi typing/ident.cmi asmcomp/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/cmmgen.cmx : typing/types.cmx bytecomp/switch.cmx \ - asmcomp/strmatch.cmx asmcomp/proc.cmx typing/primitive.cmx utils/misc.cmx \ - bytecomp/lambda.cmx typing/ident.cmx asmcomp/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/codegen.cmo : asmcomp/split.cmi asmcomp/spill.cmi asmcomp/reload.cmi \ - asmcomp/reg.cmi asmcomp/printmach.cmi asmcomp/printlinear.cmi \ - asmcomp/printcmm.cmi asmcomp/liveness.cmi asmcomp/linearize.cmi \ - asmcomp/interf.cmi asmcomp/emit.cmi asmcomp/coloring.cmi asmcomp/cmm.cmi \ - asmcomp/codegen.cmi -asmcomp/codegen.cmx : asmcomp/split.cmx asmcomp/spill.cmx asmcomp/reload.cmx \ - asmcomp/reg.cmx asmcomp/printmach.cmx asmcomp/printlinear.cmx \ - asmcomp/printcmm.cmx asmcomp/liveness.cmx asmcomp/linearize.cmx \ - asmcomp/interf.cmx asmcomp/emit.cmx asmcomp/coloring.cmx asmcomp/cmm.cmx \ - asmcomp/codegen.cmi +asmcomp/closure_offsets.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi utils/misc.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ + asmcomp/closure_offsets.cmi +asmcomp/closure_offsets.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx utils/misc.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \ + asmcomp/closure_offsets.cmi +asmcomp/cmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ + bytecomp/debuginfo.cmi asmcomp/arch.cmo asmcomp/cmm.cmi +asmcomp/cmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ + bytecomp/debuginfo.cmx asmcomp/arch.cmx asmcomp/cmm.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 \ + bytecomp/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/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 \ + bytecomp/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/coloring.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/coloring.cmi asmcomp/coloring.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/coloring.cmi asmcomp/comballoc.cmo : asmcomp/reg.cmi asmcomp/mach.cmi utils/config.cmi \ asmcomp/arch.cmo asmcomp/comballoc.cmi asmcomp/comballoc.cmx : asmcomp/reg.cmx asmcomp/mach.cmx utils/config.cmx \ asmcomp/arch.cmx asmcomp/comballoc.cmi -asmcomp/compilenv.cmo : utils/misc.cmi parsing/location.cmi typing/ident.cmi \ - typing/env.cmi utils/config.cmi asmcomp/cmx_format.cmi \ - asmcomp/clambda.cmi asmcomp/compilenv.cmi -asmcomp/compilenv.cmx : utils/misc.cmx parsing/location.cmx typing/ident.cmx \ - typing/env.cmx utils/config.cmx asmcomp/cmx_format.cmi \ - asmcomp/clambda.cmx asmcomp/compilenv.cmi +asmcomp/compilenv.cmo : utils/warnings.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ + parsing/location.cmi middle_end/base_types/linkage_name.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 +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 asmcomp/deadcode.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ asmcomp/deadcode.cmi asmcomp/deadcode.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ asmcomp/deadcode.cmi -asmcomp/debuginfo.cmo : parsing/location.cmi bytecomp/lambda.cmi \ - asmcomp/debuginfo.cmi -asmcomp/debuginfo.cmx : parsing/location.cmx bytecomp/lambda.cmx \ - asmcomp/debuginfo.cmi -asmcomp/emit.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ - asmcomp/mach.cmi asmcomp/linearize.cmi bytecomp/lambda.cmi \ - asmcomp/emitaux.cmi asmcomp/debuginfo.cmi utils/config.cmi \ - asmcomp/compilenv.cmi asmcomp/cmm.cmi utils/clflags.cmi \ - asmcomp/branch_relaxation.cmi asmcomp/arch.cmo asmcomp/emit.cmi -asmcomp/emit.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ - asmcomp/mach.cmx asmcomp/linearize.cmx bytecomp/lambda.cmx \ - asmcomp/emitaux.cmx asmcomp/debuginfo.cmx utils/config.cmx \ - asmcomp/compilenv.cmx asmcomp/cmm.cmx utils/clflags.cmx \ - asmcomp/branch_relaxation.cmx asmcomp/arch.cmx asmcomp/emit.cmi -asmcomp/emitaux.cmo : asmcomp/linearize.cmi asmcomp/debuginfo.cmi \ +asmcomp/emit.cmo : asmcomp/x86_proc.cmi asmcomp/x86_masm.cmi \ + asmcomp/x86_gas.cmi asmcomp/x86_dsl.cmi asmcomp/x86_ast.cmi \ + asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi asmcomp/mach.cmi \ + asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/emitaux.cmi \ + bytecomp/debuginfo.cmi utils/config.cmi asmcomp/compilenv.cmi \ + asmcomp/cmm.cmi utils/clflags.cmi asmcomp/branch_relaxation.cmi \ + asmcomp/arch.cmo asmcomp/emit.cmi +asmcomp/emit.cmx : asmcomp/x86_proc.cmx asmcomp/x86_masm.cmx \ + asmcomp/x86_gas.cmx asmcomp/x86_dsl.cmx asmcomp/x86_ast.cmi \ + asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx asmcomp/mach.cmx \ + asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/emitaux.cmx \ + bytecomp/debuginfo.cmx utils/config.cmx asmcomp/compilenv.cmx \ + asmcomp/cmm.cmx utils/clflags.cmx asmcomp/branch_relaxation.cmx \ + asmcomp/arch.cmx asmcomp/emit.cmi +asmcomp/emitaux.cmo : asmcomp/linearize.cmi bytecomp/debuginfo.cmi \ utils/config.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/emitaux.cmi -asmcomp/emitaux.cmx : asmcomp/linearize.cmx asmcomp/debuginfo.cmx \ +asmcomp/emitaux.cmx : asmcomp/linearize.cmx bytecomp/debuginfo.cmx \ utils/config.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/emitaux.cmi +asmcomp/export_info.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 \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ + middle_end/base_types/export_id.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi asmcomp/export_info.cmi +asmcomp/export_info.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 \ + middle_end/simple_value_approx.cmx \ + middle_end/base_types/set_of_closures_id.cmx middle_end/flambda.cmx \ + middle_end/base_types/export_id.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx asmcomp/export_info.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_id.cmi utils/misc.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi asmcomp/export_info_for_pack.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_id.cmx utils/misc.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx asmcomp/export_info_for_pack.cmi +asmcomp/flambda_to_clambda.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 \ + middle_end/base_types/static_exception.cmi \ + middle_end/base_types/set_of_closures_id.cmi typing/primitive.cmi \ + utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \ + utils/misc.cmi middle_end/base_types/linkage_name.cmi typing/ident.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + asmcomp/export_info.cmi bytecomp/debuginfo.cmi asmcomp/compilenv.cmi \ + asmcomp/closure_offsets.cmi middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi asmcomp/clambda.cmi middle_end/allocated_const.cmi \ + asmcomp/flambda_to_clambda.cmi +asmcomp/flambda_to_clambda.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 \ + middle_end/base_types/static_exception.cmx \ + middle_end/base_types/set_of_closures_id.cmx typing/primitive.cmx \ + utils/numbers.cmx middle_end/base_types/mutable_variable.cmx \ + utils/misc.cmx middle_end/base_types/linkage_name.cmx typing/ident.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + asmcomp/export_info.cmx bytecomp/debuginfo.cmx asmcomp/compilenv.cmx \ + asmcomp/closure_offsets.cmx middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx asmcomp/clambda.cmx middle_end/allocated_const.cmx \ + asmcomp/flambda_to_clambda.cmi +asmcomp/import_approx.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/base_types/symbol.cmi middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_id.cmi utils/misc.cmi \ + middle_end/freshening.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi asmcomp/export_info.cmi \ + middle_end/base_types/export_id.cmi asmcomp/compilenv.cmi \ + middle_end/base_types/closure_id.cmi asmcomp/import_approx.cmi +asmcomp/import_approx.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/base_types/symbol.cmx middle_end/simple_value_approx.cmx \ + middle_end/base_types/set_of_closures_id.cmx utils/misc.cmx \ + middle_end/freshening.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx asmcomp/export_info.cmx \ + middle_end/base_types/export_id.cmx asmcomp/compilenv.cmx \ + middle_end/base_types/closure_id.cmx asmcomp/import_approx.cmi asmcomp/interf.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \ asmcomp/interf.cmi asmcomp/interf.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \ asmcomp/interf.cmi asmcomp/linearize.cmo : asmcomp/reg.cmi asmcomp/proc.cmi utils/misc.cmi \ - asmcomp/mach.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \ + asmcomp/mach.cmi bytecomp/lambda.cmi bytecomp/debuginfo.cmi \ asmcomp/cmm.cmi asmcomp/linearize.cmi asmcomp/linearize.cmx : asmcomp/reg.cmx asmcomp/proc.cmx utils/misc.cmx \ - asmcomp/mach.cmx bytecomp/lambda.cmx asmcomp/debuginfo.cmx \ + asmcomp/mach.cmx bytecomp/lambda.cmx bytecomp/debuginfo.cmx \ asmcomp/cmm.cmx asmcomp/linearize.cmi asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ asmcomp/printmach.cmi utils/misc.cmi asmcomp/mach.cmi \ @@ -792,10 +1035,10 @@ asmcomp/liveness.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ asmcomp/liveness.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \ asmcomp/printmach.cmx utils/misc.cmx asmcomp/mach.cmx \ asmcomp/liveness.cmi -asmcomp/mach.cmo : asmcomp/reg.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \ - asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/mach.cmi -asmcomp/mach.cmx : asmcomp/reg.cmx bytecomp/lambda.cmx asmcomp/debuginfo.cmx \ - asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/mach.cmi +asmcomp/mach.cmo : asmcomp/reg.cmi bytecomp/lambda.cmi \ + bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo asmcomp/mach.cmi +asmcomp/mach.cmx : asmcomp/reg.cmx bytecomp/lambda.cmx \ + bytecomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx asmcomp/mach.cmi asmcomp/printclambda.cmo : bytecomp/printlambda.cmi bytecomp/lambda.cmi \ typing/ident.cmi asmcomp/clambda.cmi parsing/asttypes.cmi \ asmcomp/printclambda.cmi @@ -803,35 +1046,35 @@ asmcomp/printclambda.cmx : bytecomp/printlambda.cmx bytecomp/lambda.cmx \ typing/ident.cmx asmcomp/clambda.cmx parsing/asttypes.cmi \ asmcomp/printclambda.cmi asmcomp/printcmm.cmo : bytecomp/lambda.cmi typing/ident.cmi \ - asmcomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printcmm.cmi + bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/printcmm.cmi asmcomp/printcmm.cmx : bytecomp/lambda.cmx typing/ident.cmx \ - asmcomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/printcmm.cmi + bytecomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/printcmm.cmi asmcomp/printlinear.cmo : asmcomp/printmach.cmi asmcomp/mach.cmi \ - asmcomp/linearize.cmi bytecomp/lambda.cmi asmcomp/debuginfo.cmi \ + asmcomp/linearize.cmi bytecomp/lambda.cmi bytecomp/debuginfo.cmi \ asmcomp/printlinear.cmi asmcomp/printlinear.cmx : asmcomp/printmach.cmx asmcomp/mach.cmx \ - asmcomp/linearize.cmx bytecomp/lambda.cmx asmcomp/debuginfo.cmx \ + asmcomp/linearize.cmx bytecomp/lambda.cmx bytecomp/debuginfo.cmx \ asmcomp/printlinear.cmi asmcomp/printmach.cmo : asmcomp/reg.cmi asmcomp/proc.cmi \ asmcomp/printcmm.cmi asmcomp/mach.cmi bytecomp/lambda.cmi \ - asmcomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ + bytecomp/debuginfo.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ asmcomp/printmach.cmi asmcomp/printmach.cmx : asmcomp/reg.cmx asmcomp/proc.cmx \ asmcomp/printcmm.cmx asmcomp/mach.cmx bytecomp/lambda.cmx \ - asmcomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ + bytecomp/debuginfo.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ asmcomp/printmach.cmi -asmcomp/proc.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ - utils/config.cmi asmcomp/cmm.cmi utils/clflags.cmi utils/ccomp.cmi \ - asmcomp/arch.cmo asmcomp/proc.cmi -asmcomp/proc.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \ - utils/config.cmx asmcomp/cmm.cmx utils/clflags.cmx utils/ccomp.cmx \ - asmcomp/arch.cmx asmcomp/proc.cmi +asmcomp/proc.cmo : asmcomp/x86_proc.cmi asmcomp/reg.cmi utils/misc.cmi \ + asmcomp/mach.cmi utils/config.cmi asmcomp/cmm.cmi asmcomp/arch.cmo \ + asmcomp/proc.cmi +asmcomp/proc.cmx : asmcomp/x86_proc.cmx asmcomp/reg.cmx utils/misc.cmx \ + asmcomp/mach.cmx utils/config.cmx asmcomp/cmm.cmx asmcomp/arch.cmx \ + asmcomp/proc.cmi 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/reload.cmo : asmcomp/reloadgen.cmi asmcomp/reg.cmi asmcomp/mach.cmi \ - asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo asmcomp/reload.cmi + asmcomp/cmm.cmi utils/clflags.cmi asmcomp/reload.cmi asmcomp/reload.cmx : asmcomp/reloadgen.cmx asmcomp/reg.cmx asmcomp/mach.cmx \ - asmcomp/cmm.cmx utils/clflags.cmx asmcomp/arch.cmx asmcomp/reload.cmi + asmcomp/cmm.cmx utils/clflags.cmx asmcomp/reload.cmi asmcomp/reloadgen.cmo : asmcomp/reg.cmi utils/misc.cmi asmcomp/mach.cmi \ asmcomp/reloadgen.cmi asmcomp/reloadgen.cmx : asmcomp/reg.cmx utils/misc.cmx asmcomp/mach.cmx \ @@ -846,11 +1089,11 @@ asmcomp/scheduling.cmo : asmcomp/schedgen.cmi asmcomp/scheduling.cmi asmcomp/scheduling.cmx : asmcomp/schedgen.cmx asmcomp/scheduling.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 asmcomp/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.cmi \ + typing/ident.cmi bytecomp/debuginfo.cmi asmcomp/cmm.cmi utils/clflags.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 asmcomp/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \ + typing/ident.cmx bytecomp/debuginfo.cmx asmcomp/cmm.cmx utils/clflags.cmx \ asmcomp/arch.cmx asmcomp/selectgen.cmi asmcomp/selection.cmo : asmcomp/selectgen.cmi asmcomp/proc.cmi \ asmcomp/mach.cmi asmcomp/cmm.cmi utils/clflags.cmi asmcomp/arch.cmo \ @@ -870,13 +1113,828 @@ asmcomp/strmatch.cmo : bytecomp/lambda.cmi typing/ident.cmi asmcomp/cmm.cmi \ asmcomp/arch.cmo asmcomp/strmatch.cmi asmcomp/strmatch.cmx : bytecomp/lambda.cmx typing/ident.cmx asmcomp/cmm.cmx \ asmcomp/arch.cmx asmcomp/strmatch.cmi +asmcomp/un_anf.cmo : middle_end/semantics_of_primitives.cmi \ + asmcomp/printclambda.cmi utils/misc.cmi bytecomp/lambda.cmi \ + typing/ident.cmi bytecomp/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/printclambda.cmx utils/misc.cmx bytecomp/lambda.cmx \ + typing/ident.cmx bytecomp/debuginfo.cmx utils/clflags.cmx \ + asmcomp/clambda.cmx parsing/asttypes.cmi asmcomp/un_anf.cmi +asmcomp/x86_dsl.cmo : asmcomp/x86_proc.cmi asmcomp/x86_ast.cmi \ + asmcomp/x86_dsl.cmi +asmcomp/x86_dsl.cmx : asmcomp/x86_proc.cmx asmcomp/x86_ast.cmi \ + asmcomp/x86_dsl.cmi +asmcomp/x86_gas.cmo : asmcomp/x86_proc.cmi asmcomp/x86_ast.cmi \ + utils/misc.cmi asmcomp/x86_gas.cmi +asmcomp/x86_gas.cmx : asmcomp/x86_proc.cmx asmcomp/x86_ast.cmi \ + utils/misc.cmx asmcomp/x86_gas.cmi +asmcomp/x86_masm.cmo : asmcomp/x86_proc.cmi asmcomp/x86_ast.cmi \ + asmcomp/x86_masm.cmi +asmcomp/x86_masm.cmx : asmcomp/x86_proc.cmx asmcomp/x86_ast.cmi \ + asmcomp/x86_masm.cmi +asmcomp/x86_proc.cmo : asmcomp/x86_ast.cmi utils/config.cmi \ + utils/clflags.cmi utils/ccomp.cmi asmcomp/x86_proc.cmi +asmcomp/x86_proc.cmx : asmcomp/x86_ast.cmi utils/config.cmx \ + utils/clflags.cmx utils/ccomp.cmx asmcomp/x86_proc.cmi +middle_end/alias_analysis.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + bytecomp/lambda.cmi middle_end/flambda.cmi parsing/asttypes.cmi \ + middle_end/allocated_const.cmi +middle_end/allocated_const.cmi : +middle_end/augment_specialised_args.cmi : middle_end/base_types/variable.cmi \ + middle_end/projection.cmi middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi +middle_end/backend_intf.cmi : middle_end/base_types/symbol.cmi \ + middle_end/simple_value_approx.cmi typing/ident.cmi \ + middle_end/base_types/closure_id.cmi +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.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/base_types/static_exception.cmi \ + middle_end/base_types/mutable_variable.cmi bytecomp/lambda.cmi \ + typing/ident.cmi +middle_end/effect_analysis.cmi : middle_end/flambda.cmi +middle_end/extract_projections.cmi : middle_end/base_types/variable.cmi \ + middle_end/projection.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi +middle_end/find_recursive_functions.cmi : middle_end/base_types/variable.cmi \ + middle_end/flambda.cmi middle_end/backend_intf.cmi +middle_end/flambda.cmi : 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 \ + middle_end/base_types/set_of_closures_origin.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ + utils/numbers.cmi middle_end/base_types/mutable_variable.cmi \ + bytecomp/lambda.cmi utils/identifiable.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi parsing/asttypes.cmi \ + middle_end/allocated_const.cmi +middle_end/flambda_invariants.cmi : middle_end/flambda.cmi +middle_end/flambda_iterators.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi middle_end/flambda.cmi +middle_end/flambda_utils.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/switch.cmi middle_end/base_types/static_exception.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ + middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ + middle_end/backend_intf.cmi +middle_end/freshening.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/base_types/static_exception.cmi \ + middle_end/base_types/mutable_variable.cmi middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/inconstant_idents.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi middle_end/backend_intf.cmi +middle_end/initialize_symbol_to_let_symbol.cmi : middle_end/flambda.cmi +middle_end/inline_and_simplify.cmi : middle_end/base_types/variable.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/inline_and_simplify_aux.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/base_types/static_exception.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_origin.cmi \ + middle_end/projection.cmi middle_end/base_types/mutable_variable.cmi \ + middle_end/inlining_stats_types.cmi middle_end/inlining_cost.cmi \ + middle_end/freshening.cmi middle_end/flambda.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi +middle_end/inlining_cost.cmi : middle_end/projection.cmi \ + middle_end/flambda.cmi +middle_end/inlining_decision.cmi : middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ + middle_end/inlining_decision_intf.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ + bytecomp/debuginfo.cmi middle_end/base_types/closure_id.cmi +middle_end/inlining_decision_intf.cmi : middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/inlining_stats.cmi : middle_end/inlining_stats_types.cmi \ + bytecomp/debuginfo.cmi middle_end/base_types/closure_id.cmi +middle_end/inlining_stats_types.cmi : middle_end/inlining_cost.cmi +middle_end/inlining_transforms.cmi : middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ + middle_end/inlining_decision_intf.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ + bytecomp/debuginfo.cmi middle_end/base_types/closure_id.cmi +middle_end/invariant_params.cmi : middle_end/base_types/variable.cmi \ + middle_end/flambda.cmi middle_end/backend_intf.cmi +middle_end/lift_code.cmi : middle_end/base_types/variable.cmi \ + middle_end/flambda.cmi +middle_end/lift_constants.cmi : middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/lift_let_to_initialize_symbol.cmi : middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/middle_end.cmi : utils/timings.cmi bytecomp/lambda.cmi \ + typing/ident.cmi middle_end/flambda.cmi middle_end/backend_intf.cmi +middle_end/pass_wrapper.cmi : +middle_end/projection.cmi : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi utils/identifiable.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/ref_to_variables.cmi : middle_end/flambda.cmi +middle_end/remove_free_vars_equal_to_args.cmi : middle_end/flambda.cmi +middle_end/remove_unused_arguments.cmi : middle_end/flambda.cmi \ + middle_end/backend_intf.cmi +middle_end/remove_unused_closure_vars.cmi : middle_end/flambda.cmi +middle_end/remove_unused_program_constructs.cmi : middle_end/flambda.cmi +middle_end/semantics_of_primitives.cmi : bytecomp/lambda.cmi +middle_end/share_constants.cmi : middle_end/flambda.cmi +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 \ + 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.cmi : \ + middle_end/simplify_boxed_integer_ops_intf.cmi +middle_end/simplify_boxed_integer_ops_intf.cmi : \ + middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi middle_end/flambda.cmi +middle_end/simplify_common.cmi : middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi middle_end/inlining_cost.cmi middle_end/flambda.cmi +middle_end/simplify_primitives.cmi : middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi middle_end/flambda.cmi \ + bytecomp/debuginfo.cmi +middle_end/unbox_closures.cmi : middle_end/base_types/variable.cmi \ + middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi +middle_end/unbox_free_vars_of_closures.cmi : middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi +middle_end/unbox_specialised_args.cmi : middle_end/base_types/variable.cmi \ + middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda.cmi +middle_end/alias_analysis.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/flambda.cmi \ + parsing/asttypes.cmi middle_end/allocated_const.cmi \ + middle_end/alias_analysis.cmi +middle_end/alias_analysis.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/flambda.cmx \ + parsing/asttypes.cmi middle_end/allocated_const.cmx \ + middle_end/alias_analysis.cmi +middle_end/allocated_const.cmo : middle_end/allocated_const.cmi +middle_end/allocated_const.cmx : middle_end/allocated_const.cmi +middle_end/augment_specialised_args.cmo : middle_end/base_types/variable.cmi \ + middle_end/simple_value_approx.cmi middle_end/projection.cmi \ + middle_end/pass_wrapper.cmi utils/misc.cmi middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi utils/identifiable.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + bytecomp/debuginfo.cmi middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi middle_end/backend_intf.cmi \ + middle_end/augment_specialised_args.cmi +middle_end/augment_specialised_args.cmx : middle_end/base_types/variable.cmx \ + middle_end/simple_value_approx.cmx middle_end/projection.cmx \ + middle_end/pass_wrapper.cmx utils/misc.cmx middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx utils/identifiable.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + bytecomp/debuginfo.cmx middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx middle_end/backend_intf.cmi \ + middle_end/augment_specialised_args.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 bytecomp/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/closure_conversion_aux.cmi utils/clflags.cmi \ + middle_end/backend_intf.cmi parsing/asttypes.cmi \ + middle_end/closure_conversion.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 bytecomp/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/closure_conversion_aux.cmx utils/clflags.cmx \ + middle_end/backend_intf.cmi parsing/asttypes.cmi \ + middle_end/closure_conversion.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 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 bytecomp/lambda.cmx typing/ident.cmx \ + middle_end/closure_conversion_aux.cmi +middle_end/effect_analysis.cmo : middle_end/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 \ + utils/misc.cmx bytecomp/lambda.cmx middle_end/flambda.cmx \ + middle_end/effect_analysis.cmi +middle_end/extract_projections.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/simple_value_approx.cmi middle_end/projection.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/freshening.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi middle_end/extract_projections.cmi +middle_end/extract_projections.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/simple_value_approx.cmx middle_end/projection.cmx \ + middle_end/inline_and_simplify_aux.cmx middle_end/freshening.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx middle_end/extract_projections.cmi +middle_end/find_recursive_functions.cmo : middle_end/base_types/variable.cmi \ + utils/strongly_connected_components.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi middle_end/find_recursive_functions.cmi +middle_end/find_recursive_functions.cmx : middle_end/base_types/variable.cmx \ + utils/strongly_connected_components.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx middle_end/find_recursive_functions.cmi +middle_end/flambda.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 \ + middle_end/base_types/set_of_closures_origin.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ + bytecomp/printlambda.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + bytecomp/lambda.cmi utils/identifiable.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + parsing/asttypes.cmi middle_end/allocated_const.cmi \ + middle_end/flambda.cmi +middle_end/flambda.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 \ + middle_end/base_types/set_of_closures_origin.cmx \ + middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \ + bytecomp/printlambda.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + bytecomp/lambda.cmx utils/identifiable.cmx bytecomp/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + parsing/asttypes.cmi middle_end/allocated_const.cmx \ + middle_end/flambda.cmi +middle_end/flambda_invariants.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 \ + middle_end/base_types/static_exception.cmi \ + middle_end/base_types/set_of_closures_origin.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ + bytecomp/printlambda.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + bytecomp/lambda.cmi typing/ident.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi parsing/asttypes.cmi \ + middle_end/allocated_const.cmi middle_end/flambda_invariants.cmi +middle_end/flambda_invariants.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 \ + middle_end/base_types/static_exception.cmx \ + middle_end/base_types/set_of_closures_origin.cmx \ + middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \ + bytecomp/printlambda.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + bytecomp/lambda.cmx typing/ident.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx bytecomp/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx parsing/asttypes.cmi \ + middle_end/allocated_const.cmx middle_end/flambda_invariants.cmi +middle_end/flambda_iterators.cmo : middle_end/base_types/variable.cmi \ + utils/misc.cmi middle_end/flambda.cmi middle_end/flambda_iterators.cmi +middle_end/flambda_iterators.cmx : middle_end/base_types/variable.cmx \ + utils/misc.cmx middle_end/flambda.cmx middle_end/flambda_iterators.cmi +middle_end/flambda_utils.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/base_types/symbol.cmi bytecomp/switch.cmi \ + middle_end/base_types/static_exception.cmi \ + middle_end/base_types/set_of_closures_id.cmi middle_end/projection.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + middle_end/base_types/linkage_name.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmi middle_end/flambda_utils.cmi +middle_end/flambda_utils.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/base_types/symbol.cmx bytecomp/switch.cmx \ + middle_end/base_types/static_exception.cmx \ + middle_end/base_types/set_of_closures_id.cmx middle_end/projection.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + middle_end/base_types/linkage_name.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx bytecomp/debuginfo.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmx middle_end/flambda_utils.cmi +middle_end/freshening.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/static_exception.cmi middle_end/projection.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + utils/identifiable.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi middle_end/freshening.cmi +middle_end/freshening.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/static_exception.cmx middle_end/projection.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + utils/identifiable.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx middle_end/freshening.cmi +middle_end/inconstant_idents.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi \ + middle_end/base_types/set_of_closures_id.cmi utils/numbers.cmi \ + utils/misc.cmi bytecomp/lambda.cmi utils/identifiable.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \ + parsing/asttypes.cmi middle_end/inconstant_idents.cmi +middle_end/inconstant_idents.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/symbol.cmx \ + middle_end/base_types/set_of_closures_id.cmx utils/numbers.cmx \ + utils/misc.cmx bytecomp/lambda.cmx utils/identifiable.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \ + parsing/asttypes.cmi middle_end/inconstant_idents.cmi +middle_end/initialize_symbol_to_let_symbol.cmo : \ + middle_end/base_types/variable.cmi utils/misc.cmi middle_end/flambda.cmi \ + middle_end/initialize_symbol_to_let_symbol.cmi +middle_end/initialize_symbol_to_let_symbol.cmx : \ + middle_end/base_types/variable.cmx utils/misc.cmx middle_end/flambda.cmx \ + middle_end/initialize_symbol_to_let_symbol.cmi +middle_end/inline_and_simplify.cmo : utils/warnings.cmi \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/unbox_specialised_args.cmi \ + middle_end/unbox_free_vars_of_closures.cmi middle_end/unbox_closures.cmi \ + middle_end/base_types/tag.cmi middle_end/base_types/symbol.cmi \ + middle_end/base_types/static_exception.cmi \ + middle_end/simplify_primitives.cmi middle_end/simple_value_approx.cmi \ + middle_end/remove_unused_arguments.cmi \ + middle_end/remove_free_vars_equal_to_args.cmi middle_end/projection.cmi \ + typing/predef.cmi utils/misc.cmi parsing/location.cmi \ + middle_end/lift_code.cmi bytecomp/lambda.cmi \ + middle_end/invariant_params.cmi middle_end/inlining_stats.cmi \ + middle_end/inlining_decision.cmi middle_end/inlining_cost.cmi \ + middle_end/inline_and_simplify_aux.cmi typing/ident.cmi \ + middle_end/freshening.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi middle_end/effect_analysis.cmi \ + bytecomp/debuginfo.cmi middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmi middle_end/inline_and_simplify.cmi +middle_end/inline_and_simplify.cmx : utils/warnings.cmx \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/unbox_specialised_args.cmx \ + middle_end/unbox_free_vars_of_closures.cmx middle_end/unbox_closures.cmx \ + middle_end/base_types/tag.cmx middle_end/base_types/symbol.cmx \ + middle_end/base_types/static_exception.cmx \ + middle_end/simplify_primitives.cmx middle_end/simple_value_approx.cmx \ + middle_end/remove_unused_arguments.cmx \ + middle_end/remove_free_vars_equal_to_args.cmx middle_end/projection.cmx \ + typing/predef.cmx utils/misc.cmx parsing/location.cmx \ + middle_end/lift_code.cmx bytecomp/lambda.cmx \ + middle_end/invariant_params.cmx middle_end/inlining_stats.cmx \ + middle_end/inlining_decision.cmx middle_end/inlining_cost.cmx \ + middle_end/inline_and_simplify_aux.cmx typing/ident.cmx \ + middle_end/freshening.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx middle_end/effect_analysis.cmx \ + bytecomp/debuginfo.cmx middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx middle_end/backend_intf.cmi \ + middle_end/allocated_const.cmx middle_end/inline_and_simplify.cmi +middle_end/inline_and_simplify_aux.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/static_exception.cmi \ + middle_end/simple_value_approx.cmi \ + middle_end/base_types/set_of_closures_origin.cmi \ + middle_end/projection.cmi utils/numbers.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + middle_end/inlining_stats.cmi middle_end/inlining_cost.cmi \ + middle_end/freshening.cmi middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/backend_intf.cmi middle_end/inline_and_simplify_aux.cmi +middle_end/inline_and_simplify_aux.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/static_exception.cmx \ + middle_end/simple_value_approx.cmx \ + middle_end/base_types/set_of_closures_origin.cmx \ + middle_end/projection.cmx utils/numbers.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + middle_end/inlining_stats.cmx middle_end/inlining_cost.cmx \ + middle_end/freshening.cmx middle_end/flambda.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/backend_intf.cmi middle_end/inline_and_simplify_aux.cmi +middle_end/inlining_cost.cmo : middle_end/base_types/variable.cmi \ + middle_end/projection.cmi typing/primitive.cmi utils/misc.cmi \ + bytecomp/lambda.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi utils/clflags.cmi middle_end/inlining_cost.cmi +middle_end/inlining_cost.cmx : middle_end/base_types/variable.cmx \ + middle_end/projection.cmx typing/primitive.cmx utils/misc.cmx \ + bytecomp/lambda.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx utils/clflags.cmx middle_end/inlining_cost.cmi +middle_end/inlining_decision.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/simple_value_approx.cmi utils/misc.cmi bytecomp/lambda.cmi \ + middle_end/inlining_transforms.cmi middle_end/inlining_stats_types.cmi \ + middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + middle_end/find_recursive_functions.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/inlining_decision.cmi +middle_end/inlining_decision.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/simple_value_approx.cmx utils/misc.cmx bytecomp/lambda.cmx \ + middle_end/inlining_transforms.cmx middle_end/inlining_stats_types.cmx \ + middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + middle_end/find_recursive_functions.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/inlining_decision.cmi +middle_end/inlining_stats.cmo : utils/misc.cmi \ + middle_end/inlining_stats_types.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/inlining_stats.cmi +middle_end/inlining_stats.cmx : utils/misc.cmx \ + middle_end/inlining_stats_types.cmx bytecomp/debuginfo.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/inlining_stats.cmi +middle_end/inlining_stats_types.cmo : middle_end/inlining_cost.cmi \ + middle_end/inlining_stats_types.cmi +middle_end/inlining_stats_types.cmx : middle_end/inlining_cost.cmx \ + middle_end/inlining_stats_types.cmi +middle_end/inlining_transforms.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi \ + middle_end/simple_value_approx.cmi utils/misc.cmi bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi middle_end/inlining_transforms.cmi +middle_end/inlining_transforms.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx \ + middle_end/simple_value_approx.cmx utils/misc.cmx bytecomp/lambda.cmx \ + middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx middle_end/inlining_transforms.cmi +middle_end/invariant_params.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/symbol.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/backend_intf.cmi middle_end/invariant_params.cmi +middle_end/invariant_params.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/symbol.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/backend_intf.cmi middle_end/invariant_params.cmi +middle_end/lift_code.cmo : middle_end/base_types/variable.cmi \ + utils/strongly_connected_components.cmi \ + middle_end/simple_value_approx.cmi middle_end/inlining_cost.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/base_types/compilation_unit.cmi middle_end/lift_code.cmi +middle_end/lift_code.cmx : middle_end/base_types/variable.cmx \ + utils/strongly_connected_components.cmx \ + middle_end/simple_value_approx.cmx middle_end/inlining_cost.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + middle_end/base_types/compilation_unit.cmx middle_end/lift_code.cmi +middle_end/lift_constants.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/strongly_connected_components.cmi \ + middle_end/simple_value_approx.cmi utils/misc.cmi \ + middle_end/base_types/linkage_name.cmi middle_end/inconstant_idents.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi middle_end/backend_intf.cmi \ + parsing/asttypes.cmi middle_end/allocated_const.cmi \ + middle_end/alias_analysis.cmi middle_end/lift_constants.cmi +middle_end/lift_constants.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/strongly_connected_components.cmx \ + middle_end/simple_value_approx.cmx utils/misc.cmx \ + middle_end/base_types/linkage_name.cmx middle_end/inconstant_idents.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx middle_end/backend_intf.cmi \ + parsing/asttypes.cmi middle_end/allocated_const.cmx \ + middle_end/alias_analysis.cmx middle_end/lift_constants.cmi +middle_end/lift_let_to_initialize_symbol.cmo : \ + middle_end/base_types/variable.cmi middle_end/base_types/tag.cmi \ + middle_end/base_types/symbol.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda.cmi bytecomp/debuginfo.cmi parsing/asttypes.cmi \ + middle_end/lift_let_to_initialize_symbol.cmi +middle_end/lift_let_to_initialize_symbol.cmx : \ + middle_end/base_types/variable.cmx middle_end/base_types/tag.cmx \ + middle_end/base_types/symbol.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda.cmx bytecomp/debuginfo.cmx parsing/asttypes.cmi \ + middle_end/lift_let_to_initialize_symbol.cmi +middle_end/middle_end.cmo : utils/warnings.cmi \ + middle_end/base_types/variable.cmi utils/timings.cmi \ + middle_end/base_types/symbol.cmi middle_end/share_constants.cmi \ + middle_end/remove_unused_program_constructs.cmi \ + middle_end/remove_unused_closure_vars.cmi middle_end/ref_to_variables.cmi \ + utils/misc.cmi parsing/location.cmi \ + middle_end/lift_let_to_initialize_symbol.cmi \ + middle_end/lift_constants.cmi middle_end/lift_code.cmi \ + middle_end/inlining_cost.cmi middle_end/inline_and_simplify.cmi \ + middle_end/initialize_symbol_to_let_symbol.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda_invariants.cmi \ + middle_end/flambda.cmi bytecomp/debuginfo.cmi \ + middle_end/base_types/closure_id.cmi middle_end/closure_conversion.cmi \ + utils/clflags.cmi middle_end/backend_intf.cmi middle_end/middle_end.cmi +middle_end/middle_end.cmx : utils/warnings.cmx \ + middle_end/base_types/variable.cmx utils/timings.cmx \ + middle_end/base_types/symbol.cmx middle_end/share_constants.cmx \ + middle_end/remove_unused_program_constructs.cmx \ + middle_end/remove_unused_closure_vars.cmx middle_end/ref_to_variables.cmx \ + utils/misc.cmx parsing/location.cmx \ + middle_end/lift_let_to_initialize_symbol.cmx \ + middle_end/lift_constants.cmx middle_end/lift_code.cmx \ + middle_end/inlining_cost.cmx middle_end/inline_and_simplify.cmx \ + middle_end/initialize_symbol_to_let_symbol.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda_invariants.cmx \ + middle_end/flambda.cmx bytecomp/debuginfo.cmx \ + middle_end/base_types/closure_id.cmx middle_end/closure_conversion.cmx \ + utils/clflags.cmx middle_end/backend_intf.cmi middle_end/middle_end.cmi +middle_end/pass_wrapper.cmo : utils/clflags.cmi middle_end/pass_wrapper.cmi +middle_end/pass_wrapper.cmx : utils/clflags.cmx middle_end/pass_wrapper.cmi +middle_end/projection.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi utils/identifiable.cmi \ + middle_end/base_types/closure_id.cmi middle_end/projection.cmi +middle_end/projection.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx utils/identifiable.cmx \ + middle_end/base_types/closure_id.cmx middle_end/projection.cmi +middle_end/ref_to_variables.cmo : middle_end/base_types/variable.cmi \ + middle_end/base_types/mutable_variable.cmi utils/misc.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + parsing/asttypes.cmi middle_end/ref_to_variables.cmi +middle_end/ref_to_variables.cmx : middle_end/base_types/variable.cmx \ + middle_end/base_types/mutable_variable.cmx utils/misc.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + parsing/asttypes.cmi middle_end/ref_to_variables.cmi +middle_end/remove_free_vars_equal_to_args.cmo : \ + middle_end/base_types/variable.cmi middle_end/pass_wrapper.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda.cmi \ + middle_end/remove_free_vars_equal_to_args.cmi +middle_end/remove_free_vars_equal_to_args.cmx : \ + middle_end/base_types/variable.cmx middle_end/pass_wrapper.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda.cmx \ + middle_end/remove_free_vars_equal_to_args.cmi +middle_end/remove_unused_arguments.cmo : middle_end/base_types/variable.cmi \ + middle_end/projection.cmi middle_end/invariant_params.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi middle_end/find_recursive_functions.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/closure_id.cmi utils/clflags.cmi \ + middle_end/remove_unused_arguments.cmi +middle_end/remove_unused_arguments.cmx : middle_end/base_types/variable.cmx \ + middle_end/projection.cmx middle_end/invariant_params.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx middle_end/find_recursive_functions.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/closure_id.cmx utils/clflags.cmx \ + middle_end/remove_unused_arguments.cmi +middle_end/remove_unused_closure_vars.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/var_within_closure.cmi middle_end/flambda_utils.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/base_types/closure_id.cmi \ + middle_end/remove_unused_closure_vars.cmi +middle_end/remove_unused_closure_vars.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/var_within_closure.cmx middle_end/flambda_utils.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + middle_end/base_types/closure_id.cmx \ + middle_end/remove_unused_closure_vars.cmi +middle_end/remove_unused_program_constructs.cmo : \ + middle_end/base_types/symbol.cmi utils/misc.cmi middle_end/flambda.cmi \ + middle_end/effect_analysis.cmi \ + middle_end/remove_unused_program_constructs.cmi +middle_end/remove_unused_program_constructs.cmx : \ + middle_end/base_types/symbol.cmx utils/misc.cmx middle_end/flambda.cmx \ + middle_end/effect_analysis.cmx \ + middle_end/remove_unused_program_constructs.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/share_constants.cmo : middle_end/base_types/symbol.cmi \ + middle_end/flambda_iterators.cmi middle_end/flambda.cmi \ + middle_end/share_constants.cmi +middle_end/share_constants.cmx : middle_end/base_types/symbol.cmx \ + middle_end/flambda_iterators.cmx middle_end/flambda.cmx \ + middle_end/share_constants.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 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 middle_end/allocated_const.cmi \ + middle_end/simple_value_approx.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 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 middle_end/allocated_const.cmx \ + middle_end/simple_value_approx.cmi +middle_end/simplify_boxed_integer_ops.cmo : middle_end/simplify_common.cmi \ + middle_end/simplify_boxed_integer_ops_intf.cmi \ + middle_end/simple_value_approx.cmi bytecomp/lambda.cmi \ + middle_end/inlining_cost.cmi middle_end/simplify_boxed_integer_ops.cmi +middle_end/simplify_boxed_integer_ops.cmx : middle_end/simplify_common.cmx \ + middle_end/simplify_boxed_integer_ops_intf.cmi \ + middle_end/simple_value_approx.cmx bytecomp/lambda.cmx \ + middle_end/inlining_cost.cmx middle_end/simplify_boxed_integer_ops.cmi +middle_end/simplify_common.cmo : middle_end/simple_value_approx.cmi \ + bytecomp/lambda.cmi middle_end/inlining_cost.cmi \ + middle_end/effect_analysis.cmi middle_end/simplify_common.cmi +middle_end/simplify_common.cmx : middle_end/simple_value_approx.cmx \ + bytecomp/lambda.cmx middle_end/inlining_cost.cmx \ + middle_end/effect_analysis.cmx middle_end/simplify_common.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 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 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 +middle_end/unbox_closures.cmo : middle_end/base_types/variable.cmi \ + middle_end/inlining_cost.cmi middle_end/inline_and_simplify_aux.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi middle_end/base_types/closure_id.cmi \ + utils/clflags.cmi middle_end/augment_specialised_args.cmi \ + middle_end/unbox_closures.cmi +middle_end/unbox_closures.cmx : middle_end/base_types/variable.cmx \ + middle_end/inlining_cost.cmx middle_end/inline_and_simplify_aux.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx middle_end/base_types/closure_id.cmx \ + utils/clflags.cmx middle_end/augment_specialised_args.cmx \ + middle_end/unbox_closures.cmi +middle_end/unbox_free_vars_of_closures.cmo : \ + middle_end/base_types/variable.cmi middle_end/projection.cmi \ + middle_end/pass_wrapper.cmi utils/misc.cmi middle_end/inlining_cost.cmi \ + middle_end/flambda_utils.cmi middle_end/flambda_iterators.cmi \ + middle_end/flambda.cmi middle_end/extract_projections.cmi \ + utils/clflags.cmi middle_end/unbox_free_vars_of_closures.cmi +middle_end/unbox_free_vars_of_closures.cmx : \ + middle_end/base_types/variable.cmx middle_end/projection.cmx \ + middle_end/pass_wrapper.cmx utils/misc.cmx middle_end/inlining_cost.cmx \ + middle_end/flambda_utils.cmx middle_end/flambda_iterators.cmx \ + middle_end/flambda.cmx middle_end/extract_projections.cmx \ + utils/clflags.cmx middle_end/unbox_free_vars_of_closures.cmi +middle_end/unbox_specialised_args.cmo : middle_end/base_types/variable.cmi \ + middle_end/projection.cmi middle_end/invariant_params.cmi \ + middle_end/inline_and_simplify_aux.cmi middle_end/flambda.cmi \ + middle_end/extract_projections.cmi utils/clflags.cmi \ + middle_end/augment_specialised_args.cmi \ + middle_end/unbox_specialised_args.cmi +middle_end/unbox_specialised_args.cmx : middle_end/base_types/variable.cmx \ + middle_end/projection.cmx middle_end/invariant_params.cmx \ + middle_end/inline_and_simplify_aux.cmx middle_end/flambda.cmx \ + middle_end/extract_projections.cmx utils/clflags.cmx \ + middle_end/augment_specialised_args.cmx \ + middle_end/unbox_specialised_args.cmi +middle_end/base_types/closure_element.cmi : \ + middle_end/base_types/variable.cmi utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/base_types/closure_id.cmi : \ + middle_end/base_types/closure_element.cmi +middle_end/base_types/compilation_unit.cmi : \ + middle_end/base_types/linkage_name.cmi utils/identifiable.cmi \ + typing/ident.cmi +middle_end/base_types/export_id.cmi : utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/base_types/id_types.cmi : utils/identifiable.cmi +middle_end/base_types/linkage_name.cmi : utils/identifiable.cmi +middle_end/base_types/mutable_variable.cmi : utils/identifiable.cmi \ + typing/ident.cmi middle_end/base_types/compilation_unit.cmi +middle_end/base_types/set_of_closures_id.cmi : utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/base_types/set_of_closures_origin.cmi : \ + middle_end/base_types/set_of_closures_id.cmi utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/base_types/static_exception.cmi : utils/identifiable.cmi +middle_end/base_types/symbol.cmi : middle_end/base_types/linkage_name.cmi \ + utils/identifiable.cmi middle_end/base_types/compilation_unit.cmi +middle_end/base_types/tag.cmi : utils/identifiable.cmi +middle_end/base_types/var_within_closure.cmi : \ + middle_end/base_types/closure_element.cmi +middle_end/base_types/variable.cmi : utils/identifiable.cmi typing/ident.cmi \ + middle_end/base_types/compilation_unit.cmi +middle_end/base_types/closure_element.cmo : \ + middle_end/base_types/variable.cmi \ + middle_end/base_types/closure_element.cmi +middle_end/base_types/closure_element.cmx : \ + middle_end/base_types/variable.cmx \ + middle_end/base_types/closure_element.cmi +middle_end/base_types/closure_id.cmo : \ + middle_end/base_types/closure_element.cmi \ + middle_end/base_types/closure_id.cmi +middle_end/base_types/closure_id.cmx : \ + middle_end/base_types/closure_element.cmx \ + middle_end/base_types/closure_id.cmi +middle_end/base_types/compilation_unit.cmo : utils/misc.cmi \ + middle_end/base_types/linkage_name.cmi utils/identifiable.cmi \ + typing/ident.cmi middle_end/base_types/compilation_unit.cmi +middle_end/base_types/compilation_unit.cmx : utils/misc.cmx \ + middle_end/base_types/linkage_name.cmx utils/identifiable.cmx \ + typing/ident.cmx middle_end/base_types/compilation_unit.cmi +middle_end/base_types/export_id.cmo : utils/identifiable.cmi \ + middle_end/base_types/id_types.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/export_id.cmi +middle_end/base_types/export_id.cmx : utils/identifiable.cmx \ + middle_end/base_types/id_types.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/export_id.cmi +middle_end/base_types/id_types.cmo : utils/identifiable.cmi \ + middle_end/base_types/id_types.cmi +middle_end/base_types/id_types.cmx : utils/identifiable.cmx \ + middle_end/base_types/id_types.cmi +middle_end/base_types/linkage_name.cmo : utils/identifiable.cmi \ + middle_end/base_types/linkage_name.cmi +middle_end/base_types/linkage_name.cmx : utils/identifiable.cmx \ + middle_end/base_types/linkage_name.cmi +middle_end/base_types/mutable_variable.cmo : utils/identifiable.cmi \ + typing/ident.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/mutable_variable.cmi +middle_end/base_types/mutable_variable.cmx : utils/identifiable.cmx \ + typing/ident.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/mutable_variable.cmi +middle_end/base_types/set_of_closures_id.cmo : utils/identifiable.cmi \ + middle_end/base_types/id_types.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/set_of_closures_id.cmi +middle_end/base_types/set_of_closures_id.cmx : utils/identifiable.cmx \ + middle_end/base_types/id_types.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/set_of_closures_id.cmi +middle_end/base_types/set_of_closures_origin.cmo : \ + middle_end/base_types/set_of_closures_id.cmi \ + middle_end/base_types/set_of_closures_origin.cmi +middle_end/base_types/set_of_closures_origin.cmx : \ + middle_end/base_types/set_of_closures_id.cmx \ + middle_end/base_types/set_of_closures_origin.cmi +middle_end/base_types/static_exception.cmo : utils/numbers.cmi \ + bytecomp/lambda.cmi middle_end/base_types/static_exception.cmi +middle_end/base_types/static_exception.cmx : utils/numbers.cmx \ + bytecomp/lambda.cmx middle_end/base_types/static_exception.cmi +middle_end/base_types/symbol.cmo : utils/misc.cmi \ + middle_end/base_types/linkage_name.cmi utils/identifiable.cmi \ + middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/symbol.cmi +middle_end/base_types/symbol.cmx : utils/misc.cmx \ + middle_end/base_types/linkage_name.cmx utils/identifiable.cmx \ + middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/symbol.cmi +middle_end/base_types/tag.cmo : utils/numbers.cmi utils/misc.cmi \ + utils/identifiable.cmi middle_end/base_types/tag.cmi +middle_end/base_types/tag.cmx : utils/numbers.cmx utils/misc.cmx \ + utils/identifiable.cmx middle_end/base_types/tag.cmi +middle_end/base_types/var_within_closure.cmo : \ + middle_end/base_types/closure_element.cmi \ + middle_end/base_types/var_within_closure.cmi +middle_end/base_types/var_within_closure.cmx : \ + middle_end/base_types/closure_element.cmx \ + middle_end/base_types/var_within_closure.cmi +middle_end/base_types/variable.cmo : utils/misc.cmi utils/identifiable.cmi \ + typing/ident.cmi middle_end/base_types/compilation_unit.cmi \ + middle_end/base_types/variable.cmi +middle_end/base_types/variable.cmx : utils/misc.cmx utils/identifiable.cmx \ + typing/ident.cmx middle_end/base_types/compilation_unit.cmx \ + middle_end/base_types/variable.cmi driver/compenv.cmi : driver/compile.cmi : driver/compmisc.cmi : typing/env.cmi driver/errors.cmi : driver/main.cmi : driver/main_args.cmi : -driver/optcompile.cmi : +driver/optcompile.cmi : middle_end/backend_intf.cmi driver/opterrors.cmi : driver/optmain.cmi : driver/pparse.cmi : parsing/parsetree.cmi @@ -886,20 +1944,22 @@ driver/compenv.cmx : utils/warnings.cmx utils/misc.cmx parsing/location.cmx \ utils/config.cmx utils/clflags.cmx driver/compenv.cmi driver/compile.cmo : utils/warnings.cmi typing/typemod.cmi \ typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \ - typing/stypes.cmi bytecomp/simplif.cmi typing/printtyped.cmi \ - typing/printtyp.cmi bytecomp/printlambda.cmi bytecomp/printinstr.cmi \ - parsing/printast.cmi parsing/pprintast.cmi driver/pparse.cmi \ - utils/misc.cmi parsing/location.cmi typing/includemod.cmi typing/env.cmi \ - bytecomp/emitcode.cmi driver/compmisc.cmi driver/compenv.cmi \ - utils/clflags.cmi utils/ccomp.cmi bytecomp/bytegen.cmi driver/compile.cmi + utils/timings.cmi typing/stypes.cmi bytecomp/simplif.cmi \ + typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \ + bytecomp/printinstr.cmi parsing/printast.cmi parsing/pprintast.cmi \ + driver/pparse.cmi utils/misc.cmi parsing/location.cmi \ + typing/includemod.cmi typing/env.cmi bytecomp/emitcode.cmi \ + driver/compmisc.cmi driver/compenv.cmi utils/clflags.cmi utils/ccomp.cmi \ + bytecomp/bytegen.cmi parsing/builtin_attributes.cmi driver/compile.cmi driver/compile.cmx : utils/warnings.cmx typing/typemod.cmx \ typing/typedtree.cmx typing/typecore.cmx bytecomp/translmod.cmx \ - typing/stypes.cmx bytecomp/simplif.cmx typing/printtyped.cmx \ - typing/printtyp.cmx bytecomp/printlambda.cmx bytecomp/printinstr.cmx \ - parsing/printast.cmx parsing/pprintast.cmx driver/pparse.cmx \ - utils/misc.cmx parsing/location.cmx typing/includemod.cmx typing/env.cmx \ - bytecomp/emitcode.cmx driver/compmisc.cmx driver/compenv.cmx \ - utils/clflags.cmx utils/ccomp.cmx bytecomp/bytegen.cmx driver/compile.cmi + utils/timings.cmx typing/stypes.cmx bytecomp/simplif.cmx \ + typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \ + bytecomp/printinstr.cmx parsing/printast.cmx parsing/pprintast.cmx \ + driver/pparse.cmx utils/misc.cmx parsing/location.cmx \ + typing/includemod.cmx typing/env.cmx bytecomp/emitcode.cmx \ + driver/compmisc.cmx driver/compenv.cmx utils/clflags.cmx utils/ccomp.cmx \ + bytecomp/bytegen.cmx parsing/builtin_attributes.cmx driver/compile.cmi driver/compmisc.cmo : 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 \ @@ -910,54 +1970,62 @@ driver/compmisc.cmx : typing/typemod.cmx utils/misc.cmx \ parsing/asttypes.cmi driver/compmisc.cmi driver/errors.cmo : parsing/location.cmi driver/errors.cmi driver/errors.cmx : parsing/location.cmx driver/errors.cmi -driver/main.cmo : utils/warnings.cmi utils/misc.cmi driver/main_args.cmi \ - parsing/location.cmi utils/config.cmi driver/compmisc.cmi \ - driver/compile.cmi driver/compenv.cmi utils/clflags.cmi \ - bytecomp/bytepackager.cmi bytecomp/bytelink.cmi \ +driver/main.cmo : utils/warnings.cmi utils/timings.cmi utils/misc.cmi \ + driver/main_args.cmi parsing/location.cmi utils/config.cmi \ + driver/compmisc.cmi driver/compile.cmi driver/compenv.cmi \ + utils/clflags.cmi bytecomp/bytepackager.cmi bytecomp/bytelink.cmi \ bytecomp/bytelibrarian.cmi driver/main.cmi -driver/main.cmx : utils/warnings.cmx utils/misc.cmx driver/main_args.cmx \ - parsing/location.cmx utils/config.cmx driver/compmisc.cmx \ - driver/compile.cmx driver/compenv.cmx utils/clflags.cmx \ - bytecomp/bytepackager.cmx bytecomp/bytelink.cmx \ +driver/main.cmx : utils/warnings.cmx utils/timings.cmx utils/misc.cmx \ + driver/main_args.cmx parsing/location.cmx utils/config.cmx \ + driver/compmisc.cmx driver/compile.cmx driver/compenv.cmx \ + utils/clflags.cmx bytecomp/bytepackager.cmx bytecomp/bytelink.cmx \ bytecomp/bytelibrarian.cmx driver/main.cmi -driver/main_args.cmo : utils/warnings.cmi driver/main_args.cmi -driver/main_args.cmx : utils/warnings.cmx driver/main_args.cmi +driver/main_args.cmo : utils/warnings.cmi utils/clflags.cmi \ + driver/main_args.cmi +driver/main_args.cmx : utils/warnings.cmx utils/clflags.cmx \ + driver/main_args.cmi driver/optcompile.cmo : utils/warnings.cmi typing/typemod.cmi \ typing/typedtree.cmi typing/typecore.cmi bytecomp/translmod.cmi \ - typing/stypes.cmi bytecomp/simplif.cmi typing/printtyped.cmi \ - typing/printtyp.cmi bytecomp/printlambda.cmi parsing/printast.cmi \ - parsing/pprintast.cmi driver/pparse.cmi utils/misc.cmi \ + utils/timings.cmi typing/stypes.cmi bytecomp/simplif.cmi \ + typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \ + parsing/printast.cmi parsing/pprintast.cmi driver/pparse.cmi \ + utils/misc.cmi middle_end/middle_end.cmi bytecomp/lambda.cmi \ typing/includemod.cmi typing/env.cmi utils/config.cmi driver/compmisc.cmi \ asmcomp/compilenv.cmi driver/compenv.cmi utils/clflags.cmi \ - utils/ccomp.cmi asmcomp/asmgen.cmi driver/optcompile.cmi + utils/ccomp.cmi parsing/builtin_attributes.cmi asmcomp/asmgen.cmi \ + driver/optcompile.cmi driver/optcompile.cmx : utils/warnings.cmx typing/typemod.cmx \ typing/typedtree.cmx typing/typecore.cmx bytecomp/translmod.cmx \ - typing/stypes.cmx bytecomp/simplif.cmx typing/printtyped.cmx \ - typing/printtyp.cmx bytecomp/printlambda.cmx parsing/printast.cmx \ - parsing/pprintast.cmx driver/pparse.cmx utils/misc.cmx \ + utils/timings.cmx typing/stypes.cmx bytecomp/simplif.cmx \ + typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \ + parsing/printast.cmx parsing/pprintast.cmx driver/pparse.cmx \ + utils/misc.cmx middle_end/middle_end.cmx bytecomp/lambda.cmx \ typing/includemod.cmx typing/env.cmx utils/config.cmx driver/compmisc.cmx \ asmcomp/compilenv.cmx driver/compenv.cmx utils/clflags.cmx \ - utils/ccomp.cmx asmcomp/asmgen.cmx driver/optcompile.cmi + utils/ccomp.cmx parsing/builtin_attributes.cmx asmcomp/asmgen.cmx \ + driver/optcompile.cmi driver/opterrors.cmo : parsing/location.cmi driver/opterrors.cmi driver/opterrors.cmx : parsing/location.cmx driver/opterrors.cmi -driver/optmain.cmo : utils/warnings.cmi asmcomp/printmach.cmi \ - driver/optcompile.cmi utils/misc.cmi driver/main_args.cmi \ - parsing/location.cmi utils/config.cmi driver/compmisc.cmi \ - driver/compenv.cmi utils/clflags.cmi asmcomp/asmpackager.cmi \ - asmcomp/asmlink.cmi asmcomp/asmlibrarian.cmi asmcomp/arch.cmo \ - driver/optmain.cmi -driver/optmain.cmx : utils/warnings.cmx asmcomp/printmach.cmx \ - driver/optcompile.cmx utils/misc.cmx driver/main_args.cmx \ - parsing/location.cmx utils/config.cmx driver/compmisc.cmx \ - driver/compenv.cmx utils/clflags.cmx asmcomp/asmpackager.cmx \ - asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmx asmcomp/arch.cmx \ - driver/optmain.cmi -driver/pparse.cmo : parsing/parse.cmi utils/misc.cmi parsing/location.cmi \ - utils/config.cmi utils/clflags.cmi utils/ccomp.cmi parsing/ast_mapper.cmi \ - driver/pparse.cmi -driver/pparse.cmx : parsing/parse.cmx utils/misc.cmx parsing/location.cmx \ - utils/config.cmx utils/clflags.cmx utils/ccomp.cmx parsing/ast_mapper.cmx \ - driver/pparse.cmi +driver/optmain.cmo : utils/warnings.cmi utils/timings.cmi asmcomp/proc.cmi \ + asmcomp/printmach.cmi driver/optcompile.cmi utils/misc.cmi \ + driver/main_args.cmi parsing/location.cmi asmcomp/import_approx.cmi \ + utils/config.cmi driver/compmisc.cmi asmcomp/compilenv.cmi \ + driver/compenv.cmi utils/clflags.cmi middle_end/backend_intf.cmi \ + asmcomp/asmpackager.cmi asmcomp/asmlink.cmi asmcomp/asmlibrarian.cmi \ + asmcomp/arch.cmo driver/optmain.cmi +driver/optmain.cmx : utils/warnings.cmx utils/timings.cmx asmcomp/proc.cmx \ + asmcomp/printmach.cmx driver/optcompile.cmx utils/misc.cmx \ + driver/main_args.cmx parsing/location.cmx asmcomp/import_approx.cmx \ + utils/config.cmx driver/compmisc.cmx asmcomp/compilenv.cmx \ + driver/compenv.cmx utils/clflags.cmx middle_end/backend_intf.cmi \ + asmcomp/asmpackager.cmx asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmx \ + asmcomp/arch.cmx driver/optmain.cmi +driver/pparse.cmo : utils/timings.cmi parsing/parse.cmi utils/misc.cmi \ + parsing/location.cmi utils/config.cmi utils/clflags.cmi utils/ccomp.cmi \ + parsing/ast_mapper.cmi parsing/ast_invariants.cmi driver/pparse.cmi +driver/pparse.cmx : utils/timings.cmx parsing/parse.cmx utils/misc.cmx \ + parsing/location.cmx utils/config.cmx utils/clflags.cmx utils/ccomp.cmx \ + parsing/ast_mapper.cmx parsing/ast_invariants.cmx driver/pparse.cmi toplevel/genprintval.cmi : typing/types.cmi typing/path.cmi \ typing/outcometree.cmi typing/env.cmi toplevel/opttopdirs.cmi : parsing/longident.cmi @@ -998,28 +2066,34 @@ toplevel/opttopdirs.cmx : utils/warnings.cmx typing/types.cmx \ toplevel/opttopdirs.cmi toplevel/opttoploop.cmo : utils/warnings.cmi typing/types.cmi \ typing/typemod.cmi typing/typedtree.cmi typing/typecore.cmi \ - bytecomp/translmod.cmi bytecomp/simplif.cmi typing/printtyped.cmi \ - typing/printtyp.cmi bytecomp/printlambda.cmi parsing/printast.cmi \ - typing/predef.cmi parsing/pprintast.cmi typing/path.cmi \ + bytecomp/translmod.cmi utils/timings.cmi bytecomp/simplif.cmi \ + asmcomp/proc.cmi typing/printtyped.cmi typing/printtyp.cmi \ + bytecomp/printlambda.cmi parsing/printast.cmi typing/predef.cmi \ + parsing/pprintast.cmi driver/pparse.cmi typing/path.cmi \ parsing/parsetree.cmi parsing/parse.cmi typing/outcometree.cmi \ - typing/oprint.cmi utils/misc.cmi parsing/longident.cmi \ - parsing/location.cmi parsing/lexer.cmi typing/ident.cmi \ - toplevel/genprintval.cmi typing/env.cmi utils/config.cmi \ + typing/oprint.cmi utils/misc.cmi middle_end/middle_end.cmi \ + parsing/longident.cmi parsing/location.cmi parsing/lexer.cmi \ + bytecomp/lambda.cmi typing/includemod.cmi asmcomp/import_approx.cmi \ + typing/ident.cmi toplevel/genprintval.cmi typing/env.cmi utils/config.cmi \ driver/compmisc.cmi asmcomp/compilenv.cmi utils/clflags.cmi \ - typing/btype.cmi asmcomp/asmlink.cmi asmcomp/asmgen.cmi \ - toplevel/opttoploop.cmi + typing/btype.cmi middle_end/backend_intf.cmi parsing/asttypes.cmi \ + parsing/ast_helper.cmi asmcomp/asmlink.cmi asmcomp/asmgen.cmi \ + asmcomp/arch.cmo toplevel/opttoploop.cmi toplevel/opttoploop.cmx : utils/warnings.cmx typing/types.cmx \ typing/typemod.cmx typing/typedtree.cmx typing/typecore.cmx \ - bytecomp/translmod.cmx bytecomp/simplif.cmx typing/printtyped.cmx \ - typing/printtyp.cmx bytecomp/printlambda.cmx parsing/printast.cmx \ - typing/predef.cmx parsing/pprintast.cmx typing/path.cmx \ + bytecomp/translmod.cmx utils/timings.cmx bytecomp/simplif.cmx \ + asmcomp/proc.cmx typing/printtyped.cmx typing/printtyp.cmx \ + bytecomp/printlambda.cmx parsing/printast.cmx typing/predef.cmx \ + parsing/pprintast.cmx driver/pparse.cmx typing/path.cmx \ parsing/parsetree.cmi parsing/parse.cmx typing/outcometree.cmi \ - typing/oprint.cmx utils/misc.cmx parsing/longident.cmx \ - parsing/location.cmx parsing/lexer.cmx typing/ident.cmx \ - toplevel/genprintval.cmx typing/env.cmx utils/config.cmx \ + typing/oprint.cmx utils/misc.cmx middle_end/middle_end.cmx \ + parsing/longident.cmx parsing/location.cmx parsing/lexer.cmx \ + bytecomp/lambda.cmx typing/includemod.cmx asmcomp/import_approx.cmx \ + typing/ident.cmx toplevel/genprintval.cmx typing/env.cmx utils/config.cmx \ driver/compmisc.cmx asmcomp/compilenv.cmx utils/clflags.cmx \ - typing/btype.cmx asmcomp/asmlink.cmx asmcomp/asmgen.cmx \ - toplevel/opttoploop.cmi + typing/btype.cmx middle_end/backend_intf.cmi parsing/asttypes.cmi \ + parsing/ast_helper.cmx asmcomp/asmlink.cmx asmcomp/asmgen.cmx \ + asmcomp/arch.cmx toplevel/opttoploop.cmi toplevel/opttopmain.cmo : utils/warnings.cmi asmcomp/printmach.cmi \ toplevel/opttoploop.cmi toplevel/opttopdirs.cmi utils/misc.cmi \ driver/main_args.cmi parsing/location.cmi utils/config.cmi \ @@ -1033,47 +2107,49 @@ toplevel/opttopstart.cmx : toplevel/opttopmain.cmx toplevel/topdirs.cmo : utils/warnings.cmi typing/typetexp.cmi \ typing/types.cmi toplevel/trace.cmi toplevel/toploop.cmi \ bytecomp/symtable.cmi typing/printtyp.cmi typing/predef.cmi \ - typing/path.cmi bytecomp/opcodes.cmo utils/misc.cmi bytecomp/meta.cmi \ - parsing/longident.cmi parsing/location.cmi typing/ident.cmi \ - typing/env.cmi bytecomp/dll.cmi typing/ctype.cmi utils/consistbl.cmi \ - utils/config.cmi bytecomp/cmo_format.cmi utils/clflags.cmi \ - typing/btype.cmi parsing/asttypes.cmi toplevel/topdirs.cmi + typing/path.cmi parsing/parsetree.cmi bytecomp/opcodes.cmo utils/misc.cmi \ + bytecomp/meta.cmi parsing/longident.cmi parsing/location.cmi \ + typing/ident.cmi typing/env.cmi bytecomp/dll.cmi typing/ctype.cmi \ + utils/consistbl.cmi utils/config.cmi bytecomp/cmo_format.cmi \ + utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \ + toplevel/topdirs.cmi toplevel/topdirs.cmx : utils/warnings.cmx typing/typetexp.cmx \ typing/types.cmx toplevel/trace.cmx toplevel/toploop.cmx \ bytecomp/symtable.cmx typing/printtyp.cmx typing/predef.cmx \ - typing/path.cmx bytecomp/opcodes.cmx utils/misc.cmx bytecomp/meta.cmx \ - parsing/longident.cmx parsing/location.cmx typing/ident.cmx \ - typing/env.cmx bytecomp/dll.cmx typing/ctype.cmx utils/consistbl.cmx \ - utils/config.cmx bytecomp/cmo_format.cmi utils/clflags.cmx \ - typing/btype.cmx parsing/asttypes.cmi toplevel/topdirs.cmi -toplevel/toploop.cmo : utils/warnings.cmi typing/types.cmi \ - typing/typemod.cmi typing/typedtree.cmi typing/typecore.cmi \ - bytecomp/translmod.cmi bytecomp/symtable.cmi bytecomp/simplif.cmi \ - typing/printtyped.cmi typing/printtyp.cmi bytecomp/printlambda.cmi \ - bytecomp/printinstr.cmi parsing/printast.cmi typing/predef.cmi \ - parsing/pprintast.cmi driver/pparse.cmi typing/path.cmi \ + typing/path.cmx parsing/parsetree.cmi bytecomp/opcodes.cmx utils/misc.cmx \ + bytecomp/meta.cmx parsing/longident.cmx parsing/location.cmx \ + typing/ident.cmx typing/env.cmx bytecomp/dll.cmx typing/ctype.cmx \ + utils/consistbl.cmx utils/config.cmx bytecomp/cmo_format.cmi \ + utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \ + toplevel/topdirs.cmi +toplevel/toploop.cmo : utils/warnings.cmi typing/typetexp.cmi \ + typing/types.cmi typing/typemod.cmi typing/typedtree.cmi \ + typing/typecore.cmi bytecomp/translmod.cmi bytecomp/symtable.cmi \ + bytecomp/simplif.cmi typing/printtyped.cmi typing/printtyp.cmi \ + bytecomp/printlambda.cmi bytecomp/printinstr.cmi parsing/printast.cmi \ + typing/predef.cmi parsing/pprintast.cmi driver/pparse.cmi typing/path.cmi \ parsing/parsetree.cmi parsing/parse.cmi typing/outcometree.cmi \ typing/oprint.cmi utils/misc.cmi bytecomp/meta.cmi parsing/longident.cmi \ parsing/location.cmi parsing/lexer.cmi typing/includemod.cmi \ typing/ident.cmi toplevel/genprintval.cmi typing/env.cmi \ bytecomp/emitcode.cmi bytecomp/dll.cmi utils/consistbl.cmi \ utils/config.cmi driver/compmisc.cmi utils/clflags.cmi \ - bytecomp/bytegen.cmi typing/btype.cmi parsing/ast_helper.cmi \ - toplevel/toploop.cmi -toplevel/toploop.cmx : utils/warnings.cmx typing/types.cmx \ - typing/typemod.cmx typing/typedtree.cmx typing/typecore.cmx \ - bytecomp/translmod.cmx bytecomp/symtable.cmx bytecomp/simplif.cmx \ - typing/printtyped.cmx typing/printtyp.cmx bytecomp/printlambda.cmx \ - bytecomp/printinstr.cmx parsing/printast.cmx typing/predef.cmx \ - parsing/pprintast.cmx driver/pparse.cmx typing/path.cmx \ + bytecomp/bytegen.cmi typing/btype.cmi parsing/asttypes.cmi \ + parsing/ast_helper.cmi toplevel/toploop.cmi +toplevel/toploop.cmx : utils/warnings.cmx typing/typetexp.cmx \ + typing/types.cmx typing/typemod.cmx typing/typedtree.cmx \ + typing/typecore.cmx bytecomp/translmod.cmx bytecomp/symtable.cmx \ + bytecomp/simplif.cmx typing/printtyped.cmx typing/printtyp.cmx \ + bytecomp/printlambda.cmx bytecomp/printinstr.cmx parsing/printast.cmx \ + typing/predef.cmx parsing/pprintast.cmx driver/pparse.cmx typing/path.cmx \ parsing/parsetree.cmi parsing/parse.cmx typing/outcometree.cmi \ typing/oprint.cmx utils/misc.cmx bytecomp/meta.cmx parsing/longident.cmx \ parsing/location.cmx parsing/lexer.cmx typing/includemod.cmx \ typing/ident.cmx toplevel/genprintval.cmx typing/env.cmx \ bytecomp/emitcode.cmx bytecomp/dll.cmx utils/consistbl.cmx \ utils/config.cmx driver/compmisc.cmx utils/clflags.cmx \ - bytecomp/bytegen.cmx typing/btype.cmx parsing/ast_helper.cmx \ - toplevel/toploop.cmi + bytecomp/bytegen.cmx typing/btype.cmx parsing/asttypes.cmi \ + parsing/ast_helper.cmx toplevel/toploop.cmi toplevel/topmain.cmo : utils/warnings.cmi toplevel/toploop.cmi \ toplevel/topdirs.cmi utils/misc.cmi driver/main_args.cmi \ parsing/location.cmi utils/config.cmi driver/compenv.cmi \ @@ -1087,8 +2163,8 @@ toplevel/topstart.cmx : toplevel/topmain.cmx toplevel/trace.cmo : typing/types.cmi toplevel/toploop.cmi \ typing/printtyp.cmi typing/predef.cmi typing/path.cmi utils/misc.cmi \ bytecomp/meta.cmi parsing/longident.cmi typing/ctype.cmi \ - toplevel/trace.cmi + parsing/asttypes.cmi toplevel/trace.cmi toplevel/trace.cmx : typing/types.cmx toplevel/toploop.cmx \ typing/printtyp.cmx typing/predef.cmx typing/path.cmx utils/misc.cmx \ bytecomp/meta.cmx parsing/longident.cmx typing/ctype.cmx \ - toplevel/trace.cmi + parsing/asttypes.cmi toplevel/trace.cmi diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..d83330ee --- /dev/null +++ b/.gitattributes @@ -0,0 +1,127 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA * +#* * +#* Copyright 2015 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. * +#* * +#************************************************************************** + +# Default behaviour, for if core.autocrlf isn't set +* text=auto + +# Binary files +boot/ocamlc binary +boot/ocamllex binary +boot/ocamldep binary +*.gif binary +*.png binary +*.tfm binary + +# No header for text files (would be too obtrusive). +*.md ocaml-typo=missing-header +README* ocaml-typo=missing-header +*.adoc ocaml-typo=missing-header,long-line,unused-prop + +/.merlin ocaml-typo=missing-header +/Changes ocaml-typo=non-ascii,missing-header +/INSTALL ocaml-typo=missing-header +/LICENSE ocaml-typo=non-printing,missing-header +/appveyor.yml ocaml-typo=long-line,very-long-line + + +asmcomp/*/emit.mlp ocaml-typo=tab,long-line,unused-prop +asmcomp/power/NOTES.md ocaml-typo=missing-header,long-line + +asmrun/i386.S ocaml-typo=long-line + +config/gnu ocaml-typo=prune + +emacs/*.el ocaml-typo=long-line,unused-prop +emacs/COPYING ocaml-typo=tab,non-printing,missing-header +emacs/ocamltags.in ocaml-typo=non-printing + +experimental ocaml-typo=prune + +manual ocaml-typo=prune + +ocamlbuild/* ocaml-typo=long-line +ocamlbuild/AUTHORS ocaml-typo=missing-header +ocamlbuild/ChangeLog ocaml-typo=tab,missing-header +ocamlbuild/TODO ocaml-typo=missing-header + +ocamldoc/Changes.txt ocaml-typo=missing-header +ocamldoc/ocamldoc.sty ocaml-typo=missing-header + +otherlibs/win32unix/readlink.c ocaml-typo=long-line +otherlibs/win32unix/stat.c ocaml-typo=long-line +otherlibs/win32unix/symlink.c ocaml-typo=long-line + +stdlib/sharpbang ocaml-typo=white-at-eol,missing-lf + +# FIXME remove headers in testsuite/tests and remove unused-prop in next line: +testsuite/tests/** ocaml-typo=missing-header,unused-prop +testsuite/tests/lib-bigarray-2/bigarrf.f ocaml-typo=missing-header,tab +testsuite/tests/misc-unsafe/almabench.ml ocaml-typo=missing-header,long-line +testsuite/typing ocaml-typo=missing-header + +tools/magic ocaml-typo=missing-header + +yacc/*.[ch] ocaml-typo=long-line,very-long-line,unused-prop + +# Line-ending specifications, for Windows interoperability +*.sh text eol=lf +*.sh.in text eol=lf +*.awk text eol=lf + +# Test suite command fragments +*.checker text eol=lf +*.precheck text eol=lf +*.runner text eol=lf + +configure text eol=lf +config/auto-aux/hasgot text eol=lf +config/auto-aux/hasgot2 text eol=lf +config/auto-aux/runtest text eol=lf +config/auto-aux/searchpath text eol=lf +config/auto-aux/solaris-ld text eol=lf +config/auto-aux/tryassemble text eol=lf +config/auto-aux/trycompile text eol=lf +config/gnu/config.guess text eol=lf +config/gnu/config.sub text eol=lf +ocamldoc/remove_DEBUG text eol=lf +stdlib/Compflags text eol=lf +stdlib/sharpbang text eol=lf +tools/check-typo text eol=lf +tools/ci-build text eol=lf +tools/cleanup-header text eol=lf +tools/msvs-promote-path text eol=lf +tools/gdb-macros text eol=lf +tools/magic text eol=lf +tools/make-opcodes text eol=lf +tools/make-package-macosx text eol=lf +tools/ocaml-objcopy-macosx text eol=lf +tools/ocamlmktop.tpl text eol=lf +tools/ocamlsize text eol=lf + +# These two are cat scripts, so may not actually require this +config/auto-aux/sharpbang text eol=lf +config/auto-aux/sharpbang2 text eol=lf + +# Similarly, these are all Perl scripts, so may not actually require this +manual/tools/caml-tex text eol=lf +manual/tools/format-intf text eol=lf +manual/tools/htmlcut text eol=lf +manual/tools/htmltbl text eol=lf +manual/tools/htmlthread text eol=lf +manual/tools/texexpand text eol=lf + +# Checking out the parsetree test files with \r\n endings causes all the +# locations to change, so use \n endings only, even on Windows +testsuite/tests/parsing/*.ml text eol=lf diff --git a/.gitignore b/.gitignore index 87f7cda4..095b8acf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,56 +1,52 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA * +#* * +#* Copyright 2015 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. * +#* * +#************************************************************************** + +# general patterns + +*.o +*.a +*.so +*.obj +*.lib +*.dll +*.cm[ioxat] +*.cmx[as] +*.cmti +*.annot +*.exe +*.exe.manifest +.depend +.depend.nt +.DS_Store +*.out +*.out.dSYM +*.swp + +# local to root directory -# / -/*.o -/*.a -/*.so -/*.obj -/*.lib -/*.dll -/*.cm[ioxat] -/*.cmx[as] -/*.cmti -/*.annot -/*.result -/*.byte -/*.native -/program -/*.exe -/*.exe.manifest -/.depend -/.depend.nt -/.DS_Store -/configure /ocamlc /ocamlc.opt /expunge /ocaml /ocamlopt /ocamlopt.opt -/ocamlcomp.sh -/ocamlcompopt.sh /package-macosx /ocamlnat -# /asmcomp/ -/asmcomp/*.o -/asmcomp/*.a -/asmcomp/*.so -/asmcomp/*.obj -/asmcomp/*.lib -/asmcomp/*.dll -/asmcomp/*.cm[ioxat] -/asmcomp/*.cmx[as] -/asmcomp/*.cmti -/asmcomp/*.annot -/asmcomp/*.result -/asmcomp/*.byte -/asmcomp/*.native -/asmcomp/program -/asmcomp/*.exe -/asmcomp/*.exe.manifest -/asmcomp/.depend -/asmcomp/.depend.nt -/asmcomp/.DS_Store +# specific files and patterns in sub-directories + /asmcomp/emit.ml /asmcomp/arch.ml /asmcomp/proc.ml @@ -59,306 +55,85 @@ /asmcomp/scheduling.ml /asmcomp/CSE.ml -# /asmcomp/amd64/ -/asmcomp/amd64/*.o -/asmcomp/amd64/*.a -/asmcomp/amd64/*.so -/asmcomp/amd64/*.obj -/asmcomp/amd64/*.cm[ioxat] -/asmcomp/amd64/*.cmx[as] -/asmcomp/amd64/*.cmti -/asmcomp/amd64/*.annot -/asmcomp/amd64/*.result -/asmcomp/amd64/*.byte -/asmcomp/amd64/*.native -/asmcomp/amd64/program -/asmcomp/amd64/program.exe -/asmcomp/amd64/.depend -/asmcomp/amd64/.depend.nt -/asmcomp/amd64/.DS_Store - -# /asmrun/ -/asmrun/*.o -/asmrun/*.a -/asmrun/*.so -/asmrun/*.obj -/asmrun/*.lib -/asmrun/*.dll -/asmrun/*.cm[ioxat] -/asmrun/*.cmx[as] -/asmrun/*.cmti -/asmrun/*.annot -/asmrun/*.result -/asmrun/*.byte -/asmrun/*.native -/asmrun/program -/asmrun/*.exe -/asmrun/.depend -/asmrun/.depend.nt -/asmrun/.DS_Store /asmrun/*.p.c /asmrun/*.d.c -/asmrun/libasmrun.a -/asmrun/libasmrunp.a -/asmrun/main.c -/asmrun/misc.c -/asmrun/freelist.c -/asmrun/major_gc.c -/asmrun/minor_gc.c -/asmrun/memory.c /asmrun/alloc.c /asmrun/array.c +/asmrun/backtrace.c +/asmrun/callback.c +/asmrun/compact.c /asmrun/compare.c -/asmrun/ints.c -/asmrun/floats.c -/asmrun/str.c -/asmrun/io.c +/asmrun/custom.c +/asmrun/debugger.c +/asmrun/dynlink.c /asmrun/extern.c -/asmrun/intern.c -/asmrun/hash.c -/asmrun/sys.c -/asmrun/parsing.c +/asmrun/finalise.c +/asmrun/floats.c +/asmrun/freelist.c /asmrun/gc_ctrl.c -/asmrun/terminfo.c +/asmrun/globroots.c +/asmrun/hash.c +/asmrun/intern.c +/asmrun/ints.c +/asmrun/io.c +/asmrun/lexing.c +/asmrun/main.c +/asmrun/major_gc.c /asmrun/md5.c +/asmrun/memory.c +/asmrun/meta.c +/asmrun/minor_gc.c +/asmrun/misc.c /asmrun/obj.c -/asmrun/lexing.c +/asmrun/parsing.c /asmrun/printexc.c -/asmrun/callback.c -/asmrun/weak.c -/asmrun/compact.c -/asmrun/finalise.c -/asmrun/custom.c -/asmrun/meta.c -/asmrun/globroots.c -/asmrun/unix.c -/asmrun/dynlink.c /asmrun/signals.c -/asmrun/debugger.c -/asmrun/.depend.nt +/asmrun/startup_aux.c +/asmrun/str.c +/asmrun/sys.c +/asmrun/terminfo.c +/asmrun/unix.c +/asmrun/weak.c -# /boot/ -/boot/*.o -/boot/*.a -/boot/*.so -/boot/*.obj -/boot/*.lib -/boot/*.dll -/boot/*.cm[ioxat] -/boot/*.cmx[as] -/boot/*.cmti -/boot/*.annot -/boot/*.result -/boot/*.byte -/boot/*.native -/boot/program -/boot/*.exe -/boot/*.exe.manifest -/boot/.depend -/boot/.depend.nt -/boot/.DS_Store /boot/Saved /boot/ocamlrun -/boot/ocamlrun.exe /boot/ocamlyacc -/boot/ocamlyacc.exe /boot/camlheader -# /bytecomp/ -/bytecomp/*.o -/bytecomp/*.a -/bytecomp/*.so -/bytecomp/*.obj -/bytecomp/*.lib -/bytecomp/*.dll -/bytecomp/*.cm[ioxat] -/bytecomp/*.cmx[as] -/bytecomp/*.cmti -/bytecomp/*.annot -/bytecomp/*.result -/bytecomp/*.byte -/bytecomp/*.native -/bytecomp/program -/bytecomp/*.exe -/bytecomp/.depend -/bytecomp/.depend.nt -/bytecomp/.DS_Store /bytecomp/runtimedef.ml /bytecomp/opcodes.ml -# /byterun/ -/byterun/*.o -/byterun/*.a -/byterun/*.so -/byterun/*.obj -/byterun/*.cm[ioxa] -/byterun/*.cmx[as] -/byterun/*.annot -/byterun/*.result -/byterun/*.byte -/byterun/*.native -/byterun/program -/byterun/program.exe -/byterun/.depend -/byterun/.depend.nt -/byterun/.DS_Store /byterun/caml/jumptbl.h /byterun/primitives /byterun/prims.c /byterun/caml/opnames.h /byterun/caml/version.h /byterun/ocamlrun -/byterun/ocamlrun.exe /byterun/ocamlrund -/byterun/ocamlrund.exe /byterun/ld.conf /byterun/interp.a.lst /byterun/*.[sd]obj -/byterun/*.lib /byterun/.gdb_history /byterun/*.d.c /byterun/*.pic.c -# /compilerlibs/ -/compilerlibs/* - -# /config/ -/config/*.o -/config/*.a -/config/*.so -/config/*.obj -/config/*.lib -/config/*.dll -/config/*.cm[ioxat] -/config/*.cmx[as] -/config/*.cmti -/config/*.annot -/config/*.result -/config/*.byte -/config/*.native -/config/program -/config/*.exe -/config/*.exe.manifest -/config/.depend -/config/.depend.nt -/config/.DS_Store /config/m.h /config/s.h /config/Makefile -# /config/auto-aux/ -/config/auto-aux/*.o -/config/auto-aux/*.a -/config/auto-aux/*.so -/config/auto-aux/*.obj -/config/auto-aux/*.cm[ioxa] -/config/auto-aux/*.cmx[as] -/config/auto-aux/*.annot -/config/auto-aux/*.result -/config/auto-aux/*.byte -/config/auto-aux/*.native -/config/auto-aux/program -/config/auto-aux/.depend -/config/auto-aux/.depend.nt -/config/auto-aux/.DS_Store -/config/auto-aux/camlp4_config.ml - -# /config/gnu/ - -# /debugger/ -/debugger/*.o -/debugger/*.a -/debugger/*.so -/debugger/*.obj -/debugger/*.cm[ioxa] -/debugger/*.cmx[as] -/debugger/*.annot -/debugger/*.result -/debugger/*.byte -/debugger/*.native -/debugger/program -/debugger/program.exe -/debugger/.depend -/debugger/.depend.nt -/debugger/.DS_Store /debugger/lexer.ml /debugger/parser.ml /debugger/parser.mli /debugger/ocamldebug -/debugger/ocamldebug.exe /debugger/dynlink.ml /debugger/dynlink.mli -# /driver/ -/driver/*.o -/driver/*.a -/driver/*.so -/driver/*.obj -/driver/*.lib -/driver/*.dll -/driver/*.cm[ioxat] -/driver/*.cmx[as] -/driver/*.cmti -/driver/*.annot -/driver/*.result -/driver/*.byte -/driver/*.native -/driver/program -/driver/*.exe -/driver/*.exe.manifest -/driver/.depend -/driver/.depend.nt -/driver/.DS_Store - -# /emacs/ -/emacs/*.o -/emacs/*.a -/emacs/*.so -/emacs/*.obj -/emacs/*.lib -/emacs/*.dll -/emacs/*.cm[ioxat] -/emacs/*.cmx[as] -/emacs/*.cmti -/emacs/*.annot -/emacs/*.result -/emacs/*.byte -/emacs/*.native -/emacs/program -/emacs/*.exe -/emacs/*.exe.manifest -/emacs/.depend -/emacs/.depend.nt -/emacs/.DS_Store /emacs/ocamltags /emacs/*.elc -# /experimental/ - -# /experimental/garrigue/ /experimental/garrigue/*.out /experimental/garrigue/*.out2 -# /lex/ -/lex/*.o -/lex/*.a -/lex/*.so -/lex/*.obj -/lex/*.lib -/lex/*.dll -/lex/*.cm[ioxat] -/lex/*.cmx[as] -/lex/*.cmti -/lex/*.annot -/lex/*.result -/lex/*.byte -/lex/*.native -/lex/program -/lex/*.exe -/lex/*.exe.manifest -/lex/.depend -/lex/.depend.nt -/lex/.DS_Store /lex/parser.ml /lex/parser.mli /lex/lexer.ml @@ -366,42 +141,15 @@ /lex/ocamllex.opt /lex/parser.output -# /ocamlbuild/ -/ocamlbuild/*.o -/ocamlbuild/*.a -/ocamlbuild/*.so -/ocamlbuild/*.obj -/ocamlbuild/*.lib -/ocamlbuild/*.dll -/ocamlbuild/*.cm[ioxat] -/ocamlbuild/*.cmx[as] -/ocamlbuild/*.cmti -/ocamlbuild/*.annot -/ocamlbuild/*.byte -/ocamlbuild/*.native +/manual/manual/cmds/warnings-help.etex +/manual/manual/warnings-help.etex + /ocamlbuild/ocamlbuild_config.ml /ocamlbuild/lexers.ml /ocamlbuild/glob_lexer.ml +/ocamlbuild/ocamlbuild.native +/ocamlbuild/ocamlbuild.byte -# /ocamldoc/ -/ocamldoc/*.o -/ocamldoc/*.a -/ocamldoc/*.so -/ocamldoc/*.obj -/ocamldoc/*.lib -/ocamldoc/*.dll -/ocamldoc/*.cm[ioxat] -/ocamldoc/*.cmx[as] -/ocamldoc/*.cmti -/ocamldoc/*.annot -/ocamldoc/*.result -/ocamldoc/*.byte -/ocamldoc/*.native -/ocamldoc/program -/ocamldoc/*.exe -/ocamldoc/.depend -/ocamldoc/.depend.nt -/ocamldoc/.DS_Store /ocamldoc/ocamldoc /ocamldoc/ocamldoc.opt /ocamldoc/odoc_crc.ml @@ -420,262 +168,15 @@ /ocamldoc/test_latex /ocamldoc/test -# /ocamldoc/generators/ -/ocamldoc/generators/*.o -/ocamldoc/generators/*.a -/ocamldoc/generators/*.so -/ocamldoc/generators/*.obj -/ocamldoc/generators/*.lib -/ocamldoc/generators/*.dll -/ocamldoc/generators/*.cm[ioxat] -/ocamldoc/generators/*.cmx[as] -/ocamldoc/generators/*.cmti -/ocamldoc/generators/*.annot -/ocamldoc/generators/*.result -/ocamldoc/generators/*.byte -/ocamldoc/generators/*.native -/ocamldoc/generators/program -/ocamldoc/generators/*.exe -/ocamldoc/generators/*.exe.manifest -/ocamldoc/generators/.depend -/ocamldoc/generators/.depend.nt -/ocamldoc/generators/.DS_Store - -# /otherlibs/ -/otherlibs/.depend -/otherlibs/configure -/otherlibs/ocamlc -/otherlibs/ocamlc.opt -/otherlibs/expunge -/otherlibs/ocaml -/otherlibs/ocamlopt -/otherlibs/ocamlopt.opt -/otherlibs/ocamlcomp.sh -/otherlibs/ocamlcompopt.sh -/otherlibs/package-macosx -/otherlibs/.DS_Store -/otherlibs/*.annot -/otherlibs/_boot_log1 -/otherlibs/_boot_log2 -/otherlibs/_build -/otherlibs/_log -/otherlibs/myocamlbuild_config.ml -/otherlibs/ocamlnat -/otherlibs/*.cm* -/otherlibs/*.o - -# /otherlibs/bigarray/ -/otherlibs/bigarray/*.o -/otherlibs/bigarray/*.a -/otherlibs/bigarray/*.so -/otherlibs/bigarray/*.obj -/otherlibs/bigarray/*.lib -/otherlibs/bigarray/*.dll -/otherlibs/bigarray/*.cm[ioxat] -/otherlibs/bigarray/*.cmx[as] -/otherlibs/bigarray/*.cmti -/otherlibs/bigarray/*.annot -/otherlibs/bigarray/*.result -/otherlibs/bigarray/*.byte -/otherlibs/bigarray/*.native -/otherlibs/bigarray/program -/otherlibs/bigarray/*.exe -/otherlibs/bigarray/.depend -/otherlibs/bigarray/.depend.nt -/otherlibs/bigarray/.DS_Store - -# /otherlibs/dynlink/ -/otherlibs/dynlink/*.o -/otherlibs/dynlink/*.a -/otherlibs/dynlink/*.so -/otherlibs/dynlink/*.obj -/otherlibs/dynlink/*.lib -/otherlibs/dynlink/*.dll -/otherlibs/dynlink/*.cm[ioxat] -/otherlibs/dynlink/*.cmx[as] -/otherlibs/dynlink/*.cmti -/otherlibs/dynlink/*.annot -/otherlibs/dynlink/*.result -/otherlibs/dynlink/*.byte -/otherlibs/dynlink/*.native -/otherlibs/dynlink/program -/otherlibs/dynlink/*.exe -/otherlibs/dynlink/.depend -/otherlibs/dynlink/.depend.nt -/otherlibs/dynlink/.DS_Store /otherlibs/dynlink/extract_crc - -# /otherlibs/graph/ -/otherlibs/graph/*.o -/otherlibs/graph/*.a -/otherlibs/graph/*.so -/otherlibs/graph/*.obj -/otherlibs/graph/*.lib -/otherlibs/graph/*.dll -/otherlibs/graph/*.cm[ioxat] -/otherlibs/graph/*.cmx[as] -/otherlibs/graph/*.cmti -/otherlibs/graph/*.annot -/otherlibs/graph/*.result -/otherlibs/graph/*.byte -/otherlibs/graph/*.native -/otherlibs/graph/program -/otherlibs/graph/*.exe -/otherlibs/graph/*.exe.manifest -/otherlibs/graph/.depend -/otherlibs/graph/.depend.nt -/otherlibs/graph/.DS_Store - -# /otherlibs/num/ -/otherlibs/num/*.o -/otherlibs/num/*.a -/otherlibs/num/*.so -/otherlibs/num/*.obj -/otherlibs/num/*.lib -/otherlibs/num/*.dll -/otherlibs/num/*.cm[ioxat] -/otherlibs/num/*.cmx[as] -/otherlibs/num/*.cmti -/otherlibs/num/*.annot -/otherlibs/num/*.result -/otherlibs/num/*.byte -/otherlibs/num/*.native -/otherlibs/num/program -/otherlibs/num/*.exe -/otherlibs/num/.depend -/otherlibs/num/.depend.nt -/otherlibs/num/.DS_Store - -# /otherlibs/str/ -/otherlibs/str/*.o -/otherlibs/str/*.a -/otherlibs/str/*.so -/otherlibs/str/*.obj -/otherlibs/str/*.lib -/otherlibs/str/*.dll -/otherlibs/str/*.cm[ioxat] -/otherlibs/str/*.cmx[as] -/otherlibs/str/*.cmti -/otherlibs/str/*.annot -/otherlibs/str/*.result -/otherlibs/str/*.byte -/otherlibs/str/*.native -/otherlibs/str/program -/otherlibs/str/*.exe -/otherlibs/str/.depend -/otherlibs/str/.depend.nt -/otherlibs/str/.DS_Store - -# /otherlibs/systhreads/ -/otherlibs/systhreads/*.o -/otherlibs/systhreads/*.a -/otherlibs/systhreads/*.so -/otherlibs/systhreads/*.obj -/otherlibs/systhreads/*.lib -/otherlibs/systhreads/*.dll -/otherlibs/systhreads/*.cm[ioxat] -/otherlibs/systhreads/*.cmx[as] -/otherlibs/systhreads/*.cmti -/otherlibs/systhreads/*.annot -/otherlibs/systhreads/*.result -/otherlibs/systhreads/*.byte -/otherlibs/systhreads/*.native -/otherlibs/systhreads/program -/otherlibs/systhreads/*.exe -/otherlibs/systhreads/.depend -/otherlibs/systhreads/.depend.nt -/otherlibs/systhreads/.DS_Store /otherlibs/systhreads/thread.ml - -# /otherlibs/threads/ -/otherlibs/threads/*.o -/otherlibs/threads/*.a -/otherlibs/threads/*.so -/otherlibs/threads/*.obj -/otherlibs/threads/*.lib -/otherlibs/threads/*.dll -/otherlibs/threads/*.cm[ioxat] -/otherlibs/threads/*.cmx[as] -/otherlibs/threads/*.cmti -/otherlibs/threads/*.annot -/otherlibs/threads/*.result -/otherlibs/threads/*.byte -/otherlibs/threads/*.native -/otherlibs/threads/program -/otherlibs/threads/*.exe -/otherlibs/threads/*.exe.manifest -/otherlibs/threads/.depend -/otherlibs/threads/.depend.nt -/otherlibs/threads/.DS_Store /otherlibs/threads/marshal.mli /otherlibs/threads/pervasives.mli /otherlibs/threads/unix.mli - -# /otherlibs/unix/ -/otherlibs/unix/*.o -/otherlibs/unix/*.a -/otherlibs/unix/*.so -/otherlibs/unix/*.obj -/otherlibs/unix/*.lib -/otherlibs/unix/*.dll -/otherlibs/unix/*.cm[ioxat] -/otherlibs/unix/*.cmx[as] -/otherlibs/unix/*.cmti -/otherlibs/unix/*.annot -/otherlibs/unix/*.result -/otherlibs/unix/*.byte -/otherlibs/unix/*.native -/otherlibs/unix/program -/otherlibs/unix/*.exe -/otherlibs/unix/*.exe.manifest -/otherlibs/unix/.depend -/otherlibs/unix/.depend.nt -/otherlibs/unix/.DS_Store - -# /otherlibs/win32graph/ -/otherlibs/win32graph/*.o -/otherlibs/win32graph/*.a -/otherlibs/win32graph/*.so -/otherlibs/win32graph/*.obj -/otherlibs/win32graph/*.lib -/otherlibs/win32graph/*.dll -/otherlibs/win32graph/*.cm[ioxat] -/otherlibs/win32graph/*.cmx[as] -/otherlibs/win32graph/*.cmti -/otherlibs/win32graph/*.annot -/otherlibs/win32graph/*.result -/otherlibs/win32graph/*.byte -/otherlibs/win32graph/*.native -/otherlibs/win32graph/program -/otherlibs/win32graph/*.exe -/otherlibs/win32graph/.depend -/otherlibs/win32graph/.depend.nt -/otherlibs/win32graph/.DS_Store /otherlibs/win32graph/graphics.ml /otherlibs/win32graph/graphics.mli - -# /otherlibs/win32unix/ -/otherlibs/win32unix/*.o -/otherlibs/win32unix/*.a -/otherlibs/win32unix/*.so -/otherlibs/win32unix/*.obj -/otherlibs/win32unix/*.lib -/otherlibs/win32unix/*.dll -/otherlibs/win32unix/*.cm[ioxat] -/otherlibs/win32unix/*.cmx[as] -/otherlibs/win32unix/*.cmti -/otherlibs/win32unix/*.annot -/otherlibs/win32unix/*.result -/otherlibs/win32unix/*.byte -/otherlibs/win32unix/*.native -/otherlibs/win32unix/program -/otherlibs/win32unix/*.exe -/otherlibs/win32unix/.depend -/otherlibs/win32unix/.depend.nt -/otherlibs/win32unix/.DS_Store /otherlibs/win32unix/unixLabels.ml* /otherlibs/win32unix/unix.mli -/otherlibs/win32unix/unix.lib /otherlibs/win32unix/access.c /otherlibs/win32unix/addrofstr.c /otherlibs/win32unix/chdir.c @@ -703,26 +204,6 @@ /otherlibs/win32unix/unlink.c /otherlibs/win32unix/utimes.c -# /parsing/ -/parsing/*.o -/parsing/*.a -/parsing/*.so -/parsing/*.obj -/parsing/*.lib -/parsing/*.dll -/parsing/*.cm[ioxat] -/parsing/*.cmx[as] -/parsing/*.cmti -/parsing/*.annot -/parsing/*.result -/parsing/*.byte -/parsing/*.native -/parsing/program -/parsing/*.exe -/parsing/*.exe.manifest -/parsing/.depend -/parsing/.depend.nt -/parsing/.DS_Store /parsing/parser.ml /parsing/parser.mli /parsing/lexer.ml @@ -733,1945 +214,85 @@ /parsing/parser.automaton /parsing/parser.conflicts -# /stdlib/ -/stdlib/*.o -/stdlib/*.a -/stdlib/*.so -/stdlib/*.obj -/stdlib/*.lib -/stdlib/*.dll -/stdlib/*.cm[ioxat] -/stdlib/*.cmx[as] -/stdlib/*.cmti -/stdlib/*.annot -/stdlib/*.result -/stdlib/*.byte -/stdlib/*.native -/stdlib/program -/stdlib/*.exe -/stdlib/.depend -/stdlib/.depend.nt -/stdlib/.DS_Store /stdlib/camlheader -/stdlib/camlheaderd +/stdlib/target_camlheader +/stdlib/camlheader[di] +/stdlib/target_camlheader[di] /stdlib/camlheader_ur /stdlib/labelled-* /stdlib/caml /stdlib/sys.ml -# /testsuite/ -/testsuite/*.o -/testsuite/*.a -/testsuite/*.so -/testsuite/*.obj -/testsuite/*.cm[ioxa] -/testsuite/*.cmx[as] -/testsuite/*.annot -/testsuite/*.result -/testsuite/*.byte -/testsuite/*.native -/testsuite/program -/testsuite/.depend -/testsuite/.depend.nt -/testsuite/.DS_Store -/testsuite/_log - -# /testsuite/external/ -/testsuite/external/*.o -/testsuite/external/*.a -/testsuite/external/*.so -/testsuite/external/*.obj -/testsuite/external/*.lib -/testsuite/external/*.dll -/testsuite/external/*.cm[ioxat] -/testsuite/external/*.cmx[as] -/testsuite/external/*.cmti -/testsuite/external/*.annot -/testsuite/external/*.result -/testsuite/external/*.byte -/testsuite/external/*.native -/testsuite/external/program -/testsuite/external/*.exe -/testsuite/external/*.exe.manifest -/testsuite/external/.depend -/testsuite/external/.depend.nt -/testsuite/external/.DS_Store -/testsuite/external/*.tar.gz -/testsuite/external/*.tar.bz2 -/testsuite/external/*.tgz -/testsuite/external/*.tbz -/testsuite/external/*.zip -/testsuite/external/log-* -/testsuite/external/log_* -/testsuite/external/advi -/testsuite/external/advi-1.10.2 -/testsuite/external/altergo -/testsuite/external/alt-ergo-0.95.2 -/testsuite/external/binprot -/testsuite/external/bin_prot-109.30.00 -/testsuite/external/bitstring -/testsuite/external/ocaml-bitstring-2.0.3 -/testsuite/external/boomerang -/testsuite/external/boomerang-0.2 -/testsuite/external/calendar -/testsuite/external/calendar-2.03.2 -/testsuite/external/camlimages -/testsuite/external/camlimages-4.0.1 -/testsuite/external/camlpdf -/testsuite/external/camlpdf-0.5 -/testsuite/external/camlp4 -/testsuite/external/camlp4-trunk -/testsuite/external/camlp5 -/testsuite/external/camlp5-git -/testsuite/external/camlzip -/testsuite/external/camlzip-1.04 -/testsuite/external/camomile -/testsuite/external/camomile-0.8.4 -/testsuite/external/comparelib -/testsuite/external/comparelib-109.15.00 -/testsuite/external/compcert -/testsuite/external/compcert-1.13 -/testsuite/external/configfile -/testsuite/external/config-file-1.1 -/testsuite/external/coq -/testsuite/external/coq-8.4pl2 -/testsuite/external/core -/testsuite/external/core-109.37.00 -/testsuite/external/coreextended -/testsuite/external/core_extended-109.36.00 -/testsuite/external/corekernel -/testsuite/external/core_kernel-109.37.00 -/testsuite/external/cryptokit -/testsuite/external/cryptokit-1.6 -/testsuite/external/csv -/testsuite/external/csv-1.3.1 -/testsuite/external/customprintf -/testsuite/external/custom_printf-109.27.00 -/testsuite/external/dbm -/testsuite/external/camldbm-1.0 -/testsuite/external/expect -/testsuite/external/ocaml-expect-0.0.3 -/testsuite/external/extlib -/testsuite/external/extlib-1.5.2 -/testsuite/external/fieldslib -/testsuite/external/fieldslib-109.15.00 -/testsuite/external/fileutils -/testsuite/external/ocaml-fileutils-0.4.4 -/testsuite/external/findlib -/testsuite/external/findlib-1.4.1 -/testsuite/external/framac -/testsuite/external/frama-c-Oxygen-20120901 -/testsuite/external/geneweb -/testsuite/external/gw-6.05-src -/testsuite/external/herelib -/testsuite/external/herelib-109.35.00 -/testsuite/external/hevea -/testsuite/external/hevea-2.09 -/testsuite/external/kaputt -/testsuite/external/kaputt-1.2 -/testsuite/external/lablgtk -/testsuite/external/lablgtk-2.18.0 -/testsuite/external/lablgtkextras -/testsuite/external/lablgtkextras-1.3 -/testsuite/external/lwt -/testsuite/external/lwt-2.4.0 -/testsuite/external/menhir -/testsuite/external/menhir-20120123 -/testsuite/external/mldonkey -/testsuite/external/mldonkey-3.1.2 -/testsuite/external/mysql -/testsuite/external/ocaml-mysql-1.0.4 -/testsuite/external/oasis -/testsuite/external/oasis-0.3.0 -/testsuite/external/obrowser -/testsuite/external/obrowser-1.1.1 -/testsuite/external/ocamlgraph -/testsuite/external/ocamlgraph-1.8.2 -/testsuite/external/ocamlify -/testsuite/external/ocamlify-0.0.1 -/testsuite/external/ocamlmod -/testsuite/external/ocamlmod-0.0.3 -/testsuite/external/ocamlnet -/testsuite/external/ocamlnet-3.5.1 -/testsuite/external/ocamlscript -/testsuite/external/ocamlscript-2.0.3 -/testsuite/external/ocamlssl -/testsuite/external/ocaml-ssl-0.4.6 -/testsuite/external/ocamltext -/testsuite/external/ocaml-text-0.5 -/testsuite/external/ocgi -/testsuite/external/ocgi-0.5 -/testsuite/external/ocsigen -/testsuite/external/ocsigen-bundle-2.2.2 -/testsuite/external/odn -/testsuite/external/ocaml-data-notation-0.0.10 -/testsuite/external/omake -/testsuite/external/omake-0.9.8.6 -/testsuite/external/ounit -/testsuite/external/ounit-1.1.2 -/testsuite/external/paounit -/testsuite/external/pa_ounit-109.36.00 -/testsuite/external/pcre -/testsuite/external/pcre-ocaml-6.2.5 -/testsuite/external/pipebang -/testsuite/external/pipebang-109.28.00 -/testsuite/external/react -/testsuite/external/react-0.9.3 -/testsuite/external/res -/testsuite/external/res-3.2.0 -/testsuite/external/rss -/testsuite/external/ocamlrss-2.2.2 -/testsuite/external/sexplib -/testsuite/external/sexplib-109.15.00 -/testsuite/external/sks -/testsuite/external/sks-1.1.3 -/testsuite/external/sqlite -/testsuite/external/sqlite3-ocaml-2.0.1 -/testsuite/external/textutils -/testsuite/external/textutils-109.36.00 -/testsuite/external/typeconv -/testsuite/external/type_conv-109.28.00 -/testsuite/external/unison -/testsuite/external/unison-2.45.4 -/testsuite/external/variantslib -/testsuite/external/variantslib-109.15.00 -/testsuite/external/vsyml -/testsuite/external/vsyml-2010-04-06 -/testsuite/external/xmllight -/testsuite/external/xml-light.2.3 -/testsuite/external/xmlm -/testsuite/external/xmlm-1.1.0 -/testsuite/external/zarith -/testsuite/external/zarith-1.2.1 -/testsuite/external/zen -/testsuite/external/zen_2.3.2 -/testsuite/external/._ZEN_2.3.2 - -# /testsuite/interactive/ -/testsuite/interactive/# svn propset -R svn:ignore -F .svnignore . -/testsuite/interactive/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/interactive/_log -/testsuite/interactive/*.so -/testsuite/interactive/*.a -/testsuite/interactive/*.result -/testsuite/interactive/*.byte -/testsuite/interactive/*.native -/testsuite/interactive/program -/testsuite/interactive/*.cm* -/testsuite/interactive/*.o - -# /testsuite/interactive/lib-gc/ -/testsuite/interactive/lib-gc/# svn propset -R svn:ignore -F .svnignore . -/testsuite/interactive/lib-gc/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/interactive/lib-gc/_log -/testsuite/interactive/lib-gc/*.so -/testsuite/interactive/lib-gc/*.a -/testsuite/interactive/lib-gc/*.result -/testsuite/interactive/lib-gc/*.byte -/testsuite/interactive/lib-gc/*.native -/testsuite/interactive/lib-gc/program -/testsuite/interactive/lib-gc/*.cm* -/testsuite/interactive/lib-gc/*.o - -# /testsuite/interactive/lib-graph/ -/testsuite/interactive/lib-graph/# svn propset -R svn:ignore -F .svnignore . -/testsuite/interactive/lib-graph/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/interactive/lib-graph/_log -/testsuite/interactive/lib-graph/*.so -/testsuite/interactive/lib-graph/*.a -/testsuite/interactive/lib-graph/*.result -/testsuite/interactive/lib-graph/*.byte -/testsuite/interactive/lib-graph/*.native -/testsuite/interactive/lib-graph/program -/testsuite/interactive/lib-graph/*.cm* -/testsuite/interactive/lib-graph/*.o - -# /testsuite/interactive/lib-graph-2/ -/testsuite/interactive/lib-graph-2/# svn propset -R svn:ignore -F .svnignore . -/testsuite/interactive/lib-graph-2/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/interactive/lib-graph-2/_log -/testsuite/interactive/lib-graph-2/*.so -/testsuite/interactive/lib-graph-2/*.a -/testsuite/interactive/lib-graph-2/*.result -/testsuite/interactive/lib-graph-2/*.byte -/testsuite/interactive/lib-graph-2/*.native -/testsuite/interactive/lib-graph-2/program -/testsuite/interactive/lib-graph-2/*.cm* -/testsuite/interactive/lib-graph-2/*.o - -# /testsuite/interactive/lib-graph-3/ -/testsuite/interactive/lib-graph-3/# svn propset -R svn:ignore -F .svnignore . -/testsuite/interactive/lib-graph-3/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/interactive/lib-graph-3/_log -/testsuite/interactive/lib-graph-3/*.so -/testsuite/interactive/lib-graph-3/*.a -/testsuite/interactive/lib-graph-3/*.result -/testsuite/interactive/lib-graph-3/*.byte -/testsuite/interactive/lib-graph-3/*.native -/testsuite/interactive/lib-graph-3/program -/testsuite/interactive/lib-graph-3/*.cm* -/testsuite/interactive/lib-graph-3/*.o - -# /testsuite/interactive/lib-signals/ -/testsuite/interactive/lib-signals/# svn propset -R svn:ignore -F .svnignore . -/testsuite/interactive/lib-signals/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/interactive/lib-signals/_log -/testsuite/interactive/lib-signals/*.so -/testsuite/interactive/lib-signals/*.a -/testsuite/interactive/lib-signals/*.result -/testsuite/interactive/lib-signals/*.byte -/testsuite/interactive/lib-signals/*.native -/testsuite/interactive/lib-signals/program -/testsuite/interactive/lib-signals/*.cm* -/testsuite/interactive/lib-signals/*.o +/testsuite/**/*.result +/testsuite/**/*.opt_result +/testsuite/**/*.byte +/testsuite/**/*.native +/testsuite/**/program +/testsuite/**/_log -# /testsuite/lib/ -/testsuite/lib/*.o -/testsuite/lib/*.a -/testsuite/lib/*.so -/testsuite/lib/*.obj -/testsuite/lib/*.dll -/testsuite/lib/*.cm[ioxat] -/testsuite/lib/*.cmx[as] -/testsuite/lib/*.cmti -/testsuite/lib/*.annot -/testsuite/lib/*.result -/testsuite/lib/*.byte -/testsuite/lib/*.native -/testsuite/lib/program -/testsuite/lib/*.exe -/testsuite/lib/.depend -/testsuite/lib/.depend.nt -/testsuite/lib/.DS_Store +/testsuite/_retries -# /testsuite/makefiles/ -/testsuite/makefiles/# svn propset -R svn:ignore -F .svnignore . -/testsuite/makefiles/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/makefiles/_log -/testsuite/makefiles/*.so -/testsuite/makefiles/*.a -/testsuite/makefiles/*.result -/testsuite/makefiles/*.byte -/testsuite/makefiles/*.native -/testsuite/makefiles/program -/testsuite/makefiles/*.cm* -/testsuite/makefiles/*.o - -# /testsuite/tests/ -/testsuite/tests/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/_log -/testsuite/tests/*.so -/testsuite/tests/*.a -/testsuite/tests/*.result -/testsuite/tests/*.byte -/testsuite/tests/*.native -/testsuite/tests/program -/testsuite/tests/*.cm* -/testsuite/tests/*.o - -# /testsuite/tests/asmcomp/ -/testsuite/tests/asmcomp/*.o -/testsuite/tests/asmcomp/*.a -/testsuite/tests/asmcomp/*.so -/testsuite/tests/asmcomp/*.obj -/testsuite/tests/asmcomp/*.lib -/testsuite/tests/asmcomp/*.dll -/testsuite/tests/asmcomp/*.cm[ioxat] -/testsuite/tests/asmcomp/*.cmx[as] -/testsuite/tests/asmcomp/*.cmti -/testsuite/tests/asmcomp/*.annot -/testsuite/tests/asmcomp/*.result -/testsuite/tests/asmcomp/*.byte -/testsuite/tests/asmcomp/*.native -/testsuite/tests/asmcomp/program -/testsuite/tests/asmcomp/*.exe -/testsuite/tests/asmcomp/*.exe.manifest -/testsuite/tests/asmcomp/.depend -/testsuite/tests/asmcomp/.depend.nt -/testsuite/tests/asmcomp/.DS_Store /testsuite/tests/asmcomp/codegen /testsuite/tests/asmcomp/parsecmm.ml /testsuite/tests/asmcomp/parsecmm.mli /testsuite/tests/asmcomp/lexcmm.ml /testsuite/tests/asmcomp/*.s -/testsuite/tests/asmcomp/*.out -/testsuite/tests/asmcomp/*.out.dSYM - -# /testsuite/tests/backtrace/ -/testsuite/tests/backtrace/*.o -/testsuite/tests/backtrace/*.a -/testsuite/tests/backtrace/*.so -/testsuite/tests/backtrace/*.obj -/testsuite/tests/backtrace/*.lib -/testsuite/tests/backtrace/*.dll -/testsuite/tests/backtrace/*.cm[ioxat] -/testsuite/tests/backtrace/*.cmx[as] -/testsuite/tests/backtrace/*.cmti -/testsuite/tests/backtrace/*.annot -/testsuite/tests/backtrace/*.result -/testsuite/tests/backtrace/*.byte -/testsuite/tests/backtrace/*.native -/testsuite/tests/backtrace/program -/testsuite/tests/backtrace/*.exe -/testsuite/tests/backtrace/*.exe.manifest -/testsuite/tests/backtrace/.depend -/testsuite/tests/backtrace/.depend.nt -/testsuite/tests/backtrace/.DS_Store - -# /testsuite/tests/basic/ -/testsuite/tests/basic/*.o -/testsuite/tests/basic/*.a -/testsuite/tests/basic/*.so -/testsuite/tests/basic/*.obj -/testsuite/tests/basic/*.cm[ioxa] -/testsuite/tests/basic/*.cmx[as] -/testsuite/tests/basic/*.annot -/testsuite/tests/basic/*.result -/testsuite/tests/basic/*.byte -/testsuite/tests/basic/*.native -/testsuite/tests/basic/program -/testsuite/tests/basic/program.exe -/testsuite/tests/basic/.depend -/testsuite/tests/basic/.depend.nt -/testsuite/tests/basic/.DS_Store - -# /testsuite/tests/basic-float/ -/testsuite/tests/basic-float/*.o -/testsuite/tests/basic-float/*.a -/testsuite/tests/basic-float/*.so -/testsuite/tests/basic-float/*.obj -/testsuite/tests/basic-float/*.lib -/testsuite/tests/basic-float/*.dll -/testsuite/tests/basic-float/*.cm[ioxat] -/testsuite/tests/basic-float/*.cmx[as] -/testsuite/tests/basic-float/*.cmti -/testsuite/tests/basic-float/*.annot -/testsuite/tests/basic-float/*.result -/testsuite/tests/basic-float/*.byte -/testsuite/tests/basic-float/*.native -/testsuite/tests/basic-float/program -/testsuite/tests/basic-float/*.exe -/testsuite/tests/basic-float/*.exe.manifest -/testsuite/tests/basic-float/.depend -/testsuite/tests/basic-float/.depend.nt -/testsuite/tests/basic-float/.DS_Store - -# /testsuite/tests/basic-io/ -/testsuite/tests/basic-io/*.o -/testsuite/tests/basic-io/*.a -/testsuite/tests/basic-io/*.so -/testsuite/tests/basic-io/*.obj -/testsuite/tests/basic-io/*.lib -/testsuite/tests/basic-io/*.dll -/testsuite/tests/basic-io/*.cm[ioxat] -/testsuite/tests/basic-io/*.cmx[as] -/testsuite/tests/basic-io/*.cmti -/testsuite/tests/basic-io/*.annot -/testsuite/tests/basic-io/*.result -/testsuite/tests/basic-io/*.byte -/testsuite/tests/basic-io/*.native -/testsuite/tests/basic-io/program -/testsuite/tests/basic-io/*.exe -/testsuite/tests/basic-io/*.exe.manifest -/testsuite/tests/basic-io/.depend -/testsuite/tests/basic-io/.depend.nt -/testsuite/tests/basic-io/.DS_Store - -# /testsuite/tests/basic-io-2/ -/testsuite/tests/basic-io-2/*.o -/testsuite/tests/basic-io-2/*.a -/testsuite/tests/basic-io-2/*.so -/testsuite/tests/basic-io-2/*.obj -/testsuite/tests/basic-io-2/*.lib -/testsuite/tests/basic-io-2/*.dll -/testsuite/tests/basic-io-2/*.cm[ioxat] -/testsuite/tests/basic-io-2/*.cmx[as] -/testsuite/tests/basic-io-2/*.cmti -/testsuite/tests/basic-io-2/*.annot -/testsuite/tests/basic-io-2/*.result -/testsuite/tests/basic-io-2/*.byte -/testsuite/tests/basic-io-2/*.native -/testsuite/tests/basic-io-2/program -/testsuite/tests/basic-io-2/*.exe -/testsuite/tests/basic-io-2/*.exe.manifest -/testsuite/tests/basic-io-2/.depend -/testsuite/tests/basic-io-2/.depend.nt -/testsuite/tests/basic-io-2/.DS_Store - -# /testsuite/tests/basic-manyargs/ -/testsuite/tests/basic-manyargs/*.o -/testsuite/tests/basic-manyargs/*.a -/testsuite/tests/basic-manyargs/*.so -/testsuite/tests/basic-manyargs/*.obj -/testsuite/tests/basic-manyargs/*.lib -/testsuite/tests/basic-manyargs/*.dll -/testsuite/tests/basic-manyargs/*.cm[ioxat] -/testsuite/tests/basic-manyargs/*.cmx[as] -/testsuite/tests/basic-manyargs/*.cmti -/testsuite/tests/basic-manyargs/*.annot -/testsuite/tests/basic-manyargs/*.result -/testsuite/tests/basic-manyargs/*.byte -/testsuite/tests/basic-manyargs/*.native -/testsuite/tests/basic-manyargs/program -/testsuite/tests/basic-manyargs/*.exe -/testsuite/tests/basic-manyargs/*.exe.manifest -/testsuite/tests/basic-manyargs/.depend -/testsuite/tests/basic-manyargs/.depend.nt -/testsuite/tests/basic-manyargs/.DS_Store - -# /testsuite/tests/basic-modules/ -/testsuite/tests/basic-modules/*.o -/testsuite/tests/basic-modules/*.a -/testsuite/tests/basic-modules/*.so -/testsuite/tests/basic-modules/*.obj -/testsuite/tests/basic-modules/*.lib -/testsuite/tests/basic-modules/*.dll -/testsuite/tests/basic-modules/*.cm[ioxat] -/testsuite/tests/basic-modules/*.cmx[as] -/testsuite/tests/basic-modules/*.cmti -/testsuite/tests/basic-modules/*.annot -/testsuite/tests/basic-modules/*.result -/testsuite/tests/basic-modules/*.byte -/testsuite/tests/basic-modules/*.native -/testsuite/tests/basic-modules/program -/testsuite/tests/basic-modules/*.exe -/testsuite/tests/basic-modules/*.exe.manifest -/testsuite/tests/basic-modules/.depend -/testsuite/tests/basic-modules/.depend.nt -/testsuite/tests/basic-modules/.DS_Store - -# /testsuite/tests/basic-more/ -/testsuite/tests/basic-more/*.o -/testsuite/tests/basic-more/*.a -/testsuite/tests/basic-more/*.so -/testsuite/tests/basic-more/*.obj -/testsuite/tests/basic-more/*.cm[ioxa] -/testsuite/tests/basic-more/*.cmx[as] -/testsuite/tests/basic-more/*.annot -/testsuite/tests/basic-more/*.result -/testsuite/tests/basic-more/*.byte -/testsuite/tests/basic-more/*.native -/testsuite/tests/basic-more/program -/testsuite/tests/basic-more/program.exe -/testsuite/tests/basic-more/.depend -/testsuite/tests/basic-more/.depend.nt -/testsuite/tests/basic-more/.DS_Store +/testsuite/tests/asmcomp/*.out.manifest -# /testsuite/tests/basic-multdef/ -/testsuite/tests/basic-multdef/*.o -/testsuite/tests/basic-multdef/*.a -/testsuite/tests/basic-multdef/*.so -/testsuite/tests/basic-multdef/*.obj -/testsuite/tests/basic-multdef/*.lib -/testsuite/tests/basic-multdef/*.dll -/testsuite/tests/basic-multdef/*.cm[ioxat] -/testsuite/tests/basic-multdef/*.cmx[as] -/testsuite/tests/basic-multdef/*.cmti -/testsuite/tests/basic-multdef/*.annot -/testsuite/tests/basic-multdef/*.result -/testsuite/tests/basic-multdef/*.byte -/testsuite/tests/basic-multdef/*.native -/testsuite/tests/basic-multdef/program -/testsuite/tests/basic-multdef/*.exe -/testsuite/tests/basic-multdef/*.exe.manifest -/testsuite/tests/basic-multdef/.depend -/testsuite/tests/basic-multdef/.depend.nt -/testsuite/tests/basic-multdef/.DS_Store - -# /testsuite/tests/basic-private/ -/testsuite/tests/basic-private/*.o -/testsuite/tests/basic-private/*.a -/testsuite/tests/basic-private/*.so -/testsuite/tests/basic-private/*.obj -/testsuite/tests/basic-private/*.lib -/testsuite/tests/basic-private/*.dll -/testsuite/tests/basic-private/*.cm[ioxat] -/testsuite/tests/basic-private/*.cmx[as] -/testsuite/tests/basic-private/*.cmti -/testsuite/tests/basic-private/*.annot -/testsuite/tests/basic-private/*.result -/testsuite/tests/basic-private/*.byte -/testsuite/tests/basic-private/*.native -/testsuite/tests/basic-private/program -/testsuite/tests/basic-private/*.exe -/testsuite/tests/basic-private/*.exe.manifest -/testsuite/tests/basic-private/.depend -/testsuite/tests/basic-private/.depend.nt -/testsuite/tests/basic-private/.DS_Store - -# /testsuite/tests/callback/ -/testsuite/tests/callback/*.o -/testsuite/tests/callback/*.a -/testsuite/tests/callback/*.so -/testsuite/tests/callback/*.obj -/testsuite/tests/callback/*.cm[ioxa] -/testsuite/tests/callback/*.cmx[as] -/testsuite/tests/callback/*.annot -/testsuite/tests/callback/*.result -/testsuite/tests/callback/*.byte -/testsuite/tests/callback/*.native -/testsuite/tests/callback/program -/testsuite/tests/callback/program.exe -/testsuite/tests/callback/.depend -/testsuite/tests/callback/.depend.nt -/testsuite/tests/callback/.DS_Store - -# /testsuite/tests/embedded/ -/testsuite/tests/embedded/*.o -/testsuite/tests/embedded/*.a -/testsuite/tests/embedded/*.so -/testsuite/tests/embedded/*.obj -/testsuite/tests/embedded/*.lib -/testsuite/tests/embedded/*.dll -/testsuite/tests/embedded/*.cm[ioxat] -/testsuite/tests/embedded/*.cmx[as] -/testsuite/tests/embedded/*.cmti -/testsuite/tests/embedded/*.annot -/testsuite/tests/embedded/*.result -/testsuite/tests/embedded/*.byte -/testsuite/tests/embedded/*.native -/testsuite/tests/embedded/program -/testsuite/tests/embedded/*.exe -/testsuite/tests/embedded/*.exe.manifest -/testsuite/tests/embedded/.depend -/testsuite/tests/embedded/.depend.nt -/testsuite/tests/embedded/.DS_Store /testsuite/tests/embedded/caml -# /testsuite/tests/exotic-syntax/ -/testsuite/tests/exotic-syntax/*.o -/testsuite/tests/exotic-syntax/*.a -/testsuite/tests/exotic-syntax/*.so -/testsuite/tests/exotic-syntax/*.obj -/testsuite/tests/exotic-syntax/*.lib -/testsuite/tests/exotic-syntax/*.dll -/testsuite/tests/exotic-syntax/*.cm[ioxat] -/testsuite/tests/exotic-syntax/*.cmx[as] -/testsuite/tests/exotic-syntax/*.cmti -/testsuite/tests/exotic-syntax/*.annot -/testsuite/tests/exotic-syntax/*.result -/testsuite/tests/exotic-syntax/*.byte -/testsuite/tests/exotic-syntax/*.native -/testsuite/tests/exotic-syntax/program -/testsuite/tests/exotic-syntax/*.exe -/testsuite/tests/exotic-syntax/*.exe.manifest -/testsuite/tests/exotic-syntax/.depend -/testsuite/tests/exotic-syntax/.depend.nt -/testsuite/tests/exotic-syntax/.DS_Store - -# /testsuite/tests/formats-transition/ -/testsuite/tests/formats-transition/*.o -/testsuite/tests/formats-transition/*.a -/testsuite/tests/formats-transition/*.so -/testsuite/tests/formats-transition/*.obj -/testsuite/tests/formats-transition/*.lib -/testsuite/tests/formats-transition/*.dll -/testsuite/tests/formats-transition/*.cm[ioxat] -/testsuite/tests/formats-transition/*.cmx[as] -/testsuite/tests/formats-transition/*.cmti -/testsuite/tests/formats-transition/*.annot -/testsuite/tests/formats-transition/*.result -/testsuite/tests/formats-transition/*.byte -/testsuite/tests/formats-transition/*.native -/testsuite/tests/formats-transition/program -/testsuite/tests/formats-transition/*.exe -/testsuite/tests/formats-transition/*.exe.manifest -/testsuite/tests/formats-transition/.depend -/testsuite/tests/formats-transition/.depend.nt -/testsuite/tests/formats-transition/.DS_Store - -# /testsuite/tests/gc-roots/ -/testsuite/tests/gc-roots/*.o -/testsuite/tests/gc-roots/*.a -/testsuite/tests/gc-roots/*.so -/testsuite/tests/gc-roots/*.obj -/testsuite/tests/gc-roots/*.lib -/testsuite/tests/gc-roots/*.dll -/testsuite/tests/gc-roots/*.cm[ioxat] -/testsuite/tests/gc-roots/*.cmx[as] -/testsuite/tests/gc-roots/*.cmti -/testsuite/tests/gc-roots/*.annot -/testsuite/tests/gc-roots/*.result -/testsuite/tests/gc-roots/*.byte -/testsuite/tests/gc-roots/*.native -/testsuite/tests/gc-roots/program -/testsuite/tests/gc-roots/*.exe -/testsuite/tests/gc-roots/*.exe.manifest -/testsuite/tests/gc-roots/.depend -/testsuite/tests/gc-roots/.depend.nt -/testsuite/tests/gc-roots/.DS_Store - -# /testsuite/tests/letrec/ -/testsuite/tests/letrec/*.o -/testsuite/tests/letrec/*.a -/testsuite/tests/letrec/*.so -/testsuite/tests/letrec/*.obj -/testsuite/tests/letrec/*.cm[ioxa] -/testsuite/tests/letrec/*.cmx[as] -/testsuite/tests/letrec/*.annot -/testsuite/tests/letrec/*.result -/testsuite/tests/letrec/*.byte -/testsuite/tests/letrec/*.native -/testsuite/tests/letrec/program -/testsuite/tests/letrec/program.exe -/testsuite/tests/letrec/.depend -/testsuite/tests/letrec/.depend.nt -/testsuite/tests/letrec/.DS_Store - -# /testsuite/tests/lib-bigarray/ -/testsuite/tests/lib-bigarray/*.o -/testsuite/tests/lib-bigarray/*.a -/testsuite/tests/lib-bigarray/*.so -/testsuite/tests/lib-bigarray/*.obj -/testsuite/tests/lib-bigarray/*.lib -/testsuite/tests/lib-bigarray/*.dll -/testsuite/tests/lib-bigarray/*.cm[ioxat] -/testsuite/tests/lib-bigarray/*.cmx[as] -/testsuite/tests/lib-bigarray/*.cmti -/testsuite/tests/lib-bigarray/*.annot -/testsuite/tests/lib-bigarray/*.result -/testsuite/tests/lib-bigarray/*.byte -/testsuite/tests/lib-bigarray/*.native -/testsuite/tests/lib-bigarray/program -/testsuite/tests/lib-bigarray/*.exe -/testsuite/tests/lib-bigarray/*.exe.manifest -/testsuite/tests/lib-bigarray/.depend -/testsuite/tests/lib-bigarray/.depend.nt -/testsuite/tests/lib-bigarray/.DS_Store - -# /testsuite/tests/lib-bigarray-2/ -/testsuite/tests/lib-bigarray-2/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/lib-bigarray-2/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/lib-bigarray-2/_log -/testsuite/tests/lib-bigarray-2/*.so -/testsuite/tests/lib-bigarray-2/*.a -/testsuite/tests/lib-bigarray-2/*.result -/testsuite/tests/lib-bigarray-2/*.byte -/testsuite/tests/lib-bigarray-2/*.native -/testsuite/tests/lib-bigarray-2/program -/testsuite/tests/lib-bigarray-2/*.cm* -/testsuite/tests/lib-bigarray-2/*.o - -# /testsuite/tests/lib-digest/ -/testsuite/tests/lib-digest/*.o -/testsuite/tests/lib-digest/*.a -/testsuite/tests/lib-digest/*.so -/testsuite/tests/lib-digest/*.obj -/testsuite/tests/lib-digest/*.lib -/testsuite/tests/lib-digest/*.dll -/testsuite/tests/lib-digest/*.cm[ioxat] -/testsuite/tests/lib-digest/*.cmx[as] -/testsuite/tests/lib-digest/*.cmti -/testsuite/tests/lib-digest/*.annot -/testsuite/tests/lib-digest/*.result -/testsuite/tests/lib-digest/*.byte -/testsuite/tests/lib-digest/*.native -/testsuite/tests/lib-digest/program -/testsuite/tests/lib-digest/*.exe -/testsuite/tests/lib-digest/*.exe.manifest -/testsuite/tests/lib-digest/.depend -/testsuite/tests/lib-digest/.depend.nt -/testsuite/tests/lib-digest/.DS_Store - -# /testsuite/tests/lib-dynlink-bytecode/ -/testsuite/tests/lib-dynlink-bytecode/*.o -/testsuite/tests/lib-dynlink-bytecode/*.a -/testsuite/tests/lib-dynlink-bytecode/*.so -/testsuite/tests/lib-dynlink-bytecode/*.obj -/testsuite/tests/lib-dynlink-bytecode/*.lib -/testsuite/tests/lib-dynlink-bytecode/*.dll -/testsuite/tests/lib-dynlink-bytecode/*.cm[ioxat] -/testsuite/tests/lib-dynlink-bytecode/*.cmx[as] -/testsuite/tests/lib-dynlink-bytecode/*.cmti -/testsuite/tests/lib-dynlink-bytecode/*.annot -/testsuite/tests/lib-dynlink-bytecode/*.result -/testsuite/tests/lib-dynlink-bytecode/*.byte -/testsuite/tests/lib-dynlink-bytecode/*.native -/testsuite/tests/lib-dynlink-bytecode/program -/testsuite/tests/lib-dynlink-bytecode/*.exe -/testsuite/tests/lib-dynlink-bytecode/*.exe.manifest -/testsuite/tests/lib-dynlink-bytecode/.depend -/testsuite/tests/lib-dynlink-bytecode/.depend.nt -/testsuite/tests/lib-dynlink-bytecode/.DS_Store /testsuite/tests/lib-dynlink-bytecode/main /testsuite/tests/lib-dynlink-bytecode/static /testsuite/tests/lib-dynlink-bytecode/custom -/testsuite/tests/lib-dynlink-bytecode/custom.exe /testsuite/tests/lib-dynlink-bytecode/marshal.data /testsuite/tests/lib-dynlink-bytecode/caml -# /testsuite/tests/lib-dynlink-csharp/ -/testsuite/tests/lib-dynlink-csharp/*.o -/testsuite/tests/lib-dynlink-csharp/*.a -/testsuite/tests/lib-dynlink-csharp/*.so -/testsuite/tests/lib-dynlink-csharp/*.obj -/testsuite/tests/lib-dynlink-csharp/*.lib -/testsuite/tests/lib-dynlink-csharp/*.dll -/testsuite/tests/lib-dynlink-csharp/*.cm[ioxat] -/testsuite/tests/lib-dynlink-csharp/*.cmx[as] -/testsuite/tests/lib-dynlink-csharp/*.cmti -/testsuite/tests/lib-dynlink-csharp/*.annot -/testsuite/tests/lib-dynlink-csharp/*.result -/testsuite/tests/lib-dynlink-csharp/*.byte -/testsuite/tests/lib-dynlink-csharp/*.native -/testsuite/tests/lib-dynlink-csharp/program -/testsuite/tests/lib-dynlink-csharp/*.exe -/testsuite/tests/lib-dynlink-csharp/*.exe.manifest -/testsuite/tests/lib-dynlink-csharp/.depend -/testsuite/tests/lib-dynlink-csharp/.depend.nt -/testsuite/tests/lib-dynlink-csharp/.DS_Store - -# /testsuite/tests/lib-dynlink-native/ -/testsuite/tests/lib-dynlink-native/*.o -/testsuite/tests/lib-dynlink-native/*.a -/testsuite/tests/lib-dynlink-native/*.so -/testsuite/tests/lib-dynlink-native/*.obj -/testsuite/tests/lib-dynlink-native/*.lib -/testsuite/tests/lib-dynlink-native/*.dll -/testsuite/tests/lib-dynlink-native/*.cm[ioxat] -/testsuite/tests/lib-dynlink-native/*.cmx[as] -/testsuite/tests/lib-dynlink-native/*.cmti -/testsuite/tests/lib-dynlink-native/*.annot -/testsuite/tests/lib-dynlink-native/*.result -/testsuite/tests/lib-dynlink-native/*.byte -/testsuite/tests/lib-dynlink-native/*.native -/testsuite/tests/lib-dynlink-native/program -/testsuite/tests/lib-dynlink-native/*.exe -/testsuite/tests/lib-dynlink-native/*.exe.manifest -/testsuite/tests/lib-dynlink-native/.depend -/testsuite/tests/lib-dynlink-native/.depend.nt -/testsuite/tests/lib-dynlink-native/.DS_Store /testsuite/tests/lib-dynlink-native/mypack.pack.s /testsuite/tests/lib-dynlink-native/mypack.pack.asm /testsuite/tests/lib-dynlink-native/result /testsuite/tests/lib-dynlink-native/main -/testsuite/tests/lib-dynlink-native/main.exe /testsuite/tests/lib-dynlink-native/marshal.data /testsuite/tests/lib-dynlink-native/caml -# /testsuite/tests/lib-dynlink-native/sub/ -/testsuite/tests/lib-dynlink-native/sub/*.o -/testsuite/tests/lib-dynlink-native/sub/*.a -/testsuite/tests/lib-dynlink-native/sub/*.so -/testsuite/tests/lib-dynlink-native/sub/*.obj -/testsuite/tests/lib-dynlink-native/sub/*.lib -/testsuite/tests/lib-dynlink-native/sub/*.dll -/testsuite/tests/lib-dynlink-native/sub/*.cm[ioxat] -/testsuite/tests/lib-dynlink-native/sub/*.cmx[as] -/testsuite/tests/lib-dynlink-native/sub/*.cmti -/testsuite/tests/lib-dynlink-native/sub/*.annot -/testsuite/tests/lib-dynlink-native/sub/*.result -/testsuite/tests/lib-dynlink-native/sub/*.byte -/testsuite/tests/lib-dynlink-native/sub/*.native -/testsuite/tests/lib-dynlink-native/sub/program -/testsuite/tests/lib-dynlink-native/sub/*.exe -/testsuite/tests/lib-dynlink-native/sub/*.exe.manifest -/testsuite/tests/lib-dynlink-native/sub/.depend -/testsuite/tests/lib-dynlink-native/sub/.depend.nt -/testsuite/tests/lib-dynlink-native/sub/.DS_Store - -# /testsuite/tests/lib-format/ -/testsuite/tests/lib-format/*.o -/testsuite/tests/lib-format/*.a -/testsuite/tests/lib-format/*.so -/testsuite/tests/lib-format/*.obj -/testsuite/tests/lib-format/*.lib -/testsuite/tests/lib-format/*.dll -/testsuite/tests/lib-format/*.cm[ioxat] -/testsuite/tests/lib-format/*.cmx[as] -/testsuite/tests/lib-format/*.cmti -/testsuite/tests/lib-format/*.annot -/testsuite/tests/lib-format/*.result -/testsuite/tests/lib-format/*.byte -/testsuite/tests/lib-format/*.native -/testsuite/tests/lib-format/program -/testsuite/tests/lib-format/*.exe -/testsuite/tests/lib-format/*.exe.manifest -/testsuite/tests/lib-format/.depend -/testsuite/tests/lib-format/.depend.nt -/testsuite/tests/lib-format/.DS_Store - -# /testsuite/tests/lib-hashtbl/ -/testsuite/tests/lib-hashtbl/*.o -/testsuite/tests/lib-hashtbl/*.a -/testsuite/tests/lib-hashtbl/*.so -/testsuite/tests/lib-hashtbl/*.obj -/testsuite/tests/lib-hashtbl/*.cm[ioxa] -/testsuite/tests/lib-hashtbl/*.cmx[as] -/testsuite/tests/lib-hashtbl/*.annot -/testsuite/tests/lib-hashtbl/*.result -/testsuite/tests/lib-hashtbl/*.byte -/testsuite/tests/lib-hashtbl/*.native -/testsuite/tests/lib-hashtbl/program -/testsuite/tests/lib-hashtbl/program.exe -/testsuite/tests/lib-hashtbl/.depend -/testsuite/tests/lib-hashtbl/.depend.nt -/testsuite/tests/lib-hashtbl/.DS_Store - -# /testsuite/tests/lib-marshal/ -/testsuite/tests/lib-marshal/*.o -/testsuite/tests/lib-marshal/*.a -/testsuite/tests/lib-marshal/*.so -/testsuite/tests/lib-marshal/*.obj -/testsuite/tests/lib-marshal/*.lib -/testsuite/tests/lib-marshal/*.dll -/testsuite/tests/lib-marshal/*.cm[ioxat] -/testsuite/tests/lib-marshal/*.cmx[as] -/testsuite/tests/lib-marshal/*.cmti -/testsuite/tests/lib-marshal/*.annot -/testsuite/tests/lib-marshal/*.result -/testsuite/tests/lib-marshal/*.byte -/testsuite/tests/lib-marshal/*.native -/testsuite/tests/lib-marshal/program -/testsuite/tests/lib-marshal/*.exe -/testsuite/tests/lib-marshal/*.exe.manifest -/testsuite/tests/lib-marshal/.depend -/testsuite/tests/lib-marshal/.depend.nt -/testsuite/tests/lib-marshal/.DS_Store - -# /testsuite/tests/lib-num/ -/testsuite/tests/lib-num/*.o -/testsuite/tests/lib-num/*.a -/testsuite/tests/lib-num/*.so -/testsuite/tests/lib-num/*.obj -/testsuite/tests/lib-num/*.lib -/testsuite/tests/lib-num/*.dll -/testsuite/tests/lib-num/*.cm[ioxat] -/testsuite/tests/lib-num/*.cmx[as] -/testsuite/tests/lib-num/*.cmti -/testsuite/tests/lib-num/*.annot -/testsuite/tests/lib-num/*.result -/testsuite/tests/lib-num/*.byte -/testsuite/tests/lib-num/*.native -/testsuite/tests/lib-num/program -/testsuite/tests/lib-num/*.exe -/testsuite/tests/lib-num/*.exe.manifest -/testsuite/tests/lib-num/.depend -/testsuite/tests/lib-num/.depend.nt -/testsuite/tests/lib-num/.DS_Store - -# /testsuite/tests/lib-num-2/ -/testsuite/tests/lib-num-2/*.o -/testsuite/tests/lib-num-2/*.a -/testsuite/tests/lib-num-2/*.so -/testsuite/tests/lib-num-2/*.obj -/testsuite/tests/lib-num-2/*.cm[ioxa] -/testsuite/tests/lib-num-2/*.cmx[as] -/testsuite/tests/lib-num-2/*.annot -/testsuite/tests/lib-num-2/*.result -/testsuite/tests/lib-num-2/*.byte -/testsuite/tests/lib-num-2/*.native -/testsuite/tests/lib-num-2/program -/testsuite/tests/lib-num-2/program.exe -/testsuite/tests/lib-num-2/.depend -/testsuite/tests/lib-num-2/.depend.nt -/testsuite/tests/lib-num-2/.DS_Store - -# /testsuite/tests/lib-printf/ -/testsuite/tests/lib-printf/*.o -/testsuite/tests/lib-printf/*.a -/testsuite/tests/lib-printf/*.so -/testsuite/tests/lib-printf/*.obj -/testsuite/tests/lib-printf/*.lib -/testsuite/tests/lib-printf/*.dll -/testsuite/tests/lib-printf/*.cm[ioxat] -/testsuite/tests/lib-printf/*.cmx[as] -/testsuite/tests/lib-printf/*.cmti -/testsuite/tests/lib-printf/*.annot -/testsuite/tests/lib-printf/*.result -/testsuite/tests/lib-printf/*.byte -/testsuite/tests/lib-printf/*.native -/testsuite/tests/lib-printf/program -/testsuite/tests/lib-printf/*.exe -/testsuite/tests/lib-printf/*.exe.manifest -/testsuite/tests/lib-printf/.depend -/testsuite/tests/lib-printf/.depend.nt -/testsuite/tests/lib-printf/.DS_Store - -# /testsuite/tests/lib-random/ -/testsuite/tests/lib-random/*.o -/testsuite/tests/lib-random/*.a -/testsuite/tests/lib-random/*.so -/testsuite/tests/lib-random/*.obj -/testsuite/tests/lib-random/*.lib -/testsuite/tests/lib-random/*.dll -/testsuite/tests/lib-random/*.cm[ioxat] -/testsuite/tests/lib-random/*.cmx[as] -/testsuite/tests/lib-random/*.cmti -/testsuite/tests/lib-random/*.annot -/testsuite/tests/lib-random/*.result -/testsuite/tests/lib-random/*.byte -/testsuite/tests/lib-random/*.native -/testsuite/tests/lib-random/program -/testsuite/tests/lib-random/*.exe -/testsuite/tests/lib-random/*.exe.manifest -/testsuite/tests/lib-random/.depend -/testsuite/tests/lib-random/.depend.nt -/testsuite/tests/lib-random/.DS_Store - -# /testsuite/tests/lib-scanf/ -/testsuite/tests/lib-scanf/*.o -/testsuite/tests/lib-scanf/*.a -/testsuite/tests/lib-scanf/*.so -/testsuite/tests/lib-scanf/*.obj -/testsuite/tests/lib-scanf/*.lib -/testsuite/tests/lib-scanf/*.dll -/testsuite/tests/lib-scanf/*.cm[ioxat] -/testsuite/tests/lib-scanf/*.cmx[as] -/testsuite/tests/lib-scanf/*.cmti -/testsuite/tests/lib-scanf/*.annot -/testsuite/tests/lib-scanf/*.result -/testsuite/tests/lib-scanf/*.byte -/testsuite/tests/lib-scanf/*.native -/testsuite/tests/lib-scanf/program -/testsuite/tests/lib-scanf/*.exe -/testsuite/tests/lib-scanf/*.exe.manifest -/testsuite/tests/lib-scanf/.depend -/testsuite/tests/lib-scanf/.depend.nt -/testsuite/tests/lib-scanf/.DS_Store /testsuite/tests/lib-scanf/tscanf_data -# /testsuite/tests/lib-scanf-2/ -/testsuite/tests/lib-scanf-2/*.o -/testsuite/tests/lib-scanf-2/*.a -/testsuite/tests/lib-scanf-2/*.so -/testsuite/tests/lib-scanf-2/*.obj -/testsuite/tests/lib-scanf-2/*.lib -/testsuite/tests/lib-scanf-2/*.dll -/testsuite/tests/lib-scanf-2/*.cm[ioxat] -/testsuite/tests/lib-scanf-2/*.cmx[as] -/testsuite/tests/lib-scanf-2/*.cmti -/testsuite/tests/lib-scanf-2/*.annot -/testsuite/tests/lib-scanf-2/*.result -/testsuite/tests/lib-scanf-2/*.byte -/testsuite/tests/lib-scanf-2/*.native -/testsuite/tests/lib-scanf-2/program -/testsuite/tests/lib-scanf-2/*.exe -/testsuite/tests/lib-scanf-2/*.exe.manifest -/testsuite/tests/lib-scanf-2/.depend -/testsuite/tests/lib-scanf-2/.depend.nt -/testsuite/tests/lib-scanf-2/.DS_Store - -# /testsuite/tests/lib-set/ -/testsuite/tests/lib-set/*.o -/testsuite/tests/lib-set/*.a -/testsuite/tests/lib-set/*.so -/testsuite/tests/lib-set/*.obj -/testsuite/tests/lib-set/*.cm[ioxa] -/testsuite/tests/lib-set/*.cmx[as] -/testsuite/tests/lib-set/*.annot -/testsuite/tests/lib-set/*.result -/testsuite/tests/lib-set/*.byte -/testsuite/tests/lib-set/*.native -/testsuite/tests/lib-set/program -/testsuite/tests/lib-set/program.exe -/testsuite/tests/lib-set/.depend -/testsuite/tests/lib-set/.depend.nt -/testsuite/tests/lib-set/.DS_Store - -# /testsuite/tests/lib-str/ -/testsuite/tests/lib-str/*.o -/testsuite/tests/lib-str/*.a -/testsuite/tests/lib-str/*.so -/testsuite/tests/lib-str/*.obj -/testsuite/tests/lib-str/*.cm[ioxa] -/testsuite/tests/lib-str/*.cmx[as] -/testsuite/tests/lib-str/*.annot -/testsuite/tests/lib-str/*.result -/testsuite/tests/lib-str/*.byte -/testsuite/tests/lib-str/*.native -/testsuite/tests/lib-str/program -/testsuite/tests/lib-str/program.exe -/testsuite/tests/lib-str/.depend -/testsuite/tests/lib-str/.depend.nt -/testsuite/tests/lib-str/.DS_Store - -# /testsuite/tests/lib-stream/ -/testsuite/tests/lib-stream/*.o -/testsuite/tests/lib-stream/*.a -/testsuite/tests/lib-stream/*.so -/testsuite/tests/lib-stream/*.obj -/testsuite/tests/lib-stream/*.cm[ioxa] -/testsuite/tests/lib-stream/*.cmx[as] -/testsuite/tests/lib-stream/*.annot -/testsuite/tests/lib-stream/*.result -/testsuite/tests/lib-stream/*.byte -/testsuite/tests/lib-stream/*.native -/testsuite/tests/lib-stream/program -/testsuite/tests/lib-stream/program.exe -/testsuite/tests/lib-stream/.depend -/testsuite/tests/lib-stream/.depend.nt -/testsuite/tests/lib-stream/.DS_Store - -# /testsuite/tests/lib-systhreads/ -/testsuite/tests/lib-systhreads/*.o -/testsuite/tests/lib-systhreads/*.a -/testsuite/tests/lib-systhreads/*.so -/testsuite/tests/lib-systhreads/*.obj -/testsuite/tests/lib-systhreads/*.cm[ioxa] -/testsuite/tests/lib-systhreads/*.cmx[as] -/testsuite/tests/lib-systhreads/*.annot -/testsuite/tests/lib-systhreads/*.result -/testsuite/tests/lib-systhreads/*.byte -/testsuite/tests/lib-systhreads/*.native -/testsuite/tests/lib-systhreads/program -/testsuite/tests/lib-systhreads/program.exe -/testsuite/tests/lib-systhreads/.depend -/testsuite/tests/lib-systhreads/.depend.nt -/testsuite/tests/lib-systhreads/.DS_Store - -# /testsuite/tests/lib-threads/ -/testsuite/tests/lib-threads/*.o -/testsuite/tests/lib-threads/*.a -/testsuite/tests/lib-threads/*.so -/testsuite/tests/lib-threads/*.obj -/testsuite/tests/lib-threads/*.cm[ioxa] -/testsuite/tests/lib-threads/*.cmx[as] -/testsuite/tests/lib-threads/*.annot -/testsuite/tests/lib-threads/*.result -/testsuite/tests/lib-threads/*.byte -/testsuite/tests/lib-threads/*.native -/testsuite/tests/lib-threads/program -/testsuite/tests/lib-threads/program.exe -/testsuite/tests/lib-threads/.depend -/testsuite/tests/lib-threads/.depend.nt -/testsuite/tests/lib-threads/.DS_Store /testsuite/tests/lib-threads/*.byt -# /testsuite/tests/match-exception/ -/testsuite/tests/match-exception/*.o -/testsuite/tests/match-exception/*.a -/testsuite/tests/match-exception/*.so -/testsuite/tests/match-exception/*.obj -/testsuite/tests/match-exception/*.lib -/testsuite/tests/match-exception/*.dll -/testsuite/tests/match-exception/*.cm[ioxat] -/testsuite/tests/match-exception/*.cmx[as] -/testsuite/tests/match-exception/*.cmti -/testsuite/tests/match-exception/*.annot -/testsuite/tests/match-exception/*.result -/testsuite/tests/match-exception/*.byte -/testsuite/tests/match-exception/*.native -/testsuite/tests/match-exception/program -/testsuite/tests/match-exception/*.exe -/testsuite/tests/match-exception/*.exe.manifest -/testsuite/tests/match-exception/.depend -/testsuite/tests/match-exception/.depend.nt -/testsuite/tests/match-exception/.DS_Store - -# /testsuite/tests/match-exception-warnings/ -/testsuite/tests/match-exception-warnings/*.o -/testsuite/tests/match-exception-warnings/*.a -/testsuite/tests/match-exception-warnings/*.so -/testsuite/tests/match-exception-warnings/*.obj -/testsuite/tests/match-exception-warnings/*.lib -/testsuite/tests/match-exception-warnings/*.dll -/testsuite/tests/match-exception-warnings/*.cm[ioxat] -/testsuite/tests/match-exception-warnings/*.cmx[as] -/testsuite/tests/match-exception-warnings/*.cmti -/testsuite/tests/match-exception-warnings/*.annot -/testsuite/tests/match-exception-warnings/*.result -/testsuite/tests/match-exception-warnings/*.byte -/testsuite/tests/match-exception-warnings/*.native -/testsuite/tests/match-exception-warnings/program -/testsuite/tests/match-exception-warnings/*.exe -/testsuite/tests/match-exception-warnings/*.exe.manifest -/testsuite/tests/match-exception-warnings/.depend -/testsuite/tests/match-exception-warnings/.depend.nt -/testsuite/tests/match-exception-warnings/.DS_Store - -# /testsuite/tests/misc/ -/testsuite/tests/misc/*.o -/testsuite/tests/misc/*.a -/testsuite/tests/misc/*.so -/testsuite/tests/misc/*.obj -/testsuite/tests/misc/*.cm[ioxa] -/testsuite/tests/misc/*.cmx[as] -/testsuite/tests/misc/*.annot -/testsuite/tests/misc/*.result -/testsuite/tests/misc/*.byte -/testsuite/tests/misc/*.native -/testsuite/tests/misc/program -/testsuite/tests/misc/program.exe -/testsuite/tests/misc/.depend -/testsuite/tests/misc/.depend.nt -/testsuite/tests/misc/.DS_Store - -# /testsuite/tests/misc-kb/ -/testsuite/tests/misc-kb/*.o -/testsuite/tests/misc-kb/*.a -/testsuite/tests/misc-kb/*.so -/testsuite/tests/misc-kb/*.obj -/testsuite/tests/misc-kb/*.lib -/testsuite/tests/misc-kb/*.dll -/testsuite/tests/misc-kb/*.cm[ioxat] -/testsuite/tests/misc-kb/*.cmx[as] -/testsuite/tests/misc-kb/*.cmti -/testsuite/tests/misc-kb/*.annot -/testsuite/tests/misc-kb/*.result -/testsuite/tests/misc-kb/*.byte -/testsuite/tests/misc-kb/*.native -/testsuite/tests/misc-kb/program -/testsuite/tests/misc-kb/*.exe -/testsuite/tests/misc-kb/*.exe.manifest -/testsuite/tests/misc-kb/.depend -/testsuite/tests/misc-kb/.depend.nt -/testsuite/tests/misc-kb/.DS_Store - -# /testsuite/tests/misc-unsafe/ -/testsuite/tests/misc-unsafe/*.o -/testsuite/tests/misc-unsafe/*.a -/testsuite/tests/misc-unsafe/*.so -/testsuite/tests/misc-unsafe/*.obj -/testsuite/tests/misc-unsafe/*.cm[ioxa] -/testsuite/tests/misc-unsafe/*.cmx[as] -/testsuite/tests/misc-unsafe/*.annot -/testsuite/tests/misc-unsafe/*.result -/testsuite/tests/misc-unsafe/*.byte -/testsuite/tests/misc-unsafe/*.native -/testsuite/tests/misc-unsafe/program -/testsuite/tests/misc-unsafe/program.exe -/testsuite/tests/misc-unsafe/.depend -/testsuite/tests/misc-unsafe/.depend.nt -/testsuite/tests/misc-unsafe/.DS_Store - -# /testsuite/tests/prim-bigstring/ -/testsuite/tests/prim-bigstring/*.o -/testsuite/tests/prim-bigstring/*.a -/testsuite/tests/prim-bigstring/*.so -/testsuite/tests/prim-bigstring/*.obj -/testsuite/tests/prim-bigstring/*.lib -/testsuite/tests/prim-bigstring/*.dll -/testsuite/tests/prim-bigstring/*.cm[ioxat] -/testsuite/tests/prim-bigstring/*.cmx[as] -/testsuite/tests/prim-bigstring/*.cmti -/testsuite/tests/prim-bigstring/*.annot -/testsuite/tests/prim-bigstring/*.result -/testsuite/tests/prim-bigstring/*.byte -/testsuite/tests/prim-bigstring/*.native -/testsuite/tests/prim-bigstring/program -/testsuite/tests/prim-bigstring/*.exe -/testsuite/tests/prim-bigstring/*.exe.manifest -/testsuite/tests/prim-bigstring/.depend -/testsuite/tests/prim-bigstring/.depend.nt -/testsuite/tests/prim-bigstring/.DS_Store +/testsuite/tests/opaque/*/*.mli -# /testsuite/tests/prim-bswap/ -/testsuite/tests/prim-bswap/*.o -/testsuite/tests/prim-bswap/*.a -/testsuite/tests/prim-bswap/*.so -/testsuite/tests/prim-bswap/*.obj -/testsuite/tests/prim-bswap/*.cm[ioxat] -/testsuite/tests/prim-bswap/*.cmx[as] -/testsuite/tests/prim-bswap/*.cmti -/testsuite/tests/prim-bswap/*.annot -/testsuite/tests/prim-bswap/*.result -/testsuite/tests/prim-bswap/*.byte -/testsuite/tests/prim-bswap/*.native -/testsuite/tests/prim-bswap/program -/testsuite/tests/prim-bswap/program.exe -/testsuite/tests/prim-bswap/.depend -/testsuite/tests/prim-bswap/.depend.nt -/testsuite/tests/prim-bswap/.DS_Store - -# /testsuite/tests/prim-revapply/ -/testsuite/tests/prim-revapply/*.o -/testsuite/tests/prim-revapply/*.a -/testsuite/tests/prim-revapply/*.so -/testsuite/tests/prim-revapply/*.obj -/testsuite/tests/prim-revapply/*.cm[ioxa] -/testsuite/tests/prim-revapply/*.cmx[as] -/testsuite/tests/prim-revapply/*.annot -/testsuite/tests/prim-revapply/*.result -/testsuite/tests/prim-revapply/*.byte -/testsuite/tests/prim-revapply/*.native -/testsuite/tests/prim-revapply/program -/testsuite/tests/prim-revapply/program.exe -/testsuite/tests/prim-revapply/.depend -/testsuite/tests/prim-revapply/.depend.nt -/testsuite/tests/prim-revapply/.DS_Store - -# /testsuite/tests/regression/pr5080-notes/ -/testsuite/tests/regression/pr5080-notes/*.o -/testsuite/tests/regression/pr5080-notes/*.a -/testsuite/tests/regression/pr5080-notes/*.so -/testsuite/tests/regression/pr5080-notes/*.obj -/testsuite/tests/regression/pr5080-notes/*.cm[ioxa] -/testsuite/tests/regression/pr5080-notes/*.cmx[as] -/testsuite/tests/regression/pr5080-notes/*.annot -/testsuite/tests/regression/pr5080-notes/*.result -/testsuite/tests/regression/pr5080-notes/*.byte -/testsuite/tests/regression/pr5080-notes/*.native -/testsuite/tests/regression/pr5080-notes/program -/testsuite/tests/regression/pr5080-notes/program.exe -/testsuite/tests/regression/pr5080-notes/.depend -/testsuite/tests/regression/pr5080-notes/.depend.nt -/testsuite/tests/regression/pr5080-notes/.DS_Store - -# /testsuite/tests/regression/pr5233/ -/testsuite/tests/regression/pr5233/*.o -/testsuite/tests/regression/pr5233/*.a -/testsuite/tests/regression/pr5233/*.so -/testsuite/tests/regression/pr5233/*.obj -/testsuite/tests/regression/pr5233/*.lib -/testsuite/tests/regression/pr5233/*.dll -/testsuite/tests/regression/pr5233/*.cm[ioxat] -/testsuite/tests/regression/pr5233/*.cmx[as] -/testsuite/tests/regression/pr5233/*.cmti -/testsuite/tests/regression/pr5233/*.annot -/testsuite/tests/regression/pr5233/*.result -/testsuite/tests/regression/pr5233/*.byte -/testsuite/tests/regression/pr5233/*.native -/testsuite/tests/regression/pr5233/program -/testsuite/tests/regression/pr5233/*.exe -/testsuite/tests/regression/pr5233/*.exe.manifest -/testsuite/tests/regression/pr5233/.depend -/testsuite/tests/regression/pr5233/.depend.nt -/testsuite/tests/regression/pr5233/.DS_Store - -# /testsuite/tests/regression/pr5757/ -/testsuite/tests/regression/pr5757/*.o -/testsuite/tests/regression/pr5757/*.a -/testsuite/tests/regression/pr5757/*.so -/testsuite/tests/regression/pr5757/*.obj -/testsuite/tests/regression/pr5757/*.lib -/testsuite/tests/regression/pr5757/*.dll -/testsuite/tests/regression/pr5757/*.cm[ioxat] -/testsuite/tests/regression/pr5757/*.cmx[as] -/testsuite/tests/regression/pr5757/*.cmti -/testsuite/tests/regression/pr5757/*.annot -/testsuite/tests/regression/pr5757/*.result -/testsuite/tests/regression/pr5757/*.byte -/testsuite/tests/regression/pr5757/*.native -/testsuite/tests/regression/pr5757/program -/testsuite/tests/regression/pr5757/*.exe -/testsuite/tests/regression/pr5757/*.exe.manifest -/testsuite/tests/regression/pr5757/.depend -/testsuite/tests/regression/pr5757/.depend.nt -/testsuite/tests/regression/pr5757/.DS_Store - -# /testsuite/tests/regression/pr6024/ -/testsuite/tests/regression/pr6024/*.o -/testsuite/tests/regression/pr6024/*.a -/testsuite/tests/regression/pr6024/*.so -/testsuite/tests/regression/pr6024/*.obj -/testsuite/tests/regression/pr6024/*.lib -/testsuite/tests/regression/pr6024/*.dll -/testsuite/tests/regression/pr6024/*.cm[ioxat] -/testsuite/tests/regression/pr6024/*.cmx[as] -/testsuite/tests/regression/pr6024/*.cmti -/testsuite/tests/regression/pr6024/*.annot -/testsuite/tests/regression/pr6024/*.result -/testsuite/tests/regression/pr6024/*.byte -/testsuite/tests/regression/pr6024/*.native -/testsuite/tests/regression/pr6024/program -/testsuite/tests/regression/pr6024/*.exe -/testsuite/tests/regression/pr6024/*.exe.manifest -/testsuite/tests/regression/pr6024/.depend -/testsuite/tests/regression/pr6024/.depend.nt -/testsuite/tests/regression/pr6024/.DS_Store - -# /testsuite/tests/runtime-errors/ -/testsuite/tests/runtime-errors/*.o -/testsuite/tests/runtime-errors/*.a -/testsuite/tests/runtime-errors/*.so -/testsuite/tests/runtime-errors/*.obj -/testsuite/tests/runtime-errors/*.lib -/testsuite/tests/runtime-errors/*.dll -/testsuite/tests/runtime-errors/*.cm[ioxat] -/testsuite/tests/runtime-errors/*.cmx[as] -/testsuite/tests/runtime-errors/*.cmti -/testsuite/tests/runtime-errors/*.annot -/testsuite/tests/runtime-errors/*.result -/testsuite/tests/runtime-errors/*.byte -/testsuite/tests/runtime-errors/*.native -/testsuite/tests/runtime-errors/program -/testsuite/tests/runtime-errors/*.exe -/testsuite/tests/runtime-errors/*.exe.manifest -/testsuite/tests/runtime-errors/.depend -/testsuite/tests/runtime-errors/.depend.nt -/testsuite/tests/runtime-errors/.DS_Store /testsuite/tests/runtime-errors/*.bytecode -# /testsuite/tests/tool-debugger/ -/testsuite/tests/tool-debugger/*.o -/testsuite/tests/tool-debugger/*.a -/testsuite/tests/tool-debugger/*.so -/testsuite/tests/tool-debugger/*.obj -/testsuite/tests/tool-debugger/*.lib -/testsuite/tests/tool-debugger/*.dll -/testsuite/tests/tool-debugger/*.cm[ioxat] -/testsuite/tests/tool-debugger/*.cmx[as] -/testsuite/tests/tool-debugger/*.cmti -/testsuite/tests/tool-debugger/*.annot -/testsuite/tests/tool-debugger/*.result -/testsuite/tests/tool-debugger/*.byte -/testsuite/tests/tool-debugger/*.native -/testsuite/tests/tool-debugger/program -/testsuite/tests/tool-debugger/*.exe -/testsuite/tests/tool-debugger/*.exe.manifest -/testsuite/tests/tool-debugger/.depend -/testsuite/tests/tool-debugger/.depend.nt -/testsuite/tests/tool-debugger/.DS_Store -/testsuite/tests/tool-debugger/compiler-libs - -# /testsuite/tests/tool-debugger/basic/ -/testsuite/tests/tool-debugger/basic/*.o -/testsuite/tests/tool-debugger/basic/*.a -/testsuite/tests/tool-debugger/basic/*.so -/testsuite/tests/tool-debugger/basic/*.obj -/testsuite/tests/tool-debugger/basic/*.lib -/testsuite/tests/tool-debugger/basic/*.dll -/testsuite/tests/tool-debugger/basic/*.cm[ioxat] -/testsuite/tests/tool-debugger/basic/*.cmx[as] -/testsuite/tests/tool-debugger/basic/*.cmti -/testsuite/tests/tool-debugger/basic/*.annot -/testsuite/tests/tool-debugger/basic/*.result -/testsuite/tests/tool-debugger/basic/*.byte -/testsuite/tests/tool-debugger/basic/*.native -/testsuite/tests/tool-debugger/basic/program -/testsuite/tests/tool-debugger/basic/*.exe -/testsuite/tests/tool-debugger/basic/*.exe.manifest -/testsuite/tests/tool-debugger/basic/.depend -/testsuite/tests/tool-debugger/basic/.depend.nt -/testsuite/tests/tool-debugger/basic/.DS_Store -/testsuite/tests/tool-debugger/basic/compiler-libs - -# /testsuite/tests/tool-debugger/find-artifacts/ -/testsuite/tests/tool-debugger/find-artifacts/*.o -/testsuite/tests/tool-debugger/find-artifacts/*.a -/testsuite/tests/tool-debugger/find-artifacts/*.so -/testsuite/tests/tool-debugger/find-artifacts/*.obj -/testsuite/tests/tool-debugger/find-artifacts/*.lib -/testsuite/tests/tool-debugger/find-artifacts/*.dll -/testsuite/tests/tool-debugger/find-artifacts/*.cm[ioxat] -/testsuite/tests/tool-debugger/find-artifacts/*.cmx[as] -/testsuite/tests/tool-debugger/find-artifacts/*.cmti -/testsuite/tests/tool-debugger/find-artifacts/*.annot -/testsuite/tests/tool-debugger/find-artifacts/*.result -/testsuite/tests/tool-debugger/find-artifacts/*.byte -/testsuite/tests/tool-debugger/find-artifacts/*.native -/testsuite/tests/tool-debugger/find-artifacts/program -/testsuite/tests/tool-debugger/find-artifacts/*.exe -/testsuite/tests/tool-debugger/find-artifacts/*.exe.manifest -/testsuite/tests/tool-debugger/find-artifacts/.depend -/testsuite/tests/tool-debugger/find-artifacts/.depend.nt -/testsuite/tests/tool-debugger/find-artifacts/.DS_Store -/testsuite/tests/tool-debugger/find-artifacts/compiler-libs +/testsuite/tests/tool-debugger/**/compiler-libs /testsuite/tests/tool-debugger/find-artifacts/out - -# /testsuite/tests/tool-debugger/no_debug_event/ -/testsuite/tests/tool-debugger/no_debug_event/*.o -/testsuite/tests/tool-debugger/no_debug_event/*.a -/testsuite/tests/tool-debugger/no_debug_event/*.so -/testsuite/tests/tool-debugger/no_debug_event/*.obj -/testsuite/tests/tool-debugger/no_debug_event/*.lib -/testsuite/tests/tool-debugger/no_debug_event/*.dll -/testsuite/tests/tool-debugger/no_debug_event/*.cm[ioxat] -/testsuite/tests/tool-debugger/no_debug_event/*.cmx[as] -/testsuite/tests/tool-debugger/no_debug_event/*.cmti -/testsuite/tests/tool-debugger/no_debug_event/*.annot -/testsuite/tests/tool-debugger/no_debug_event/*.result -/testsuite/tests/tool-debugger/no_debug_event/*.byte -/testsuite/tests/tool-debugger/no_debug_event/*.native -/testsuite/tests/tool-debugger/no_debug_event/program -/testsuite/tests/tool-debugger/no_debug_event/*.exe -/testsuite/tests/tool-debugger/no_debug_event/*.exe.manifest -/testsuite/tests/tool-debugger/no_debug_event/.depend -/testsuite/tests/tool-debugger/no_debug_event/.depend.nt -/testsuite/tests/tool-debugger/no_debug_event/.DS_Store -/testsuite/tests/tool-debugger/no_debug_event/compiler-libs /testsuite/tests/tool-debugger/no_debug_event/out /testsuite/tests/tool-debugger/no_debug_event/c -/testsuite/tests/tool-debugger/no_debug_event/c.exe -# /testsuite/tests/tool-lexyacc/ -/testsuite/tests/tool-lexyacc/*.o -/testsuite/tests/tool-lexyacc/*.a -/testsuite/tests/tool-lexyacc/*.so -/testsuite/tests/tool-lexyacc/*.obj -/testsuite/tests/tool-lexyacc/*.lib -/testsuite/tests/tool-lexyacc/*.dll -/testsuite/tests/tool-lexyacc/*.cm[ioxat] -/testsuite/tests/tool-lexyacc/*.cmx[as] -/testsuite/tests/tool-lexyacc/*.cmti -/testsuite/tests/tool-lexyacc/*.annot -/testsuite/tests/tool-lexyacc/*.result -/testsuite/tests/tool-lexyacc/*.byte -/testsuite/tests/tool-lexyacc/*.native -/testsuite/tests/tool-lexyacc/program -/testsuite/tests/tool-lexyacc/*.exe -/testsuite/tests/tool-lexyacc/*.exe.manifest -/testsuite/tests/tool-lexyacc/.depend -/testsuite/tests/tool-lexyacc/.depend.nt -/testsuite/tests/tool-lexyacc/.DS_Store -/testsuite/tests/tool-lexyacc/scanner.ml -/testsuite/tests/tool-lexyacc/grammar.mli -/testsuite/tests/tool-lexyacc/grammar.ml - -# /testsuite/tests/tool-ocaml/ -/testsuite/tests/tool-ocaml/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/tool-ocaml/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/tool-ocaml/_log -/testsuite/tests/tool-ocaml/*.so -/testsuite/tests/tool-ocaml/*.a -/testsuite/tests/tool-ocaml/*.result -/testsuite/tests/tool-ocaml/*.byte -/testsuite/tests/tool-ocaml/*.native -/testsuite/tests/tool-ocaml/program -/testsuite/tests/tool-ocaml/*.cm* -/testsuite/tests/tool-ocaml/*.o +/testsuite/tests/tool-ocamldep-modalias/*.byt* +/testsuite/tests/tool-ocamldep-modalias/*.opt* +/testsuite/tests/tool-ocamldep-modalias/depend.mk +/testsuite/tests/tool-ocamldep-modalias/depend.mk2 +/testsuite/tests/tool-ocamldep-modalias/depend.mod +/testsuite/tests/tool-ocamldep-modalias/depend.mod2 +/testsuite/tests/tool-ocamldep-modalias/depend.mod3 -# /testsuite/tests/tool-ocamldoc/ -/testsuite/tests/tool-ocamldoc/*.o -/testsuite/tests/tool-ocamldoc/*.a -/testsuite/tests/tool-ocamldoc/*.so -/testsuite/tests/tool-ocamldoc/*.obj -/testsuite/tests/tool-ocamldoc/*.cm[ioxa] -/testsuite/tests/tool-ocamldoc/*.cmx[as] -/testsuite/tests/tool-ocamldoc/*.annot -/testsuite/tests/tool-ocamldoc/*.result -/testsuite/tests/tool-ocamldoc/*.byte -/testsuite/tests/tool-ocamldoc/*.native -/testsuite/tests/tool-ocamldoc/program -/testsuite/tests/tool-ocamldoc/.depend -/testsuite/tests/tool-ocamldoc/.depend.nt -/testsuite/tests/tool-ocamldoc/.DS_Store /testsuite/tests/tool-ocamldoc/*.html /testsuite/tests/tool-ocamldoc/*.sty /testsuite/tests/tool-ocamldoc/*.css -/testsuite/tests/tool-ocamldoc/ocamldoc.out - -# /testsuite/tests/tool-toplevel/ -/testsuite/tests/tool-toplevel/*.o -/testsuite/tests/tool-toplevel/*.a -/testsuite/tests/tool-toplevel/*.so -/testsuite/tests/tool-toplevel/*.obj -/testsuite/tests/tool-toplevel/*.lib -/testsuite/tests/tool-toplevel/*.dll -/testsuite/tests/tool-toplevel/*.cm[ioxat] -/testsuite/tests/tool-toplevel/*.cmx[as] -/testsuite/tests/tool-toplevel/*.cmti -/testsuite/tests/tool-toplevel/*.annot -/testsuite/tests/tool-toplevel/*.result -/testsuite/tests/tool-toplevel/*.byte -/testsuite/tests/tool-toplevel/*.native -/testsuite/tests/tool-toplevel/program -/testsuite/tests/tool-toplevel/*.exe -/testsuite/tests/tool-toplevel/*.exe.manifest -/testsuite/tests/tool-toplevel/.depend -/testsuite/tests/tool-toplevel/.depend.nt -/testsuite/tests/tool-toplevel/.DS_Store - -# /testsuite/tests/typing-extensions/ -/testsuite/tests/typing-extensions/*.o -/testsuite/tests/typing-extensions/*.a -/testsuite/tests/typing-extensions/*.so -/testsuite/tests/typing-extensions/*.obj -/testsuite/tests/typing-extensions/*.lib -/testsuite/tests/typing-extensions/*.dll -/testsuite/tests/typing-extensions/*.cm[ioxat] -/testsuite/tests/typing-extensions/*.cmx[as] -/testsuite/tests/typing-extensions/*.cmti -/testsuite/tests/typing-extensions/*.annot -/testsuite/tests/typing-extensions/*.result -/testsuite/tests/typing-extensions/*.byte -/testsuite/tests/typing-extensions/*.native -/testsuite/tests/typing-extensions/program -/testsuite/tests/typing-extensions/*.exe -/testsuite/tests/typing-extensions/*.exe.manifest -/testsuite/tests/typing-extensions/.depend -/testsuite/tests/typing-extensions/.depend.nt -/testsuite/tests/typing-extensions/.DS_Store - -# /testsuite/tests/typing-fstclassmod/ -/testsuite/tests/typing-fstclassmod/*.o -/testsuite/tests/typing-fstclassmod/*.a -/testsuite/tests/typing-fstclassmod/*.so -/testsuite/tests/typing-fstclassmod/*.obj -/testsuite/tests/typing-fstclassmod/*.lib -/testsuite/tests/typing-fstclassmod/*.dll -/testsuite/tests/typing-fstclassmod/*.cm[ioxat] -/testsuite/tests/typing-fstclassmod/*.cmx[as] -/testsuite/tests/typing-fstclassmod/*.cmti -/testsuite/tests/typing-fstclassmod/*.annot -/testsuite/tests/typing-fstclassmod/*.result -/testsuite/tests/typing-fstclassmod/*.byte -/testsuite/tests/typing-fstclassmod/*.native -/testsuite/tests/typing-fstclassmod/program -/testsuite/tests/typing-fstclassmod/*.exe -/testsuite/tests/typing-fstclassmod/*.exe.manifest -/testsuite/tests/typing-fstclassmod/.depend -/testsuite/tests/typing-fstclassmod/.depend.nt -/testsuite/tests/typing-fstclassmod/.DS_Store - -# /testsuite/tests/typing-gadts/ -/testsuite/tests/typing-gadts/*.o -/testsuite/tests/typing-gadts/*.a -/testsuite/tests/typing-gadts/*.so -/testsuite/tests/typing-gadts/*.obj -/testsuite/tests/typing-gadts/*.cm[ioxa] -/testsuite/tests/typing-gadts/*.cmx[as] -/testsuite/tests/typing-gadts/*.annot -/testsuite/tests/typing-gadts/*.result -/testsuite/tests/typing-gadts/*.byte -/testsuite/tests/typing-gadts/*.native -/testsuite/tests/typing-gadts/program -/testsuite/tests/typing-gadts/.depend -/testsuite/tests/typing-gadts/.depend.nt -/testsuite/tests/typing-gadts/.DS_Store - -# /testsuite/tests/typing-implicit_unpack/ -/testsuite/tests/typing-implicit_unpack/*.o -/testsuite/tests/typing-implicit_unpack/*.a -/testsuite/tests/typing-implicit_unpack/*.so -/testsuite/tests/typing-implicit_unpack/*.obj -/testsuite/tests/typing-implicit_unpack/*.cm[ioxa] -/testsuite/tests/typing-implicit_unpack/*.cmx[as] -/testsuite/tests/typing-implicit_unpack/*.annot -/testsuite/tests/typing-implicit_unpack/*.result -/testsuite/tests/typing-implicit_unpack/*.byte -/testsuite/tests/typing-implicit_unpack/*.native -/testsuite/tests/typing-implicit_unpack/program -/testsuite/tests/typing-implicit_unpack/.depend -/testsuite/tests/typing-implicit_unpack/.depend.nt -/testsuite/tests/typing-implicit_unpack/.DS_Store - -# /testsuite/tests/typing-labels/ -/testsuite/tests/typing-labels/*.o -/testsuite/tests/typing-labels/*.a -/testsuite/tests/typing-labels/*.so -/testsuite/tests/typing-labels/*.obj -/testsuite/tests/typing-labels/*.cm[ioxa] -/testsuite/tests/typing-labels/*.cmx[as] -/testsuite/tests/typing-labels/*.annot -/testsuite/tests/typing-labels/*.result -/testsuite/tests/typing-labels/*.byte -/testsuite/tests/typing-labels/*.native -/testsuite/tests/typing-labels/program -/testsuite/tests/typing-labels/program.exe -/testsuite/tests/typing-labels/.depend -/testsuite/tests/typing-labels/.depend.nt -/testsuite/tests/typing-labels/.DS_Store -# /testsuite/tests/typing-misc/ -/testsuite/tests/typing-misc/*.o -/testsuite/tests/typing-misc/*.a -/testsuite/tests/typing-misc/*.so -/testsuite/tests/typing-misc/*.obj -/testsuite/tests/typing-misc/*.cm[ioxa] -/testsuite/tests/typing-misc/*.cmx[as] -/testsuite/tests/typing-misc/*.annot -/testsuite/tests/typing-misc/*.result -/testsuite/tests/typing-misc/*.byte -/testsuite/tests/typing-misc/*.native -/testsuite/tests/typing-misc/program -/testsuite/tests/typing-misc/.depend -/testsuite/tests/typing-misc/.depend.nt -/testsuite/tests/typing-misc/.DS_Store +/testsuite/tests/tool-ocamldoc-2/ocamldoc.sty -# /testsuite/tests/typing-modules/ -/testsuite/tests/typing-modules/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/typing-modules/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/typing-modules/_log -/testsuite/tests/typing-modules/*.so -/testsuite/tests/typing-modules/*.a -/testsuite/tests/typing-modules/*.result -/testsuite/tests/typing-modules/*.byte -/testsuite/tests/typing-modules/*.native -/testsuite/tests/typing-modules/program - -# /testsuite/tests/typing-modules-bugs/ -/testsuite/tests/typing-modules-bugs/*.o -/testsuite/tests/typing-modules-bugs/*.a -/testsuite/tests/typing-modules-bugs/*.so -/testsuite/tests/typing-modules-bugs/*.obj -/testsuite/tests/typing-modules-bugs/*.cm[ioxa] -/testsuite/tests/typing-modules-bugs/*.cmx[as] -/testsuite/tests/typing-modules-bugs/*.annot -/testsuite/tests/typing-modules-bugs/*.result -/testsuite/tests/typing-modules-bugs/*.byte -/testsuite/tests/typing-modules-bugs/*.native -/testsuite/tests/typing-modules-bugs/program -/testsuite/tests/typing-modules-bugs/program.exe -/testsuite/tests/typing-modules-bugs/.depend -/testsuite/tests/typing-modules-bugs/.depend.nt -/testsuite/tests/typing-modules-bugs/.DS_Store - -# /testsuite/tests/typing-objects/ -/testsuite/tests/typing-objects/*.o -/testsuite/tests/typing-objects/*.a -/testsuite/tests/typing-objects/*.so -/testsuite/tests/typing-objects/*.obj -/testsuite/tests/typing-objects/*.cm[ioxa] -/testsuite/tests/typing-objects/*.cmx[as] -/testsuite/tests/typing-objects/*.annot -/testsuite/tests/typing-objects/*.result -/testsuite/tests/typing-objects/*.byte -/testsuite/tests/typing-objects/*.native -/testsuite/tests/typing-objects/program -/testsuite/tests/typing-objects/.depend -/testsuite/tests/typing-objects/.depend.nt -/testsuite/tests/typing-objects/.DS_Store - -# /testsuite/tests/typing-objects-bugs/ -/testsuite/tests/typing-objects-bugs/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/typing-objects-bugs/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/typing-objects-bugs/_log -/testsuite/tests/typing-objects-bugs/*.so -/testsuite/tests/typing-objects-bugs/*.a -/testsuite/tests/typing-objects-bugs/*.result -/testsuite/tests/typing-objects-bugs/*.byte -/testsuite/tests/typing-objects-bugs/*.native -/testsuite/tests/typing-objects-bugs/program -/testsuite/tests/typing-objects-bugs/*.cm* -/testsuite/tests/typing-objects-bugs/*.o - -# /testsuite/tests/typing-poly/ -/testsuite/tests/typing-poly/*.o -/testsuite/tests/typing-poly/*.a -/testsuite/tests/typing-poly/*.so -/testsuite/tests/typing-poly/*.obj -/testsuite/tests/typing-poly/*.cm[ioxa] -/testsuite/tests/typing-poly/*.cmx[as] -/testsuite/tests/typing-poly/*.annot -/testsuite/tests/typing-poly/*.result -/testsuite/tests/typing-poly/*.byte -/testsuite/tests/typing-poly/*.native -/testsuite/tests/typing-poly/program -/testsuite/tests/typing-poly/.depend -/testsuite/tests/typing-poly/.depend.nt -/testsuite/tests/typing-poly/.DS_Store - -# /testsuite/tests/typing-poly-bugs/ -/testsuite/tests/typing-poly-bugs/*.o -/testsuite/tests/typing-poly-bugs/*.a -/testsuite/tests/typing-poly-bugs/*.so -/testsuite/tests/typing-poly-bugs/*.obj -/testsuite/tests/typing-poly-bugs/*.cm[ioxa] -/testsuite/tests/typing-poly-bugs/*.cmx[as] -/testsuite/tests/typing-poly-bugs/*.annot -/testsuite/tests/typing-poly-bugs/*.result -/testsuite/tests/typing-poly-bugs/*.byte -/testsuite/tests/typing-poly-bugs/*.native -/testsuite/tests/typing-poly-bugs/program -/testsuite/tests/typing-poly-bugs/program.exe -/testsuite/tests/typing-poly-bugs/.depend -/testsuite/tests/typing-poly-bugs/.depend.nt -/testsuite/tests/typing-poly-bugs/.DS_Store - -# /testsuite/tests/typing-polyvariants-bugs/ -/testsuite/tests/typing-polyvariants-bugs/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/typing-polyvariants-bugs/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/typing-polyvariants-bugs/_log -/testsuite/tests/typing-polyvariants-bugs/*.so -/testsuite/tests/typing-polyvariants-bugs/*.a -/testsuite/tests/typing-polyvariants-bugs/*.result -/testsuite/tests/typing-polyvariants-bugs/*.byte -/testsuite/tests/typing-polyvariants-bugs/*.native -/testsuite/tests/typing-polyvariants-bugs/program -/testsuite/tests/typing-polyvariants-bugs/*.cm* -/testsuite/tests/typing-polyvariants-bugs/*.o - -# /testsuite/tests/typing-polyvariants-bugs-2/ -/testsuite/tests/typing-polyvariants-bugs-2/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/typing-polyvariants-bugs-2/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/typing-polyvariants-bugs-2/_log -/testsuite/tests/typing-polyvariants-bugs-2/*.so -/testsuite/tests/typing-polyvariants-bugs-2/*.a -/testsuite/tests/typing-polyvariants-bugs-2/*.result -/testsuite/tests/typing-polyvariants-bugs-2/*.byte -/testsuite/tests/typing-polyvariants-bugs-2/*.native -/testsuite/tests/typing-polyvariants-bugs-2/program -/testsuite/tests/typing-polyvariants-bugs-2/*.cm* -/testsuite/tests/typing-polyvariants-bugs-2/*.o - -# /testsuite/tests/typing-private/ -/testsuite/tests/typing-private/*.o -/testsuite/tests/typing-private/*.a -/testsuite/tests/typing-private/*.so -/testsuite/tests/typing-private/*.obj -/testsuite/tests/typing-private/*.cm[ioxa] -/testsuite/tests/typing-private/*.cmx[as] -/testsuite/tests/typing-private/*.annot -/testsuite/tests/typing-private/*.result -/testsuite/tests/typing-private/*.byte -/testsuite/tests/typing-private/*.native -/testsuite/tests/typing-private/program -/testsuite/tests/typing-private/.depend -/testsuite/tests/typing-private/.depend.nt -/testsuite/tests/typing-private/.DS_Store - -# /testsuite/tests/typing-private-bugs/ -/testsuite/tests/typing-private-bugs/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/typing-private-bugs/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/typing-private-bugs/_log -/testsuite/tests/typing-private-bugs/*.so -/testsuite/tests/typing-private-bugs/*.a -/testsuite/tests/typing-private-bugs/*.result -/testsuite/tests/typing-private-bugs/*.byte -/testsuite/tests/typing-private-bugs/*.native -/testsuite/tests/typing-private-bugs/program -/testsuite/tests/typing-private-bugs/*.cm* -/testsuite/tests/typing-private-bugs/*.o - -# /testsuite/tests/typing-recmod/ -/testsuite/tests/typing-recmod/# svn propset -R svn:ignore -F .svnignore . -/testsuite/tests/typing-recmod/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done -/testsuite/tests/typing-recmod/_log -/testsuite/tests/typing-recmod/*.so -/testsuite/tests/typing-recmod/*.a -/testsuite/tests/typing-recmod/*.result -/testsuite/tests/typing-recmod/*.byte -/testsuite/tests/typing-recmod/*.native -/testsuite/tests/typing-recmod/program -/testsuite/tests/typing-recmod/*.cm* -/testsuite/tests/typing-recmod/*.o - -# /testsuite/tests/typing-short-paths/ -/testsuite/tests/typing-short-paths/*.o -/testsuite/tests/typing-short-paths/*.a -/testsuite/tests/typing-short-paths/*.so -/testsuite/tests/typing-short-paths/*.obj -/testsuite/tests/typing-short-paths/*.cm[ioxat] -/testsuite/tests/typing-short-paths/*.cmx[as] -/testsuite/tests/typing-short-paths/*.cmti -/testsuite/tests/typing-short-paths/*.annot -/testsuite/tests/typing-short-paths/*.result -/testsuite/tests/typing-short-paths/*.byte -/testsuite/tests/typing-short-paths/*.native -/testsuite/tests/typing-short-paths/program -/testsuite/tests/typing-short-paths/program.exe -/testsuite/tests/typing-short-paths/.depend -/testsuite/tests/typing-short-paths/.depend.nt -/testsuite/tests/typing-short-paths/.DS_Store - -# /testsuite/tests/typing-signatures/ -/testsuite/tests/typing-signatures/*.o -/testsuite/tests/typing-signatures/*.a -/testsuite/tests/typing-signatures/*.so -/testsuite/tests/typing-signatures/*.obj -/testsuite/tests/typing-signatures/*.cm[ioxa] -/testsuite/tests/typing-signatures/*.cmx[as] -/testsuite/tests/typing-signatures/*.annot -/testsuite/tests/typing-signatures/*.result -/testsuite/tests/typing-signatures/*.byte -/testsuite/tests/typing-signatures/*.native -/testsuite/tests/typing-signatures/program -/testsuite/tests/typing-signatures/.depend -/testsuite/tests/typing-signatures/.depend.nt -/testsuite/tests/typing-signatures/.DS_Store - -# /testsuite/tests/typing-sigsubst/ -/testsuite/tests/typing-sigsubst/*.o -/testsuite/tests/typing-sigsubst/*.a -/testsuite/tests/typing-sigsubst/*.so -/testsuite/tests/typing-sigsubst/*.obj -/testsuite/tests/typing-sigsubst/*.cm[ioxa] -/testsuite/tests/typing-sigsubst/*.cmx[as] -/testsuite/tests/typing-sigsubst/*.annot -/testsuite/tests/typing-sigsubst/*.result -/testsuite/tests/typing-sigsubst/*.byte -/testsuite/tests/typing-sigsubst/*.native -/testsuite/tests/typing-sigsubst/program -/testsuite/tests/typing-sigsubst/.depend -/testsuite/tests/typing-sigsubst/.depend.nt -/testsuite/tests/typing-sigsubst/.DS_Store - -# /testsuite/tests/typing-typeparam/ -/testsuite/tests/typing-typeparam/*.o -/testsuite/tests/typing-typeparam/*.a -/testsuite/tests/typing-typeparam/*.so -/testsuite/tests/typing-typeparam/*.obj -/testsuite/tests/typing-typeparam/*.cm[ioxa] -/testsuite/tests/typing-typeparam/*.cmx[as] -/testsuite/tests/typing-typeparam/*.annot -/testsuite/tests/typing-typeparam/*.result -/testsuite/tests/typing-typeparam/*.byte -/testsuite/tests/typing-typeparam/*.native -/testsuite/tests/typing-typeparam/program -/testsuite/tests/typing-typeparam/.depend -/testsuite/tests/typing-typeparam/.depend.nt -/testsuite/tests/typing-typeparam/.DS_Store +/testsuite/tests/tool-lexyacc/scanner.ml +/testsuite/tests/tool-lexyacc/grammar.mli +/testsuite/tests/tool-lexyacc/grammar.ml -# /testsuite/tests/typing-warnings/ -/testsuite/tests/typing-warnings/*.o -/testsuite/tests/typing-warnings/*.a -/testsuite/tests/typing-warnings/*.so -/testsuite/tests/typing-warnings/*.obj -/testsuite/tests/typing-warnings/*.cm[ioxat] -/testsuite/tests/typing-warnings/*.cmx[as] -/testsuite/tests/typing-warnings/*.cmti -/testsuite/tests/typing-warnings/*.annot -/testsuite/tests/typing-warnings/*.result -/testsuite/tests/typing-warnings/*.byte -/testsuite/tests/typing-warnings/*.native -/testsuite/tests/typing-warnings/program -/testsuite/tests/typing-warnings/program.exe -/testsuite/tests/typing-warnings/.depend -/testsuite/tests/typing-warnings/.depend.nt -/testsuite/tests/typing-warnings/.DS_Store +/testsuite/tests/unboxed-primitive-args/main.ml +/testsuite/tests/unboxed-primitive-args/stubs.c -# /testsuite/tests/utils/ -/testsuite/tests/utils/*.o -/testsuite/tests/utils/*.a -/testsuite/tests/utils/*.so -/testsuite/tests/utils/*.obj -/testsuite/tests/utils/*.cm[ioxat] -/testsuite/tests/utils/*.cmx[as] -/testsuite/tests/utils/*.cmti -/testsuite/tests/utils/*.annot -/testsuite/tests/utils/*.result -/testsuite/tests/utils/*.byte -/testsuite/tests/utils/*.native -/testsuite/tests/utils/program -/testsuite/tests/utils/program.exe -/testsuite/tests/utils/.depend -/testsuite/tests/utils/.depend.nt -/testsuite/tests/utils/.DS_Store +/testsuite/tests/unwind/unwind_test -# /testsuite/tests/warnings/ -/testsuite/tests/warnings/*.o -/testsuite/tests/warnings/*.a -/testsuite/tests/warnings/*.so -/testsuite/tests/warnings/*.obj -/testsuite/tests/warnings/*.lib -/testsuite/tests/warnings/*.dll -/testsuite/tests/warnings/*.cm[ioxat] -/testsuite/tests/warnings/*.cmx[as] -/testsuite/tests/warnings/*.cmti -/testsuite/tests/warnings/*.annot -/testsuite/tests/warnings/*.result -/testsuite/tests/warnings/*.byte -/testsuite/tests/warnings/*.native -/testsuite/tests/warnings/program -/testsuite/tests/warnings/*.exe -/testsuite/tests/warnings/*.exe.manifest -/testsuite/tests/warnings/.depend -/testsuite/tests/warnings/.depend.nt -/testsuite/tests/warnings/.DS_Store +/testsuite/tests/warnings/w55.opt.opt_result +/testsuite/tests/warnings/w58.opt.opt_result -# /tools/ -/tools/*.o -/tools/*.a -/tools/*.so -/tools/*.obj -/tools/*.lib -/tools/*.dll -/tools/*.cm[ioxat] -/tools/*.cmx[as] -/tools/*.cmti -/tools/*.annot -/tools/*.result -/tools/*.byte -/tools/*.native -/tools/program -/tools/*.exe -/tools/*.exe.manifest -/tools/.depend -/tools/.depend.nt -/tools/.DS_Store /tools/ocamldep /tools/ocamldep.opt /tools/ocamldep.bak @@ -2699,86 +320,11 @@ /tools/objinfo_helper /tools/read_cmt /tools/read_cmt.opt +/tools/cmpbyt +/tools/stripdebug -# /toplevel/ -/toplevel/.depend -/toplevel/configure -/toplevel/ocamlc -/toplevel/ocamlc.opt -/toplevel/expunge -/toplevel/ocaml -/toplevel/ocamlopt -/toplevel/ocamlopt.opt -/toplevel/ocamlcomp.sh -/toplevel/ocamlcompopt.sh -/toplevel/package-macosx -/toplevel/.DS_Store -/toplevel/*.annot -/toplevel/_boot_log1 -/toplevel/_boot_log2 -/toplevel/_build -/toplevel/_log -/toplevel/myocamlbuild_config.ml -/toplevel/ocamlnat -/toplevel/*.cm* -/toplevel/*.o - -# /typing/ -/typing/*.o -/typing/*.a -/typing/*.so -/typing/*.obj -/typing/*.dll -/typing/*.cm[ioxat] -/typing/*.cmx[as] -/typing/*.cmti -/typing/*.annot -/typing/*.result -/typing/*.byte -/typing/*.native -/typing/program -/typing/*.exe -/typing/.depend -/typing/.depend.nt -/typing/.DS_Store - -# /utils/ -/utils/*.o -/utils/*.a -/utils/*.so -/utils/*.obj -/utils/*.dll -/utils/*.cm[ioxat] -/utils/*.cmx[as] -/utils/*.cmti -/utils/*.annot -/utils/*.result -/utils/*.byte -/utils/*.native -/utils/program -/utils/*.exe -/utils/.depend -/utils/.depend.nt -/utils/.DS_Store /utils/config.ml -# /yacc/ -/yacc/*.o -/yacc/*.a -/yacc/*.so -/yacc/*.obj -/yacc/*.cm[ioxa] -/yacc/*.cmx[as] -/yacc/*.annot -/yacc/*.result -/yacc/*.byte -/yacc/*.native -/yacc/program -/yacc/program.exe -/yacc/.depend -/yacc/.depend.nt -/yacc/.DS_Store /yacc/ocamlyacc -/yacc/ocamlyacc.exe /yacc/version.h /yacc/.gdb_history diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..dca1e0d2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "flexdll"] + path = flexdll + url = https://github.com/alainfrisch/flexdll.git diff --git a/.ignore b/.ignore deleted file mode 100644 index 6dce10ee..00000000 --- a/.ignore +++ /dev/null @@ -1,11 +0,0 @@ -configure -ocamlc -ocamlc.opt -expunge -ocaml -ocamlopt -ocamlopt.opt -ocamlcomp.sh -ocamlcompopt.sh -package-macosx -ocamlnat diff --git a/.merlin b/.merlin index 99779840..38628a47 100644 --- a/.merlin +++ b/.merlin @@ -1,6 +1,12 @@ S ./asmcomp B ./asmcomp +S ./middle_end +B ./middle_end + +S ./middle_end/base_types +B ./middle_end/base_types + S ./bytecomp B ./bytecomp @@ -48,4 +54,3 @@ B ./typing S ./utils B ./utils - diff --git a/.travis-ci.sh b/.travis-ci.sh old mode 100644 new mode 100755 index e34353af..8f847924 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -1,18 +1,126 @@ -case $XARCH in -i386) - ./configure - make world.opt - sudo make install - (cd testsuite && make all) - git clone git://github.com/ocaml/camlp4 -b 4.02 - (cd camlp4 && ./configure && make && sudo make install) - git clone git://github.com/ocaml/opam - (cd opam && ./configure && make lib-ext && make && sudo make install) - opam init -y -a git://github.com/ocaml/opam-repository - opam install -y utop - ;; -*) - echo unknown arch - exit 1 - ;; +#************************************************************************** +#* * +#* OCaml * +#* * +#* Anil Madhavapeddy, OCaml Labs * +#* * +#* Copyright 2014 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. * +#* * +#************************************************************************** + +PREFIX=~/local + +BuildAndTest () { + case $XARCH in + i386) + echo< /dev/null \ + && exit 1 || echo pass +} + +CheckTestsuiteModified () { + echo< /dev/null \ + && exit 1 || echo pass +} + +case $CI_KIND in +build) BuildAndTest;; +changes) CheckChangesModified;; +tests) CheckTestsuiteModified;; +*) echo unknown CI kind + exit 1 + ;; esac diff --git a/.travis.yml b/.travis.yml index 3015c16d..8ff82d84 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,29 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Anil Madhavapeddy, OCaml Labs * +#* * +#* Copyright 2014 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. * +#* * +#************************************************************************** + +sudo: false language: c +git: + submodules: false script: bash -ex .travis-ci.sh -env: - - XARCH=i386 +matrix: + include: + - env: CI_KIND=build XARCH=i386 + - env: CI_KIND=build XARCH=i386 CONFIG_ARG=-flambda + - env: CI_KIND=changes + - env: CI_KIND=tests + allow_failures: + - env: CI_KIND=changes + - env: CI_KIND=tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..f2476686 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,292 @@ +# How to contribute changes + +:+1::tada: First off, thank you for taking time to contribute! :tada::+1: + +The following is a set of guidelines for proposing changes to the +OCaml distribution. These are just guidelines, not rules, use your +best judgment and feel free to propose changes to this document itself +in a pull request. + +## Contribution + +Adding or modifying code is far from the only way to contribute to the +OCaml distribution. Bug reports (in particular when they come with +a reproducible example), simple typos or clarifications in the +documentation also help, and help evaluating and integrating existing +change proposals also help. Providing good answers on the discussion +forums, or asking the good questions that highlight deficiencies in +existing documentations, also help. We currently have more +contributors willing to propose changes than contributors willing to +review other people's changes, so more eyes on the existing change +requests is a good way to increase the integration bandwidth of external +contributions. + +There are also many valuable ways to contribute to the wider OCaml +ecosystem that do not involve changes to the OCaml distribution. + +The rest of the document is concerned with the form of change +proposals against the OCaml distribution. (Code changes, but also +improvement to documentation or implementation comments, which are +valuable changes on their own.) + + +## Coding guidelines + +You should not leave trailing whitespace; not have line longer than 80 +columns, not use tab characters (spaces only), and not use non-ASCII +characters. These typographical rules can be checked with the script +`tools/check-typo`. + +Otherwise, there are no strongly enforced guidelines specific to the +compiler -- and, as a result, the style may differ in the different +parts of the compiler. The general [OCaml Programming +Guidelines](https://ocaml.org/learn/tutorials/guidelines.html) are +good to keep in mind, and otherwise we strive for good taste and local +consistency (following the code located around your change). + +If you strongly feel that a style-related change would improve quality +of the existing code (for example, giving more descriptive names to +some variables throughout a module, factoring repeated code patterns +as auxiliary functions, or adding comments to document a part of the +code that you had trouble understanding), you can have code cleanup +commits at the beginning of your patch series, or submit code cleanups +as your change proposal. Those cleanups should remain separate commits +from the functional changes in the rest of the patch series; it is +easier to review commits that are specifically marked as exactly +preserving the code semantics. + + +## Test you must. + +Whenever applicable, merge requests must come with tests +exercising the affected features: regression tests for bug fixes, +and correctness tests for new features (including corner cases and +failure cases). For regression tests, testing other aspects of the +feature (in particular, related edge cases) that are not currently +covered is a good way to catch other instances of bugs -- this did +happen several times in the past. Warnings and errors should also +be tested. + +Tests go in the sub-directories of `testsuite/tests`. Running +`make all` in `testsuite/` runs all tests (this takes +a few minutes), and you can use `make one DIR=tests/foo` to run +the tests of a specific sub-directory. There are many kind of tests +already, so the easiest way to start is to extend or copy an +existing test. + +In general, running a test produces one (or several) `.result` file, +that are compared to one (or several) `.reference` file present in the +repository; the test succeeds if they are identical. If your patch +breaks a test, diffing the `.result` and `.reference` file is a way to +see what went wrong. Some reasonable compiler changes affect the +compiler output in way that make those outputs differ (for example +slight modifications of warning or error messages may break all tests +checking warnings). If you are positive that the new `.result` file +is correct (and that the change in behavior does not endanger +backward compatibility), you can replace the old `.reference` file +with it. Finally, when adding new tests, do not forget to include your +`.reference` files (but not `.result`) in the versioned repository. + +Testing is also a way to make sure reviewers see working +(and failing) examples of the feature you fix, extend or +introduce, rather than just an abstract description of it. + + +### Run tests before sending a PR + +You should run all the tests before creating the merge request or +pushing new commits (even if Travis will also do it for you): `make +tests` (this takes a few minutes). + +Unfortunately some of the `lib-threads` test are non-deterministic +and fail once in a while (it's hard to test these well). If they +consistently break after your change, you should investigate, but if +you only see a transient failure once and your change has no reason +to affect threading, it's probably not your fault. + + +## Description of the proposed change + +### In the merge request interface + +The description of the merge request must contain a precise +explanation of the proposed change. + +Before going in the implementation details, you should include +a summary of the change, and a high-level description of the design +of the proposed change, with example use-cases. + +### In the patches + +If some of the explanations you provide for the merge request would +make sense as comments in the code, or documentation in the manual, +you should include them there as well. + +In-code comments help make the codebase more accessible to newcomers +(many places in the compiler could benefit from a few +extra explanations), and they are also useful to code reviewers. In +particular, any subtlety in code that cannot be made +self-explanatory should come with an explanation in comment. If you +add some non-obvious code specifically to fix a bug, include the +issue number in comments. + +Do not assume that code reviewers are all experts in the existing +codebase. If you use subtle code, add a comment, even if the same +kind of code is used somewhere else in the same module. (If this is +a common and useful domain-specific idiom that is already explained +somewhere, pointing to this explanation in your commit message is +better than adding redundant explanations.) + +### User documentation + +Changes affecting the compiler libraries should be reflected in the +documentation comments of the relevant `.mli` files. + +It is recommended to included changes to the OCaml Reference Manual +(in particular for any change in the surface language), which is now +part of the main repository (under `manual/`). + +Finally, changes in command-line options should be integrated in the +manual, but also in the man pages present in the `man/` sub-directory +of the OCaml distribution. + +### Changelog + +Any user-visible change should have a Changelog entry: + +- in the right section (named sections if major feature, generic + "Bug fixes" and "Feature requests" otherwise) + +- using the label "`*`" if it breaks existing programs, "`-`" otherwise + +- with the issue number `PR#{N}` if from mantis, `GPR#{N}` if from github + (several numbers separated by commas can be used) + +- maintaining the order: each section lists Mantis PRs first in ascending + numerical order, followed by Github PRs + +- with a concise readable description of the change (possibly taken + from a commit message, but it should make sense to end-users + reading release notes) + +- crediting the people that worked on the feature + + The people that wrote the code should be credited of course, + but also substantial code reviews or design advice, and the + reporter of the bug (if applicable) or designer of the + feature request (if novel). + +- following the format + + {label} {issue number(s)}: {readable description} + ({credits}) + + note that the `{credits}` should be on their own line, aligned with the + issue number for readability + (`{readable description}` can be multiline to not overflow 80 + columns, and should be aligned with the issue number as well.) + +This changelog can be included in the main commit, if the merge +request is just one patch, or as a separate commit, if it's +a patch series and no particular commit feels best suited to +receive the Changelog entry. + +(Do not under-estimate the importance of a good changelog. Users do + read the release notes, and things forgotten from the changelog + will cause pain or regrets down the line.) + + +## Clean patch series + +Clean patch series are useful, both during the review process and +for code maintenance after it has been merged. Before submitting +your request, you should rebase your patch series: + +- on top of the OCaml branch in which you want to merge + (usually `trunk`), solving any conflicts. + +- into a few well-separated, self-contained patches (github PRs + can generate gazillions of micro-changes) + +- erasing history that does not make sense after the issue is merged + (back-and-forth between different designs, etc. The PR number + allows interested people to go back to the original discussion if + needed.) + +- bisectable: the distribution should be in a good state after + the application of each patch (in particular, later commits that + fix bugs in previous commits should always be squashed into the commit + they fix) + +- with readable commit messages (this is for future developers + needing to understand a change that happened in the past). Commit + messages should not overflow 80 columns, with the following format: + + {one-liner header description (with issue number if applicable)} + {blank line} + {one or several paragraphs of explanation if needed} + +During review, you may make many other changes to the patch +series. You can rebase it on the fly (if you `git push -f` on the +branch of the pull request in your personal clone, Github will +update the pull request automatically; remember to always create +a new branch for any) or wait until the discussion has converged, +once we agree the request is ready for merging. Doing a good +rebase is grunt work that takes some time and care (use `git +log -u` to make sure the rebase patches make sense), but: + +- It is easier and faster to do for the author of the patch than + for others (if rebasing against the current trunk creates + a conflict with another change you don't understand well, feel + free to ask). + +- Maintainers are usually short on time, and asking them to do + a rebase means they have less time to review and merge other + contributions. + +- The long-term benefits of keeping a clean, bisectable history + cannot be overstated. Imagine that in three years, under the + pressure of a coming release, a contributor ends up somewhere in + the middle of your patch series, wondering if or why it is the + cause of a specific issue. Wasting his or her time then + (with a "yolo" commit message, a big ugly commit of unrelated + changes, or an un-testable intermediary state) is a sure way to + generate ill will. + + +## Contributor License Agreement + +We distinguish two kind of contributions: + +- Small changes that do not bear a specific mark of their authors + (another developer recreating the change without access to the + original patch would write an indistinguishable patch), and are thus + not protected by copyright, do not require any particular + paperwork. This is convenient for everyone, and of course does not + mean that those contributions are of lesser importance. (For example + a bugfix can be obvious once a bug is understood, reported and + reproduced, and yet invaluable for users.) + +- Larger changes that are covered by copyright. For them, we require + contributors to sign a Contributor License Agreement (CLA), which + gives [INRIA](http://www.inria.fr/en/) (Institut National de + Recherche en Informatique et en Automatique) the rights to integrate + the contribution, maintain it, evolve it, and redistribute it under + the license of its choice. This is not a copyright *assignment* + (as requested by the Free Software Foundation for example), + contributors retain the copyright on their contribution, and can use + it as they see fit. The OCaml CLA is lightly adapted from [the + CLA](https://www.apache.org/licenses/icla.txt) of the Apache + Foundation, and is available in two versions: [for individual + contributors](http://caml.inria.fr/pub/docs/CLA-individual.doc) and + [for corporations](http://caml.inria.fr/pub/docs/CLA-corporate.doc). + +You must understand that, by proposing a contribution for integration +in the OCaml distribution, you accept that it be considered under one +of those regimes. In particular, in all cases you give INRIA the +permission to freely re-license the OCaml distribution including the +contribution. + +This ability to re-license allows INRIA to provide members of the +[Caml Consortium](http://caml.inria.fr/consortium/) with a license on +the Caml code base that is more permissive than the public license. diff --git a/Changes b/Changes index 3587d44b..9e871450 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,1044 @@ -OCaml 4.02.3: +OCaml 4.03.0: ------------- +(Changes that can break existing programs are marked with a "*") + +Language features: +================== + +- PR#5528: inline records for constructor arguments + (Alain Frisch) + +- PR#6220, PR#6403, PR#6437, PR#6801: + Improved redundancy and exhaustiveness checks for GADTs. + Namely, the redundancy checker now checks whether the uncovered pattern + of the pattern is actually inhabited, exploding at most one wild card. + This is also done for exhaustiveness when there is only one case. + Additionally, one can now write unreachable cases, of the form + "pat -> .", which are treated by the redundancy check. + (Jacques Garrigue) + +- PR#6374: allow "_ t" as a short-hand for "(_, _, ..) t" for n-ary type + constructors + (Alain Frisch) + +- PR#6714: allow [@@ocaml.warning] on most structure and signature items: + values, modules, module types + (whitequark) + +- PR#6806: Syntax shortcut for putting a type annotation on a record field: + { f1 : typ = e } is sugar for { f1 = (e : typ) } + { f1 : typ } is sugar for { f1 = (f1 : typ) } + (Valentin Gatien-Baron, review by Jérémie Dimino) + +- PR#6806: Allow type annotations before the "->" in "fun -> " + fun x y : (int * int) -> (x, y) + (Valentin Gatien-Baron, review by Jérémie Dimino) + +- GPR#26: support for "(type a b)" as syntactic sugar for "(type a) (type b)" + (Gabriel Scherer) + +- GPR#42: short functor type syntax: "S -> T" for "functor (_ : S) -> T" + (Leo White) + +- GPR#88: allow field punning in object copying expressions: + {< x; y; >} is sugar for {< x = x; y = y; >} + (Jeremy Yallop) + +- GPR#112: octal escape sequences for char and string literals + "Make it \o033[1mBOLD\o033[0m" + (Rafaël Bocquet, request by John Whitingthon) + +- GPR#167: allow to annotate externals' arguments and result types so + they can be unboxed or untagged: [@unboxed], [@untagged]. Supports + untagging int and unboxing int32, int64, nativeint and float. + (Jérémie Dimino, Mark Shinwell) + +- GPR#173: [@inline] and [@inlined] attributes (for function declarations + and call sites respectively) to control inlining + (Pierre Chambart, Mark Shinwell) + +- GPR#188: accept [@@immediate] attribute on type declarations to mark types + that are represented at runtime by an integer + (Will Crichton, reviewed by Leo White) + +* GPR#234: allow "[]" as a user-defined constructor. Demand parenthesis + around "::" when using "::" as user-defined constructor: + code using "| :: of ..." must change to "| (::) of ...". + (Runhang Li, review by Damien Doligez) + +- GPR#240: replace special annotations on externals by attributes: + * "float" is generalized to [@@unboxed] + * "noalloc" becomes [@@noalloc] + Deprecate "float" and "noalloc". + (Jérémie Dimino) + +- GPR#254: @ocaml.warn_on_literal_pattern attribute on constructors to + warn when the argument is matches against a constant pattern. This + attribute is applied on predefined exception constructors which + carry purely informational (with no stability guarantee) messages. + (Alain Frisch) + +- GPR#268: hexadecimal notation for floating-point literals: -0x1.ffffp+987 + In OCaml source code, FP literals can be written using the hexadecimal + notation 0xp from ISO C99. + (Xavier Leroy) + +- GPR#273: allow to get the extension slot of an extension constructor + by writing [%extension_constructor ] + (Jérémie Dimino) + +- GPR#282: change short-paths penalty heuristic to assign the same cost to + idents containing double underscores as to idents starting with an underscore + (Thomas Refis, Leo White) + +- PR#6681 GPR#326: signature items are now accepted as payloads for + extension and attributes, using the syntax [%foo: SIG ] or [@foo: SIG ]. + Examples: "[%%client: val foo : int]" or "val%client foo : int". + (Alain Frisch and Gabriel Radanne) + +* GPR#342: Allow shortcuts for extension and attributes on all keywords: + module%foo, class[@foo], etc. + The attribute in "let[@foo] .. in .." is now attached to the value binding, + not to the expression. + (Gabriel Radanne) + +Compilers: +========== + +* PR#4231, PR#5461: warning 31 is now fatal by default + (Warning 31: A module is linked twice in the same executable.) + This is an interim solution; double-linking of modules has dangerous + semantics, eg. exception constructors end up with two distinct declarations. + (Alain Frisch) + +- PR#4800: better compilation of tuple assignment + (Gabriel Scherer and Alain Frisch) + +- PR#5995: keep -for-pack into account to name exceptions; + -for-pack should now be used during bytecode compilation as well + (Alain Frisch, report by Christophe Troestler) + +- PR#6400: better error message for '_' used as an expression + (Alain Frisch, report by whitequark) + +- PR#6501: harden the native-code generator against certain uses of "%identity" + (Xavier Leroy, report by Antoine Miné) + +- PR#6636: add --version option + (whitequark) + +- PR#6679: fix pprintast printing of constraints in type declarations + (Alain Frisch, report by Jun Furuse) + +- PR#6737: fix Typedtree attributes on (fun x -> body) expressions + (Alain Frisch, report by Oleg Kiselyov) + +* PR#6865: remove special case for parsing "let _ = expr" in structures + (Jérémie Dimino, Alain Frisch) + +* PR#6438, PR#7059, GPR#315: Pattern guard disables exhaustiveness check + (function Some x when x = 0 -> ()) will now raise warning 8 (non-exhaustive) + instead of warning 25 (all clauses are guarded). 25 isn't raised anymore. + Projects that set warning 8 as an error may fail to compile (presumably + this is the semantics they wanted). + (Alain Frisch, request by Martin Jambon and John Whitington) + +- PR#6920: fix debug informations around uses of %apply or %revapply + (Jérémie Dimino, report by Daniel Bünzli) + +- PR#6939: Segfault with improper use of let-rec + (Alain Frisch) + +- PR#6943: native-code generator for POWER/PowerPC 64 bits, both in + big-endian (ppc64) and little-endian (ppc64le) configuration. + (Xavier Leroy, with inspiration from RedHat's unofficial ppc64 and ppc64le + ports) + +- PR#6979: better code generation in x86-32 backend for copying floats to + the stack + (Marc Lasson, review by Xavier Leroy) + +- PR#7018: fix missing identifier renaming during inlining + (Alain Frisch, review by Xavier Leroy) + +- PR#7022, GPR#259: unbox float and boxed ints earlier, avoid second pass + (Alain Frisch) + +- PR#7026, GPR#288: remove write barrier for polymorphic variants without + arguments + (Simon Cruanes) + +- PR#7031: new warning 57, ambiguous guarded or-patterns + (Luc Maranget, Gabriel Scherer, report by Martin Clochard and Claude Marché) + +- PR#7064, GPR#316: allowing to mark compilation units and sub-modules as + deprecated + (Alain Frisch) + +- PR#7067: fix performance regression (wrt. 4.01) in the native compiler + for long nested structures + (Alain Frisch, report by Daniel Bünzli, review by Jacques Garrigue) + +- PR#7097: fix strange syntax error message around illegal packaged module + signature constraints + (Alain Frisch, report by Jun Furuse) + +- PR#7118, PR#7120, GPR#408, GPR#476: Bug fixed in stack unwinding + metadata generation. Was a cause of crashes in GUI programs on OS X. + (Bart Jacobs, review by Mark Shinwell) + +- PR#7168: Exceeding stack limit in bytecode can lead to a crash. + (Jacques-Henri Jourdan) + +- PR#7232: Strange Pprintast output with ppx_deriving + (Damien Doligez, report by Anton Bachin) + +- GPR#17: some cmm optimizations of integer operations with constants + (Stephen Dolan, review by Pierre Chambart) + +- GPR#89: improve type-specialization of unapplied primitives: + unapplied annotations (compare : int -> _), + type propagation (List.sort compare [1;2;3]) + and propagation from module signatures now lead to specialization + (Frédéric Bour, review by Gabriel Scherer) + +- GPR#107: Prevent more unnecessary float boxing, especially in `if` and `match` + (Vladimir Brankov, review by Alain Frisch) + +- GPR#109: new (lazy) unboxing strategy for float and int references + (Vladimir Brankov, review by Alain Frisch) + +- GPR#115: More precise typing of values at the C-- and Mach level. + (Xavier Leroy, review by Pierre Chambart) + +- GPR#132: Flambda: new intermediate language and "middle-end" optimizers + (Pierre Chambart, Mark Shinwell, Leo White) + +- GPR#212, PR#7226, GPR#542: emit column position in gas assembly `.loc` + (Frédéric Bour, Anton Bachin) + +- GPR#207: Colors in compiler messages (warnings, errors) + configure with -color {auto|always|never} or TERM=dumb + (Simon Cruanes, review by Gabriel Scherer) + +- GPR#258: more precise information on PowerPC instruction sizes + (Pierre Chambart, Xavier Leroy) + +- GPR#263: improve code generation for if-equivalents of (&&) and (||) + (Pierre Chambart) + +- GPR#270: Make [transl_exception_constructor] generate [Immutable] blocks + (Mark Shinwell) + +- GPR#271: Fix incorrect mutability flag when records are built using "with" + (Mark Shinwell) + +- GPR#275: native-code generator for IBM z System running Linux. + In memoriam Gene Amdahl, 1922-2015. + (Bill O'Farrell, Tristan Amini, Xavier Leroy) + +- GPR#282: relax short-paths safety check in presence of module aliases, take + penalty into account while building the printing map. + (Thomas Refis, Leo White) + +- GPR#306: Instrument the compiler to debug performance regressions + (Pierre Chambart) + +- GPR#319: add warning 58 for missing cmx files, and + extend -opaque option to mli files: a missing .cmx does not warn + if the corresponding .cmi is compiled -opaque. + (Leo White) + +- GPR#388: OCAML_FLEXLINK environment variable allows overriding flexlink + command (David Allsopp) + +- GPR#392: put all parsetree invariants in a new module Ast_invariants + (Jérémie Dimino) + +- GPR#407: don't display the name of compiled .c files when calling the + Microsoft C Compiler (same as the assembler). + (David Allsopp) + +- GPR#431: permit constant float arrays to be eligible for pattern match + branch merging + (Pierre Chambart) + +- GPR#455: provide more debugging information to Js_of_ocaml + (Jérôme Vouillon) + +- GPR#514, GPR#554: Added several command-line flags to explicitly enable + settings that are currently the default: + `-alias-deps`, `-app-funct`, `-no-keep-docs`, `-no-keep-locs`, + `-no-principal`, `-no-rectypes`, `-no-strict-formats` + (Demi Obenour) + +- GPR#545: use reraise to preserve backtrace on + `match .. with exception e -> raise e` + (Nicolas Ojeda Bar, review by Gabriel Scherer) + +Runtime system: +=============== + +- PR#3612, PR#92: allow allocating custom block with finalizers + in the minor heap. + (Pierre Chambart) + +* PR#6517: use ISO C99 types {,u}int{32,64}_t in preference to our homegrown + types {,u}int{32,64}. + C stubs may have to be updated as {,u}int{32,64}_t are not defined anymore. + (Xavier Leroy) + +- PR#6760: closures evaluated in the toplevel can now be marshalled + (whitequark, review by Jacques-Henri Jourdan) + +- PR#6902, GPR#210: emit a runtime warning on stderr + when finalizing an I/O channel which is still open: + "channel opened on file '...' dies without being closed" + this is controlled by OCAMLRUNPARAM=W=1 or with Sys.enable_runtime_warnings. + The behavior of affected program is not changed, + but they should still be fixed. + (Alain Frisch, review by Damien Doligez) + +- Signal handling: for read-and-clear, use GCC/Clang atomic builtins + if available. + (Xavier Leroy) + +- PR#6910, GPR#224: marshaling (output_value, input_value, et al) + now support marshaled data bigger than 4 Gb. + (Xavier Leroy) + +* GPR#226: select higher levels of optimization for GCC >= 3.4 and Clang + when compiling the run-time system and C stub code. + "-std=gnu99 -O2 -fno-strict-aliasing -fwrapv" is used by default. + This also affects default flags for user stubs compiled with "ocamlc -c foo.c" + and may uncover bugs in them. + (Xavier Leroy) + +- GPR#262: Multiple GC roots per compilation unit + (Pierre Chambart, Mark Shinwell, review by Damien Doligez) + +* 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) + +- GPR#325: Add v=0x400 flag to OCAMLRUNPARAM to display GC stats on exit + (Louis Gesbert, review by Alain Frisch) + +Standard library: +================= + +- PR#1460, GPR#230: Array.map2, Array.iter2 + (John Christopher McAlpine) + +- PR#5197, GPR#63: Arg: allow flags such as --flag=arg as well as --flag arg + (Richard Jones) + +- PR#6017, PR#7034, GPR#267: More efficient ifprintf implementation + (Jeremy Yallop, review by Gabriel Scherer) + +- PR#6296: Some documentation on the floating-point representations + recognized by Pervasives.float_of_string + (Xavier Leroy) + +- PR#6316: Scanf.scanf failure on %u formats when reading big integers + (Xavier Leroy, Benoît Vaugon) + +- PR#6321: guarantee that "hypot infinity nan = infinity" + (for conformance with ISO C99) + (Xavier Leroy) + +- PR#6390, GPR#36: expose Sys.{int_size,max_wosize} for js_of_ocaml portability + (Hugo Heuzard) + +- PR#6449: Add Map.union + (Alain Frisch) + +* PR#6494: Add 'equal' functions in modules + Bytes, Char, Digest, Int32, Int64, Nativeint, and String + Users defining their own modules with signature 'module type of Int32' + have to extend their implementation. + (Romain Calascibetta) + +* PR#6524, GPR#79: Filename: Optional ?perms argument to open_temp_file + May break partial applications of the function (fix by passing ?perms:None) + (Daniel Bünzli, review by Jacques-Pascal Deplaix) + +* PR#6525, GPR#80: Add Uchar module to the standard library + May introduce module name conflicts with existing projects. + (Daniel Bünzli, review by Yoriyuki Yamagata and Damien Doligez) + +- PR#6577: improve performance of %L, %l, %n, %S, %C format specifiers + (Alain Frisch) + +- PR#6585: fix memory leak in win32unix/createprocess.c + (Alain Frisch, report by user 'aha') + +- PR#6645, GPR#174: Guarantee that Set.add, Set.remove, Set.filter + return the original set if no change is required + (Alain Frisch, Mohamed Iguernlala) + +- PR#6649, GPR#222: accept (int_of_string "+3") + (John Christopher McAlpine) + +- PR#6694, PR#6695, GPR#124: deprecate functions using ISO-8859-1 character set + in Char, Bytes, String and provide alternatives *_acii using US-ASCII. + Affected functions: + {Char,String,Bytes}.{uppercase,lowercase}, + {String,Bytes}.{capitalize,uncaptialize} + (whitequark, review by Damien Doligez) + +- GPR#22: Add the Ephemeron module that implements ephemerons and weak + hash table + (François Bobot, review by Damien Doligez, Daniel Bünzli, + Alain Frisch, Pierre Chambart) + +- GPR#164: more efficient (branchless) implementation of Pervasives.compare + specialized at type 'float'. + (Vladimir Brankov) + +- GPR#175: Guarantee that Map.add, Map.remove, Map.filter + return the original map if no change is required. + (Mohamed Iguernlala) + +- GPR#201: generalize types of Printf.{ifprintf,ikfprintf} + (Maxence Guesdon) + +- GPR#216: add the missing POSIX.1-2001 signals in Sys + (Guillaume Bury) + +- GPR#239: remove type-unsafe code from Stream + (Pierre Chambart, review by Gabriel Scherer and Jeremy Yallop) + +- GPR#250: Check for negative start element in Array.sub + (Jeremy Yallop) + +- GPR#265: new implementation of Queue avoiding Obj.magic + (Jérémie Dimino) + +- GPR#268, GPR#303: '%h' and '%H' modifiers for printf and scanf to + support floating-point numbers in hexadecimal notation + (Xavier Leroy, Benoît Vaugon) + +- GPR#272: Switch classify_float to [@@unboxed] + (Alain Frisch) + +- Improve speed of classify_float by not going through fpclassify() + (Alain Frisch, Xavier Leroy) + +- GPR#277: Switch the following externals to [@@unboxed]: + * {Nativeint,Int32,Int64}.{of,to}_float + * Int{32,64}.float_of_bits + * Int{32,64}.bits_of_float + (Jérémie Dimino) + +- GPR#281: Switch the following externals to [@@unboxed]: + * Sys.time (and [@@noalloc]) + * Pervasives.ldexp (and [@@noalloc]) + * Pervasives.compare for float, nativeint, int32, int64. + (François Bobot) + +- PR#3622, GPR#195: add function Stack.fold + (Simon Cruanes) + +- GPR#329: Add exists, for_all, mem and memq functions in Array + (Bernhard Schommer) + +- GPR#337: Add [Hashtbl.filter_map_inplace] + (Alain Frisch) + +- GPR#356: Add [Format.kasprintf] + (Jérémie Dimino, Mark Shinwell) + +Type system: +============ + +- PR#5545: Type annotations on methods cannot control the choice of abbreviation + (Jacques Garrigue) + +* PR#6465: allow incremental weakening of module aliases. + This is done by adding equations to submodules when expanding aliases. + In theory this may be incompatible is some corner cases defining a module + type through inference, but no breakage known on published code. + (Jacques Garrigue) + +- PR#6593: Functor application in tests/basic-modules fails after commit 15405 + (Jacques Garrigue) + +Toplevel and debugger: +====================== + +- PR#6113: Add descriptions to directives, and display them via #help + (Nick Giannarakis, Berke Durak, Francis Southern and Gabriel Scherer) + +- PR#6396: Warnings-as-errors not properly flushed in the toplevel + (Alain Frisch) + +- PR#6401: use proper error reporting for toplevel environment initialization: + no more Env.Error(_) at start time + (Gabriel Scherer, Alain Frisch) + +- PR#6468: toplevel now supports backtraces if invoked with OCAMLRUNPARAM=b + (whitequark and Jake Donham, + review by Gabriel Scherer and Jacques-Henri Jourdan) + +- PR#6906: wrong error location for unmatched paren with #use in toplevel + (Damien Doligez, report by Kenichi Asai) + +- PR#6935, GPR#298: crash in debugger when load_printer is given a directory + (Junsong Li, review by Gabriel Scherer) + +- PR#7081: report preprocessor warnings in the toplevel + (Valentin Gatien-Baron, review by Jérémie Dimino) + +- PR#7098: Loss of ppx context in toplevel after an exception + (Alain Frisch, report by whitequark) + +- PR#7101: The toplevel does not close in_channel for libraries specified on + its command line + (Alain Frisch) + +- PR#7119: the toplevel does not respect [@@@warning] + (Alain Frisch, report by Gabriel Radanne) + +Other libraries: +================ + +* Unix library: channels created by Unix.in_channel_of_descr or + Unix.out_channel_of_descr no longer support text mode under Windows. + Calling [set_binary_mode_{in,out} chan false] on these channels + now causes an error. + (Xavier Leroy) + +- PR#4023 and GPR#68: add Unix.sleepf (sleep with sub-second resolution) + (Evgenii Lepikhin and Xavier Leroy) + +* Protect Unix.sleep against interruptions by handled signals. + Before, a handled signal could cause Unix.sleep to return early. + Now, the sleep is restarted until the given time is elapsed. + (Xavier Leroy) + +* PR#6120, GPR#462: implement Unix.symlink and Unix.readlink on + Windows. Unix.symlink has a new optional argument to_dir (ignored on + non-native Windows platforms). stat functions reimplemented to avoid + buggy Microsoft CRT implementations (native Windows only) + (David Allsopp, review by Daniel Bünzli) + +- PR#6263: add kind_size_in_bytes and size_in_bytes functions + to Bigarray module. + (Runhang Li, review by Mark Shinwell) + +- PR#6289: Unix.utimes uses the current time only if both arguments + are exactly 0.0. Also, use sub-second resolution if available. + (Xavier Leroy, report by Christophe Troestler) + +- PR#6896: serious reimplementation of Big_int.float_of_big_int and + Ratio.float_of_ratio, ensuring that the result is correctly rounded. + (Xavier Leroy) + +- PR#6989: in Str library, make sure that all \(...\) groups are binding + and can be consulted with Str.matched_group. There used to be + a limitation to 32 binding groups. + (Xavier Leroy) + +- PR#7013: spurious wake-up in the Event module + (Xavier Leroy) + +- PR#7024: in documentation of Str regular expressions, clarify what + "end of line" means for "^" and "$" regexps. + (Xavier Leroy, question by Fredrik Lindgren) + +- PR#7209: do not run at_exit handlers in [Unix.create_process] and + similar functions when the [exec] call fails in the child process + (Jérémie Dimino) + +OCamldep: +========= + +- GPR#286: add support for module aliases + (Jacques Garrigue) + +Manual: +======= + +- GPR#302: The OCaml reference manual is now included in the manual/ + subdirectory of the main OCaml source repository. Contributions to + the manual are warmly welcome. + (François Bobot, review by Florian Angeletti) + +- PR#6601: replace strcpy with caml_strdup in sample code + (Christopher Zimmermann) + +- PR#6676: ongoing simplification of the "Language Extensions" section + (Alain Frisch, John Whitington) + +- PR#6898: Update win32 support documentation of the Unix library + (Damien Doligez, report by Daniel Bünzli) + +- PR#7092, GPR#379: Add missing documentation for new 4.03 features + (Florian Angeletti) + +- PR#7094, GPR#468, GPR#551: add new section 8.5 to document warnings + The general idea is to document warnings that may require explanations. + Currently documented warnings are: + - 52: Fragile constant pattern. + - 57: Ambiguous or-pattern variables under guard + (Florian Angeletti and Gabriel Scherer) + +- PR#7109, GPR#380: Fix bigarray documentation layout + (Florian Angeletti, Leo White) + +Bug fixes: +========== + +- PR#3612: memory leak in bigarray read from file + (Pierre Chambart, report by Gary Huber) + +* PR#4166, PR#6956: force linking when calling external C primitives + (Jacques Garrigue, reports by Markus Mottl and Christophe Troestler) + +* PR#4466, PR#5325: under Windows, concurrent read and write operations + on the same socket could block unexpectedly. Fixed by keeping sockets + in asynchronous mode rather than creating them in synchronous mode. + (Xavier Leroy) + +* PR#4539: change exception string raised when comparing functional values + May break programs matching on the string argument of Invalid_argument. + Matching on the string argument of Invalid_argument or Failure is a + programming mistake: these strings may change in future versions. + (Nicolas Braud-Santoni, report by Eric Cooper) + +- PR#4832: Filling bigarrays may block out runtime + (Markus Mottl) + +- PR#5663: program rejected due to nongeneralizable type variable that + appears nowhere + (Jacques Garrigue, report by Stephen Weeks) + +- PR#5780: report more informative type names in GADTs error messages + (Jacques Garrigue, report by Sebastien Furic) + +- PR#5887: move the byterun/*.h headers to byterun/caml/*.h to avoid header + name clashes + (Jérôme Vouillon and Adrien Nader and whitequark) + +* PR#6081: ocaml now adds script's directory to search path, not current + directory + (Thomas Leonard and Damien Doligez) + +- PR#6108, PR#6802: fail cleanly if dynlink.cma or ocamltoplevel.cma + are loaded inside the toplevel loop. + (Xavier Leroy) + +- PR#6171: Confusing error message when a type escapes its scope. + (Jacques Garrigue and Leo White, report by John Whitington) + +- PR#6340: Incorrect handling of \r when processing "Windows" source files + (Damien Doligez, report by David Allsopp) + +- PR#6342: Incorrect error message when type constraints differ + (Alain Frisch, report by Philippe Wang) + +* PR#6521: {Bytes,Char,String}.escaped were locale-dependent + we now escape all non-ASCII-printable instead of a locale-dependent subset. + (Damien Doligez, report by Jun Furuse) + +- PR#6526: ocamllex should not warn on unescaped newline inside comments + (Damien Doligez, report by user 'dhekir') + +- PR#6341: ocamldoc -colorize-code adds spurious
tags to
 blocks
+  (Maxence Guesdon, report by Damien Doligez)
+
+- PR#6560: Wrong failure message for {Int32,Int64,NativeInt}.of_string
+  It reported (Failure "int_of_string"), now "Int32.of_string" etc.
+  (Maxime Dénès and Gabriel Scherer)
+
+- PR#6648: show_module should indicate its elision
+  (Jacques Garrigue, report by Leo White)
+
+- PR#6650: Cty_constr not handled correctly by Subst
+  (Jacques Garrigue, report by Leo White)
+
+- PR#6651: Failing component lookup
+  (Jacques Garrigue, report by Leo White)
+
+* PR#6664: Crash when finalising lazy values of the wrong type.
+  (Damien Doligez)
+
+- PR#6672: Unused variance specification allowed in with constraint
+  (Jacques Garrigue, report by Leo White)
+
+- PR#6677: Allow to disable warning 39 (useless "rec") with [@ocaml.warning]
+  applied to the first value binding of the would-be "rec" declaration
+  (Alain Frisch, report by Jun Furuse)
+
+- PR#6744: Univars can escape through polymorphic variants (partial fix)
+  (Jacques Garrigue, report by Leo White)
+
+- PR#6752: Extensible variant types and scope escaping
+  A side-effect of the fix is that (ocamlc -i) sometimes reports
+  (type-sound) invalid signature, with a type used before its declaration.
+  (Jacques Garrigue, report by Maxence Guesdon)
+
+- PR#6762: improve warning 45 in presence of re-exported type definitions
+  (Warning 45: open statement shadows the constructor)
+  (Alain Frisch, report by Olivier Andrieu)
+
+- PR#6776: Failure to kill the "tick" thread, segfault when exiting the runtime
+  (Damien Doligez, report by Thomas Braibant)
+
+- PR#6780: Poor error message for wrong -farch and -ffpu options (ocamlopt, ARM)
+  (Xavier Leroy, report by whitequark)
+
+- PR#6805: Duplicated expression in case of hole in a non-failing switch.
+  (Luc Maranget)
+
+* PR#6808: the parsing of OCAMLRUNPARAM is too lax
+  (Damien Doligez)
+
+- PR#6874: Inefficient code generated for module function arguments
+  (Jacques Garrigue, report by Markus Mottl)
+
+- PR#6888: The list command of ocamldebug uses the wrong file
+  (Damien Doligez, report by Pierre-Marie Pédrot)
+
+- PR#6897: Bad error message for some pattern matching on extensible variants
+  (Alain Frisch, report by Gabriel Radanne)
+
+- PR#6899: Optional parameters and non generalizable type variables
+  (Thomas Refis and Leo White)
+
+- PR#6907: Stack overflow printing error in class declaration
+  (Jacques Garrigue, report by Ivan Gotovchits)
+
+- PR#6931: Incorrect error message on type error inside record construction
+  (Damien Doligez, report by Leo White)
+
+- PR#6938: fix regression on "%047.27{l,L,n}{d,i,x,X,o,u}"
+  (Benoît Vaugon, report by Arduino Cascella)
+
+- PR#6944: let module X = Path in … is not typed as a module alias
+  (Jacques Garrigue, report by Frédéric Bour)
+
+- PR#6945 and GPR#227: protect Sys and Unix functions against string
+    arguments containing the null character '\000'
+  (Simon Cruanes and Xavier Leroy, report by Daniel Bünzli)
+
+- PR#6946: Uncaught exception with wrong type for "%ignore"
+  (Jacques Garrigue, report by Leo White)
+
+- PR#6954: Infinite loop in type checker with module aliases
+  (Jacques Garrigue, report by Mark Mottl)
+
+- PR#6972, GPR#276: 4.02.3 regression on documentation comments in .cmt files
+  (Leo White, report by Olivier Andrieu)
+
+- PR#6977: String literals in comments interpret escape sequences
+  (Damien Doligez, report by Daniel Bünzli and David Sheets)
+
+- PR#6980: Assert failure from polymorphic variants and existentials
+  (Jacques Garrigue, report by Leo White)
+
+- PR#6981: Ctype.Unify(_) with associated functor arg refering to previous one
+  (Jacques Garrigue, report by Nicholas Labich)
+
+- PR#6982: unexpected type error when packing a module alias
+  (Jacques Garrigue, report by Valentin Gatien-Baron)
+
+- PR#6985: `module type of struct include Bar end exposes
+           %s#row when Bar contains private row types
+  (Jacques Garrigue, report by Nicholas Labich)
+
+- PR#6992: Segfault from bug in GADT/module typing
+  (Jacques Garrigue, report by Stephen Dolan)
+
+- PR#6993: Segfault from recursive modules violating exhaustiveness assumptions
+  (Jacques Garrigue, report by Stephen Dolan)
+
+- PR#6998: Typer fails reading unnecessary cmis with -no-alias-deps and -w -49
+  (Leo White, report by Valentin Gatien-Baron)
+
+- PR#7003: String.sub may cause segmentation fault on sizes above 2^31
+  (Damien Doligez, report by Radek Micek)
+
+- PR#7008: Fatal error in ocamlc with empty compilation unit name
+  (Damien Doligez, report by Cesar Kunz)
+
+- PR#7012: Variable name forgotten when it starts with a capital letter
+  (Jacques Garrigue, Gabriel Scherer,
+   report by Thomas Leonard and Florian Angeletti)
+
+- PR#7016: fix Stack overflow in GADT typing
+  Note: Equi-recursive types are considered when checking GADT pattern
+  exhaustiveness, even when -rectypes is not used.
+  (Jacques Garrigue, report by Mikhail Mandrykin)
+
+- PR#7030: libasmrun_shared.so fails to build on SPARC Solaris
+  (report and fix by Patrick Star)
+
+- PR#7036: Module alias is not taken into account when checking module
+  type compatibility (in a class type)
+  (Jacques Garrigue)
+
+- PR#7037: more reproducible builds, don't put temp file names into objects
+  (Xavier Leroy)
+
+- PR#7038: out of memory condition in caml_io_mutex_lock
+  (Xavier Leroy, report by Marc Lasson)
+
+- PR#7039: Unix.getsockname returns garbage for unnamed PF_UNIX sockets
+  (Xavier Leroy)
+
+- PR#7042 and GPR#295: CSE optimization confuses the FP literals +0.0 and -0.0
+  (Xavier Leroy)
+
+- PR#7075: Fix repetitions in ocamldoc generated documentation
+  (Florian Angeletti)
+
+- PR#7082: Object type in recursive module's `with` annotation
+  (Jacques Garrigue and Alain Frisch, report by Nicholas Labich)
+
+- PR#7096: ocamldoc uses an incorrect subscript/superscript style
+  (Gabriel Scherer, report by user 'pierpa')
+
+- PR#7108: ocamldoc, have -html preserve custom/extended html generators
+  (Armaël Guéneau)
+
+- PR#7111: reject empty let bindings instead of printing incorrect syntax
+  (Jérémie Dimino)
+
+* PR#7113: -safe-string can break GADT compatibility check
+  bytes and string are now considered compatible even with -safe-string,
+  which may break exhaustivity for code assuming they were disjoint
+  (Jacques Garrigue, report by Jeremy Yallop)
+
+- PR#7115: shadowing in a branch of a GADT match breaks unused variable warning
+  (Alain Frisch, report by Valentin Gatien-Baron)
+
+- PR#7133, GPR#450: generate local jump labels on OS X
+  (Bart Jacobs)
+
+- PR#7135: only warn about ground coercions in -principal mode
+  (Jacques Garrigue, report by Jeremy Yallop)
+
+- PR#7152: Typing equality involving non-generalizable type variable
+  (Jacques Garrigue, report by François Bobot)
+
+- PR#7160: Type synonym definitions can weaken gadt constructor types
+  (Jacques Garrigue, report by Mikhail Mandrykin)
+
+- PR#7181: Misleading error message with GADTs and polymorphic variants
+  (Jacques Garrigue, report by Pierre Chambart)
+
+- PR#7182: Assertion failure with recursive modules and externals
+  (Jacques Garrigue, report by Jeremy Yallop)
+
+- PR#7196: "let open" is not correctly pretty-printed to the left of a ';'
+  (Gabriel Scherer, report by Christophe Raffalli)
+
+- PR#7214: Assertion failure in Env.add_gadt_instances
+  (Jacques Garrigue, report by Stephen Dolan)
+
+- PR#7220: fix a memory leak when using both threads and exception backtraces
+  (Gabriel Scherer, review by François Bobot, report by Rob Hoes)
+
+- PR#7222: Escaped existential type
+  (Jacques Garrigue, report by Florian Angeletti)
+
+- PR#7230: Scrutinee discarded in match with only refutation cases
+  (Jacques Garrigue, report by Jeremy Yallop)
+
+- PR#7234: Compatibility check wrong for abstract type constructors
+  (Jacques Garrigue, report by Stephen Dolan)
+
+- GPR#205: Clear caml_backtrace_last_exn before registering as root
+  (report and fix by Frederic Bour)
+
+- GPR#220: minor -dsource error on recursive modules
+  (Hongbo Zhang)
+
+- GPR#228: fix a dangling internal pointer in (bytecode )debug_info
+  (Gabriel Scherer and Mark Shinwell and Xavier Leroy)
+
+- GPR#233: Make CamlinternalMod.init_mod robust to optimization
+  (Pierre Chambart, Mark Shinwell)
+
+- GPR#249: fix a few hardcoded ar commands
+  (Daniel Bünzli)
+
+- GPR#251: fix cross-compilation with ocamldoc enabled
+  (whitequark)
+
+- GPR#280: Fix stdlib dependencies for .p.cmx
+  (Pierre Chambart, Mark Shinwell)
+
+- GPR#283: Fix memory leaks in intern.c when OOM is raised
+  (Marc Lasson, review by Alain Frisch)
+
+- GPR#22: Fix the cleaning of weak pointers. In very rare cases
+  accessing a value during the cleaning of the weak pointers could
+  result in the value being removed from one weak arrays and kept in
+  another one. That breaks the property that a value is removed from a
+  weak pointer only when it is dead and garbage collected.
+  (François Bobot, review by Damien Doligez)
+
+- GPR#313: Prevent quadratic cases in CSE
+  (Pierre Chambart, review by Xavier Leroy)
+
+- PR#6795, PR#6996: Make ocamldep report errors passed in
+  [%ocaml.error] extension points
+  (Jérémie Dimino)
+
+- GPR#355: make ocamlnat build again
+  (Jérémie Dimino, Thomas Refis)
+
+- GPR#405: fix compilation under Visual Studio 2015
+  (David Allsopp)
+
+- GPR#441: better type error location in presence of type constraints
+  (Thomas Refis, report by Arseniy Alekseyev)
+
+- GPR#477: reallow docstrings inside object types, and inside polymorphic
+  variant and arrow types
+  (Thomas Refis)
+
+Features wishes:
+================
+
+- PR#4518, GPR#29: change location format for reporting errors in ocamldoc
+  (Sergei Lebedev)
+
+- PR#4714: List.cons
+
+- PR#5418 (comments) : generate dependencies with $(CC) instead of gcc
+  (Damien Doligez, report by Michael Grünewald)
+
+- PR#6167: OCAMLPARAM support for disabling PIC generation ("pic=0")
+  (Gabor Pali)
+
+- PR#6367, GPR#25: introduce Asttypes.arg_label to encode labelled arguments
+  (Frédéric Bour and Jacques Garrigue)
+
+- PR#6452, GPR#140: add internal suport for custom printing formats
+  (Jérémie Dimino)
+
+- PR#6611: remove the option wrapper on optional arguments in the syntax tree
+  (Alain Frisch, review by Damien Doligez, request by whitequark)
+
+- PR#6635: support M.[], M.(), M.{< >} and M.[| |]
+  (Jeremy Yallop, review by Gabriel Radanne)
+
+- PR#6691: install .cmt[i] files for stdlib and compiler-libs
+  (David Sheets, request by Gabriel Radanne)
+
+- PR#6722: compatibility with x32 architecture (x86-64 in ILP32 mode).
+  ocamlopt is not supported, but bytecode compiles cleanly.
+  (Adam Borowski and Xavier Leroy)
+
+- PR#6742: remove duplicate virtual_flag information from Tstr_class
+  (Gabriel Radanne and Jacques Garrigue)
+
+- PR#6719: improve Buffer.add_channel when not enough input is available
+  (Simon Cruanes)
+
+* PR#6816: reject integer and float literals directly followed by an identifier.
+  This was prevously read as two separate tokens.
+  [let abc = 1 in (+) 123abc] was accepted and is now rejected.
+  (Hugo Heuzard)
+
+- PR#6876: improve warning 6 by listing the omitted labels.
+  (Warning 6: Label omitted in function application)
+  (Eyyüb Sari)
+
+- PR#6924: tiny optim to avoid some spilling of floats in x87
+  (Alain Frisch)
+
+- GPR#111: `(f [@taillcall]) x y` warns if `f x y` is not a tail-call
+  (Simon Cruanes)
+
+- GPR#118: ocamldep -allow-approx: fallback to a lexer-based approximation
+  (Frédéric Bour)
+
+- GPR#137: add untypeast.ml (in open recursion style) to compiler-libs
+  (Gabriel Radanne)
+
+- GPR#142: add a CAMLdrop macro for undoing CAMLparam*/CAMLlocal*
+  (Thomas Braibant and Damien Doligez)
+
+- GPR#145: speeedup bigarray access by optimizing Cmmgen.bigarray_indexing
+  (Vladimir Brankov, review by Gabriel Scherer)
+
+- GPR#147: [type 'a result = Ok of 'a | Error of 'b] in Pervasives
+  (Yaron Minsky)
+
+- GPR#156, GPR#279: optimize caml_frame_descriptors realloc (dynlink speedup)
+  (Pierre Chambart, Alain Frisch,
+   review by François Bobot, Xavier Leroy and Damien Doligez)
+
+- GPR#165, GPR#221: fix windows compilation warnings
+  (Bernhard Schommer, Gabriel Scherer, report by Alain Frisch)
+
+* GPR#170: Parse arbitrary precision integers.
+  Accept a single [A-Za-z] as modifier for integers (generalizing 'l','L','n')
+  and floats.
+  May cause breakage (ie. ppx preprocessor) because of changes in the parsetree.
+  This changes PR#6816 a little bit by reading the literal [123a] as a single
+  token that can later be rewritten by a ppx preprocessor.
+  (Hugo Heuzard)
+
+- GPR#189: Added .dylib and .so as extensions for ocamlmklib
+  (Edgar Aroutiounian, whitequark)
+
+- GPR#191: Making gc.h and some part of memory.h public
+  (Thomas Refis)
+
+- GPR#196: Make [Thread.id] and [Thread.self] [noalloc]
+  (Clark Gaebel)
+
+- GPR#237: a CONTRIBUTING document
+  (François Bobot, Gabriel Scherer, review by Xavier Leroy)
+
+- GPR#245: remove a few remaining French comments
+  (Florian Angeletti)
+
+- GPR#252: improve build instructions in MSVC Windows README
+  (Philip Daian)
+
+- GPR#308: add experimental support for NetBSD/arm (verified on RaspberryPi)
+  (Rich Neswold)
+
+- GPR#335: Type error messages specifies if a type is abstract
+  because no corresponding cmi could be found.
+  (Hugo Heuzard)
+
+- GPR#365: prevent printing just a single type variable on one side
+  of a type error clash.
+  (Hugo Heuzard)
+
+- GPR#383: configure: define _ALL_SOURCE for build on AIX7.1
+  (tkob)
+
+- GPR#401: automatically retry failed test directories in the testsuite
+  (David Allsopp)
+
+- GPR#451: an optional 'parallel' target in testsuite/Makefile using the
+  GNU parallel tool to run tests in parallel.
+  (Gabriel Scherer)
+
+- GPR#555: ensure that register typing constraints are respected at
+  join points in the control flow graph
+  (Mark Shinwell, debugging & test case by Arseniy Alekseyev and Leo White,
+    code review by Xavier Leroy)
+
+Build system:
+=============
+
+- GPR#388: FlexDLL added as a Git submodule and bootstrappable with the compiler
+  (David Allsopp)
+
+OCaml 4.02.3 (27 Jul 2015):
+---------------------------
+
 Bug fixes:
 - PR#6908: Top-level custom printing for GADTs: interface change in 4.02.2
   (Grégoire Henry, report by Jeremy Yallop)
@@ -17,8 +1055,8 @@ Feature wishes:
 - GPR#37: New primitive: caml_alloc_dummy_function
   (Hugo Heuzard)
 
-OCaml 4.02.2:
--------------
+OCaml 4.02.2 (17 Jun 2015):
+---------------------------
 
 (Changes that can break existing programs are marked with a "*")
 
@@ -32,16 +1070,18 @@ Language features:
   (Alain Frisch, request by Gabriel Radanne)
 * PR#6016: add a "nonrec" keyword for type declarations
   (Jérémie Dimino)
+* PR#6612, GPR#152: change the precedence of attributes in type declarations
+  (Jérémie Dimino)
 
 Compilers:
 - PR#6600: make -short-paths faster by building the printing map
   incrementally
   (Jacques Garrigue)
 - PR#6642: replace $CAMLORIGIN in -ccopt with the path to cma or cmxa
-  (Peter Zotov, Gabriel Scherer, review by Damien Doligez)
+  (whitequark, Gabriel Scherer, review by Damien Doligez)
 - PR#6797: new option -output-complete-obj
   to output an object file with included runtime and autolink libraries
-  (Peter Zotov)
+  (whitequark)
 - PR#6845: -no-check-prims to tell ocamlc not to check primitives in runtime
   (Alain Frisch)
 - GPR#149: Attach documentation comments to parse tree
@@ -57,18 +1097,18 @@ OCamlbuild:
 - PR#6237: explicit "infer" tag to control or disable menhir --infer
   (Hugo Heuzard)
 - PR#6625: pass -linkpkg to files built with -output-obj.
-  (Peter Zotov)
+  (whitequark)
 - PR#6702: explicit "linkpkg" and "dontlink(foo)" flags
-  (Peter Zotov, Gabriel Scherer)
+  (whitequark, Gabriel Scherer)
 - PR#6712: Ignore common VCS directories
-  (Peter Zotov)
+  (whitequark)
 - PR#6720: pass -g to C compilers when tag 'debug' is set
-  (Peter Zotov, Gabriel Scherer)
+  (whitequark, Gabriel Scherer)
 - PR#6733: add .byte.so and .native.so targets to pass
   -output-obj -cclib -shared.
-  (Peter Zotov)
+  (whitequark)
 - PR#6733: "runtime_variant(X)" to pass -runtime-variant X option.
-  (Peter Zotov)
+  (whitequark)
 - PR#6774: new menhir-specific flags "only_tokens" and "external_tokens(Foo)"
   (François Pottier)
 
@@ -90,7 +1130,7 @@ Build system:
 - PR#5418 (comments) : generate dependencies with $(CC) instead of gcc
   (Damien Doligez and Michael Grünewald)
 - PR#6266: Cross compilation for iOs, Android etc
-  (Peter Zotov, review by Damien Doligez and Mark Shinwell)
+  (whitequark, review by Damien Doligez and Mark Shinwell)
 
 Installation procedure:
 - Update instructions for x86-64 PIC mode and POWER architecture builds
@@ -107,7 +1147,7 @@ Bug fixes:
   (Gabriel Scherer, request by the Coq team)
 - PR#5887: move the byterun/*.h headers to byterun/caml/*.h to avoid
   header name clashes
-  (Jérôme Vouillon and Adrien Nader and Peter Zotov)
+  (Jérôme Vouillon and Adrien Nader and whitequark)
 - PR#6281: Graphics window does not acknowledge second click (double click)
   (Kyle Headley)
 - PR#6490: incorrect backtraces in gdb on AArch64.  Also fixes incorrect
@@ -120,9 +1160,9 @@ Bug fixes:
 - PR#6607: The manual doesn't mention 0x200 flag for OCAMLRUNPARAM=v
   (Alain Frisch)
 - PR#6616: allow meaningful use of -use-runtime without -custom.
-  (Peter Zotov)
+  (whitequark)
 - PR#6617: allow android build with pthreads support (since SDK r10c)
-  (Peter Zotov)
+  (whitequark)
 - PR#6626: ocamlbuild on cygwin cannot find ocamlfind
   (Gergely Szilvasy)
 - PR#6628: Configure script rejects legitimate arguments
@@ -152,9 +1192,9 @@ Bug fixes:
   type variable in place of a local abstract type
   (Jacques Garrigue, report by Mikhail Mandrykin)
 - PR#6693 (part two): Incorrect relocation types in x86-64 runtime system
-  (Peter Zotov, review by Jacques-Henri Jourdan, Xavier Leroy and Mark Shinwell)
+  (whitequark, review by Jacques-Henri Jourdan, Xavier Leroy and Mark Shinwell)
 - PR#6717: Pprintast does not print let-pattern attributes
-  (Gabriel Scherer, report by Peter Zotov)
+  (Gabriel Scherer, report by whitequark)
 - PR#6727: Printf.sprintf "%F" misbehavior
   (Benoît Vaugon, report by Vassili Karpov)
 - PR#6747: ocamlobjinfo: missing symbol caml_plugin_header due to underscore
@@ -171,17 +1211,18 @@ Bug fixes:
   (Jacques Garrigue, report by David Sheets)
 - PR#6768: Typechecker overflow the stack on cyclic type
   (Jacques Garrigue, report by user 'darktenaibre')
+- PR#6770: (duplicate of PR#6686)
 - PR#6772: asmrun/signals_asm.c doesn't compile on NetBSD/i386
   (Kenji Tokudome)
 - PR#6775: Digest.file leaks file descriptor on error
   (Valentin Gatien-Baron)
 - PR#6779: Cross-compilers cannot link bytecode using custom primitives
-  (Damien Doligez, request by Peter Zotov)
+  (Damien Doligez, request by whitequark)
 - PR#6787: Soundness bug with polymorphic variants
   (Jacques Garrigue, with help from Leo White and Grégoire Henry,
    report by Michael O'Connor)
 - PR#6790: otherlibs should be built with -g
-  (Damien Doligez, report by Peter Zotov)
+  (Damien Doligez, report by whitequark)
 - PR#6791: "%s@[", "%s@{" regression in Scanf
   (Benoît Vaugon)
 - PR#6793: ocamlbuild passes nonsensical "-ocamlc ..." commands to menhir
@@ -204,6 +1245,7 @@ Bug fixes:
   (Mark Shinwell, report by Michael Grünewald)
 - PR#6841: Changing compilation unit name with -o breaks ocamldebug
   (Jacques Garrigue, report by Jordan Walke)
+- PR#6842: export Typemod.modtype_of_package
 - PR#6843: record weak dependencies even when the .cmi is missing
   (Leo White, Gabriel Scherer)
 - PR#6849: Inverted pattern unification error
@@ -243,15 +1285,15 @@ Feature wishes:
 - PR#6452, GPR#140: add internal suport for custom printing formats
   (Jérémie Dimino)
 - PR#6641: add -g, -ocamlcflags, -ocamloptflags options to ocamlmklib
-  (Peter Zotov)
+  (whitequark)
 - PR#6693: also build libasmrun_shared.so and lib{asm,caml}run_pic.a
-  (Peter Zotov, review by Mark Shinwell)
+  (whitequark, review by Mark Shinwell)
 - PR#6842: export Typemod.modtype_of_package
   (Jacques Garrigue, request by Jun Furuse)
 - GPR#139: more versatile specification of locations of .annot
   (Christophe Troestler, review by Damien Doligez)
-- GPR#157: store the path of cmos inside debug section at link time
-  (Hugo Heuzard, review by Damien Doligez)
+- GPR#171: allow custom warning printers / catchers
+  (Benjamin Canou, review by Damien Doligez)
 - GPR#191: Making gc.h and some part of memory.h public
   (Thomas Refis)
 
@@ -263,6 +1305,7 @@ OCaml 4.02.1 (14 Oct 2014):
 Standard library:
 * Add optional argument ?limit to Arg.align.
 
+Bug Fixes:
 - PR#4099: Bug in Makefile.nt: won't stop on error
   (George Necula)
 - PR#6181: Improve MSVC build
@@ -270,7 +1313,7 @@ Standard library:
 - PR#6207: Configure doesn't detect features correctly on Haiku
   (Jessica Hamilton)
 - PR#6466: Non-exhaustive matching warning message for open types is confusing
-  (Peter Zotov)
+  (whitequark)
 - PR#6529: fix quadratic-time algorithm in Consistbl.extract.
   (Xavier Leroy, Alain Frisch, relase-worthy report by Jacques-Pascal Deplaix)
 - PR#6530: Add stack overflow handling for native code (OpenBSD i386 and amd64)
@@ -284,7 +1327,7 @@ Standard library:
 - PR#6544: Bytes and CamlinternalFormat missing from threads stdlib.cma
   (Christopher Zimmermann)
 - PR#6546: -dsource omits parens for `List ((`String "A")::[]) in patterns
-  (Gabriel Scherer, report by Peter Zotov)
+  (Gabriel Scherer, report by whitequark)
 - PR#6547: __MODULE__ aborts the compiler if the module name cannot be inferred
   (Jacques Garrigue, report by Kaustuv Chaudhuri)
 - PR#6549: Debug section is sometimes not readable when using -pack
@@ -368,7 +1411,8 @@ Type system:
   (Jacques Garrigue, suggestion by Leo White)
 * Module aliases are now typed in a specific way, which remembers their
   identity. Compiled interfaces become smaller, but may depend on the
-  original modules. This also changes the signature inferred by "module type of".
+  original modules. This also changes the signature inferred by
+  "module type of".
   (Jacques Garrigue, feedback from Leo White, Mark Shinwell and Nick Chapman)
 - PR#6331: Slight change in the criterion to distinguish private
   abbreviations and private row types: create a private abbreviation for
@@ -663,15 +1707,15 @@ Features wishes:
 - PR#6358: obey DESTDIR in install targets
   (Gabriel Scherer, request by François Berenger)
 - PR#6388, PR#6424: more parsetree correctness checks for -ppx users
-  (Alain Frisch, request by Peter Zotov and Jun Furuse)
+  (Alain Frisch, request by whitequark and Jun Furuse)
 - PR#6406: Expose OCaml version in C headers
-  (Peter Zotov and Romain Calascibetta)
+  (whitequark and Romain Calascibetta)
 - PR#6446: improve "unused declaration" warnings wrt. name shadowing
   (Alain Frisch)
 - PR#6495: ocamlbuild tags 'safe_string', 'unsafe_string'
   (Anil Madhavapeddy)
 - PR#6497: pass context information to -ppx preprocessors
-  (Peter Zotov, Alain Frisch)
+  (whitequark, Alain Frisch)
 - ocamllex: user-definable refill action
   (Frédéric Bour, review by Gabriel Scherer and Luc Maranget)
 - shorten syntax for functor signatures: "functor (M1:S1) (M2:S2) .. -> .."
@@ -690,7 +1734,7 @@ Other libraries:
 Type system:
 - PR#5759: use well-disciplined type information propagation to
   disambiguate label and constructor names
-  (Jacques Garrigue, Alain Frisch and Leo P. White)
+  (Jacques Garrigue, Alain Frisch and Leo White)
 * Propagate type information towards pattern-matching, even in the presence of
   polymorphic variants (discarding only information about possibly-present
   constructors). As a result, matching against absent constructors is no longer
@@ -739,7 +1783,7 @@ Compilers:
 - PR#5571: incorrect ordinal number in error message
   (Alain Frisch, report by John Carr)
 - PR#6073: add signature to Tstr_include
-  (patch by Leo P. White)
+  (patch by Leo White)
 
 Standard library:
 - PR#5899: expose a way to inspect the current call stack,
@@ -913,7 +1957,7 @@ Bug fixes:
 - PR#5814: read_cmt -annot does not report internal references
   (Alain Frisch)
 - PR#5815: Multiple exceptions in signatures gives an error
-  (Leo P. White)
+  (Leo White)
 - PR#5816: read_cmt -annot does not work for partial .cmt files
   (Alain Frisch)
 - PR#5819: segfault when using [with] on large recursive record (ocamlopt)
@@ -951,7 +1995,7 @@ Bug fixes:
 - PR#5891: ocamlbuild: support rectypes tag for mlpack
   (Khoo Yit Phang)
 - PR#5892: GADT exhaustiveness check is broken
-  (Jacques Garrigue and Leo P. White)
+  (Jacques Garrigue and Leo White)
 - PR#5906: GADT exhaustiveness check is still broken
   (Jacques Garrigue, report by Sébastien Briais)
 - PR#5907: Undetected cycle during typecheck causes exceptions
@@ -979,7 +2023,7 @@ Bug fixes:
 - PR#5945: Mix-up of Minor_heap_min and Minor_heap_max units
   (Benoît Vaugon)
 - PR#5948: GADT with polymorphic variants bug
-  (Jacques Garrigue, report by Leo P. White)
+  (Jacques Garrigue, report by Leo White)
 - PR#5953: Unix.system does not handle EINTR
   (Jérémie Dimino)
 - PR#5965: disallow auto-reference to a recursive module in its definition
@@ -997,13 +2041,13 @@ Bug fixes:
 - PR#5982: caml_leave_blocking section and errno corruption
   (Jérémie Dimino)
 - PR#5985: Unexpected interaction between variance and GADTs
-  (Jacques Garrigue, Jeremy Yallop and Leo P. White and Gabriel Scherer)
+  (Jacques Garrigue, Jeremy Yallop and Leo White and Gabriel Scherer)
 - PR#5988: missing from the documentation: -impl is a valid flag for ocamlopt
   (Damien Doligez, report by Vincent Bernardoff)
 - PR#5989: Assumed inequalities involving private rows
   (Jacques Garrigue, report by Jeremy Yallop)
 - PR#5992: Crash when pattern-matching lazy values modifies the scrutinee
-  (Luc Maranget, Leo P. White)
+  (Luc Maranget, Leo White)
 - PR#5993: Variance of private type abbreviations not checked for modules
   (Jacques Garrigue)
 - PR#5997: Non-compatibility assumed for concrete types with same constructor
@@ -1049,7 +2093,7 @@ Bug fixes:
 - PR#6158: Fatal error using GADTs
   (Jacques Garrigue, report by Jeremy Yallop)
 - PR#6163: Assert_failure using polymorphic variants in GADTs
-  (Jacques Garrigue, report by Leo P. White)
+  (Jacques Garrigue, report by Leo White)
 - PR#6164: segmentation fault on Num.power_num of 0/1
   (Fabrice Le Fessant, report by Johannes Kanig)
 - PR#6210: Camlp4 location error
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index a83bbd3b..00000000
--- a/INSTALL
+++ /dev/null
@@ -1,356 +0,0 @@
-            Installing OCaml on a Unix machine
-            ----------------------------------
-
-PREREQUISITES
-
-* The GNU C compiler gcc is recommended, as the bytecode
-  interpreter takes advantage of gcc-specific features to enhance
-  performance.  gcc is the standard compiler under Linux, MacOS X,
-  and many other systems.
-
-* If you do not have write access to /tmp, you should set the environment
-  variable TMPDIR to the name of some other temporary directory.
-
-* Under HP/UX, the GNU C compiler gcc, the GNU assembler gas, and GNU make
-  are all *required*.  The vendor-provided compiler, assembler and make
-  have major problems.
-
-* GNU make is needed to build ocamlbuild.  If your system's default
-  make is not GNU make, you need to define the GNUMAKE environment
-  variable to the name of GNU make, typically with this command:
-
-    export GNUMAKE=gmake
-
-INSTALLATION INSTRUCTIONS
-
-1- Configure the system. From the top directory, do:
-
-        ./configure
-
-This generates the three configuration files "Makefile", "m.h" and "s.h"
-in the config/ subdirectory.
-
-The "configure" script accepts the following options:
-
--prefix                    (default: /usr/local)
-        Set the PREFIX variable used to define the defaults of the
-        following three options.  Must be an absolute path name.
-
--bindir                    (default: $(PREFIX)/bin)
-        Directory where the binaries will be installed.
-        Must be an absolute path name, or start with "$(PREFIX)"
-
--libdir                    (default: $(PREFIX)/lib/ocaml)
-        Directory where the OCaml library will be installed
-        Must be an absolute path name, or start with "$(PREFIX)"
-
--mandir                    (default: $(PREFIX)/man/man1)
-        Directory where the manual pages will be installed
-        Must be an absolute path name, or start with "$(PREFIX)"
-
--cc     (default: gcc if available, cc otherwise)
-        C compiler to use for building the system
-
--libs          (default: none)
-        Extra libraries to link with the system
-
--no-curses
-        Do not use the curses library.
-
--host                 (default: determined automatically)
-        The type of the host machine, in GNU's "configuration name"
-        format (CPU-COMPANY-SYSTEM or CPU-COMPANY-KERNEL-SYSTEM).
-        This info is generally determined automatically by the
-        "configure" script, and rarely ever needs to be provided by
-        hand. The installation instructions for gcc or emacs contain a
-        complete list of configuration names.
-
--target             (default: same as -host)
-        The type of the target machine, in GNU's "configuration name"
-        format (CPU-COMPANY-SYSTEM or CPU-COMPANY-KERNEL-SYSTEM).
-        Setting this will setup OCaml as a cross-compiler which runs on
-        $host and produces code for $target. This requires a C toolchain
-        which also produces code for $target and a native OCaml
-        compiler of the exact same version (if you want a cross 4.00.1,
-        you need a native 4.00.1).
-
--x11include        (default: determined automatically)
--x11lib                (default: determined automatically)
-        Location of the X11 include directory (e.g. /usr/X11R6/include)
-        and the X11 library directory (e.g. /usr/X11R6/lib).
-
--no-pthread
-        Do not attempt to use POSIX threads.
-
--with-pthread
-        Attempt to use POSIX threads (this is the default).
-
--no-shared-libs
-        Do not configure support for shared libraries
-
--dldefs 
--dllibs 
-        These options specify where to find the libraries for dynamic
-        linking (i.e. use of shared libraries).  "-dldefs" specifies
-        options for finding the header files, and "-dllibs" for finding
-        the C libraries.
-
--as      (default: determined automatically)
-        The assembler to use for assembling ocamlopt-generated code.
-
--aspp    (default: determined automatically)
-        The assembler to use for assembling the parts of the
-        run-time system manually written in assembly language.
-        This assembler must preprocess its input with the C preprocessor.
-
--with-debug-runtime
-        Compile and install the debug version of the runtimes, useful
-        for debugging C stubs and other low-level code.
-
--verbose
-        Verbose output of the configuration tests. Use it if the outcome
-        of configure is not what you were expecting.
-
--no-debugger
-        Do not build ocamldebug.
-
--no-ocamldoc
-        Do not build ocamldoc.
-
--no-ocamlbuild
-        Do not build ocamlbuild.
-
--no-graph
-        Do not compile the Graphics library.
-
--partialld   (default: determined automatically)
-        The linker and options to use for producing an object file
-        (rather than an executable) from several other object files.
-
--no-cfi
-        Do not compile support for CFI directives.
-
-Examples:
-
-  Standard installation in /usr/{bin,lib,man} instead of /usr/local:
-    ./configure -prefix /usr
-
-  Installation in /usr, man pages in section "l":
-    ./configure -bindir /usr/bin -libdir /usr/lib/ocaml -mandir /usr/man/manl
-  or:
-    ./configure -prefix /usr -mandir '$(PREFIX)/man/manl'
-
-  On a Linux x86-64 host, to build a 32-bit version of OCaml:
-    ./configure -cc "gcc -m32" -as "as --32" -aspp "gcc -m32 -c" \
-                -host i386-linux -partialld "ld -r -melf_i386"
-
-  On a Linux x86-64 host, to build the run-time system in PIC mode,
-  no special options should be required---the libraries should be built
-  automatically.  The old instructions were:
-    ./configure -cc "gcc -fPIC" -aspp "gcc -c -fPIC"
-
-  On a 64-bit POWER architecture host running Linux, OCaml only operates
-  in a 32-bit environment.  If your system compiler is configured as 32-bit,
-  e.g. Red Hat 5.9, you don't need to do anything special.  If that is
-  not the case (e.g. Red Hat 6.4), then IBM's "Advance Toolchain" can
-  be used.  For example:
-    export PATH=/opt/at7.0/bin:$PATH
-    ./configure -cc "gcc -m32" -as "as -a32" -aspp "gcc -m32 -c" \
-      -partialld "ld -r -m elf32ppc"
-
-  On a MacOSX 10.5/Intel Core 2 or MacOSX 10.5/PowerPC host,
-  to build a 64-bit version of OCaml:
-    ./configure -cc "gcc -m64"
-
-  On Intel Mac OS X, to build a 32-bit version of OCaml:
-    ./configure -host "i386-apple-darwin13.2.0" -cc "gcc -arch i386 -m32" \
-      -as "as -arch i386" -aspp "gcc -arch i386 -m32 -c"
-
-  For Sun Solaris with the "acc" compiler:
-    ./configure -cc "acc -fast" -libs "-lucb"
-
-  For Sun Solaris on Sparc 64bit, to compile natively (32bit only)
-    ./configure -cc "gcc -m32" -as "as -32" -aspp "gcc -m32 -c"
-
-  For AIX 4.3 with the IBM compiler xlc:
-    ./configure -cc "xlc_r -D_AIX43 -Wl,-bexpall,-brtl -qmaxmem=8192"
-
-
-If something goes wrong during the automatic configuration, or if the
-generated files cause errors later on, then look at the template files
-
-        config/Makefile-templ
-        config/m-templ.h
-        config/s-templ.h
-
-for guidance on how to edit the generated files by hand.
-
-2- From the top directory, do:
-
-        make world
-
-This builds the OCaml bytecode compiler for the first time.  This
-phase is fairly verbose; consider redirecting the output to a file:
-
-        make world > log.world 2>&1     # in sh
-        make world >& log.world         # in csh
-
-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:
-
-        make bootstrap
-
-or, better:
-
-        make bootstrap > log.bootstrap 2>&1     # in sh
-        make bootstrap >& log.bootstrap         # in csh
-
-The "make bootstrap" checks that the bytecode programs compiled with
-the new compiler are identical to the bytecode programs compiled with
-the old compiler. If this is the case, you can be pretty sure the
-system has been correctly compiled. Otherwise, this does not
-necessarily mean something went wrong. The best thing to do is to try
-a second bootstrapping phase: just do "make bootstrap" again.  It will
-either crash almost immediately, or re-re-compile everything correctly
-and reach the fixpoint.
-
-4- If your platform is supported by the native-code compiler (as
-reported during the autoconfiguration), you can now build the
-native-code compiler. From the top directory, do:
-
-        make opt
-or:
-        make opt > log.opt 2>&1     # in sh
-        make opt >& log.opt         # in csh
-
-5- Compile fast versions of the OCaml compilers, by compiling them
-with the native-code compiler (you have only compiled them to bytecode
-so far).  Just do:
-
-        make opt.opt
-
-Later, you can compile your programs to bytecode using ocamlc.opt
-instead of ocamlc, and to native-code using ocamlopt.opt instead of
-ocamlopt.  The ".opt" compilers should run faster than the normal
-compilers, especially on large input files, but they may take longer
-to start due to increased code size.  If compilation times are an issue on
-your programs, try the ".opt" compilers to see if they make a
-significant difference.
-
-An alternative, and faster approach to steps 2 to 5 is
-
-        make world.opt          # to build using native-code compilers
-
-The result is equivalent to "make world opt opt.opt", but this may
-fail if anything goes wrong in native-code generation.
-
-6- You can now install the OCaml system. This will create the
-following commands (in the binary directory selected during
-autoconfiguration):
-
-        ocamlc           the batch bytecode compiler
-        ocamlopt         the batch native-code compiler (if supported)
-        ocamlrun         the runtime system for the bytecode compiler
-        ocamlyacc        the parser generator
-        ocamllex         the lexer generator
-        ocaml            the interactive, toplevel-based system
-        ocamlmktop       a tool to make toplevel systems that integrate
-                         user-defined C primitives and OCaml code
-        ocamldebug       the source-level replay debugger
-        ocamldep         generator of "make" dependencies for OCaml sources
-        ocamldoc         documentation generator
-        ocamlprof        execution count profiler
-        ocamlcp          the bytecode compiler in profiling mode
-
-and also, if you built them during step 5,
-
-        ocamlc.opt       the batch bytecode compiler compiled with ocamlopt
-        ocamlopt.opt     the batch native-code compiler compiled with ocamlopt
-        ocamllex.opt     the lexer generator compiled with ocamlopt
-
-From the top directory, become superuser and do:
-
-        umask 022       # make sure to give read & execute permission to all
-        make install
-
-7- Installation is complete. Time to clean up. From the toplevel
-directory, do "make clean".
-
-8- (Optional) The emacs/ subdirectory contains Emacs-Lisp files for an
-OCaml editing mode and an interface for the debugger.  To install
-these files, change to the emacs/ subdirectory and do
-
-        make EMACSDIR= install
-or
-        make install
-
-In the latter case, the destination directory defaults to the
-"site-lisp" directory of your Emacs installation.
-
-9- After installation, do *not* strip the ocamldebug and ocamlbrowser
-executables.  (These are mixed-mode executables, containing both
-compiled C code and OCaml bytecode; stripping erases the bytecode!)
-Other executables such as ocamlrun can safely be stripped.
-
-IF SOMETHING GOES WRONG:
-
-Read the "common problems" and "machine-specific hints" section at the
-end of this file.
-
-Check the files m.h and s.h in config/. Wrong endianness or alignment
-constraints in m.h will immediately crash the bytecode interpreter.
-
-If you get a "segmentation violation" signal, check the limits on the
-stack size and data segment size (type "limit" under csh or
-"ulimit -a" under bash). Make sure the limit on the stack size is
-at least 4M.
-
-Try recompiling the runtime system with optimizations turned off
-(change CFLAGS in byterun/Makefile and asmrun/Makefile).
-The runtime system contains some complex, atypical pieces of C code
-that can uncover bugs in optimizing compilers. Alternatively, try
-another C compiler (e.g. gcc instead of the vendor-supplied cc).
-
-You can also build a debug version of the runtime system. Go to the
-byterun/ directory and do "make ocamlrund". Then, copy ocamlrund to
-../boot/ocamlrun, and try again. This version of the runtime system
-contains lots of assertions and sanity checks that could help you
-pinpoint the problem.
-
-
-COMMON PROBLEMS:
-
-* The Makefiles do not support parallel make (e.g. make -j2).
-Fix: do not pass the -j option to make, and be patient.
-
-* The Makefiles use the "include" directive, which is not supported by
-all versions of make. Use GNU make if this is a problem.
-
-* Solaris make mishandles a space in our Makefiles, so you have to use GNU
-make to build on Solaris.
-
-* The Makefiles assume that make executes commands by calling /bin/sh. They
-won't work if /bin/csh is called instead. You may have to unset the SHELL
-environment variable, or set it to /bin/sh.
-
-* On some systems, localization causes build problems.  You should
-try to set the C locale (export LC_ALL=C) before compiling if you have
-strange errors while compiling OCaml.
-
-* gcc 2.7.2.1 generates incorrect code for the runtime system in -O mode
-on some Intel x86 platforms (e.g. Linux RedHat 4.1 and 4.2).
-If this causes a problem, the solution is to upgrade to 2.7.2.3 or above.
-
-* Some versions of gcc 2.96 for the Intel x86 (as found in RedHat 7.2,
-Mandrake 8.0 and Mandrake 8.1) generates incorrect code for the runtime
-system.  The "configure" script tries to work around this problem.
-
-* On HP 9000/700 machines under HP/UX 9.  Some versions of cc are
-unable to compile correctly the runtime system (wrong code is
-generated for (x - y) where x is a pointer and y an integer).
-Fix: use gcc.
-
-* Under MacOS X 10.6, with XCode 4.0.2, the configure script mistakenly
-detects support for CFI directives in the assembler.
-Fix: give the "-no-cfi" option to configure.
diff --git a/INSTALL.adoc b/INSTALL.adoc
new file mode 100644
index 00000000..cdea168d
--- /dev/null
+++ b/INSTALL.adoc
@@ -0,0 +1,366 @@
+= Installing OCaml on a Unix(-like) machine =
+
+== PREREQUISITES
+
+* The GNU C Compiler (gcc) is recommended, as the bytecode interpreter takes
+  advantage of GCC-specific features to enhance performance. gcc is the standard
+  compiler under Linux, OS X, and many other systems.
+
+* If you do not have write access to `/tmp`, you should set the environment
+  variable `TMPDIR` to the name of some other temporary directory.
+
+* Under HP/UX, the GNU C Compiler (gcc), the GNU Assembler (gas), and GNU Make
+  are all *required*.  The vendor-provided compiler, assembler and make tools
+  have major problems.
+
+* Under Cygwin, the `gcc-core` and `make` packages are required.  `flexdll` is
+  necessary for shared library support.  `libX11-devel` is necessary for graph
+  library support and `libintl-devel` is necessary for the `ocamlobjinfo` tool
+  to be able to process `.cmxs` files.  `diffutils` is necessary to run the test
+  suite.
+
+== INSTALLATION INSTRUCTIONS
+
+1. Configure the system. From the top directory, do:
+
+        ./configure
++
+This generates the three configuration files `Makefile`, `m.h` and `s.h`
+in the `config/` subdirectory.
++
+The `configure` script accepts the following options:
++
+`-prefix `::                   (default: `/usr/local`)
+        Set the `PREFIX` variable used to define the defaults of the following
+        three options.  Must be an absolute path name.
+
+`-bindir `::                   (default: `$(PREFIX)/bin`)
+        Directory where the binaries will be installed.  Must be an absolute
+        path name, or start with `$(PREFIX)`.
+
+`-libdir `::                   (default: `$(PREFIX)/lib/ocaml`)
+        Directory where the OCaml library will be installed.  Must be an
+        absolute path name, or start with `$(PREFIX)`.
+
+`-mandir `::                   (default: `$(PREFIX)/man/man1`)
+        Directory where the manual pages will be installed.  Must be an absolute
+        path name, or start with `$(PREFIX)`.
+
+`-cc `::    (default: `gcc` if found, otherwise `cc`)
+        C compiler to use for building the system.
+
+`-libs `::         (default: none)
+        Extra libraries to link with the system.
+
+`-no-curses`::
+        Do not use the curses library.
+
+`-host `::                (default: determined automatically)
+        The type of the host machine, in GNU's "configuration name" format
+        (CPU-COMPANY-SYSTEM or CPU-COMPANY-KERNEL-SYSTEM).  This info is
+        generally determined automatically by the `configure` script, and rarely
+        ever needs to be provided by hand.  The installation instructions for
+        GCC or GNU Emacs contain a complete list of configuration names.
+
+`-target `::            (default: same as `-host`)
+        The type of the target machine, in GNU's "configuration name" format
+        (CPU-COMPANY-SYSTEM or CPU-COMPANY-KERNEL-SYSTEM). Setting this will
+        setup OCaml as a cross-compiler which runs on `$host` and produces code
+        for `$target`. This requires a C toolchain which also produces code for
+        `$target` and a native OCaml compiler of the exact same version (if you
+        want a cross 4.00.1, you need a native 4.00.1).
+
+`-x11include `::       (default: determined automatically)
+`-x11lib `::               (default: determined automatically)
+        Location of the X11 include directory (e.g. `/usr/X11R6/include`) and
+        the X11 library directory (e.g. `/usr/X11R6/lib`).
+
+`-no-pthread`::
+        Do not attempt to use POSIX threads.
+
+`-with-pthread`::
+        Attempt to use POSIX threads (this is the default).
+
+`-no-shared-libs`::
+        Do not configure support for shared libraries.
+
+`-dldefs `::
+`-dllibs `::
+        These options specify where to find the libraries for dynamic linking
+        (i.e. use of shared libraries).  `-dldefs` specifies options for finding
+        the header files, and `-dllibs` for finding the C libraries.
+
+`-as `::     (default: determined automatically)
+        The assembler to use for assembling ocamlopt-generated code.
+
+`-aspp `::   (default: determined automatically)
+        The assembler to use for assembling the parts of the run-time system
+        manually written in assembly language. This assembler must pre-process
+        its input with the C preprocessor.
+
+`-with-debug-runtime`::
+        Compile and install the debug version of the runtimes, useful for
+        debugging C stubs and other low-level code.
+
+`-with-instrumented-runtime`::
+        Compile and install the instrumented version of the runtimes, useful
+        mainly for fine-tuning the GC.  Works only on Linux.
+
+`-verbose`::
+        Verbose output of the configuration tests.  Use it if the outcome of
+        `configure` is not what you were expecting.
+
+`-no-debugger`::
+        Do not build `ocamldebug`.
+
+`-no-native-compiler`::
+        Do not build the native compiler -- bytecode compilation only.
+
+`-no-ocamldoc`::
+        Do not build `ocamldoc`.
+
+`-no-ocamlbuild`::
+        Deprecated since 4.03.0, as `ocamlbuild` is now distributed separately
+        from the compiler distribution.
+
+`-no-graph`::
+        Do not compile the Graphics library.
+
+`-partialld `:: (default: determined automatically)
+        The linker and options to use for producing an object file (rather than
+        an executable) from several other object files.
+
+`-no-cfi`::
+        Do not compile support for CFI directives.
++
+Examples:
+
+* Standard installation in `/usr/{bin,lib,man}` instead of `/usr/local`:
+    ./configure -prefix /usr
+
+
+* Installation in `/usr`, man pages in section "l":
+
+    ./configure -bindir /usr/bin -libdir /usr/lib/ocaml -mandir /usr/man/manl
++
+or:
+
+    ./configure -prefix /usr -mandir '$(PREFIX)/man/manl'
+
+* On a Linux x86-64 host, to build a 32-bit version of OCaml:
+
+    ./configure -cc "gcc -m32" -as "as --32" -aspp "gcc -m32 -c" \
+                -host i386-linux -partialld "ld -r -melf_i386"
+
+* On a Linux x86-64 host, to build the run-time system in PIC mode, no special
+  options should be required -- the libraries should be built automatically.
+  The old instructions were:
+
+    ./configure -cc "gcc -fPIC" -aspp "gcc -c -fPIC"
++
+On a 64-bit POWER architecture host running Linux, OCaml only operates in a
+  32-bit environment.  If your system compiler is configured as 32-bit, e.g.
+  Red Hat 5.9, you don't need to do anything special.  If that is not the case
+  (e.g. Red Hat 6.4), then IBM's "Advance Toolchain" can be used.  For example:
+
+    export PATH=/opt/at7.0/bin:$PATH
+    ./configure -cc "gcc -m32" -as "as -a32" -aspp "gcc -m32 -c" \
+      -partialld "ld -r -m elf32ppc"
+
+* On a OS X 10.5/Intel Core 2 or OS X 10.5/PowerPC host, to build a 64-bit
+  version of OCaml:
+
+    ./configure -cc "gcc -m64"
+
+* On OS X Intel, to build a 32-bit version of OCaml:
+
+    ./configure -host "i386-apple-darwin13.2.0" -cc "gcc -arch i386 -m32" \
+      -as "as -arch i386" -aspp "gcc -arch i386 -m32 -c"
+
+* For Sun Solaris with the `acc` compiler:
+
+    ./configure -cc "acc -fast" -libs "-lucb"
+
+* For Sun Solaris on Sparc 64bit, to compile natively (32bit only)
+
+    ./configure -cc "gcc -m32" -as "as -32" -aspp "gcc -m32 -c"
+
+* For AIX 4.3 with the IBM compiler `xlc`:
+
+    ./configure -cc "xlc_r -D_AIX43 -Wl,-bexpall,-brtl -qmaxmem=8192"
++
+If something goes wrong during the automatic configuration, or if the generated
+files cause errors later on, then look at the template files:
+
+        config/Makefile-templ
+        config/m-templ.h
+        config/s-templ.h
++
+for guidance on how to edit the generated files by hand.
+
+2. From the top directory, do:
+
+        make world
++
+This builds the OCaml bytecode compiler for the first time.  This phase is
+fairly verbose; consider redirecting the output to a file:
+
+        make world > log.world 2>&1     # in sh
+        make world >& log.world         # in csh
+
+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:
+
+        make bootstrap
++
+or, better:
+
+        make bootstrap > log.bootstrap 2>&1     # in sh
+        make bootstrap >& log.bootstrap         # in csh
++
+The `make bootstrap` checks that the bytecode programs compiled with the new
+compiler are identical to the bytecode programs compiled with the old compiler.
+If this is the case, you can be pretty sure the system has been correctly
+compiled. Otherwise, this does not necessarily mean something went wrong.  The
+best thing to do is to try a second bootstrapping phase: just do
+`make bootstrap` again.  It will either crash almost immediately, or
+re-re-compile everything correctly and reach the fix-point.
+
+4. If your platform is supported by the native-code compiler (as reported during
+   the auto-configuration), you can now build the native-code compiler.  From
+   the top directory, do:
+
+        make opt
++
+or:
+
+        make opt > log.opt 2>&1     # in sh
+        make opt >& log.opt         # in csh
+
+5. anchor:step-5[] Compile fast versions of the OCaml compilers, by compiling
+   them with the native-code compiler (you will have only compiled them to
+   bytecode in steps 2-4).  Just do:
+
+        make opt.opt
++
+Later, you can compile your programs to bytecode using ocamlc.opt instead of
+ocamlc, and to native-code using ocamlopt.opt instead of ocamlopt.  The ".opt"
+compilers should run faster than the normal compilers, especially on large input
+files, but they may take longer to start due to increased code size.  If
+compilation times are an issue on your programs, try the ".opt" compilers to see
+if they make a significant difference.
++
+An alternative, and faster approach to steps 2 to 5 is
+
+        make world.opt          # to build using native-code compilers
++
+The result is equivalent to `make world opt opt.opt`, but this may fail if
+anything goes wrong in native-code generation.
+
+6. You can now install the OCaml system. This will create the following commands
+   (in the binary directory selected during autoconfiguration):
++
+[width="70%",frame="topbot",cols="25%,75%"]
+|===============================================================================
+| `ocamlc`     | the batch bytecode compiler
+| `ocamlopt`   | the batch native-code compiler (if supported)
+| `ocamlrun`   | the runtime system for the bytecode compiler
+| `ocamlyacc`  | the parser generator
+| `ocamllex`   | the lexer generator
+| `ocaml`      | the interactive, toplevel-based system
+| `ocamlmktop` | a tool to make toplevel systems that integrate user-defined C
+                 primitives and OCaml code
+| `ocamldebug` | the source-level replay debugger
+| `ocamldep`   | generator of "make" dependencies for OCaml sources
+| `ocamldoc`   | the documentation generator
+| `ocamlprof`  | the execution count profiler
+| `ocamlcp`    | the bytecode compiler in profiling mode
+|===============================================================================
++
+and also, if you built them during <>: `ocamlc.opt`,
+`ocamlopt.opt`, `ocamllex.opt`, `ocamldep.opt` and `ocamldoc.opt`
++
+From the top directory, become superuser and do:
+
+        umask 022       # make sure to give read & execute permission to all
+        make install
+
+7. Installation is complete. Time to clean up. From the toplevel directory,
+   do:
+
+        make clean
+
+8. (Optional) The `emacs/` subdirectory contains Emacs-Lisp files for an OCaml
+   editing mode and an interface for the debugger.  To install these files,
+   change to the `emacs/` subdirectory and do:
+
+        make EMACSDIR= install
++
+or
+
+        make install
++
+In the latter case, the destination directory defaults to the
+`site-lisp` directory of your Emacs installation.
+
+9. After installation, do *not* strip the `ocamldebug` and `ocamlbrowser`
+   executables. These are mixed-mode executables (containing both compiled C
+   code and OCaml bytecode) and stripping erases the bytecode!  Other
+   executables such as `ocamlrun` can safely be stripped.
+
+== IF SOMETHING GOES WRONG
+
+Read the "common problems" and "machine-specific hints" section at the end of
+this file.
+
+Check the files `m.h` and `s.h` in `config/`. Wrong endian-ness or alignment
+constraints in `m.h` will immediately crash the bytecode interpreter.
+
+If you get a "segmentation violation" signal, check the limits on the stack size
+and data segment size (type `limit` under csh or `ulimit -a` under bash). Make
+sure the limit on the stack size is at least 4M.
+
+Try recompiling the runtime system with optimizations turned off (change
+`CFLAGS` in `byterun/Makefile` and `asmrun/Makefile`). The runtime system
+contains some complex, atypical pieces of C code which can uncover bugs in
+optimizing compilers.  Alternatively, try another C compiler (e.g. `gcc` instead
+of the vendor-supplied `cc`).
+
+You can also build a debug version of the runtime system. Go to the `byterun/`
+directory and do `make ocamlrund`.  Then, copy `ocamlrund` to
+`../boot/ocamlrun`, and try again.  This version of the runtime system contains
+lots of assertions and sanity checks that could help you pinpoint the problem.
+
+
+== COMMON PROBLEMS
+
+* The Makefiles use the `include` directive, which is not supported by all
+  versions of make. Use GNU Make if this is a problem.
+
+* Solaris make mishandles a space in our Makefiles, so you have to use GNU make
+  to build on Solaris.
+
+* The Makefiles assume that make executes commands by calling `/bin/sh`. They
+  won't work if `/bin/csh` is called instead.  You may have to unset the `SHELL`
+  environment variable, or set it to `/bin/sh`.
+
+* On some systems, localization causes build problems.  You should try to set
+  the C locale (`export LC_ALL=C`) before compiling if you have strange errors
+  while compiling OCaml.
+
+* GCC 2.7.2.1 generates incorrect code for the runtime system in `-O` mode on
+  some Intel x86 platforms (e.g. Linux RedHat 4.1 and 4.2). If this causes a
+  problem, the solution is to upgrade to 2.7.2.3 or above.
+
+* Some versions of GCC 2.96 for the Intel x86 (as found in RedHat 7.2,
+  Mandrake 8.0 and Mandrake 8.1) generate incorrect code for the runtime system.
+  The `configure` script tries to work around this problem.
+
+* On HP 9000/700 machines under HP/UX 9, some versions of `cc` are unable to
+  compile correctly the runtime system (wrong code is generated for `(x - y)`
+  where `x` is a pointer and `y` an integer). Fix: use `gcc`.
+
+* Under OS X 10.6, with XCode 4.0.2, the `configure` script mistakenly detects
+  support for CFI directives in the assembler. Fix: give the `-no-cfi` option to
+  `configure`.
diff --git a/LICENSE b/LICENSE
index 8209011f..515f12e7 100644
--- a/LICENSE
+++ b/LICENSE
@@ -7,7 +7,7 @@ and "the Compiler" refers to all files marked "Copyright INRIA" in the
 following directories and their sub-directories:
 
   asmcomp, boot, build, bytecomp, debugger, driver, lex, man,
-  ocamlbuild, ocamldoc, parsing, testsuite, tools, toplevel, typing,
+  ocamldoc, parsing, testsuite, tools, toplevel, typing,
   utils, yacc
 
 The Compiler is distributed under the terms of the Q Public License
diff --git a/Makefile b/Makefile
index ead65207..75c7973b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,120 +1,26 @@
-#########################################################################
-#                                                                       #
-#                                 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 Q Public License version 1.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.          *
+#*                                                                        *
+#**************************************************************************
 
 # The main Makefile
 
-include config/Makefile
-CAMLRUN ?= boot/ocamlrun
-CAMLYACC ?= boot/ocamlyacc
-include stdlib/StdlibModules
-
-CAMLC=$(CAMLRUN) boot/ocamlc -nostdlib -I boot
-CAMLOPT=$(CAMLRUN) ./ocamlopt -nostdlib -I stdlib -I otherlibs/dynlink
-COMPFLAGS=-strict-sequence -w +33..39+48+50 -warn-error A -bin-annot \
-          -safe-string $(INCLUDES)
-LINKFLAGS=
-
-YACCFLAGS=-v
-CAMLLEX=$(CAMLRUN) boot/ocamllex
-CAMLDEP=$(CAMLRUN) tools/ocamldep
-DEPFLAGS=$(INCLUDES)
+MAKEREC=$(MAKE)
+include Makefile.shared
+
 SHELL=/bin/sh
 MKDIR=mkdir -p
 
-OCAMLBUILDBYTE=$(WITH_OCAMLBUILD:=.byte)
-OCAMLBUILDNATIVE=$(WITH_OCAMLBUILD:=.native)
-
-OCAMLDOC_OPT=$(WITH_OCAMLDOC:=.opt)
-
-INCLUDES=-I utils -I parsing -I typing -I bytecomp -I asmcomp -I driver \
-	 -I toplevel
-
-UTILS=utils/misc.cmo utils/tbl.cmo utils/config.cmo \
-  utils/clflags.cmo utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
-  utils/consistbl.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
-
-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/cmt_format.cmo \
-  typing/includemod.cmo typing/typetexp.cmo typing/parmatch.cmo \
-  typing/stypes.cmo typing/typecore.cmo \
-  typing/typedecl.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/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/errors.cmo driver/compile.cmo
-
-ASMCOMP=asmcomp/arch.cmo asmcomp/debuginfo.cmo \
-  asmcomp/cmm.cmo asmcomp/printcmm.cmo \
-  asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
-  asmcomp/clambda.cmo asmcomp/printclambda.cmo asmcomp/compilenv.cmo \
-  asmcomp/closure.cmo asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
-  asmcomp/printmach.cmo asmcomp/selectgen.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
-
-TOPLEVEL=toplevel/genprintval.cmo toplevel/toploop.cmo \
-  toplevel/trace.cmo toplevel/topdirs.cmo toplevel/topmain.cmo
-
-BYTESTART=driver/main.cmo
-
-OPTSTART=driver/optmain.cmo
-
-TOPLEVELSTART=toplevel/topstart.cmo
-
-NATTOPOBJS=$(UTILS) $(PARSING) $(TYPING) $(COMP) $(ASMCOMP) \
-  toplevel/genprintval.cmo toplevel/opttoploop.cmo toplevel/opttopdirs.cmo \
-  toplevel/opttopmain.cmo toplevel/opttopstart.cmo
-
-PERVASIVES=$(STDLIB_MODULES) outcometree topdirs toploop
-
 # For users who don't read the INSTALL file
 defaultentry:
 	@echo "Please refer to the installation instructions in file INSTALL."
@@ -129,7 +35,7 @@ all:
 	$(MAKE) runtime
 	$(MAKE) coreall
 	$(MAKE) ocaml
-	$(MAKE) otherlibraries $(OCAMLBUILDBYTE) $(WITH_DEBUGGER) \
+	$(MAKE) otherlibraries $(WITH_DEBUGGER) \
 	  $(WITH_OCAMLDOC)
 
 # Compile everything the first time
@@ -166,7 +72,7 @@ coreboot:
 # Rebuild the library (using byterun/ocamlrun ./ocamlc)
 	$(MAKE) library-cross
 # Promote the new compiler and the new runtime
-	$(MAKE) promote
+	$(MAKE) CAMLRUN=byterun/ocamlrun promote
 # Rebuild the core system
 	$(MAKE) partialclean
 	$(MAKE) core
@@ -222,10 +128,10 @@ backup:
 # Promote the newly compiled system to the rank of cross compiler
 # (Runs on the old runtime, produces code for the new runtime)
 promote-cross:
-	cp ocamlc boot/ocamlc
-	cp lex/ocamllex boot/ocamllex
+	$(CAMLRUN) tools/stripdebug ocamlc boot/ocamlc
+	$(CAMLRUN) tools/stripdebug lex/ocamllex boot/ocamllex
 	cp yacc/ocamlyacc$(EXE) boot/ocamlyacc$(EXE)
-	cp tools/ocamldep boot/ocamldep
+	$(CAMLRUN) tools/stripdebug tools/ocamldep boot/ocamldep
 	cd stdlib; cp $(LIBFILES) ../boot
 
 # Promote the newly compiled system to the rank of bootstrap compiler
@@ -241,8 +147,9 @@ restore:
 
 # Check if fixpoint reached
 compare:
-	@if cmp boot/ocamlc ocamlc && cmp boot/ocamllex lex/ocamllex \
-	    && cmp boot/ocamldep tools/ocamldep; \
+	@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
@@ -261,7 +168,7 @@ opt:
 	$(MAKE) runtimeopt
 	$(MAKE) ocamlopt
 	$(MAKE) libraryopt
-	$(MAKE) otherlibrariesopt ocamltoolsopt $(OCAMLBUILDNATIVE)
+	$(MAKE) otherlibrariesopt ocamltoolsopt
 
 # Native-code versions of the tools
 opt.opt:
@@ -271,12 +178,10 @@ opt.opt:
 	$(MAKE) ocaml
 	$(MAKE) opt-core
 	$(MAKE) ocamlc.opt
-	$(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC) \
-	        $(OCAMLBUILDBYTE)
+	$(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
 	$(MAKE) ocamlopt.opt
 	$(MAKE) otherlibrariesopt
-	$(MAKE) ocamllex.opt ocamltoolsopt ocamltoolsopt.opt $(OCAMLDOC_OPT) \
-	        $(OCAMLBUILDNATIVE)
+	$(MAKE) ocamllex.opt ocamltoolsopt ocamltoolsopt.opt $(OCAMLDOC_OPT)
 
 base.opt:
 	$(MAKE) checkstack
@@ -285,8 +190,7 @@ base.opt:
 	$(MAKE) ocaml
 	$(MAKE) opt-core
 	$(MAKE) ocamlc.opt
-	$(MAKE) otherlibraries $(OCAMLBUILDBYTE) $(WITH_DEBUGGER) \
-	  $(WITH_OCAMLDOC)
+	$(MAKE) otherlibraries $(WITH_DEBUGGER) $(WITH_OCAMLDOC)
 	$(MAKE) ocamlopt.opt
 	$(MAKE) otherlibrariesopt
 
@@ -312,8 +216,9 @@ install:
 	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.so dllnums.so dllthreads.so \
-	  dllunix.so dllgraphics.so dllstr.so
+	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$(EXE)
 	cp ocaml $(INSTALL_BINDIR)/ocaml$(EXE)
@@ -336,25 +241,24 @@ install:
 	for i in $(OTHERLIBRARIES); do \
 	  (cd otherlibs/$$i; $(MAKE) install) || exit $$?; \
 	done
-	if test -n "$(WITH_OCAMLDOC)"; then (cd ocamldoc; $(MAKE) install); else :; fi
-	if test -n "$(WITH_DEBUGGER)"; then (cd debugger; $(MAKE) install); \
-	   else :; fi
-	if test -n "$(WITH_OCAMLBUILD)"; then (cd ocamlbuild; $(MAKE) install); \
-	   else :; fi
+	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 -f ocamlopt; then $(MAKE) installopt; else :; fi
+	if test -f ocamlopt; then $(MAKE) installopt; fi
 
 # Installation of the native-code compiler
 installopt:
 	cd asmrun; $(MAKE) install
 	cp ocamlopt $(INSTALL_BINDIR)/ocamlopt$(EXE)
 	cd stdlib; $(MAKE) 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; $(MAKE) installopt); \
 		else :; fi
-	if test -n "$(WITH_OCAMLBUILD)"; then (cd ocamlbuild; $(MAKE) installopt); \
-	   else :; fi
 	for i in $(OTHERLIBRARIES); \
 	  do (cd otherlibs/$$i; $(MAKE) installopt) || exit $$?; done
 	if test -f ocamlopt.opt ; then $(MAKE) installoptopt; fi
@@ -364,12 +268,22 @@ 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 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); \
+	  cp compilerlibs/ocamlopttoplevel.cmxa \
+	     compilerlibs/ocamlopttoplevel.a \
+	     $(OPTTOPLEVELSTART:.cmo=.cmx) $(OPTTOPLEVELSTART:.cmo=.o) \
+	     $(INSTALL_COMPLIBDIR); \
+	fi
 	cd $(INSTALL_COMPLIBDIR) && $(RANLIB) ocamlcommon.a ocamlbytecomp.a \
 	   ocamloptcomp.a
 
@@ -398,12 +312,14 @@ partialclean::
 
 ocamlc: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma $(BYTESTART)
 	$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamlc \
-	   compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma $(BYTESTART)
+	   compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
+	   $(BYTESTART)
 
 # The native-code compiler
 
-compilerlibs/ocamloptcomp.cma: $(ASMCOMP)
-	$(CAMLC) -a -o $@ $(ASMCOMP)
+compilerlibs/ocamloptcomp.cma: $(MIDDLE_END) $(ASMCOMP)
+	$(CAMLC) -a -o $@ $(MIDDLE_END) $(ASMCOMP)
+
 partialclean::
 	rm -f compilerlibs/ocamloptcomp.cma
 
@@ -432,11 +348,39 @@ ocaml: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma \
 partialclean::
 	rm -f ocaml
 
+RUNTOP=./byterun/ocamlrun ./ocaml -nostdlib -I stdlib -noinit $(TOPFLAGS)
+NATRUNTOP=./ocamlnat -nostdlib -I stdlib -noinit $(TOPFLAGS)
+
+runtop:
+	$(MAKE) runtime
+	$(MAKE) coreall
+	$(MAKE) ocaml
+	@rlwrap --help 2>/dev/null && rlwrap $(RUNTOP) || $(RUNTOP)
+
+natruntop:
+	$(MAKE) runtime
+	$(MAKE) coreall
+	$(MAKE) opt.opt
+	$(MAKE) ocamlnat
+	@rlwrap --help 2>/dev/null && rlwrap $(NATRUNTOP) || $(NATRUNTOP)
+
 # The native toplevel
 
-ocamlnat: ocamlopt otherlibs/dynlink/dynlink.cmxa $(NATTOPOBJS:.cmo=.cmx)
-	$(CAMLOPT) $(LINKFLAGS) otherlibs/dynlink/dynlink.cmxa -o ocamlnat \
-	           $(NATTOPOBJS:.cmo=.cmx) -linkall
+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 \
+    otherlibs/dynlink/dynlink.cmxa compilerlibs/ocamlopttoplevel.cmxa \
+    $(OPTTOPLEVELSTART:.cmo=.cmx)
+	$(CAMLOPT) $(LINKFLAGS) -linkall -o ocamlnat \
+	    otherlibs/dynlink/dynlink.cmxa compilerlibs/ocamlcommon.cmxa \
+	    compilerlibs/ocamloptcomp.cmxa compilerlibs/ocamlopttoplevel.cmxa \
+	    $(OPTTOPLEVELSTART:.cmo=.cmx)
+
+partialclean::
+	rm -f ocamlnat
 
 toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
 
@@ -452,6 +396,7 @@ utils/config.ml: utils/config.mlp config/Makefile
 	    -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)|' \
@@ -464,7 +409,7 @@ utils/config.ml: utils/config.mlp config/Makefile
 	    -e 's|%%EXT_OBJ%%|.o|' \
 	    -e 's|%%EXT_ASM%%|.s|' \
 	    -e 's|%%EXT_LIB%%|.a|' \
-	    -e 's|%%EXT_DLL%%|.so|' \
+	    -e 's|%%EXT_DLL%%|$(EXT_DLL)|' \
 	    -e 's|%%SYSTHREAD_SUPPORT%%|$(SYSTHREAD_SUPPORT)|' \
 	    -e 's|%%ASM%%|$(ASM)|' \
 	    -e 's|%%ASM_CFI_SUPPORTED%%|$(ASM_CFI_SUPPORTED)|' \
@@ -474,6 +419,7 @@ utils/config.ml: utils/config.mlp config/Makefile
 	    -e 's|%%MKMAINDLL%%|$(MKMAINDLL)|' \
 	    -e 's|%%HOST%%|$(HOST)|' \
 	    -e 's|%%TARGET%%|$(TARGET)|' \
+	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
 	    utils/config.mlp > utils/config.ml
 
 partialclean::
@@ -526,8 +472,8 @@ partialclean::
 
 # The native-code compiler compiled with itself
 
-compilerlibs/ocamloptcomp.cmxa: $(ASMCOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(ASMCOMP:.cmo=.cmx)
+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
 
@@ -540,7 +486,8 @@ ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
 partialclean::
 	rm -f ocamlopt.opt
 
-$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx): ocamlopt
+$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
+$(ASMCOMP:.cmo=.cmx): ocamlopt
 
 # The numeric opcodes
 
@@ -560,11 +507,11 @@ 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 | \
-	 sed -e '$$s/;$$//'; \
+	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p' \
+	     byterun/caml/fail.h; \
 	 echo '|]'; \
 	 echo 'let builtin_primitives = [|'; \
-	 sed -e 's/.*/  "&";/' -e '$$s/;$$//' byterun/primitives; \
+	 sed -e 's/.*/  "&";/' byterun/primitives; \
 	 echo '|]') > bytecomp/runtimedef.ml
 
 partialclean::
@@ -625,7 +572,8 @@ 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 \
+	echo \# 1 \"$(ARCH)/emit.mlp\" > asmcomp/emit.ml
+	$(CAMLRUN) tools/cvt_emit >asmcomp/emit.ml \
 	|| { rm -f asmcomp/emit.ml; exit 2; }
 
 partialclean::
@@ -713,25 +661,6 @@ ocamlyacc:
 clean::
 	cd yacc; $(MAKE) clean
 
-# Tools
-
-ocamltools: ocamlc ocamlyacc ocamllex asmcomp/cmx_format.cmi \
-            asmcomp/printclambda.cmo
-	cd tools; $(MAKE) all
-
-ocamltoolsopt: ocamlopt
-	cd tools; $(MAKE) opt
-
-ocamltoolsopt.opt: ocamlc.opt ocamlyacc ocamllex asmcomp/cmx_format.cmi \
-                   asmcomp/printclambda.cmx
-	cd tools; $(MAKE) opt.opt
-
-partialclean::
-	cd tools; $(MAKE) clean
-
-alldepend::
-	cd tools; $(MAKE) depend
-
 # OCamldoc
 
 ocamldoc: ocamlc ocamlyacc ocamllex otherlibraries
@@ -786,20 +715,6 @@ partialclean::
 alldepend::
 	cd debugger; $(MAKE) depend
 
-# Ocamlbuild
-
-ocamlbuild.byte: ocamlc otherlibraries
-	cd ocamlbuild && $(MAKE) all
-
-ocamlbuild.native: ocamlopt otherlibrariesopt
-	cd ocamlbuild && $(MAKE) allopt
-
-partialclean::
-	cd ocamlbuild && $(MAKE) clean
-
-alldepend::
-	cd ocamlbuild && $(MAKE) depend
-
 # Check that the stack limit is reasonable.
 
 checkstack:
@@ -839,12 +754,14 @@ clean::
 	$(CAMLOPT) $(COMPFLAGS) -c $<
 
 partialclean::
-	for d in utils parsing typing bytecomp asmcomp driver toplevel tools; \
+	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
 	rm -f *~
 
 depend: beforedepend
-	(for d in utils parsing typing bytecomp asmcomp driver toplevel; \
+	(for d in utils parsing typing bytecomp asmcomp middle_end \
+	 middle_end/base_types driver toplevel; \
 	 do $(CAMLDEP) $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
 	 done) > .depend
 
@@ -864,7 +781,7 @@ distclean:
 .PHONY: compare core coreall
 .PHONY: coreboot defaultentry depend distclean install installopt
 .PHONY: library library-cross libraryopt
-.PHONY: ocamlbuild.byte ocamlbuild.native ocamldebugger ocamldoc
+.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
diff --git a/Makefile.nt b/Makefile.nt
index 9666b7bd..079fca74 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -1,118 +1,78 @@
-#########################################################################
-#                                                                       #
-#                                 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 Q Public License version 1.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.          *
+#*                                                                        *
+#**************************************************************************
 
 # The main Makefile
 
-include config/Makefile
-CAMLRUN ?= boot/ocamlrun
-CAMLYACC ?= boot/ocamlyacc
-include stdlib/StdlibModules
-
-CAMLC=$(CAMLRUN) boot/ocamlc -nostdlib -I boot
-CAMLOPT=$(CAMLRUN) ./ocamlopt -nostdlib -I stdlib -I otherlibs/dynlink
-COMPFLAGS=-strict-sequence -w +33..39+48 -warn-error A -bin-annot $(INCLUDES)
-LINKFLAGS=
-YACCFLAGS=
-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 asmcomp -I driver \
-	 -I toplevel
-
-UTILS=utils/misc.cmo utils/tbl.cmo utils/config.cmo \
-  utils/clflags.cmo utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
-  utils/consistbl.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
-
-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/cmt_format.cmo \
-  typing/includemod.cmo typing/typetexp.cmo typing/parmatch.cmo \
-  typing/stypes.cmo typing/typecore.cmo \
-  typing/typedecl.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/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/errors.cmo driver/compile.cmo
-
-ASMCOMP=asmcomp/arch.cmo asmcomp/debuginfo.cmo \
-  asmcomp/cmm.cmo asmcomp/printcmm.cmo \
-  asmcomp/reg.cmo asmcomp/mach.cmo asmcomp/proc.cmo \
-  asmcomp/clambda.cmo asmcomp/printclambda.cmo asmcomp/compilenv.cmo \
-  asmcomp/closure.cmo asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
-  asmcomp/printmach.cmo asmcomp/selectgen.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/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
-  asmcomp/asmlink.cmo asmcomp/asmlibrarian.cmo asmcomp/asmpackager.cmo \
-  driver/opterrors.cmo driver/optcompile.cmo
-
-TOPLEVEL=toplevel/genprintval.cmo toplevel/toploop.cmo \
-  toplevel/trace.cmo toplevel/topdirs.cmo toplevel/topmain.cmo
-
-BYTESTART=driver/main.cmo
-
-OPTSTART=driver/optmain.cmo
-
-TOPLEVELSTART=toplevel/topstart.cmo
-
-PERVASIVES=$(STDLIB_MODULES) outcometree topdirs toploop
+include Makefile.shared
 
 # For users who don't read the INSTALL file
 defaultentry:
-	@echo "Please refer to the installation instructions in file README.win32."
+	@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 $(OCAMLBUILDBYTE) $(WITH_DEBUGGER) \
-  $(WITH_OCAMLDOC)
+  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.
@@ -151,11 +111,11 @@ LIBFILES=stdlib.cma std_exit.cmo *.cmi camlheader
 
 # Start up the system from the distribution compiler
 coldstart:
-	cd byterun ; $(MAKEREC) all
+	cd byterun ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
 	cp byterun/ocamlrun.exe boot/ocamlrun.exe
-	cd yacc ; $(MAKEREC) all
+	cd yacc ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
 	cp yacc/ocamlyacc.exe boot/ocamlyacc.exe
-	cd stdlib ; $(MAKEREC) COMPILER=../boot/ocamlc all
+	cd stdlib ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) COMPILER=../boot/ocamlc all
 	cd stdlib ; cp $(LIBFILES) ../boot
 
 # Build the core system: the minimum needed to make depend and bootstrap
@@ -176,10 +136,10 @@ backup:
 # Promote the newly compiled system to the rank of cross compiler
 # (Runs on the old runtime, produces code for the new runtime)
 promote-cross:
-	cp ocamlc boot/ocamlc
-	cp lex/ocamllex boot/ocamllex
+	$(CAMLRUN) tools/stripdebug ocamlc boot/ocamlc
+	$(CAMLRUN) tools/stripdebug lex/ocamllex boot/ocamllex
 	cp yacc/ocamlyacc.exe boot/ocamlyacc.exe
-	cp tools/ocamldep boot/ocamldep
+	$(CAMLRUN) tools/stripdebug tools/ocamldep boot/ocamldep
 	cd stdlib ; cp $(LIBFILES) ../boot
 
 # Promote the newly compiled system to the rank of bootstrap compiler
@@ -195,9 +155,12 @@ restore:
 
 # Check if fixpoint reached
 compare:
-	- cmp -i 4096 boot/ocamlc ocamlc
-	- cmp -i 4096 boot/ocamllex lex/ocamllex
-	- cmp -i 4096 boot/ocamldep tools/ocamldep
+	@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:
@@ -205,17 +168,19 @@ cleanboot:
 
 # Compile the native-code compiler
 opt-core:
-	$(MAKE) -f Makefile.nt runtimeopt
-	$(MAKE) -f Makefile.nt ocamlopt
-	$(MAKE) -f Makefile.nt libraryopt
+	$(MAKEREC) runtimeopt
+	$(MAKEREC) ocamlopt
+	$(MAKEREC) libraryopt
 
 opt:
-	$(MAKE) -f Makefile.nt opt-core
-	$(MAKE) -f Makefile.nt otherlibrariesopt ocamltoolsopt
+	$(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 $(OCAMLBUILDNATIVE) $(OCAMLDOC_OPT)
+         ocamltoolsopt ocamltoolsopt.opt otherlibrariesopt $(OCAMLDOC_OPT) \
+         $(if $(wildcard flexdll/Makefile),flexlink.opt)
 
 # Complete build using fast compilers
 world.opt: coldstart opt.opt
@@ -229,74 +194,104 @@ 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)/
+	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.exe"
+	cp ocaml "$(INSTALL_BINDIR)/ocaml.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.exe"
+	cp yacc/ocamlyacc.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)
+	   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)
+	   "$(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); \
-	  else :; fi
-	if test -n "$(WITH_DEBUGGER)"; then (cd debugger; $(MAKEREC) install); \
-	   else :; fi
-	if test -n "$(WITH_OCAMLBUILD)"; then (cd ocamlbuild; $(MAKE) install); \
-	   else :; fi
-	cp config/Makefile $(INSTALL_LIBDIR)/Makefile.config
-	cp README $(INSTALL_DISTRIB)/Readme.general.txt
-	cp README.win32 $(INSTALL_DISTRIB)/Readme.windows.txt
-	cp LICENSE $(INSTALL_DISTRIB)/License.txt
-	cp Changes $(INSTALL_DISTRIB)/Changes.txt
+	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"
+	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"
+
+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
-	cd stdlib ; $(MAKEREC) installopt
-	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
-	if test -n "$(WITH_OCAMLBUILD)"; then (cd ocamlbuild; $(MAKE) installopt); \
-	   else :; fi
+	cd asmrun && $(MAKEREC) install
+	cp ocamlopt "$(INSTALL_BINDIR)/ocamlopt.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; $(MAKE) installopt
+	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.opt$(EXE)"
+	cp ocamlopt.opt "$(INSTALL_BINDIR)/ocamlopt.opt$(EXE)"
+	cp lex/ocamllex.opt "$(INSTALL_BINDIR)/ocamllex.opt$(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)
+           "$(INSTALL_COMPLIBDIR)"
+
+# Run all tests
+
+tests: opt.opt
+	cd testsuite && $(MAKE) clean && $(MAKE) all
+
+# The clean target
 
 clean:: partialclean
 
@@ -315,7 +310,8 @@ partialclean::
 	rm -f compilerlibs/ocamlbytecomp.cma
 
 ocamlc: compilerlibs/ocamlcommon.cma compilerlibs/ocamlbytecomp.cma $(BYTESTART)
-	$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamlc compilerlibs/ocamlcommon.cma \
+	$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamlc \
+	         compilerlibs/ocamlcommon.cma \
 	         compilerlibs/ocamlbytecomp.cma $(BYTESTART)
 
 partialclean::
@@ -323,8 +319,8 @@ partialclean::
 
 # The native-code compiler
 
-compilerlibs/ocamloptcomp.cma: $(ASMCOMP)
-	$(CAMLC) -a -o $@ $(ASMCOMP)
+compilerlibs/ocamloptcomp.cma: $(MIDDLE_END) $(ASMCOMP)
+	$(CAMLC) -a -o $@ $(MIDDLE_END) $(ASMCOMP)
 partialclean::
 	rm -f compilerlibs/ocamloptcomp.cma
 
@@ -362,7 +358,7 @@ ocamlnat: ocamlopt otherlibs/dynlink/dynlink.cmxa $(NATTOPOBJS:.cmo=.cmx)
 toplevel/opttoploop.cmx: otherlibs/dynlink/dynlink.cmxa
 
 otherlibs/dynlink/dynlink.cmxa: otherlibs/dynlink/natdynlink.ml
-	cd otherlibs/dynlink && $(MAKE) -f Makefile.nt allopt
+	cd otherlibs/dynlink && $(MAKEREC) allopt
 
 
 # The configuration file
@@ -399,6 +395,8 @@ utils/config.ml: utils/config.mlp config/Makefile
 	    -e 's|%%CC_PROFILE%%||' \
 	    -e 's|%%HOST%%|$(HOST)|' \
 	    -e 's|%%TARGET%%|$(TARGET)|' \
+	    -e 's|%%FLAMBDA%%|$(FLAMBDA)|' \
+	    -e 's|%%FLEXLINK_FLAGS%%|$(FLEXLINK_FLAGS)|' \
 	    utils/config.mlp > utils/config.ml
 
 partialclean::
@@ -451,8 +449,8 @@ partialclean::
 
 # The native-code compiler compiled with itself
 
-compilerlibs/ocamloptcomp.cmxa: $(ASMCOMP:.cmo=.cmx)
-	$(CAMLOPT) -a -o $@ $(ASMCOMP:.cmo=.cmx)
+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)
 
@@ -465,7 +463,8 @@ ocamlopt.opt: compilerlibs/ocamlcommon.cmxa compilerlibs/ocamloptcomp.cmxa \
 partialclean::
 	rm -f ocamlopt.opt
 
-$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(ASMCOMP:.cmo=.cmx): ocamlopt
+$(COMMON:.cmo=.cmx) $(BYTECOMP:.cmo=.cmx) $(MIDDLE_END:.cmo=.cmx) \
+$(ASMCOMP:.cmo=.cmx): ocamlopt
 
 # The numeric opcodes
 
@@ -485,11 +484,11 @@ 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 | \
-	 sed -e '$$s/;$$//'; \
+	 sed -n -e 's|.*/\* \("[A-Za-z_]*"\) \*/$$|  \1;|p' \
+	     byterun/caml/fail.h; \
 	 echo '|]'; \
 	 echo 'let builtin_primitives = [|'; \
-	 sed -e 's/.*/  "&";/' -e '$$s/;$$//' byterun/primitives; \
+	 sed -e 's/.*/  "&";/' byterun/primitives; \
 	 echo '|]') > bytecomp/runtimedef.ml
 
 partialclean::
@@ -507,12 +506,6 @@ partialclean::
 
 beforedepend:: asmcomp/arch.ml
 
-ifeq ($(TOOLCHAIN),msvc)
-ASMCOMP_EMIT=asmcomp/$(ARCH)/emit_nt.mlp
-else
-ASMCOMP_EMIT=asmcomp/$(ARCH)/emit.mlp
-endif
-
 asmcomp/proc.ml: asmcomp/$(ARCH)/proc.ml
 	cp asmcomp/$(ARCH)/proc.ml asmcomp/proc.ml
 
@@ -555,8 +548,8 @@ beforedepend:: asmcomp/scheduling.ml
 
 # Preprocess the code emitters
 
-asmcomp/emit.ml: $(ASMCOMP_EMIT) tools/cvt_emit
-	$(CAMLRUN) tools/cvt_emit < $(ASMCOMP_EMIT) > asmcomp/emit.ml
+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
@@ -581,7 +574,7 @@ partialclean::
 runtime: makeruntime stdlib/libcamlrun.$(A)
 
 makeruntime:
-	cd byterun ; $(MAKEREC) all
+	cd byterun ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
 stdlib/libcamlrun.$(A): byterun/libcamlrun.$(A)
 	cp byterun/libcamlrun.$(A) stdlib/libcamlrun.$(A)
 clean::
@@ -607,15 +600,16 @@ alldepend::
 # The library
 
 library:
-	cd stdlib ; $(MAKEREC) all
+	cd stdlib && $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
 library-cross:
-	cd stdlib ; $(MAKEREC) CAMLRUN=../byterun/ocamlrun all
+	cd stdlib \
+	&& $(MAKEREC) $(BOOT_FLEXLINK_CMD) CAMLRUN=../byterun/ocamlrun all
 libraryopt:
-	cd stdlib ; $(MAKEREC) allopt
+	cd stdlib && $(MAKEREC) $(BOOT_FLEXLINK_CMD) allopt
 partialclean::
-	cd stdlib ; $(MAKEREC) clean
+	cd stdlib && $(MAKEREC) clean
 alldepend::
-	cd stdlib ; $(MAKEREC) depend
+	cd stdlib && $(MAKEREC) depend
 
 # The lexer and parser generators
 
@@ -629,28 +623,10 @@ alldepend::
 	cd lex ; $(MAKEREC) depend
 
 ocamlyacc:
-	cd yacc ; $(MAKEREC) all
+	cd yacc ; $(MAKEREC) $(BOOT_FLEXLINK_CMD) all
 clean::
 	cd yacc ; $(MAKEREC) clean
 
-# Tools
-
-ocamltools: ocamlc ocamlyacc ocamllex asmcomp/cmx_format.cmi \
-            asmcomp/printclambda.cmo
-	cd tools ; $(MAKEREC) all
-
-ocamltoolsopt:
-	cd tools ; $(MAKEREC) opt
-
-ocamltoolsopt.opt: ocamlc.opt ocamlyacc ocamllex asmcomp/cmx_format.cmi \
-                   asmcomp/printclambda.cmx
-	cd tools ; $(MAKEREC) opt.opt
-
-partialclean::
-	cd tools ; $(MAKEREC) clean
-alldepend::
-	cd tools ; $(MAKEREC) depend
-
 # OCamldoc
 
 ocamldoc:
@@ -694,20 +670,6 @@ partialclean::
 alldepend::
 	cd debugger; $(MAKEREC) depend
 
-# Ocamlbuild
-
-ocamlbuild.byte: ocamlc otherlibraries
-	cd ocamlbuild && $(MAKE) all
-
-ocamlbuild.native: ocamlopt otherlibrariesopt
-	cd ocamlbuild && $(MAKE) allopt
-
-partialclean::
-	cd ocamlbuild && $(MAKE) clean
-
-alldepend::
-	cd ocamlbuild && $(MAKE) depend
-
 # Make clean in the test suite
 
 clean::
@@ -732,19 +694,23 @@ partialclean::
 	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 driver toplevel; \
+	(for d in utils parsing typing bytecomp asmcomp middle_end \
+	 middle_end/base_types driver toplevel; \
 	 do $(CAMLDEP) $(DEPFLAGS) $$d/*.mli $$d/*.ml; \
 	 done) > .depend
 
 alldepend:: depend
 
 distclean:
-	$(MAKE) clean
+	$(MAKEREC) clean
 	rm -f asmrun/.depend.nt byterun/.depend.nt
 	rm -f boot/ocamlrun boot/ocamlrun.exe boot/camlheader boot/ocamlyacc \
 	      boot/*.cm* boot/libcamlrun.a
@@ -757,11 +723,12 @@ distclean:
 .PHONY: partialclean beforedepend alldepend cleanboot coldstart
 .PHONY: compare core coreall
 .PHONY: coreboot defaultentry depend distclean install installopt
-.PHONY: library library-cross libraryopt ocamlbuild-mixed-boot
-.PHONY: ocamlbuild.byte ocamlbuild.native ocamldebugger ocamldoc
+.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
diff --git a/Makefile.shared b/Makefile.shared
new file mode 100644
index 00000000..f79b6322
--- /dev/null
+++ b/Makefile.shared
@@ -0,0 +1,244 @@
+#**************************************************************************
+#*                                                                        *
+#*                                 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
+CAMLOPT=$(CAMLRUN) ./ocamlopt -g -nostdlib -I stdlib -I otherlibs/dynlink
+COMPFLAGS=-strict-sequence -principal -w +33..39+48+50 -warn-error A \
+          -bin-annot -safe-string -strict-formats $(INCLUDES)
+LINKFLAGS=
+
+YACCFLAGS=-v
+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
+
+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/typecore.cmo \
+  typing/typedecl.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 \
+  bytecomp/debuginfo.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/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/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/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 "objinfo" 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)
+partialclean::
+	rm -f compilerlibs/ocamlmiddleend.cma
+
+
+# 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 asmcomp/cmx_format.cmi \
+                   asmcomp/printclambda.cmx
+	cd tools; $(MAKEREC) opt.opt
+
+partialclean::
+	cd tools; $(MAKEREC) clean
+
+alldepend::
+	cd tools; $(MAKEREC) depend
diff --git a/README b/README
deleted file mode 100644
index 093ad8ed..00000000
--- a/README
+++ /dev/null
@@ -1,130 +0,0 @@
-OVERVIEW:
-
-OCaml is an implementation of the ML language, based on the Caml Light
-dialect extended with a complete class-based object system and a
-powerful module system in the style of Standard ML.
-
-OCaml comprises two compilers. One generates bytecode which is then
-interpreted by a C program. This compiler runs quickly, generates
-compact code with moderate memory requirements, and is portable to
-essentially any 32 or 64 bit Unix platform. Performance of generated
-programs is quite good for a bytecoded implementation.  This compiler
-can be used either as a standalone, batch-oriented compiler that
-produces standalone programs, or as an interactive, toplevel-based
-system.
-
-The other compiler generates high-performance native code for a number
-of processors. Compilation takes longer and generates bigger code, but
-the generated programs deliver excellent performance, while retaining
-the moderate memory requirements of the bytecode compiler. The
-native-code compiler currently runs on the following platforms:
-
-Tier 1 (actively used and maintained by the core OCaml team):
-
-    AMD64 (Opteron)    Linux, MacOS X, MS Windows
-    IA32 (Pentium)     Linux, FreeBSD, MacOS X, MS Windows
-    PowerPC            Linux, MacOS X
-    ARM                Linux
-
-Tier 2 (maintained when possible, with help from users):
-
-    AMD64              FreeBSD, OpenBSD
-    IA32 (Pentium)     NetBSD, OpenBSD, Solaris 9
-    PowerPC            NetBSD
-    SPARC              Solaris, Linux, NetBSD
-
-Other operating systems for the processors above have not been tested,
-but the compiler may work under other operating systems with little work.
-
-Before the introduction of objects, OCaml was known as Caml Special
-Light. 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
-  INSTALL               instructions for installation
-  LICENSE               license and copyright notice
-  Makefile              main Makefile
-  README                this file
-  README.win32          infos on the MS Windows ports of OCaml
-  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
-  config/               autoconfiguration stuff
-  debugger/             source-level replay debugger
-  driver/               driver code for the compilers
-  emacs/                OCaml editing mode and debugger interface for GNU Emacs
-  lex/                  lexer generator
-  maccaml/              the Macintosh GUI
-  ocamldoc/             documentation generator
-  otherlibs/            several external libraries
-  parsing/              syntax analysis
-  stdlib/               standard library
-  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, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-2007, 2008, 2009, 2010, 2011, 2012 Institut National de Recherche en
-Informatique et en Automatique (INRIA) and distributed under the
-conditions stated in file LICENSE.
-
-INSTALLATION:
-
-See the file INSTALL for installation instructions on Unix, Linux and
-MacOS X machines.  For MS Windows, see README.win32.
-
-DOCUMENTATION:
-
-The OCaml manual is distributed in HTML, PDF, Postscript, DVI, and
-Emacs Info files.  It is available on the World Wide Web, at
-
-        http://caml.inria.fr/
-
-AVAILABILITY:
-
-The complete OCaml distribution can be accessed at
-
-        http://caml.inria.fr/
-
-KEEPING IN TOUCH WITH THE CAML COMMUNITY:
-
-There exists a mailing list of users of the OCaml implementations
-developed at INRIA. The purpose of this list is to share
-experience, exchange ideas (and even code), and report on applications
-of the OCaml language. Messages can be written in English or in
-French. The list has more than 1000 subscribers.
-
-Messages to the list should be sent to:
-
-              caml-list@inria.fr
-
-You can subscribe to this list via the Web interface at
-
-        https://sympa-roc.inria.fr/wws/info/caml-list
-
-Archives of the list are available on the Web site above.
-
-The Usenet news groups comp.lang.ml and comp.lang.functional
-also contains discussions about the ML family of programming languages,
-including OCaml.
-
-BUG REPORTS AND USER FEEDBACK:
-
-Please report bugs using the Web interface to the bug-tracking system
-at http://caml.inria.fr/bin/caml-bugs
-
-To be effective, bug reports should include a complete program
-(preferably small) that exhibits the unexpected behavior, and the
-configuration you are using (machine type, etc).
-
-You can also contact the implementors directly at caml@inria.fr.
diff --git a/README.adoc b/README.adoc
new file mode 100644
index 00000000..73e477a8
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,139 @@
+= README =
+
+== OVERVIEW
+
+OCaml is an implementation of the ML language, based on the Caml Light
+dialect extended with a complete class-based object system and a
+powerful module system in the style of Standard ML.
+
+OCaml comprises two compilers. One generates bytecode which is then
+interpreted by a C program. This compiler runs quickly, generates
+compact code with moderate memory requirements, and is portable to
+essentially any 32 or 64 bit Unix platform. Performance of generated
+programs is quite good for a bytecoded implementation.  This compiler
+can be used either as a standalone, batch-oriented compiler that
+produces standalone programs, or as an interactive, toplevel-based
+system.
+
+The other compiler generates high-performance native code for a number
+of processors. Compilation takes longer and generates bigger code, but
+the generated programs deliver excellent performance, while retaining
+the moderate memory requirements of the bytecode compiler. The
+native-code compiler currently runs on the following platforms:
+
+Tier 1 (actively used and maintained by the core OCaml team):
+
+AMD64 (Opteron)::    Linux, OS X, MS Windows
+IA32 (Pentium)::     Linux, FreeBSD, OS X, MS Windows
+PowerPC::            Linux, OS X
+ARM::                Linux
+
+Tier 2 (maintained when possible, with help from users):
+
+AMD64::              FreeBSD, OpenBSD, NetBSD
+IA32 (Pentium)::     NetBSD, OpenBSD, Solaris 9
+PowerPC::            NetBSD
+ARM::                NetBSD
+SPARC::              Solaris, Linux, NetBSD
+
+Other operating systems for the processors above have not been tested,
+but the compiler may work under other operating systems with little work.
+
+Before the introduction of objects, OCaml was known as Caml Special
+Light. 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
+  INSTALL.adoc::          instructions for installation
+  LICENSE::               license and copyright notice
+  Makefile::              main Makefile
+  README.adoc::           this file
+  README.win32.adoc::     infos on the MS Windows ports of OCaml
+  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
+  config/::               autoconfiguration stuff
+  debugger/::             source-level replay debugger
+  driver/::               driver code for the compilers
+  emacs/::                editing mode and debugger interface for GNU Emacs
+  lex/::                  lexer generator
+  ocamldoc/::             documentation generator
+  otherlibs/::            several external libraries
+  parsing/::              syntax analysis
+  stdlib/::               standard library
+  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, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+2007, 2008, 2009, 2010, 2011, 2012 Institut National de Recherche en
+Informatique et en Automatique (INRIA) and distributed under the
+conditions stated in file LICENSE.
+
+== INSTALLATION
+
+See the file INSTALL for installation instructions on machines running Unix,
+Linux, OS X and Cygwin.  For native Microsoft Windows, see
+link:README.win32.adoc[].
+
+== DOCUMENTATION
+
+The OCaml manual is distributed in HTML, PDF, Postscript, DVI, and
+Emacs Info files.  It is available at
+
+http://caml.inria.fr/
+
+The community also maintains the Web site http://ocaml.org, with tutorials
+and other useful informations for OCaml users.
+
+== AVAILABILITY
+
+The complete OCaml distribution can be accessed at
+
+http://caml.inria.fr/
+
+== KEEPING IN TOUCH WITH THE CAML COMMUNITY
+
+There exists a mailing list of users of the OCaml implementations
+developed at INRIA. The purpose of this list is to share
+experience, exchange ideas (and even code), and report on applications
+of the OCaml language. Messages can be written in English or in
+French. The list has more than 1000 subscribers.
+
+Messages to the list should be sent to:
+
+mailto:caml-list@inria.fr[]
+
+You can subscribe to this list via the Web interface at
+
+https://sympa.inria.fr/sympa/subscribe/caml-list
+
+Archives of the list are available on the Web site above.
+
+The Usenet news `groups comp.lang.ml` and `comp.lang.functional`
+also contains discussions about the ML family of programming languages,
+including OCaml.
+
+The IRC channel `#ocaml` on https://freenode.net/[Freenode] also has several
+hundred users and welcomes questions.
+
+== BUG REPORTS AND USER FEEDBACK
+
+Please report bugs using the Web interface to the bug-tracking system
+at http://caml.inria.fr/bin/caml-bugs
+
+To be effective, bug reports should include a complete program
+(preferably small) that exhibits the unexpected behavior, and the
+configuration you are using (machine type, etc).
+
+You can also contact the implementors directly at mailto:caml@inria.fr[].
diff --git a/README.win32 b/README.win32
deleted file mode 100644
index 0f520f46..00000000
--- a/README.win32
+++ /dev/null
@@ -1,453 +0,0 @@
-       Release notes on the MS Windows ports of OCaml
-       ----------------------------------------------
-
-There are no less than five ports of OCaml for MS Windows available:
-  - a native Win32 port, built with the Microsoft development tools;
-  - a native Win32 port, built with the 32-bit version of the gcc
-    compiler from the mingw-w64 project, packaged in Cygwin
-    (under the name mingw64-i686);
-  - a native Win32 port, built with the 64-bit version of the gcc
-    compiler from the mingw-w64 project, packaged in Cygwin
-    (under the name mingw64-x86_64);
-  - a port consisting of the Unix sources compiled under the Cygwin
-    Unix-like environment for Windows;
-  - a native Win64 port (64-bit Windows), built with the Microsoft
-    development tools.
-
-Here is a summary of the main differences between these ports:
-
-                                      Native MS     Native MinGW        Cygwin
-
-64 bits?                            Win32 or Win64  Win32 or Win64     Win32 only
-
-Third-party software required
-  - for base bytecode system            none            none            none
-  - for ocamlc -custom                  MSVC            Cygwin          Cygwin
-  - for native-code generation          MSVC+MASM       Cygwin          Cygwin
-
-Speed of bytecode interpreter           70%             100%            100%
-
-Replay debugger                         yes (**)        yes (**)        yes
-
-The Unix library                        partial         partial         full
-
-The Threads library                     yes             yes             yes
-
-The Graphics library                    yes             yes             no
-
-Restrictions on generated executables?  none            none            yes (*)
-
-(*) 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 MSVC or by
-MinGW have no such restrictions.
-
-(**) The debugger is supported but the "replay" functions are not enabled.
-Other functions are available (step, goto, run...).
-
-The remainder of this document gives more information on each port.
-
-------------------------------------------------------------------------------
-
-           The native Win32 port built with Microsoft Windows SDK
-           ------------------------------------------------------
-
-REQUIREMENTS:
-
-This port runs under MS Windows 7 (32 and 64 bits), Vista, XP, and 2000.
-
-The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...)
-runs without any additional tools.
-
-The native-code compiler (ocamlopt) requires the Microsoft Windows SDK
-(item [1]) and the flexdll tool (item [2]).
-
-Statically linking OCaml bytecode with C code (ocamlc -custom) also requires
-items [1] and [2].
-
-
-INSTALLATION:
-
-The binary distribution is a self-installing executable archive.
-Just run it and it should install OCaml automatically.
-
-THIRD-PARTY SOFTWARE:
-
-[1] Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 Service Pack 1.
-    Can be downloaded for free from
-    http://www.microsoft.com/downloads/en/default.aspx
-    under the name "Microsoft Windows 7 SDK".
-
-[2] flexdll version 0.31 or later.
-    Can be downloaded from http://alain.frisch.fr/flexdll.html
-
-RECOMPILATION FROM THE SOURCES:
-
-The command-line tools can be recompiled from the Unix source
-distribution (ocaml-X.YY.Z.tar.gz), which also contains the files modified
-for Windows.
-
-You will need the following software components to perform the recompilation:
-- Windows NT, 2000, XP, Vista, or 7 (32 or 64 bits).
-- Items [1] and [2] from the list of recommended software above.
-- The Cygwin port of GNU tools, available from http://www.cygwin.com/
-  Install at least the following packages (and their dependencies):
-  diffutils, dos2unix, gcc-core, make, ncurses.
-
-First, you need to set up your cygwin environment for using the MS
-tools.  The following assumes that you have installed [1], [2], and [3]
-in their default directories.  If this is not the case, you will need
-to adjust the paths accordingly.
-
-  Open a Windows Command Prompt and enter the following command:
-    set PFPATH=C:\Program Files
-  If you are compiling on the 64-bit version of Windows 7, enter the
-  following instead:
-    set PFPATH=C:\Program Files (x86)
-
-  Then enter the following commands:
-    cd "%PFPATH%\Microsoft Visual Studio 9.0\VC\bin"
-    set FLEXDLLDIR=%PFPATH%\flexdll
-    vcvars32
-    echo VCPATH="`cygpath -p '%Path%'`" >C:\cygwin\tmp\msenv
-    echo LIBPATH="%LIBPATH%" >>C:\cygwin\tmp\msenv
-    echo INCLUDE="%INCLUDE%;%FLEXDLLDIR%" >>C:\cygwin\tmp\msenv
-    echo FLPATH="`cygpath '%FLEXDLLDIR%'`" >>C:\cygwin\tmp\msenv
-    echo PATH="$VCPATH:$FLPATH:$PATH" >>C:\cygwin\tmp\msenv
-    echo export PATH LIB LIBPATH INCLUDE >>C:\cygwin\tmp\msenv
-    echo export OCAMLBUILD_FIND=/usr/bin/find >>C:\cygwin\tmp\msenv
-
-  Open a Cygwin shell and enter the following commands:
-    tr -d '\r' .msenv32
-    echo '. $HOME/.msenv32' >>.bashrc
-
-Now, close the Command Prompt and the shell and you're set up for
-using the MS tools under Cygwin.
-
-
-To recompile OCaml, start a new Cygwin shell and change to the top-level
-directory of the OCaml distribution.  Then, do
-
-        cp config/m-nt.h config/m.h
-        cp config/s-nt.h config/s.h
-        cp config/Makefile.msvc config/Makefile
-
-Then, edit config/Makefile as needed, following the comments in this file.
-Normally, the only variable that need to be changed is
-        PREFIX      where to install everything
-
-Finally, use "make -f Makefile.nt" to build the system, e.g.
-
-        make -f Makefile.nt world
-        make -f Makefile.nt bootstrap
-        make -f Makefile.nt opt
-        make -f Makefile.nt opt.opt
-        make -f Makefile.nt install
-
-NOTES:
-
-* The VC++ compiler does not implement "computed gotos", and therefore
-generates inefficient code for byterun/interp.c. Consequently, the
-performance of bytecode programs is about 2/3 of that obtained under
-Unix/GCC or Cygwin or Mingw on similar hardware.
-
-* Libraries available in this port: "num", "str", "threads", "graphics",
-and large parts of "unix".
-
-* The replay debugger is partially supported (no reverse execution).
-
-CREDITS:
-
-The initial port of Caml Special Light (the ancestor of OCaml) to
-Windows NT was done by Kevin Gallo at Microsoft Research, who kindly
-contributed his changes to the OCaml project.
-
-------------------------------------------------------------------------------
-
-           The native Win32 and Win64 ports built with Mingw
-           -------------------------------------------------
-
-REQUIREMENTS:
-
-Those ports run under MS Windows Seven, Vista, XP, and 2000.
-
-The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...)
-runs without any additional tools.
-
-The native-code compiler (ocamlopt), as well as static linking of
-OCaml bytecode with C code (ocamlc -custom), require
-the Cygwin development tools, available at
-        http://www.cygwin.com/
-and the flexdll tool, available at
-        http://alain.frisch.fr/flexdll.html
-You will need to install at least the following Cygwin packages for
-the 32-bit flavor (use the Setup tool from Cygwin):
-
- mingw64-i686-binutils
- mingw64-i686-gcc-core
- mingw64-i686-runtime
-
-and the following packages for the 64-bit:
-
- mingw64-x86_64-binutils
- mingw64-x86_64-gcc-core
- mingw64-x86_64-runtime
-
-NOTES:
-
-  - Do not use the Cygwin version of flexdll for this port.
-
-  - There is another 32-bit gcc compiler, from the MinGW.org
-    project, packaged in Cygwin under the name mingw-gcc.
-    It is not currently supported by flexdll and OCaml.
-
-  - The standard gcc compiler shipped with Cygwin used to
-    support a "-mno-cygwin" option, which turned the compiler
-    into a mingw compiler. This option was used
-    by previous versions of flexdll and OCaml, but it is no
-    longer available in recent version, hence the switch
-    to another toolchain packaged in Cygwin.
-
-  - The standalone mingw toolchain from the MinGW-w64 project
-    (http://mingw-w64.sourceforge.net/) is not supported.
-    Please use the version packaged in Cygwin instead.
-
-INSTALLATION:
-
-The binary distribution is a self-installing executable archive.
-Just run it and it should install OCaml automatically.
-
-
-RECOMPILATION FROM THE SOURCES:
-
-You will need the following software components to perform the recompilation:
-- Windows NT, 2000, XP, Vista, or Seven.
-- Cygwin: http://cygwin.com/
-  Install at least the following packages (and their dependencies, as
-  computed by Cygwin's setup.exe):
-
-  For both flavor of OCaml (32-bit and 64-bit):
-     diffutils
-     make
-     ncurses
-
-  For the 32 bit flavor of OCaml:
-     mingw64-i686-binutils
-     mingw64-i686-gcc-core
-     mingw64-i686-runtime
-
-  For the 64 bit flavor of OCaml:
-     mingw64-x86_64-binutils
-     mingw64-x86_64-gcc-core
-     mingw64-x86_64-runtime
-
-- The flexdll tool (see above).  Do not forget to add the flexdll directory
-  to your PATH
-
-The standalone mingw toolchain from the MinGW-w64 project
-(http://mingw-w64.sourceforge.net/) is not supported.  Please use the
-version packaged in Cygwin instead.
-
-Start a new Cygwin shell and unpack the source distribution
-(ocaml-X.YY.Z.tar.gz) with "tar xzf".  Change to the top-level
-directory of the OCaml distribution.  Then, do
-
-        cp config/m-nt.h config/m.h
-        cp config/s-nt.h config/s.h
-
-For a 32 bit OCaml:
-        cp config/Makefile.mingw config/Makefile
-
-For a 64 bit OCaml:
-        cp config/Makefile.mingw64 config/Makefile
-
-Then, edit config/Makefile as needed, following the comments in this file.
-Normally, the only variable that need to be changed is
-        PREFIX      where to install everything
-
-Finally, use "make -f Makefile.nt" to build the system, e.g.
-
-        make -f Makefile.nt world
-        make -f Makefile.nt bootstrap
-        make -f Makefile.nt opt
-        make -f Makefile.nt opt.opt
-        make -f Makefile.nt install
-
-
-NOTES:
-
-* Libraries available in this port: "num", "str", "threads", "graphics",
-  and large parts of "unix".
-
-* The replay debugger is partially supported (no reverse execution).
-
-* The default Makefile.mingw and Makefile.mingw64 pass -static-libgcc to the linker.
-  For more information on this topic:
-
-  http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/Link-Options.html#Link-Options
-  http://caml.inria.fr/mantis/view.php?id=6411
-
-------------------------------------------------------------------------------
-
-                  The Cygwin port of OCaml
-                  ------------------------
-
-REQUIREMENTS:
-
-This port requires the Cygwin environment from Cygnus/RedHat, which
-is freely available at:
-          http://www.cygwin.com/
-
-It also requires the flexdll tool, available at:
-          http://alain.frisch.fr/flexdll.html
-
-This port runs under all versions of MS Windows supported by Cygwin.
-
-
-INSTALLATION:
-
-We do not distribute binaries for this port, but they can be found
-in the Cygwin distribution (use the Setup tool from Cygwin and select
-the OCaml packages).  Alternatively, recompile from the source distribution.
-
-
-RECOMPILATION FROM THE SOURCES:
-
-Before starting, make sure that the gcc version installed by cygwin
-is not 4.5.3 (it has a bug that affects OCaml).  If needed, use cygwin's
-setup.exe to downgrade to 4.3.4.
-
-You will need to recompile (and install) flexdll from source with
-Cygwin's C compiler because the official binary version of flexdll
-doesn't handle Cygwin's symbolic links and sometimes fails to
-launch the C compiler.
-
-In order to recompile flexdll, you first need to configure, compile,
-and install OCaml without flexdll support (configure with options
--no-shared-libs), then modify the flexdll Makefile to change
-line 51 from:
-  LINKFLAGS = -ccopt "-link version_res.o"
-to:
-  LINKFLAGS = -cclib version_res.o
-
-Then "make CHAINS=cygwin" and add the flexdll directory to your PATH.
-Make sure to add it before "/usr/bin" or you will get cygwin's flexlink.
-
-Then, in OCaml's source directory, type:
-  make clean
-  make distclean
-and follow the instructions for Unix machines given in the file INSTALL.
-
-
-NOTES:
-
-- There is a problem with cygwin's port of gcc version 4.5.3.  You should
-  use cygwin's setup program to downgrade to 4.3.4 before compiling OCaml.
-- The replay debugger is fully supported.
-- When upgrading from 3.12.0 to 3.12.1, you will need to remove
-  /usr/local/bin/ocamlmktop.exe before typing "make install".
-- In order to use the "graph" library, you will need to use Cygwin's
-  setup.exe to install the xinit, and libX11-devel packages before compiling
-  OCaml.
-
-------------------------------------------------------------------------------
-
-       The native Win64 port built with Microsoft Windows SDK
-       ------------------------------------------------------
-
-REQUIREMENTS:
-
-This port runs under MS Windows XP 64, Windows Server 64, and
-Windows 7 64 on Intel64/AMD64 machines.
-
-The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...)
-runs without any additional tools.
-
-Statically linking OCaml bytecode with C code (ocamlc -custom) requires the
-Microsoft Platform SDK compiler (item [1] in the section
-"third-party software" below) and the flexdll tool (item [2]).
-
-The native-code compiler (ocamlopt) requires the Microsoft compiler
-and the Microsoft assembler MASM64 (item [1]) and the flexdll tool (item [2]).
-
-INSTALLATION:
-
-There is no binary distribution yet.  Please compile from sources as
-described below.
-
-
-THIRD-PARTY SOFTWARE:
-
-[1] Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 Service Pack 1.
-    Can be downloaded for free from
-    http://www.microsoft.com/downloads/en/default.aspx
-    under the name "Microsoft Windows 7 SDK".
-
-[2] flexdll version 0.31 or later.
-    Can be downloaded from http://alain.frisch.fr/flexdll.html
-
-
-RECOMPILATION FROM THE SOURCES:
-
-The command-line tools can be recompiled from the Unix source
-distribution (ocaml-X.YZ.tar.gz), which also contains the files modified
-for Windows.
-
-You will need the following software components to perform the recompilation:
-- Windows XP 64, Windows Server 64, or Windows 7 64.
-- Items [1] and [2] from the list of recommended software above.
-- The Cygwin port of GNU tools, available from http://www.cygwin.com/
-  Install at least the following packages: diffutils, make, ncurses.
-
-First, you need to set up your cygwin environment for using the MS
-tools.  The following assumes that you have installed [1] and [2]
-in their default directories.  If this is not the case, you will need
-to adjust the paths accordingly.
-
-  Open a Windows Command Prompt and enter the following commands:
-    set PFPATH=C:\Program Files (x86)
-    cd "%PFPATH%\Microsoft Visual Studio 9.0\VC\bin"
-    vcvars64
-    echo VCPATH="`cygpath -p '%Path%'`" >C:\cygwin\tmp\msenv
-    echo LIBPATH="%LIBPATH%" >>C:\cygwin\tmp\msenv
-    echo FLPATH="`cygpath '%PFPATH%\flexdll'`" >>C:\cygwin\tmp\msenv
-    echo PATH="$VCPATH:$FLPATH:$PATH" >>C:\cygwin\tmp\msenv
-    echo export PATH LIB LIBPATH INCLUDE >>C:\cygwin\tmp\msenv
-    echo export OCAMLBUILD_FIND=/usr/bin/find >>C:\cygwin\tmp\msenv
-
-  Open a Cygwin shell and enter the following commands:
-    tr -d '\r' .msenv64
-    echo '. $HOME/.msenv64' >>.bashrc
-
-Now, close the Command Prompt and the shell and you're set up for
-using the MS tools under Cygwin.
-
-
-To recompile OCaml, start a new Cygwin shell and change to the top-level
-directory of the OCaml distribution.  Then, do
-
-        cp config/m-nt.h config/m.h
-        cp config/s-nt.h config/s.h
-        cp config/Makefile.msvc64 config/Makefile
-
-Then, edit config/Makefile as needed, following the comments in this file.
-Normally, the only variable that need to be changed is
-        PREFIX      where to install everything
-
-Finally, use "make -f Makefile.nt" to build the system, e.g.
-
-        make -f Makefile.nt world
-        make -f Makefile.nt bootstrap
-        make -f Makefile.nt opt
-        make -f Makefile.nt opt.opt
-        make -f Makefile.nt install
-
-
-NOTES:
-
-* Libraries available in this port: "num", "str", "threads", "graphics",
-  and large parts of "unix".
-
-* The replay debugger is partially supported (no reverse execution).
-
-* The graphical browser ocamlbrowser is not supported.
diff --git a/README.win32.adoc b/README.win32.adoc
new file mode 100644
index 00000000..f8b65eaf
--- /dev/null
+++ b/README.win32.adoc
@@ -0,0 +1,329 @@
+= Release notes for the Microsoft Windows ports of OCaml =
+:toc: macro
+
+There are no fewer than three ports of OCaml for Microsoft Windows, each
+available in 32 and 64-bit versions:
+
+  - native Windows, built with the Microsoft C/C++ Optimizing Compiler
+  - native Windows, built using the Mingw-w64 version of GCC
+  - Cygwin (http://www.cygwin.com[www.cygwin.com])
+
+Here is a summary of the main differences between these ports:
+
+|=====
+|                                        | Native Microsoft       | Native Mingw-w64 | Cygwin
+4+^| Third-party software required
+| for base bytecode system               | none                   | none             | none
+| for `ocamlc -custom`                     | Microsoft Visual C++   | Cygwin           | Cygwin
+| for native-code generation             | Microsoft Visual C++   | Cygwin           | Cygwin
+4+^| Features
+| Speed of bytecode interpreter          | 70%                    | 100%             | 100%
+| Replay debugger                        | yes <>       | yes <> | yes
+| The Unix library                       | partial                | partial          | full
+| The Threads library                    | yes                    | yes              | yes
+| The Graphics library                   | yes                    | yes              | no
+| Restrictions on generated executables? | none                   | none             | yes <>
+|=====
+
+[[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.
+
+[[tb2]]
+(**):: The debugger is supported but the "replay" functions are not enabled.
+Other functions are available (step, goto, run...).
+
+Cygwin aims to provide a Unix-like environment on Windows, and the build
+procedure for it is the same as for other flavours of Unix.  See
+link:INSTALL.adoc[] for full instructions.
+
+The native ports require Windows XP or later and naturally the 64-bit versions
+need a 64-bit edition of Windows (note that this is both to run *and* build).
+
+The two native Windows ports have to be built differently, and the remainder of
+this document gives more information.
+
+toc::[]
+
+== PREREQUISITES
+
+All the Windows ports require a Unix-like build environment.  Although other
+methods are available, the officially supported environment for doing this is
+32-bit (x86) Cygwin.
+
+Only the `make` Cygwin package is required. `diffutils` is required if you wish
+to be able to run the test suite.
+
+Unless you are also compiling the Cygwin port of OCaml, you should not install
+the `gcc-core` or `flexdll` packages. If you do, care may be required to ensure
+that a particular build is using the correct installation of `flexlink`.
+
+[[bmflex]]
+In addition to Cygwin, FlexDLL must also be installed, which is available from
+http://alain.frisch.fr/flexdll.html. A binary distribution is available;
+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.
+
+The base bytecode system (ocamlc, ocaml, ocamllex, ocamlyacc, ...) of all three
+ports runs without any additional tools.
+
+== Microsoft Visual C/C++ Ports
+
+=== REQUIREMENTS
+
+The native-code compiler (`ocamlopt`) and static linking of OCaml bytecode with
+C code (`ocamlc -custom`) require a Microsoft Visual C/C++ Compiler and the
+`flexlink` tool (see <>).
+
+Any edition (including Express/Community editions) of Microsoft Visual Studio
+2005 or later may be used to provide the required Windows headers and the C
+compiler. Additionally, some older Microsoft Windows SDKs include the
+Visual C/C++ Compiler.
+
+|=====
+|                    | `cl` Version | Express                 | SDK
+| Visual Studio 2005 | 14.00.x.x    | 32-bit only <> |
+| Visual Studio 2008 | 15.00.x.x    | 32-bit only             | Windows SDK 7.0 also provides 32/64-bit compilers
+| Visual Studio 2010 | 16.00.x.x    | 32-bit only             | Windows SDK 7.1 also provides 32/64-bit compilers
+| 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               |
+|=====
+
+[[vs1]]
+(*):: Visual C++ 2005 Express Edition does not provide an assembler; this can be
+      downloaded separately from
+      https://www.microsoft.com/en-gb/download/details.aspx?id=12654
+
+=== COMPILATION FROM THE SOURCES
+
+The command-line tools must be compiled from the Unix source distribution
+(`ocaml-X.YY.Z.tar.gz`), which also contains the files modified for Windows.
+
+Microsoft Visual C/C++ is designed to be used from special developer mode
+Command Prompts which set the environment variables for the required compiler.
+There are multiple ways of setting up your environment ready for their use.  The
+simplest is to start the appropriate command prompt shortcut from the program
+group of the compiler you have installed.
+
+The details differ depending on whether you are using a Windows SDK to provide
+the compiler or Microsoft Visual Studio itself.
+
+For the Windows SDK, there is only one command prompt called "CMD Shell" in
+versions 6.1 and 7.0 and "Windows SDK 7.1 Command Prompt" in version 7.1. This
+launches a Command Prompt which will usually select a `DEBUG` build environment
+for the operating system that you are running. You should then run:
+
+  SetEnv /Release /x86
+
+for 32-bit or:
+
+  SetEnv /Release /x64
+
+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.
+
+Unlike `SetEnv` for the Windows SDK, the architecture is selected by using a
+different shortcut, rather than by running a command.
+
+For Visual Studio 2005-2010, excluding version-specific prefixes, these are
+named "Command Prompt" for 32-bit and "x64 Cross Tools Command Prompt" or
+"x64 Win64 Command Prompt" for 64-bit. It does not matter whether you use a
+"Cross Tools" or "Win64" version for x64, this simply refers to whether the
+compiler itself is a 32-bit or 64-bit program; both produce 64-bit output and
+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
+architecture.
+
+You cannot at present use a cross-compiler to compile 64-bit OCaml on 32-bit
+Windows.
+
+Once you have started a Command Prompt, you can verify that you have the
+compiler you are expecting simply by running:
+
+  cl
+  Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x86
+  ...
+
+You then need to start Cygwin from this Command Prompt.  Assuming you have
+installed it to its default location of `C:\cygwin`, simply run:
+
+  C:\cygwin\bin\mintty -
+
+(note the space and hyphen at the end of the command).
+
+This should open a terminal window and start bash.  You should be able to run
+`cl` from this.  You can now change to the top-level directory of the directory
+of the OCaml distribution.
+
+The Microsoft Linker is provided by a command called `link` which unfortunately
+conflicts with a Cygwin command of the same name.  It is therefore necessary to
+ensure that the directory containing the Microsoft C/C++ Compiler appears at
+the beginning of `PATH`, before Cygwin's `/usr/bin`.  You can automate this from
+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
+quickly as it will be unable to link `ocamlrun`.
+
+Now run:
+
+        cp config/m-nt.h config/m.h
+        cp config/s-nt.h config/s.h
+
+followed by:
+
+        cp config/Makefile.msvc config/Makefile
+
+for 32-bit, or:
+
+        cp config/Makefile.msvc64 config/Makefile
+
+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.
+
+        make -f Makefile.nt 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
+will need to use `ocamlopt` (or `ocamlc -custom`) from the same Visual Studio or
+Windows SDK Command Prompt as you compiled OCaml from, or `ocamlopt` will not
+be able to find `cl`.
+
+If you wish to use `ocamlopt` from Cygwin's bash on a regular basis, you may
+like to copy the `tools/msvs-promote-path` script and add the `eval` line to
+your `~/.bashrc` file.
+
+* The Microsoft Visual C/C++ compiler does not implement "computed gotos", and
+  therefore generates inefficient code for `byterun/interp.c`.  Consequently,
+  the performance of bytecode programs is about 2/3 of that obtained under
+  Unix/GCC,  Cygwin or Mingw-w64 on similar hardware.
+
+* Libraries available in this port: `bigarray`, `dynlink`, `graphics`, `num`,
+  `str`, `threads`, and large parts of `unix`.
+
+* The replay debugger is partially supported (no reverse execution).
+
+=== CREDITS
+
+The initial port of Caml Special Light (the ancestor of OCaml) to Windows NT
+was done by Kevin Gallo at Microsoft Research, who kindly contributed his
+changes to the OCaml project.
+
+== Mingw-w64 Ports
+
+=== REQUIREMENTS
+
+The native-code compiler (`ocamlopt`) and static linking of OCaml bytecode with
+C code (`ocamlc -custom`) require the appropriate Mingw-w64 gcc and the
+`flexlink` tool (see <>). Mingw-w64 gcc is provided by the
+`mingw64-i686-gcc-core` package for 32-bit and the `mingw64-x86_64-gcc-core`
+package for 64-bit.
+
+  - Do not try to use the Cygwin version of flexdll for this port.
+
+  - The standalone mingw toolchain from the Mingw-w64 project
+    (http://mingw-w64.org/) is not supported. Please use the version packaged in
+    Cygwin instead.
+
+=== COMPILATION FROM THE SOURCES
+
+The command-line tools must be compiled from the Unix source distribution
+(`ocaml-X.YY.Z.tar.gz`), which also contains the files modified for Windows.
+
+Now run:
+
+        cp config/m-nt.h config/m.h
+        cp config/s-nt.h config/s.h
+
+followed by:
+
+        cp config/Makefile.mingw config/Makefile
+
+for 32-bit, or:
+
+        cp config/Makefile.mingw64 config/Makefile
+
+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.
+
+        make -f Makefile.nt 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
+bash or by adding Cygwin's bin directory (e.g. `C:\cygwin\bin`) to your `PATH`.
+
+* Libraries available in this port: `bigarray`, `dynlink`, `graphics`, `num`,
+  `str`, `threads`, and large parts of `unix`.
+
+* The replay debugger is partially supported (no reverse execution).
+
+* The default `config/Makefile.mingw` and `config/Makefile.mingw64` pass
+  `-static-libgcc` to the linker. For more information on this topic:
+
+  - http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/Link-Options.html#Link-Options
+  - http://caml.inria.fr/mantis/view.php?id=6411
+
+[[seflexdll]]
+== FlexDLL
+Although the core of FlexDLL is necessarily written in C, the `flexlink` program
+is, naturally, written in OCaml.  This creates a circular dependency if you wish
+to build entirely from sources.  Since OCaml 4.03 and FlexDLL 0.35, it is now
+possible to bootstrap the two programs simultaneously.  The process is identical
+for both ports.  If you choose to compile this way, it is not necessary to
+install FlexDLL separately -- indeed, if you do install FlexDLL separately, you
+may need to be careful to ensure that `ocamlopt` picks up the correct `flexlink`
+in your `PATH`.
+
+You must place the FlexDLL sources for Version 0.35 or later in the directory
+`flexdll/` at the top-level directory of the directory of the OCaml
+distribution.  This can be done in one of three ways:
+
+ * Extracting the sources from a tarball from
+   http://alain.frisch.fr/flexdll.html#download
+ * Cloning the git repository by running:
++
+  git clone https://github.com/alainfrisch/flexdll.git
+
+ * If you are compiling from a git clone of the OCaml repository, instead of
+   using a sources tarball, you can run:
++
+  git submodule update --init
+
+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 -f Makefile.nt 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"
+   `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
+   installed FlexDLL, you must erase the contents of `flexdll/` before
+   compiling.
+
+== Trademarks
+
+Microsoft, Visual C++, Visual Studio and Windows are registered trademarks of
+Microsoft Corporation in the United States and/or other countries.
diff --git a/VERSION b/VERSION
index dbd6b8fc..a376e21d 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.02.3
+4.03.0
 
 # 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
new file mode 100644
index 00000000..ac0db2fb
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,56 @@
+# Compile the 64 bits version
+platform:
+  - x64
+
+branches:
+  only:
+    - trunk
+
+# Do a shallow clone of the repo to speed up the build
+clone_depth: 1
+
+environment:
+  global:
+    CYG_ROOT: C:/cygwin
+    CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
+    CYG_CACHE: C:/cygwin/var/cache/setup
+    OCAMLROOT: "%PROGRAMFILES%/OCaml"
+
+cache:
+  - C:\cygwin\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"
+  - cinst 7zip.commandline
+  - 7za x -y flexdll.zip
+  - for %%F in (*.c *.h *.exe *.o *.obj) do copy %%F "%OCAMLROOT%\bin\flexdll"
+  # 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'
+  - '%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%
+
+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 "$APPVEYOR_BUILD_FOLDER/appveyor_build.sh"'
+
+test_script:
+  - ocamlc -version
+  - set CAML_LD_LIBRARY_PATH=%OCAMLROOT%/lib/stublibs
+  - '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER && make -f Makefile.nt tests"'
diff --git a/appveyor_build.sh b/appveyor_build.sh
new file mode 100644
index 00000000..7b95b046
--- /dev/null
+++ b/appveyor_build.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+function run {
+    NAME=$1
+    shift
+    echo "-=-=- $NAME -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+    $@
+    CODE=$?
+    if [ $CODE -ne 0 ]; then
+        echo "-=-=- $NAME failed! -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+        exit $CODE
+    else
+        echo "-=-=- End of $NAME -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-"
+    fi
+}
+
+cd $APPVEYOR_BUILD_FOLDER
+
+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
+#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
diff --git a/asmcomp/.ignore b/asmcomp/.ignore
deleted file mode 100644
index 8c24e74a..00000000
--- a/asmcomp/.ignore
+++ /dev/null
@@ -1,7 +0,0 @@
-emit.ml
-arch.ml
-proc.ml
-selection.ml
-reload.ml
-scheduling.ml
-CSE.ml
diff --git a/asmcomp/CSEgen.ml b/asmcomp/CSEgen.ml
index 6571ad53..73bd903d 100644
--- a/asmcomp/CSEgen.ml
+++ b/asmcomp/CSEgen.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Common subexpression elimination by value numbering over extended
    basic blocks. *)
@@ -17,14 +20,51 @@ open Mach
 
 type valnum = int
 
+(* Classification of operations *)
+
+type op_class =
+  | Op_pure           (* pure arithmetic, produce one or several result *)
+  | Op_checkbound     (* checkbound-style: no result, can raise an exn *)
+  | Op_load           (* memory load *)
+  | Op_store of bool  (* memory store, false = init, true = assign *)
+  | Op_other   (* anything else that does not allocate nor store in memory *)
+
 (* We maintain sets of equations of the form
        valnums = operation(valnums)
    plus a mapping from registers to valnums (value numbers). *)
 
 type rhs = operation * valnum array
 
-module Equations =
-  Map.Make(struct type t = rhs let compare = Pervasives.compare end)
+module Equations = struct
+  module Rhs_map =
+    Map.Make(struct type t = rhs let compare = Pervasives.compare end)
+
+  type 'a t =
+    { load_equations : 'a Rhs_map.t;
+      other_equations : 'a Rhs_map.t }
+
+  let empty =
+    { load_equations = Rhs_map.empty;
+      other_equations = Rhs_map.empty }
+
+  let add op_class op v m =
+    match op_class with
+    | Op_load ->
+      { m with load_equations = Rhs_map.add op v m.load_equations }
+    | _ ->
+      { m with other_equations = Rhs_map.add op v m.other_equations }
+
+  let find op_class op m =
+    match op_class with
+    | Op_load ->
+      Rhs_map.find op m.load_equations
+    | _ ->
+      Rhs_map.find op m.other_equations
+
+  let remove_loads m =
+    { load_equations = Rhs_map.empty;
+      other_equations = m.other_equations }
+end
 
 type numbering =
   { num_next: int;                      (* next fresh value number *)
@@ -76,9 +116,9 @@ let valnum_regs n rs =
 (* Look up the set of equations for an equation with the given rhs.
    Return [Some res] if there is one, where [res] is the lhs. *)
 
-let find_equation n rhs =
+let find_equation op_class n rhs =
   try
-    Some(Equations.find rhs n.num_eqs)
+    Some(Equations.find op_class rhs n.num_eqs)
   with Not_found ->
     None
 
@@ -138,9 +178,9 @@ let set_move n src dst =
 (* Record the equation [fresh valnums = rhs] and associate the given
    result registers [rs] to [fresh valnums]. *)
 
-let set_fresh_regs n rs rhs =
+let set_fresh_regs n rs rhs op_class =
   let (n1, vs) = fresh_valnum_regs n rs in
-  { n1 with num_eqs = Equations.add rhs vs n.num_eqs }
+  { n1 with num_eqs = Equations.add op_class rhs vs n.num_eqs }
 
 (* Forget everything we know about the given result registers,
    which are receiving unpredictable values at run-time. *)
@@ -150,8 +190,14 @@ let set_unknown_regs n rs =
 
 (* Keep only the equations satisfying the given predicate. *)
 
-let filter_equations pred n =
-  { n with num_eqs = Equations.filter (fun (op,_) res -> pred op) n.num_eqs }
+let remove_load_numbering n =
+  { n with num_eqs = Equations.remove_loads n.num_eqs }
+
+(* Forget everything we know about registers of type [Addr]. *)
+
+let kill_addr_regs n =
+  { n with num_reg =
+              Reg.Map.filter (fun r n -> r.Reg.typ <> Cmm.Addr) n.num_reg }
 
 (* Prepend a set of moves before [i] to assign [srcs] to [dsts].  *)
 
@@ -167,15 +213,6 @@ let insert_move srcs dsts i =
          let i1 = array_fold2 insert_single_move i tmps dsts in
          array_fold2 insert_single_move i1 srcs tmps
 
-(* Classification of operations *)
-
-type op_class =
-  | Op_pure           (* pure arithmetic, produce one or several result *)
-  | Op_checkbound     (* checkbound-style: no result, can raise an exn *)
-  | Op_load           (* memory load *)
-  | Op_store of bool  (* memory store, false = init, true = assign *)
-  | Op_other   (* anything else that does not allocate nor store in memory *)
-
 class cse_generic = object (self)
 
 (* Default classification of operations.  Can be overriden in
@@ -211,7 +248,7 @@ method is_cheap_operation op =
    non-initializing store *)
 
 method private kill_loads n =
-  filter_equations (fun o -> self#class_of_operation o <> Op_load) n
+  remove_load_numbering n
 
 (* Perform CSE on the given instruction [i] and its successors.
    [n] is the value numbering current at the beginning of [i]. *)
@@ -231,7 +268,8 @@ method private cse n i =
          - equations involving memory loads, since the callee can
            perform arbitrary memory stores;
          - equations involving arithmetic operations that can
-           produce bad pointers into the heap (see below for Ialloc);
+           produce [Addr]-typed derived pointers into the heap
+           (see below for Ialloc);
          - mappings from hardware registers to value numbers,
            since the callee does not preserve these registers.
          That doesn't leave much usable information: checkbounds
@@ -241,19 +279,24 @@ method private cse n i =
       {i with next = self#cse empty_numbering i.next}
   | Iop (Ialloc _) ->
       (* For allocations, we must avoid extending the live range of a
-         pseudoregister across the allocation if this pseudoreg can
-         contain a value that looks like a pointer into the heap but
-         is not a pointer to the beginning of a Caml object.  PR#6484
-         is an example of such a value (a derived pointer into a
-         block).  In the absence of more precise typing information,
-         we just forget everything. *)
-       {i with next = self#cse empty_numbering i.next}
+         pseudoregister across the allocation if this pseudoreg
+         is a derived heap pointer (a pointer into the heap that does
+         not point to the beginning of a Caml block).  PR#6484 is an
+         example of this situation.  Such pseudoregs have type [Addr].
+         Pseudoregs with types other than [Addr] can be kept.
+         Moreover, allocation can trigger the asynchronous execution
+         of arbitrary Caml code (finalizer, signal handler, context
+         switch), which can contain non-initializing stores.
+         Hence, all equations over loads must be removed. *)
+       let n1 = kill_addr_regs (self#kill_loads n) in
+       let n2 = set_unknown_regs n1 i.res in
+       {i with next = self#cse n2 i.next}
   | Iop op ->
       begin match self#class_of_operation op with
-      | Op_pure | Op_checkbound | Op_load ->
+      | (Op_pure | Op_checkbound | Op_load) as op_class ->
           let (n1, varg) = valnum_regs n i.arg in
           let n2 = set_unknown_regs n1 (Proc.destroyed_at_oper i.desc) in
-          begin match find_equation n1 (op, varg) with
+          begin match find_equation op_class n1 (op, varg) with
           | Some vres ->
               (* This operation was computed earlier. *)
               (* Are there registers that hold the results computed earlier? *)
@@ -277,7 +320,7 @@ method private cse n i =
               end
           | None ->
               (* This operation produces a result we haven't seen earlier. *)
-              let n3 = set_fresh_regs n2 i.res (op, varg) in
+              let n3 = set_fresh_regs n2 i.res (op, varg) op_class in
               {i with next = self#cse n3 i.next}
           end
       | Op_store false | Op_other ->
diff --git a/asmcomp/CSEgen.mli b/asmcomp/CSEgen.mli
index 0b375ff5..98b5f5b0 100644
--- a/asmcomp/CSEgen.mli
+++ b/asmcomp/CSEgen.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Common subexpression elimination by value numbering over extended
    basic blocks. *)
diff --git a/asmcomp/amd64/CSE.ml b/asmcomp/amd64/CSE.ml
index aee43d2b..d85e1629 100644
--- a/asmcomp/amd64/CSE.ml
+++ b/asmcomp/amd64/CSE.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* CSE for the AMD64 *)
 
diff --git a/asmcomp/amd64/NOTES.md b/asmcomp/amd64/NOTES.md
new file mode 100644
index 00000000..b0adc698
--- /dev/null
+++ b/asmcomp/amd64/NOTES.md
@@ -0,0 +1,21 @@
+# Supported platforms
+
+Intel and AMD x86 processors in 64-bit mode, a.k.a `x86_64`.
+
+Floating-point architecture: SSE2, supported by all x86_64 processors.
+
+Operating systems: Linux, BSD, MacOS X, MS Windows.
+
+Debian architecture name: `amd64`
+
+# Reference documents
+
+* Instruction set architecture:
+  any Intel or AMD manual less than 10 years old.
+* ELF application binary interface:
+  _System V Application Binary Interface,
+   AMD64 Architecture Processor Supplement_
+* MacOS X application binary interface:
+  _OS X ABI Function Call Guide: x86-64 Function Calling Conventions_
+* Windows 64 application binary interface:
+  _x64 Software Conventions_ from MSDN
diff --git a/asmcomp/amd64/arch.ml b/asmcomp/amd64/arch.ml
index a4f1abd9..a38e9ad5 100644
--- a/asmcomp/amd64/arch.ml
+++ b/asmcomp/amd64/arch.ml
@@ -1,23 +1,24 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2000 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2000 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Machine-specific command-line options *)
 
-let pic_code = ref true
-
 let command_line_options =
-  [ "-fPIC", Arg.Set pic_code,
+  [ "-fPIC", Arg.Set Clflags.pic_code,
       " Generate position-independent machine code (default)";
-    "-fno-PIC", Arg.Clear pic_code,
+    "-fno-PIC", Arg.Clear Clflags.pic_code,
       " Generate position-dependent machine code" ]
 
 (* Specific operations for the AMD64 processor *)
diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp
index d56d0f5f..6d058913 100644
--- a/asmcomp/amd64/emit.mlp
+++ b/asmcomp/amd64/emit.mlp
@@ -1,17 +1,22 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-(* Emission of x86-64 (AMD 64) assembly code *)
-
+# 2 "asmcomp/amd64/emit.mlp"
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Emission of Intel x86_64 assembly code *)
+
+open Misc
 open Cmm
 open Arch
 open Proc
@@ -20,15 +25,43 @@ open Mach
 open Linearize
 open Emitaux
 
+open X86_ast
+open X86_proc
+open X86_dsl
+
 (* [Branch_relaxation] is not used in this file, but is required by
    emit.mlp files for certain other targets; the reference here ensures
    that when releases are being prepared the .depend files are correct
    for all targets. *)
 open! Branch_relaxation
 
-let macosx = (Config.system = "macosx")
-let mingw64 = (Config.system = "mingw64")
-let cygwin = (Config.system = "cygwin")
+let _label s = D.label ~typ:QWORD s
+
+(* Override proc.ml *)
+
+let int_reg_name =
+  [| RAX; RBX; RDI; RSI; RDX; RCX; R8; R9;
+     R12; R13; R10; R11; RBP; |]
+
+let float_reg_name = Array.init 16 (fun i -> XMM i)
+
+let register_name r =
+  if r < 100 then Reg64 (int_reg_name.(r))
+  else Regf (float_reg_name.(r - 100))
+
+(* CFI directives *)
+
+let cfi_startproc () =
+  if Config.asm_cfi_supported then D.cfi_startproc ()
+
+let cfi_endproc () =
+  if Config.asm_cfi_supported then D.cfi_endproc ()
+
+let cfi_adjust_cfa_offset n =
+  if Config.asm_cfi_supported then D.cfi_adjust_cfa_offset n
+
+let emit_debug_info dbg =
+  emit_debug_info_gen dbg D.file D.loc
 
 let fp = Config.with_frame_pointers
 
@@ -47,14 +80,14 @@ let frame_size () =                     (* includes return address *)
   if frame_required() then begin
     let sz =
       (!stack_offset + 8 * (num_stack_slots.(0) + num_stack_slots.(1)) + 8
-      + (if fp then 8 else 0) )
+       + (if fp then 8 else 0))
     in Misc.align sz 16
   end else
     !stack_offset + 8
 
 let slot_offset loc cl =
   match loc with
-    Incoming n -> frame_size() + n
+  | Incoming n -> frame_size() + n
   | Local n ->
       if cl = 0
       then !stack_offset + n * 8
@@ -63,106 +96,150 @@ let slot_offset loc cl =
 
 (* Symbols *)
 
-let emit_symbol s =
-    if macosx then emit_string "_";
-    Emitaux.emit_symbol '$' s
+let symbol_prefix = if system = S_macosx then "_" else ""
+
+let emit_symbol s = string_of_symbol symbol_prefix s
+
+(* Record symbols used and defined - at the end generate extern for those
+   used but not defined *)
+
+let symbols_defined = ref StringSet.empty
+let symbols_used = ref StringSet.empty
+
+let add_def_symbol s = symbols_defined := StringSet.add s !symbols_defined
+let add_used_symbol s = symbols_used := StringSet.add s !symbols_used
 
-let emit_call s =
-  if !Clflags.dlcode && not macosx && not mingw64 && not cygwin
-  then `call	{emit_symbol s}@PLT`
-  else `call	{emit_symbol s}`
+let imp_table = Hashtbl.create 16
 
-let emit_jump s =
-  if !Clflags.dlcode && not macosx && not mingw64 && not cygwin
-  then `jmp	{emit_symbol s}@PLT`
-  else `jmp	{emit_symbol s}`
+let reset_imp_table () = Hashtbl.clear imp_table
 
-let load_symbol_addr s =
-  if !Clflags.dlcode && not mingw64 && not cygwin
-  then `movq	{emit_symbol s}@GOTPCREL(%rip)`
-  else if !pic_code
-  then `leaq	{emit_symbol s}(%rip)`
-  else `movq	${emit_symbol s}`
+let get_imp_symbol s =
+  match Hashtbl.find imp_table s with
+  | exception Not_found ->
+      let imps = "__caml_imp_" ^ s in
+      Hashtbl.add imp_table s imps;
+      imps
+  | imps -> imps
+
+let emit_imp_table () =
+  let f s imps =
+    _label (emit_symbol imps);
+    D.qword (ConstLabel (emit_symbol s))
+  in
+  D.data();
+  D.comment "relocation table start";
+  D.align 8;
+  Hashtbl.iter f imp_table;
+  D.comment "relocation table end"
+
+let mem__imp s =
+  let imp_s = get_imp_symbol s in
+  mem64_rip QWORD (emit_symbol imp_s)
+
+let rel_plt s =
+  if windows && !Clflags.dlcode then mem__imp s
+  else
+    let use_plt =
+      match system with
+      | S_macosx | S_mingw64 | S_cygwin | S_win64 -> false
+      | _ -> !Clflags.dlcode
+    in
+    sym (if use_plt then emit_symbol s ^ "@PLT" else emit_symbol s)
+
+let emit_call s = I.call (rel_plt s)
+
+let emit_jump s = I.jmp (rel_plt s)
+
+let load_symbol_addr s arg =
+  if !Clflags.dlcode then
+    if windows then begin
+      (* I.mov (mem__imp s) arg (\* mov __caml_imp_foo(%rip), ... *\) *)
+      I.mov (sym (emit_symbol s)) arg (* movabsq $foo, ... *)
+    end else I.mov (mem64_rip QWORD (emit_symbol s ^ "@GOTPCREL")) arg
+  else if !Clflags.pic_code then
+    I.lea (mem64_rip NONE (emit_symbol s)) arg
+  else
+    I.mov (sym (emit_symbol s)) arg
 
 (* Output a label *)
 
 let emit_label lbl =
-  emit_string ".L"; emit_int lbl
+  match system with
+  | S_macosx | S_win64 -> "L" ^ string_of_int lbl
+  | _ -> ".L" ^ string_of_int lbl
 
 let emit_data_label lbl =
-  emit_string ".Ld"; emit_int lbl
+  match system with
+  | S_win64 -> "Ld" ^ string_of_int lbl
+  | _ -> ".Ld" ^ string_of_int lbl
 
-(* Output a .align directive. *)
+let label s = sym (emit_label s)
 
-let emit_align n =
-    let n = if macosx then Misc.log2 n else n in
-  `	.align	{emit_int n}\n`
+let def_label s = D.label (emit_label s)
 
 let emit_Llabel fallthrough lbl =
-  if not fallthrough && !fastcode_flag then emit_align 4;
-  emit_label lbl
+  if not fallthrough && !fastcode_flag then D.align 4;
+  def_label lbl
 
 (* Output a pseudo-register *)
 
-let emit_reg = function
-    { loc = Reg r } ->
-      emit_string (register_name r)
+let reg = function
+  | { loc = Reg.Reg r } -> register_name r
+  | { loc = Stack s; typ = Float } as r ->
+      let ofs = slot_offset s (register_class r) in
+      mem64 REAL8 ofs RSP
   | { loc = Stack s } as r ->
       let ofs = slot_offset s (register_class r) in
-      `{emit_int ofs}(%rsp)`
+      mem64 QWORD ofs RSP
   | { loc = Unknown } ->
       assert false
 
+let reg64 = function
+  | { loc = Reg.Reg r } -> int_reg_name.(r)
+  | _ -> assert false
+
+
+let res i n = reg i.res.(n)
+
+let arg i n = reg i.arg.(n)
+
 (* Output a reference to the lower 8, 16 or 32 bits of a register *)
 
-let reg_low_8_name =
-  [| "%al"; "%bl"; "%dil"; "%sil"; "%dl"; "%cl"; "%r8b"; "%r9b";
-     "%r12b"; "%r13b"; "%r10b"; "%r11b"; "%bpl" |]
-let reg_low_16_name =
-  [| "%ax"; "%bx"; "%di"; "%si"; "%dx"; "%cx"; "%r8w"; "%r9w";
-     "%r12w"; "%r13w"; "%r10w"; "%r11w"; "%bp" |]
-let reg_low_32_name =
-  [| "%eax"; "%ebx"; "%edi"; "%esi"; "%edx"; "%ecx"; "%r8d"; "%r9d";
-     "%r12d"; "%r13d"; "%r10d"; "%r11d"; "%ebp" |]
-
-let emit_subreg tbl r =
+let reg_low_8_name  = Array.map (fun r -> Reg8L r) int_reg_name
+let reg_low_16_name = Array.map (fun r -> Reg16 r) int_reg_name
+let reg_low_32_name = Array.map (fun r -> Reg32 r) int_reg_name
+
+let emit_subreg tbl typ r =
   match r.loc with
-    Reg r when r < 13 ->
-      emit_string tbl.(r)
-  | Stack s ->
-      let ofs = slot_offset s (register_class r) in
-      `{emit_int ofs}(%rsp)`
-  | _ ->
-      assert false
+  | Reg.Reg r when r < 13 -> tbl.(r)
+  | Stack s -> mem64 typ (slot_offset s (register_class r)) RSP
+  | _ -> assert false
+
+let arg8 i n = emit_subreg reg_low_8_name BYTE i.arg.(n)
+let arg16 i n = emit_subreg reg_low_16_name WORD i.arg.(n)
+let arg32 i n = emit_subreg reg_low_32_name DWORD i.arg.(n)
+let arg64 i n = reg64 i.arg.(n)
 
-let emit_reg8 r = emit_subreg reg_low_8_name r
-let emit_reg16 r = emit_subreg reg_low_16_name r
-let emit_reg32 r = emit_subreg reg_low_32_name r
+let res16 i n = emit_subreg reg_low_16_name WORD i.res.(n)
+let res32 i n = emit_subreg reg_low_32_name DWORD i.res.(n)
 
 (* Output an addressing mode *)
 
-let emit_addressing addr r n =
+let addressing addr typ i n =
   match addr with
-  | Ibased _ when !Clflags.dlcode -> assert false
-  | Ibased(s, d) ->
-      `{emit_symbol s}`;
-      if d <> 0 then ` + {emit_int d}`;
-      `(%rip)`
+  | Ibased(s, ofs) ->
+      add_used_symbol s;
+      mem64_rip typ (emit_symbol s) ~ofs
   | Iindexed d ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)})`
+      mem64 typ d (arg64 i n)
   | Iindexed2 d ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)}, {emit_reg r.(n+1)})`
+      mem64 typ ~base:(arg64 i n) d (arg64 i (n+1))
   | Iscaled(2, d) ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)}, {emit_reg r.(n)})`
+      mem64 typ ~base:(arg64 i n) d (arg64 i n)
   | Iscaled(scale, d) ->
-      if d <> 0 then emit_int d;
-      `(, {emit_reg r.(n)}, {emit_int scale})`
+      mem64 typ ~scale d (arg64 i n)
   | Iindexed2scaled(scale, d) ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)}, {emit_reg r.(n+1)}, {emit_int scale})`
+      mem64 typ ~scale ~base:(arg64 i n) d (arg64 i (n+1))
 
 (* Record live pointers at call points -- see Emitaux *)
 
@@ -171,11 +248,14 @@ let record_frame_label live dbg =
   let live_offset = ref [] in
   Reg.Set.iter
     (function
-        {typ = Addr; loc = Reg r} ->
+      | {typ = Val; loc = Reg r} ->
           live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
+      | {typ = Val; loc = Stack s} as reg ->
           live_offset := slot_offset s (register_class reg) :: !live_offset
-      | _ -> ())
+      | {typ = Addr} as r ->
+          Misc.fatal_error ("bad GC root " ^ Reg.name r)
+      | _ -> ()
+    )
     live;
   frame_descriptors :=
     { fd_lbl = lbl;
@@ -185,7 +265,8 @@ let record_frame_label live dbg =
   lbl
 
 let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:\n`
+  let lbl = record_frame_label live dbg in
+  def_label lbl
 
 (* Record calls to the GC -- we've moved them out of the way *)
 
@@ -197,8 +278,10 @@ 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_frame}:	jmp	{emit_label gc.gc_return_lbl}\n`
+  def_label gc.gc_lbl;
+  emit_call "caml_call_gc";
+  def_label gc.gc_frame;
+  I.jmp (label gc.gc_return_lbl)
 
 (* Record calls to caml_ml_array_bound_error.
    In -g mode, we maintain one call to caml_ml_array_bound_error
@@ -216,67 +299,70 @@ let bound_error_label dbg =
     let lbl_bound_error = new_label() in
     let lbl_frame = record_frame_label Reg.Set.empty dbg in
     bound_error_sites :=
-     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
-   lbl_bound_error
- end else begin
-   if !bound_error_call = 0 then bound_error_call := new_label();
-   !bound_error_call
- end
+      { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
+    lbl_bound_error
+  end else begin
+    if !bound_error_call = 0 then bound_error_call := new_label();
+    !bound_error_call
+  end
 
 let emit_call_bound_error bd =
-  `{emit_label bd.bd_lbl}:	{emit_call "caml_ml_array_bound_error"}\n`;
-  `{emit_label bd.bd_frame}:\n`
+  def_label bd.bd_lbl;
+  emit_call "caml_ml_array_bound_error";
+  def_label bd.bd_frame
 
 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
+    def_label !bound_error_call;
+    emit_call "caml_ml_array_bound_error"
+  end
 
 (* Names for instructions *)
 
 let instr_for_intop = function
-    Iadd -> "addq"
-  | Isub -> "subq"
-  | Imul -> "imulq"
-  | Iand -> "andq"
-  | Ior -> "orq"
-  | Ixor -> "xorq"
-  | Ilsl -> "salq"
-  | Ilsr -> "shrq"
-  | Iasr -> "sarq"
+  | Iadd -> I.add
+  | Isub -> I.sub
+  | Imul -> (fun arg1 arg2 -> I.imul arg1 (Some arg2))
+  | Iand -> I.and_
+  | Ior -> I.or_
+  | Ixor -> I.xor
+  | Ilsl -> I.sal
+  | Ilsr -> I.shr
+  | Iasr -> I.sar
   | _ -> assert false
 
 let instr_for_floatop = function
-    Iaddf -> "addsd"
-  | Isubf -> "subsd"
-  | Imulf -> "mulsd"
-  | Idivf -> "divsd"
+  | Iaddf -> I.addsd
+  | Isubf -> I.subsd
+  | Imulf -> I.mulsd
+  | Idivf -> I.divsd
   | _ -> assert false
 
 let instr_for_floatarithmem = function
-    Ifloatadd -> "addsd"
-  | Ifloatsub -> "subsd"
-  | Ifloatmul -> "mulsd"
-  | Ifloatdiv -> "divsd"
-
-let name_for_cond_branch = function
-    Isigned Ceq -> "e"     | Isigned Cne -> "ne"
-  | Isigned Cle -> "le"     | Isigned Cgt -> "g"
-  | Isigned Clt -> "l"     | Isigned Cge -> "ge"
-  | Iunsigned Ceq -> "e"   | Iunsigned Cne -> "ne"
-  | Iunsigned Cle -> "be"  | Iunsigned Cgt -> "a"
-  | Iunsigned Clt -> "b"  | Iunsigned Cge -> "ae"
+  | Ifloatadd -> I.addsd
+  | Ifloatsub -> I.subsd
+  | Ifloatmul -> I.mulsd
+  | Ifloatdiv -> I.divsd
+
+let cond = function
+  | Isigned Ceq   -> E   | Isigned Cne   -> NE
+  | Isigned Cle   -> LE  | Isigned Cgt   -> G
+  | Isigned Clt   -> L   | Isigned Cge   -> GE
+  | Iunsigned Ceq -> E   | Iunsigned Cne -> NE
+  | Iunsigned Cle -> BE  | Iunsigned Cgt -> A
+  | Iunsigned Clt -> B   | Iunsigned Cge -> AE
 
 (* Output an = 0 or <> 0 test. *)
 
 let output_test_zero arg =
   match arg.loc with
-    Reg r -> `	testq	{emit_reg arg}, {emit_reg arg}\n`
-  | _     -> `	cmpq	$0, {emit_reg arg}\n`
+  | Reg.Reg _ -> I.test (reg arg) (reg arg)
+  | _  -> I.cmp (int 0) (reg arg)
 
 (* Output a floating-point compare and branch *)
 
-let emit_float_test cmp neg arg lbl =
+let emit_float_test cmp neg i lbl =
   (* Effect of comisd on flags and conditional branches:
                      ZF PF CF  cond. branches taken
         unordered     1  1  1  je, jb, jbe, jp
@@ -289,52 +375,46 @@ let emit_float_test cmp neg arg lbl =
   match (cmp, neg) with
   | (Ceq, false) | (Cne, true) ->
       let next = new_label() in
-      `	ucomisd	{emit_reg arg.(1)}, {emit_reg arg.(0)}\n`;
-      `	jp	{emit_label next}\n`;    (* skip if unordered *)
-      `	je	{emit_label lbl}\n`;     (* branch taken if x=y *)
-      `{emit_label next}:\n`
+      I.ucomisd (arg i 1) (arg i 0);
+      I.jp (label next);          (* skip if unordered *)
+      I.je lbl;                   (* branch taken if x=y *)
+      def_label next
   | (Cne, false) | (Ceq, true) ->
-      `	ucomisd	{emit_reg arg.(1)}, {emit_reg arg.(0)}\n`;
-      `	jp	{emit_label lbl}\n`;     (* branch taken if unordered *)
-      `	jne	{emit_label lbl}\n`      (* branch taken if xy *)
+      I.ucomisd (arg i 1) (arg i 0);
+      I.jp lbl;                   (* branch taken if unordered *)
+      I.jne lbl                   (* branch taken if xy *)
   | (Clt, _) ->
-      `	comisd	{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;  (* swap compare *)
-      if not neg then
-      `	ja	{emit_label lbl}\n`     (* branch taken if y>x i.e. xx i.e. x
-      `	comisd	{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;  (* swap compare *)
-      if not neg then
-      `	jae	{emit_label lbl}\n`     (* branch taken if y>=x i.e. x<=y *)
-      else
-      `	jb	{emit_label lbl}\n` (* taken if unordered or y=x i.e. x<=y *)
+      else            I.jb lbl    (* taken if unordered or y
-      `	comisd	{emit_reg arg.(1)}, {emit_reg arg.(0)}\n`;
-      if not neg then
-      `	ja	{emit_label lbl}\n`     (* branch taken if x>y *)
-      else
-      `	jbe	{emit_label lbl}\n` (* taken if unordered or x<=y i.e. !(x>y) *)
+      I.comisd (arg i 1) (arg i 0);
+      if not neg then I.ja lbl    (* branch taken if x>y *)
+      else            I.jbe lbl   (* taken if unordered or x<=y i.e. !(x>y) *)
   | (Cge, _) ->
-      `	comisd	{emit_reg arg.(1)}, {emit_reg arg.(0)}\n`;  (* swap compare *)
-      if not neg then
-      `	jae	{emit_label lbl}\n`     (* branch taken if x>=y *)
-      else
-      `	jb	{emit_label lbl}\n` (* taken if unordered or x=y) *)
+      I.comisd (arg i 1) (arg i 0);(* swap compare *)
+      if not neg then I.jae lbl   (* branch taken if x>=y *)
+      else            I.jb lbl    (* taken if unordered or x=y) *)
 
 (* Deallocate the stack frame before a return or tail call *)
 
 let output_epilogue f =
   if frame_required() then begin
     let n = frame_size() - 8 - (if fp then 8 else 0) in
-    `	addq	${emit_int n}, %rsp\n`;
-    cfi_adjust_cfa_offset (-n);
-    if fp then begin
-       `	popq	%rbp\n`
+    if n <> 0
+    then begin
+      I.add (int n) rsp;
+      cfi_adjust_cfa_offset (-n);
     end;
+    if fp then I.pop rbp;
     f ();
     (* reset CFA back cause function body may continue *)
-    cfi_adjust_cfa_offset n
+    if n <> 0
+    then cfi_adjust_cfa_offset n
   end
   else
     f ()
@@ -344,18 +424,24 @@ let output_epilogue f =
 let float_constants = ref ([] : (int64 * int) list)
 
 let add_float_constant cst =
-  let repr = Int64.bits_of_float cst in
   try
-    List.assoc repr !float_constants
-  with
-    Not_found ->
-      let lbl = new_label() in
-      float_constants := (repr, lbl) :: !float_constants;
-      lbl
+    List.assoc cst !float_constants
+  with Not_found ->
+    let lbl = new_label() in
+    float_constants := (cst, lbl) :: !float_constants;
+    lbl
+
+let emit_float_constant f lbl =
+  _label (emit_label lbl);
+  D.qword (Const f)
+
+let emit_global_label s =
+  let lbl = Compilenv.make_symbol (Some s) in
+  add_def_symbol lbl;
+  let lbl = emit_symbol lbl in
+  D.global lbl;
+  _label lbl
 
-let emit_float_constant (cst, lbl) =
-  `{emit_label lbl}:`;
-  emit_float64_directive ".quad" cst
 
 (* Output the assembly code for an instruction *)
 
@@ -366,326 +452,337 @@ let tailrec_entry_point = ref 0
 
 (* Emit an instruction *)
 let emit_instr fallthrough i =
-    emit_debug_info i.dbg;
-    match i.desc with
-      Lend -> ()
-    | Lop(Imove | Ispill | Ireload) ->
-        let src = i.arg.(0) and dst = i.res.(0) in
-        if src.loc <> dst.loc then begin
-          match src.typ, src.loc, dst.loc with
-            Float, Reg _, Reg _ ->
-              `	movapd	{emit_reg src}, {emit_reg dst}\n`
-          | Float, _, _ ->
-              `	movsd	{emit_reg src}, {emit_reg dst}\n`
-          | _ ->
-              `	movq	{emit_reg src}, {emit_reg dst}\n`
+  emit_debug_info i.dbg;
+  match i.desc with
+  | Lend -> ()
+  | Lop(Imove | Ispill | Ireload) ->
+      let src = i.arg.(0) and dst = i.res.(0) in
+      if src.loc <> dst.loc then
+        begin match src.typ, src.loc, dst.loc with
+        | Float, Reg.Reg _, Reg.Reg _ -> I.movapd (reg src) (reg dst)
+        | Float, _, _ -> I.movsd (reg src) (reg dst)
+        | _ -> I.mov (reg src) (reg dst)
         end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
-        if n = 0n then begin
-          match i.res.(0).loc with
-            Reg n -> `	xorq	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
-          | _     -> `	movq	$0, {emit_reg i.res.(0)}\n`
-        end else if n <= 0x7FFFFFFFn && n >= -0x80000000n then
-          `	movq	${emit_nativeint n}, {emit_reg i.res.(0)}\n`
-        else
-          `	movabsq	${emit_nativeint n}, {emit_reg i.res.(0)}\n`
-    | Lop(Iconst_float f) ->
-        begin match Int64.bits_of_float f with
-        | 0x0000_0000_0000_0000L ->       (* +0.0 *)
-          `	xorpd	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
-        | _ ->
+  | Lop(Iconst_int n | Iconst_blockheader n) ->
+      if n = 0n then begin
+        match i.res.(0).loc with
+        | Reg _ -> I.xor (res i 0) (res i 0)
+        | _     -> I.mov (int 0) (res i 0)
+      end
+      else
+        I.mov (nat n) (res i 0)
+  | Lop(Iconst_float f) ->
+      begin match f with
+      | 0x0000_0000_0000_0000L ->       (* +0.0 *)
+          I.xorpd (res i 0) (res i 0)
+      | _ ->
           let lbl = add_float_constant f in
-          `	movsd	{emit_label lbl}(%rip), {emit_reg i.res.(0)}\n`
-        end
-    | Lop(Iconst_symbol s) ->
-        `	{load_symbol_addr s}, {emit_reg i.res.(0)}\n`
-    | Lop(Icall_ind) ->
-        `	call	*{emit_reg i.arg.(0)}\n`;
-        record_frame i.live i.dbg
-    | Lop(Icall_imm(s)) ->
-        `	{emit_call s}\n`;
-        record_frame i.live i.dbg
-    | Lop(Itailcall_ind) ->
-        output_epilogue begin fun () ->
-        `	jmp	*{emit_reg i.arg.(0)}\n`
-        end
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then
-          `	jmp	{emit_label !tailrec_entry_point}\n`
-        else begin
-          output_epilogue begin fun () ->
-          `	{emit_jump s}\n`
-          end
-        end
-    | Lop(Iextcall(s, alloc)) ->
-        if alloc then begin
-          `	{load_symbol_addr s}, %rax\n`;
-          `	{emit_call "caml_c_call"}\n`;
-          record_frame i.live i.dbg;
-          `	{load_symbol_addr "caml_young_ptr"}, %r11\n`;
-          `	movq    (%r11), %r15\n`;
-        end else begin
-          `	{emit_call s}\n`
-        end
-    | Lop(Istackoffset n) ->
-        if n < 0
-        then `	addq	${emit_int(-n)}, %rsp\n`
-        else `	subq	${emit_int(n)}, %rsp\n`;
-        cfi_adjust_cfa_offset n;
-        stack_offset := !stack_offset + n
-    | Lop(Iload(chunk, addr)) ->
-        let dest = i.res.(0) in
-        begin match chunk with
-          | Word ->
-              `	movq	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Byte_unsigned ->
-              `	movzbq	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Byte_signed ->
-              `	movsbq	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Sixteen_unsigned ->
-              `	movzwq	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Sixteen_signed ->
-              `	movswq	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Thirtytwo_unsigned ->
-              `	movl	{emit_addressing addr i.arg 0}, {emit_reg32 dest}\n`
-          | Thirtytwo_signed ->
-              `	movslq	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Single ->
-            `	cvtss2sd {emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Double | Double_u ->
-            `	movsd	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-        end
-    | Lop(Istore(chunk, addr, _)) ->
-        begin match chunk with
-          | Word ->
-            `	movq	{emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Byte_unsigned | Byte_signed ->
-            `	movb	{emit_reg8 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Sixteen_unsigned | Sixteen_signed ->
-            `	movw	{emit_reg16 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Thirtytwo_signed | Thirtytwo_unsigned ->
-            `	movl	{emit_reg32 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Single ->
-            `	cvtsd2ss {emit_reg i.arg.(0)}, %xmm15\n`;
-            `	movss	%xmm15, {emit_addressing addr i.arg 1}\n`
-          | Double | Double_u ->
-            `	movsd	{emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-        end
-    | Lop(Ialloc n) ->
-        if !fastcode_flag then begin
-          let lbl_redo = new_label() in
-          `{emit_label lbl_redo}:	subq	${emit_int n}, %r15\n`;
-          if !Clflags.dlcode then begin
-            `	{load_symbol_addr "caml_young_limit"}, %rax\n`;
-            `	cmpq	(%rax), %r15\n`;
-          end else
-            `	cmpq	{emit_symbol "caml_young_limit"}(%rip), %r15\n`;
-          let lbl_call_gc = new_label() in
-          let lbl_frame = record_frame_label i.live Debuginfo.none in
-          `	jb	{emit_label lbl_call_gc}\n`;
-          `	leaq	8(%r15), {emit_reg i.res.(0)}\n`;
-          call_gc_sites :=
-            { gc_lbl = lbl_call_gc;
-              gc_return_lbl = lbl_redo;
-              gc_frame = lbl_frame } :: !call_gc_sites
-        end else begin
-          begin match n with
-            16  -> `	{emit_call "caml_alloc1"}\n`
-          | 24 -> `	{emit_call "caml_alloc2"}\n`
-          | 32 -> `	{emit_call "caml_alloc3"}\n`
-          | _  -> `	movq	${emit_int n}, %rax\n`;
-                  `	{emit_call "caml_allocN"}\n`
-          end;
-          `{record_frame i.live Debuginfo.none}	leaq	8(%r15), {emit_reg i.res.(0)}\n`
-        end
-    | Lop(Iintop(Icomp cmp)) ->
-        `	cmpq	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}	%al\n`;
-        `	movzbq	%al, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Icomp cmp, n)) ->
-        `	cmpq	${emit_int n}, {emit_reg i.arg.(0)}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}	%al\n`;
-        `	movzbq	%al, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop Icheckbound) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmpq	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop_imm(Icheckbound, n)) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmpq	${emit_int n}, {emit_reg i.arg.(0)}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop(Idiv | Imod)) ->
-        `	cqto\n`;
-        `	idivq	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop(Ilsl | Ilsr | Iasr as op)) ->
-        (* We have i.arg.(0) = i.res.(0) and i.arg.(1) = %rcx *)
-        `	{emit_string(instr_for_intop op)}	%cl, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop Imulh) ->
-        `	imulq	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop op) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, n)) when i.arg.(0).loc <> i.res.(0).loc ->
-        `	leaq	{emit_int n}({emit_reg i.arg.(0)}), {emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
-        `	incq	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
-        `	decq	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(op, n)) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	${emit_int n}, {emit_reg i.res.(0)}\n`
-    | Lop(Inegf) ->
-        `	xorpd	{emit_symbol "caml_negf_mask"}(%rip), {emit_reg i.res.(0)}\n`
-    | Lop(Iabsf) ->
-        `	andpd	{emit_symbol "caml_absf_mask"}(%rip), {emit_reg i.res.(0)}\n`
-    | Lop(Iaddf | Isubf | Imulf | Idivf as floatop) ->
-        `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
-    | Lop(Ifloatofint) ->
-        `	cvtsi2sdq	{emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
-    | Lop(Iintoffloat) ->
-        `	cvttsd2siq	{emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
-    | Lop(Ispecific(Ilea addr)) ->
-        `	leaq	{emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
-    | Lop(Ispecific(Istore_int(n, addr, _))) ->
-        `	movq	${emit_nativeint n}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
-        assert (not !pic_code && not !Clflags.dlcode);
-        `	movq	${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Ioffset_loc(n, addr))) ->
-        `	addq	${emit_int n}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Ifloatarithmem(op, addr))) ->
-        `	{emit_string(instr_for_floatarithmem op)}	{emit_addressing addr i.arg 1}, {emit_reg i.res.(0)}\n`
-    | Lop(Ispecific(Ibswap size)) ->
-       begin match size with
-       | 16 ->
-        `	xchg	%ah, %al\n`;
-        `	movzwq	{emit_reg16 i.res.(0)}, {emit_reg i.res.(0)}\n`
-       | 32 ->
-        `	bswap	{emit_reg32 i.res.(0)}\n`;
-        `	movslq	{emit_reg32 i.res.(0)}, {emit_reg i.res.(0)}\n`
-       | 64 ->
-        `	bswap	{emit_reg i.res.(0)}\n`
-       | _ -> assert false
-       end
-    | Lop(Ispecific Isqrtf) ->
-        `	sqrtsd	{emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
-    | Lop(Ispecific(Ifloatsqrtf addr)) ->
-        `	sqrtsd	{emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
-    | Lreloadretaddr ->
-        ()
-    | Lreturn ->
+          I.movsd (mem64_rip NONE (emit_label lbl)) (res i 0)
+      end
+  | Lop(Iconst_symbol s) ->
+      add_used_symbol s;
+      load_symbol_addr s (res i 0)
+  | Lop(Icall_ind) ->
+      I.call (arg i 0);
+      record_frame i.live i.dbg
+  | Lop(Icall_imm s) ->
+      add_used_symbol s;
+      emit_call s;
+      record_frame i.live i.dbg
+  | Lop(Itailcall_ind) ->
+      output_epilogue begin fun () ->
+        I.jmp (arg i 0)
+      end
+  | Lop(Itailcall_imm s) ->
+      if s = !function_name then
+        I.jmp (label !tailrec_entry_point)
+      else begin
         output_epilogue begin fun () ->
-        `	ret\n`
-        end
-    | Llabel lbl ->
-        `{emit_Llabel fallthrough lbl}:\n`
-    | Lbranch lbl ->
-        `	jmp	{emit_label lbl}\n`
-    | Lcondbranch(tst, lbl) ->
-        begin match tst with
-          Itruetest ->
-            output_test_zero i.arg.(0);
-            `	jne	{emit_label lbl}\n`
-        | Ifalsetest ->
-            output_test_zero i.arg.(0);
-            `	je	{emit_label lbl}\n`
-        | Iinttest cmp ->
-            `	cmpq	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm((Isigned Ceq | Isigned Cne |
-                        Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
-            output_test_zero i.arg.(0);
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm(cmp, n) ->
-            `	cmpq	${emit_int n}, {emit_reg i.arg.(0)}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Ifloattest(cmp, neg) ->
-            emit_float_test cmp neg i.arg lbl
-        | Ioddtest ->
-            `	testb	$1, {emit_reg8 i.arg.(0)}\n`;
-            `	jne	{emit_label lbl}\n`
-        | Ieventest ->
-            `	testb	$1, {emit_reg8 i.arg.(0)}\n`;
-            `	je	{emit_label lbl}\n`
+          add_used_symbol s;
+          emit_jump s
         end
-    | Lcondbranch3(lbl0, lbl1, lbl2) ->
-            `	cmpq	$1, {emit_reg i.arg.(0)}\n`;
-            begin match lbl0 with
-              None -> ()
-            | Some lbl -> `	jb	{emit_label lbl}\n`
-            end;
-            begin match lbl1 with
-              None -> ()
-            | Some lbl -> `	je	{emit_label lbl}\n`
-            end;
-            begin match lbl2 with
-              None -> ()
-            | Some lbl -> `	jg	{emit_label lbl}\n`
-            end
-    | Lswitch jumptbl ->
-        let lbl = new_label() in
-        (* rax and rdx are clobbered by the Lswitch,
-           meaning that no variable that is live across the Lswitch
-           is assigned to rax or rdx.  However, the argument to Lswitch
-           can still be assigned to one of these two registers, so
-           we must be careful not to clobber it before use. *)
-        let (tmp1, tmp2) =
-          if i.arg.(0).loc = Reg 0 (* rax *)
-          then (phys_reg 4 (*rdx*), phys_reg 0 (*rax*))
-          else (phys_reg 0 (*rax*), phys_reg 4 (*rdx*)) in
-        `	leaq	{emit_label lbl}(%rip), {emit_reg tmp1}\n`;
-        `	movslq	({emit_reg tmp1}, {emit_reg i.arg.(0)}, 4), {emit_reg tmp2}\n`;
-        `	addq	{emit_reg tmp2}, {emit_reg tmp1}\n`;
-        `	jmp	*{emit_reg tmp1}\n`;
-        if macosx then
-          `	.const\n`
-        else if mingw64 || cygwin then
-          `	.section .rdata,\"dr\"\n`
-        else
-          `	.section .rodata\n`;
-        emit_align 4;
-        `{emit_label lbl}:`;
-        for i = 0 to Array.length jumptbl - 1 do
-          `	.long	{emit_label jumptbl.(i)} - {emit_label lbl}\n`
-        done;
-        `	.text\n`
-    | Lsetuptrap lbl ->
-        `	call	{emit_label lbl}\n`
-    | Lpushtrap ->
-        cfi_adjust_cfa_offset 8;
-        `	pushq	%r14\n`;
-        cfi_adjust_cfa_offset 8;
-        `	movq	%rsp, %r14\n`;
-        stack_offset := !stack_offset + 16
-    | Lpoptrap ->
-        `	popq	%r14\n`;
-        cfi_adjust_cfa_offset (-8);
-        `	addq	$8, %rsp\n`;
-        cfi_adjust_cfa_offset (-8);
-        stack_offset := !stack_offset - 16
-    | Lraise k ->
-        begin match !Clflags.debug, k with
-        | true, Lambda.Raise_regular ->
-          `	{emit_call "caml_raise_exn"}\n`;
+      end
+  | Lop(Iextcall(s, alloc)) ->
+      add_used_symbol s;
+      if alloc then begin
+        load_symbol_addr s rax;
+        emit_call "caml_c_call";
+        record_frame i.live i.dbg;
+        if system <> S_win64 then begin
+          (* TODO: investigate why such a diff.
+             This comes from:
+            http://caml.inria.fr/cgi-bin/viewvc.cgi?view=revision&revision=12664
+
+             If we do the same for Win64, we probably need to change
+             amd64nt.asm accordingly.
+          *)
+          load_symbol_addr "caml_young_ptr" r11;
+          I.mov (mem64 QWORD 0 R11) r15
+        end;
+      end else
+        emit_call s
+  | Lop(Istackoffset n) ->
+      if n < 0
+      then I.add (int (-n)) rsp
+      else if n > 0
+      then I.sub (int n) rsp;
+      if n <> 0
+      then cfi_adjust_cfa_offset n;
+      stack_offset := !stack_offset + n
+  | Lop(Iload(chunk, addr)) ->
+      let dest = res i 0 in
+      begin match chunk with
+      | Word_int | Word_val ->
+          I.mov (addressing addr QWORD i 0) dest
+      | Byte_unsigned ->
+          I.movzx (addressing addr BYTE i 0) dest
+      | Byte_signed ->
+          I.movsx (addressing addr BYTE i 0) dest
+      | Sixteen_unsigned ->
+          I.movzx (addressing addr WORD i 0) dest
+      | Sixteen_signed ->
+          I.movsx (addressing addr WORD i 0) dest;
+      | Thirtytwo_unsigned ->
+          I.mov (addressing addr DWORD i 0) (res32 i 0)
+      | Thirtytwo_signed ->
+          I.movsxd (addressing addr DWORD i 0) dest
+      | Single ->
+          I.cvtss2sd (addressing addr REAL4 i 0) dest
+      | Double | Double_u ->
+          I.movsd (addressing addr REAL8 i 0) dest
+      end
+  | Lop(Istore(chunk, addr, _)) ->
+      begin match chunk with
+      | Word_int | Word_val ->
+          I.mov (arg i 0) (addressing addr QWORD i 1)
+      | Byte_unsigned | Byte_signed ->
+          I.mov (arg8 i 0) (addressing addr BYTE i 1)
+      | Sixteen_unsigned | Sixteen_signed ->
+          I.mov (arg16 i 0) (addressing addr WORD i 1)
+      | Thirtytwo_signed | Thirtytwo_unsigned ->
+          I.mov (arg32 i 0) (addressing addr DWORD i 1)
+      | Single ->
+          I.cvtsd2ss (arg i 0) xmm15;
+          I.movss xmm15 (addressing addr REAL4 i 1)
+      | Double | Double_u ->
+          I.movsd (arg i 0) (addressing addr REAL8 i 1)
+      end
+  | Lop(Ialloc n) ->
+      if !fastcode_flag then begin
+        let lbl_redo = new_label() in
+        def_label lbl_redo;
+        I.sub (int n) r15;
+        if !Clflags.dlcode then begin
+          load_symbol_addr "caml_young_limit" rax;
+          I.cmp (mem64 QWORD 0 RAX) r15;
+        end else
+          I.cmp (mem64_rip QWORD (emit_symbol "caml_young_limit")) r15;
+        let lbl_call_gc = new_label() in
+        let lbl_frame = record_frame_label i.live Debuginfo.none in
+        I.jb (label lbl_call_gc);
+        I.lea (mem64 NONE 8 R15) (res i 0);
+        call_gc_sites :=
+          { gc_lbl = lbl_call_gc;
+            gc_return_lbl = lbl_redo;
+            gc_frame = lbl_frame } :: !call_gc_sites
+      end else begin
+        begin match n with
+        | 16 -> emit_call "caml_alloc1"
+        | 24 -> emit_call "caml_alloc2"
+        | 32 -> emit_call "caml_alloc3"
+        | _  ->
+            I.mov (int n) rax;
+            emit_call "caml_allocN"
+        end;
+        record_frame i.live Debuginfo.none;
+        I.lea (mem64 NONE 8 R15) (res i 0)
+      end
+  | Lop(Iintop(Icomp cmp)) ->
+      I.cmp (arg i 1) (arg i 0);
+      I.set (cond cmp) al;
+      I.movzx al (res i 0)
+  | Lop(Iintop_imm(Icomp cmp, n)) ->
+      I.cmp (int n) (arg i 0);
+      I.set (cond cmp) al;
+      I.movzx al (res i 0)
+  | Lop(Iintop Icheckbound) ->
+      let lbl = bound_error_label i.dbg in
+      I.cmp (arg i 1) (arg i 0);
+      I.jbe (label lbl)
+  | Lop(Iintop_imm(Icheckbound, n)) ->
+      let lbl = bound_error_label i.dbg in
+      I.cmp (int n) (arg i 0);
+      I.jbe (label lbl)
+  | Lop(Iintop(Idiv | Imod)) ->
+      I.cqo ();
+      I.idiv (arg i 1)
+  | Lop(Iintop(Ilsl | Ilsr | Iasr as op)) ->
+      (* We have i.arg.(0) = i.res.(0) and i.arg.(1) = %rcx *)
+      instr_for_intop op cl (res i 0)
+  | Lop(Iintop Imulh) ->
+      I.imul (arg i 1) None
+  | Lop(Iintop op) ->
+      (* We have i.arg.(0) = i.res.(0) *)
+      instr_for_intop op (arg i 1) (res i 0)
+  | Lop(Iintop_imm(Iadd, n)) when i.arg.(0).loc <> i.res.(0).loc ->
+      I.lea (mem64 NONE n (arg64 i 0)) (res i 0)
+  | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
+      I.inc (res i 0)
+  | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
+      I.dec (res i 0)
+  | Lop(Iintop_imm(op, n)) ->
+      (* We have i.arg.(0) = i.res.(0) *)
+      instr_for_intop op (int n) (res i 0)
+  | Lop(Inegf) ->
+      I.xorpd (mem64_rip OWORD (emit_symbol "caml_negf_mask")) (res i 0)
+  | Lop(Iabsf) ->
+      I.andpd (mem64_rip OWORD (emit_symbol "caml_absf_mask")) (res i 0)
+  | Lop(Iaddf | Isubf | Imulf | Idivf as floatop) ->
+      instr_for_floatop floatop (arg i 1) (res i 0)
+  | Lop(Ifloatofint) ->
+      I.cvtsi2sd  (arg i 0)  (res i 0)
+  | Lop(Iintoffloat) ->
+      I.cvttsd2si (arg i 0) (res i 0)
+  | Lop(Ispecific(Ilea addr)) ->
+      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))) ->
+      instr_for_floatarithmem op (addressing addr REAL8 i 1) (res i 0)
+  | Lop(Ispecific(Ibswap 16)) ->
+      I.xchg ah al;
+      I.movzx (res16 i 0) (res i 0)
+  | Lop(Ispecific(Ibswap 32)) ->
+      I.bswap (res32 i 0);
+      I.movsxd (res32 i 0) (res i 0)
+  | Lop(Ispecific(Ibswap 64)) ->
+      I.bswap (res i 0)
+  | Lop(Ispecific(Ibswap _)) ->
+      assert false
+  | Lop(Ispecific Isqrtf) ->
+      I.sqrtsd (arg i 0) (res i 0)
+  | Lop(Ispecific(Ifloatsqrtf addr)) ->
+      I.sqrtsd (addressing addr REAL8 i 0) (res i 0)
+  | Lreloadretaddr ->
+      ()
+  | Lreturn ->
+      output_epilogue begin fun () ->
+        I.ret ()
+      end
+  | Llabel lbl ->
+      emit_Llabel fallthrough lbl
+  | Lbranch lbl ->
+      I.jmp (label lbl)
+  | Lcondbranch(tst, lbl) ->
+      let lbl = label lbl in
+      begin match tst with
+      | Itruetest ->
+          output_test_zero i.arg.(0);
+          I.jne lbl
+      | Ifalsetest ->
+          output_test_zero i.arg.(0);
+          I.je lbl
+      | Iinttest cmp ->
+          I.cmp (arg i 1) (arg i 0);
+          I.j (cond cmp) lbl
+      | Iinttest_imm((Isigned Ceq | Isigned Cne |
+                      Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
+          output_test_zero i.arg.(0);
+          I.j (cond cmp) lbl
+      | Iinttest_imm(cmp, n) ->
+          I.cmp (int n) (arg i 0);
+          I.j (cond cmp) lbl
+      | Ifloattest(cmp, neg) ->
+          emit_float_test cmp neg i lbl
+      | Ioddtest ->
+          I.test (int 1) (arg8 i 0);
+          I.jne lbl
+      | Ieventest ->
+          I.test (int 1) (arg8 i 0);
+          I.je lbl
+      end
+  | Lcondbranch3(lbl0, lbl1, lbl2) ->
+      I.cmp (int 1) (arg i 0);
+      begin match lbl0 with
+      | None -> ()
+      | Some lbl -> I.jb (label lbl)
+      end;
+      begin match lbl1 with
+      | None -> ()
+      | Some lbl -> I.je (label lbl)
+      end;
+      begin match lbl2 with
+      | None -> ()
+      | Some lbl -> I.jg (label lbl)
+      end
+  | Lswitch jumptbl ->
+      let lbl = emit_label (new_label()) in
+      (* rax and rdx are clobbered by the Lswitch,
+         meaning that no variable that is live across the Lswitch
+         is assigned to rax or rdx.  However, the argument to Lswitch
+         can still be assigned to one of these two registers, so
+         we must be careful not to clobber it before use. *)
+      let (tmp1, tmp2) =
+        if i.arg.(0).loc = Reg 0 (* rax *)
+        then (phys_reg 4 (*rdx*), phys_reg 0 (*rax*))
+        else (phys_reg 0 (*rax*), phys_reg 4 (*rdx*)) in
+
+      I.lea (mem64_rip NONE lbl) (reg tmp1);
+      I.movsxd (mem64 DWORD 0 (arg64 i 0) ~scale:4 ~base:(reg64 tmp1))
+               (reg tmp2);
+      I.add (reg tmp2) (reg tmp1);
+      I.jmp (reg tmp1);
+
+      begin match system with
+      | S_mingw64 | S_cygwin -> D.section [".rdata"] (Some "dr") []
+      | S_macosx | S_win64 -> () (* with LLVM/OS X and MASM, use the text segment *)
+      | _ -> D.section [".rodata"] None []
+      end;
+      D.align 4;
+      _label lbl;
+      for i = 0 to Array.length jumptbl - 1 do
+        D.long (ConstSub (ConstLabel(emit_label jumptbl.(i)),
+                         ConstLabel lbl))
+      done;
+      D.text ()
+  | Lsetuptrap lbl ->
+      I.call (label lbl)
+  | Lpushtrap ->
+      cfi_adjust_cfa_offset 8;
+      I.push r14;
+      cfi_adjust_cfa_offset 8;
+      I.mov rsp r14;
+      stack_offset := !stack_offset + 16
+  | Lpoptrap ->
+      I.pop r14;
+      cfi_adjust_cfa_offset (-8);
+      I.add (int 8) rsp;
+      cfi_adjust_cfa_offset (-8);
+      stack_offset := !stack_offset - 16
+  | Lraise k ->
+      begin match !Clflags.debug, k with
+      | true, Lambda.Raise_regular ->
+          emit_call "caml_raise_exn";
           record_frame Reg.Set.empty i.dbg
-        | true, Lambda.Raise_reraise ->
-          `	{emit_call "caml_reraise_exn"}\n`;
+      | true, Lambda.Raise_reraise ->
+          emit_call "caml_reraise_exn";
           record_frame Reg.Set.empty i.dbg
-        | false, _
-        | true, Lambda.Raise_notrace ->
-          `	movq	%r14, %rsp\n`;
-          `	popq	%r14\n`;
-          `	ret\n`
-        end
+      | false, _
+      | true, Lambda.Raise_notrace ->
+          I.mov r14 rsp;
+          I.pop r14;
+          I.ret ()
+      end
 
 let rec emit_all fallthrough i =
   match i.desc with
-  |  Lend -> ()
+  | Lend -> ()
   | _ ->
       emit_instr fallthrough i;
       emit_all (Linearize.has_fallthrough i.desc) i.next
@@ -693,20 +790,17 @@ let rec emit_all fallthrough i =
 (* Emission of the profiling prelude *)
 
 let emit_profile () =
-  match Config.system with
-  | "linux" | "gnu" ->
-      (* mcount preserves rax, rcx, rdx, rsi, rdi, r8, r9 explicitly
-         and rbx, rbp, r12-r15 like all C functions.  This includes
-         all the registers used for argument passing, so we don't
-         need to preserve other regs.  We do need to initialize rbp
-         like mcount expects it, though. *)
-      `	pushq	%r10\n`;
-      if not fp then
-        `	movq	%rsp, %rbp\n`;
-      `	{emit_call "mcount"}\n`;
-      `	popq	%r10\n`
-  | _ ->
-      () (*unsupported yet*)
+  if system = S_gnu || system = S_linux then begin
+    (* mcount preserves rax, rcx, rdx, rsi, rdi, r8, r9 explicitly
+       and rbx, rbp, r12-r15 like all C functions.  This includes
+       all the registers used for argument passing, so we don't
+       need to preserve other regs.  We do need to initialize rbp
+       like mcount expects it, though. *)
+    I.push r10;
+    if not fp then I.mov rsp rbp;
+    emit_call "mcount";
+    I.pop r10
+  end
 
 (* Emission of a function declaration *)
 
@@ -718,147 +812,200 @@ let fundecl fundecl =
   call_gc_sites := [];
   bound_error_sites := [];
   bound_error_call := 0;
-  `	.text\n`;
-  emit_align 16;
-  if macosx
+  D.text ();
+  D.align 16;
+  add_def_symbol fundecl.fun_name;
+  if system = S_macosx
   && not !Clflags.output_c_object
   && is_generic_function fundecl.fun_name
   then (* PR#4690 *)
-    `	.private_extern	{emit_symbol fundecl.fun_name}\n`
+    D.private_extern (emit_symbol fundecl.fun_name)
   else
-    `	.globl	{emit_symbol fundecl.fun_name}\n`;
-  `{emit_symbol fundecl.fun_name}:\n`;
+    D.global (emit_symbol fundecl.fun_name);
+  D.label (emit_symbol fundecl.fun_name);
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc ();
   if fp then begin
-       `	pushq	%rbp\n`;
-       cfi_adjust_cfa_offset 8;
-       `	movq	%rsp, %rbp\n`;
+    I.push rbp;
+    cfi_adjust_cfa_offset 8;
+    I.mov rsp rbp;
   end;
   if !Clflags.gprofile then emit_profile();
   if frame_required() then begin
     let n = frame_size() - 8 - (if fp then 8 else 0) in
-    `	subq	${emit_int n}, %rsp\n`;
-    cfi_adjust_cfa_offset n;
+    if n <> 0
+    then begin
+      I.sub (int n) rsp;
+      cfi_adjust_cfa_offset n;
+    end;
   end;
-  `{emit_label !tailrec_entry_point}:\n`;
+  def_label !tailrec_entry_point;
   emit_all true fundecl.fun_body;
   List.iter emit_call_gc !call_gc_sites;
   emit_call_bound_errors ();
+  if frame_required() then begin
+    let n = frame_size() - 8 - (if fp then 8 else 0) in
+    if n <> 0
+    then begin
+      cfi_adjust_cfa_offset (-n);
+    end;
+  end;
   cfi_endproc ();
-  begin match Config.system with
-    "linux" | "gnu" ->
-      `	.type	{emit_symbol fundecl.fun_name},@function\n`;
-      `	.size	{emit_symbol fundecl.fun_name},.-{emit_symbol fundecl.fun_name}\n`
-    | _ -> ()
+  begin match system with
+  | S_gnu | S_linux ->
+      D.type_ (emit_symbol fundecl.fun_name) "@function";
+      D.size (emit_symbol fundecl.fun_name)
+        (ConstSub (
+            ConstThis,
+            ConstLabel (emit_symbol fundecl.fun_name)))
+  | _ -> ()
   end
 
 (* Emission of data *)
 
 let emit_item = function
-    Cglobal_symbol s ->
-      `	.globl	{emit_symbol s}\n`;
-  | Cdefine_symbol s ->
-      `{emit_symbol s}:\n`
-  | Cdefine_label lbl ->
-      `{emit_data_label lbl}:\n`
-  | Cint8 n ->
-      `	.byte	{emit_int n}\n`
-  | Cint16 n ->
-      `	.word	{emit_int n}\n`
-  | Cint32 n ->
-      `	.long	{emit_nativeint n}\n`
-  | Cint n ->
-      `	.quad	{emit_nativeint n}\n`
-  | Csingle f ->
-      emit_float32_directive ".long" (Int32.bits_of_float f)
-  | Cdouble f ->
-      emit_float64_directive ".quad" (Int64.bits_of_float f)
-  | Csymbol_address s ->
-      `	.quad	{emit_symbol s}\n`
-  | Clabel_address lbl ->
-      `	.quad	{emit_data_label lbl}\n`
-  | Cstring s ->
-      emit_string_directive "	.ascii	" s
-  | Cskip n ->
-      if n > 0 then `	.space	{emit_int n}\n`
-  | Calign n ->
-      emit_align n
+  | Cglobal_symbol s -> D.global (emit_symbol s)
+  | Cdefine_symbol s -> add_def_symbol s; _label (emit_symbol s)
+  | Cdefine_label lbl -> _label (emit_data_label lbl)
+  | Cint8 n -> D.byte (const n)
+  | Cint16 n -> D.word (const n)
+  | Cint32 n -> D.long (const_nat n)
+  | Cint n -> D.qword (const_nat n)
+  | Csingle f -> D.long  (Const (Int64.of_int32 (Int32.bits_of_float f)))
+  | Cdouble f -> D.qword (Const (Int64.bits_of_float f))
+  | Csymbol_address s -> add_used_symbol s; D.qword (ConstLabel (emit_symbol s))
+  | Clabel_address lbl -> D.qword (ConstLabel (emit_data_label lbl))
+  | Cstring s -> D.bytes s
+  | Cskip n -> if n > 0 then D.space n
+  | Calign n -> D.align n
 
 let data l =
-  `	.data\n`;
+  D.data ();
   List.iter emit_item l
 
 (* Beginning / end of an assembly file *)
 
 let begin_assembly() =
+  X86_proc.reset_asm_code ();
   reset_debug_info();                   (* PR#5603 *)
+  reset_imp_table();
   float_constants := [];
+  if system = S_win64 then begin
+    D.extrn "caml_young_ptr" QWORD;
+    D.extrn "caml_young_limit" QWORD;
+    D.extrn "caml_exception_pointer" QWORD;
+    D.extrn "caml_call_gc" NEAR;
+    D.extrn "caml_c_call" NEAR;
+    D.extrn "caml_allocN" NEAR;
+    D.extrn "caml_alloc1" NEAR;
+    D.extrn "caml_alloc2" NEAR;
+    D.extrn "caml_alloc3" NEAR;
+    D.extrn "caml_ml_array_bound_error" NEAR;
+    D.extrn "caml_raise_exn" NEAR;
+    D.extrn "caml_reraise_exn" NEAR;
+  end;
+
+
   if !Clflags.dlcode then begin
     (* from amd64.S; could emit these constants on demand *)
-    if macosx then
-      `	.literal16\n`
-    else if mingw64 || cygwin then
-      `	.section .rdata,\"dr\"\n`
-    else
-      `	.section .rodata.cst8,\"a\",@progbits\n`;
-    emit_align 16;
-    `{emit_symbol "caml_negf_mask"}:	.quad   0x8000000000000000, 0\n`;
-    emit_align 16;
-    `{emit_symbol "caml_absf_mask"}:	.quad   0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF\n`
+    begin match system with
+    | S_macosx -> D.section ["__TEXT";"__literal16"] None ["16byte_literals"]
+    | S_mingw64 | S_cygwin -> D.section [".rdata"] (Some "dr") []
+    | S_win64 -> D.data ()
+    | _ -> D.section [".rodata.cst8"] (Some "a") ["@progbits"]
+    end;
+    D.align 16;
+    _label (emit_symbol "caml_negf_mask");
+    D.qword (Const 0x8000000000000000L);
+    D.qword (Const 0L);
+    D.align 16;
+    _label (emit_symbol "caml_absf_mask");
+    D.qword (Const 0x7FFFFFFFFFFFFFFFL);
+    D.qword (Const 0xFFFFFFFFFFFFFFFFL);
   end;
-  let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
-  `	.data\n`;
-  `	.globl	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin}:\n`;
-  let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
-  `	.text\n`;
-  `	.globl	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin}:\n`;
-  if macosx then `	nop\n` (* PR#4690 *)
+
+  D.data ();
+  emit_global_label "data_begin";
+
+  D.text ();
+  emit_global_label "code_begin";
+  if system = S_macosx then I.nop (); (* PR#4690 *)
+  ()
 
 let end_assembly() =
   if !float_constants <> [] then begin
-    if macosx then
-      `	.literal8\n`
-    else if mingw64 || cygwin then
-      `	.section .rdata,\"dr\"\n`
-    else
-      `	.section .rodata.cst8,\"a\",@progbits\n`;
-    List.iter emit_float_constant !float_constants
+    begin match system with
+    | S_macosx -> D.section ["__TEXT";"__literal8"] None ["8byte_literals"]
+    | S_mingw64 | S_cygwin -> D.section [".rdata"] (Some "dr") []
+    | S_win64 -> D.data ()
+    | _ -> D.section [".rodata.cst8"] (Some "a") ["@progbits"]
+    end;
+    List.iter (fun (cst,lbl) -> emit_float_constant cst lbl) !float_constants
   end;
-  let lbl_end = Compilenv.make_symbol (Some "code_end") in
-  `	.text\n`;
-  if macosx then `	nop\n`; (* suppress "ld warning: atom sorting error" *)
-  `	.globl	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end}:\n`;
-  `	.data\n`;
-  let lbl_end = Compilenv.make_symbol (Some "data_end") in
-  `	.globl	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end}:\n`;
-  `	.long	0\n`;
-  let lbl = Compilenv.make_symbol (Some "frametable") in
-  `	.globl	{emit_symbol lbl}\n`;
-  `{emit_symbol lbl}:\n`;
+
+  D.text ();
+  if system = S_macosx then I.nop ();
+  (* suppress "ld warning: atom sorting error" *)
+
+  emit_global_label "code_end";
+
+  emit_imp_table();
+
+  D.data ();
+  emit_global_label "data_end";
+  D.long (const 0);
+
+  emit_global_label "frametable";
+
+  let setcnt = ref 0 in
   emit_frames
-    { efa_label = (fun l -> `	.quad	{emit_label l}\n`);
-      efa_16 = (fun n -> `	.word	{emit_int n}\n`);
-      efa_32 = (fun n -> `	.long	{emit_int32 n}\n`);
-      efa_word = (fun n -> `	.quad	{emit_int n}\n`);
-      efa_align = emit_align;
+    { efa_label = (fun l -> D.qword (ConstLabel (emit_label l)));
+      efa_16 = (fun n -> D.word (const n));
+      efa_32 = (fun n -> D.long (const_32 n));
+      efa_word = (fun n -> D.qword (const n));
+      efa_align = D.align;
       efa_label_rel =
-        if macosx then begin
-          let setcnt = ref 0 in
-          fun lbl ofs ->
-            incr setcnt;
-            `	.set	L$set${emit_int !setcnt}, ({emit_label lbl} - .) + {emit_int32 ofs}\n`;
-            `	.long L$set${emit_int !setcnt}\n`
-        end else begin
-	  fun lbl ofs ->
-             `	.long	({emit_label lbl} - .) + {emit_int32 ofs}\n`
-	end;
-      efa_def_label = (fun l -> `{emit_label l}:\n`);
-      efa_string = (fun s -> emit_string_directive "	.asciz	" s) };
-  if Config.system = "linux" then
+        (fun lbl ofs ->
+           let c =
+             ConstAdd (
+               ConstSub(ConstLabel(emit_label lbl), ConstThis),
+               const_32 ofs
+             ) in
+           if system = S_macosx then begin
+             incr setcnt;
+             let s = Printf.sprintf "L$set$%d" !setcnt in
+             D.setvar (s, c);
+             D.long (ConstLabel s)
+           end else
+             D.long c
+        );
+      efa_def_label = (fun l -> _label (emit_label l));
+      efa_string = (fun s -> D.bytes (s ^ "\000"))
+    };
+
+  if system = S_linux then
     (* Mark stack as non-executable, PR#4564 *)
-    `	.section .note.GNU-stack,\"\",%progbits\n`
+    D.section [".note.GNU-stack"] (Some "") [ "%progbits" ];
+
+  if system = S_win64 then begin
+    D.comment "External functions";
+    StringSet.iter
+      (fun s ->
+         if not (StringSet.mem s !symbols_defined) then
+           D.extrn (emit_symbol s) NEAR)
+      !symbols_used;
+    symbols_used := StringSet.empty;
+    symbols_defined := StringSet.empty;
+  end;
+
+  let asm =
+    if !Emitaux.create_asm_file then
+      Some
+        (
+         (if X86_proc.masm then X86_masm.generate_asm
+          else X86_gas.generate_asm) !Emitaux.output_channel
+        )
+    else
+      None
+  in
+  X86_proc.generate_code asm
diff --git a/asmcomp/amd64/emit_nt.mlp b/asmcomp/amd64/emit_nt.mlp
deleted file mode 100644
index f14e69cd..00000000
--- a/asmcomp/amd64/emit_nt.mlp
+++ /dev/null
@@ -1,795 +0,0 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-(* Emission of x86-64 (AMD 64) assembly code, MASM syntax *)
-
-module StringSet =
-  Set.Make(struct type t = string let compare (x:t) y = compare x y end)
-
-open Cmm
-open Arch
-open Proc
-open Reg
-open Mach
-open Linearize
-open Emitaux
-
-let rdx = phys_reg 4
-
-(* Tradeoff between code size and code speed *)
-
-let fastcode_flag = ref true
-
-let stack_offset = ref 0
-
-(* Layout of the stack frame *)
-
-let frame_required () =
-  !contains_calls || num_stack_slots.(0) > 0 || num_stack_slots.(1) > 0
-
-let frame_size () =                     (* includes return address *)
-  if frame_required() then begin
-    let sz =
-      (!stack_offset + 8 * (num_stack_slots.(0) + num_stack_slots.(1)) + 8)
-    in Misc.align sz 16
-  end else
-    !stack_offset + 8
-
-let slot_offset loc cl =
-  match loc with
-    Incoming n -> frame_size() + n
-  | Local n ->
-      if cl = 0
-      then !stack_offset + n * 8
-      else !stack_offset + (num_stack_slots.(0) + n) * 8
-  | Outgoing n -> n
-
-(* Output a 32 or 64 bit integer in hex *)
-
-let emit_int32 n = emit_printf "0%lxh" n
-let emit_int64 n = emit_printf "0%Lxh" n
-
-(* Symbols *)
-
-let emit_symbol s =
-  Emitaux.emit_symbol '$' s
-
-(* Record symbols used and defined - at the end generate extern for those
-   used but not defined *)
-
-let symbols_defined = ref StringSet.empty
-let symbols_used = ref StringSet.empty
-
-let add_def_symbol s =
-  symbols_defined := StringSet.add s !symbols_defined
-
-let add_used_symbol s =
-  symbols_used := StringSet.add s !symbols_used
-
-(* Output a label *)
-
-let emit_label lbl =
-  emit_string "L"; emit_int lbl
-
-let emit_data_label lbl =
-  emit_string "Ld"; emit_int lbl
-
-(* Output a .align directive. *)
-
-let emit_align n =
-  `	ALIGN	{emit_int n}\n`
-
-let emit_Llabel fallthrough lbl =
-  if not fallthrough && !fastcode_flag then emit_align 4;
-  emit_label lbl
-
-(* Output a pseudo-register *)
-
-let emit_reg = function
-    { loc = Reg r } ->
-      emit_string (register_name r)
-  | { loc = Stack s; typ = Float } as r ->
-      let ofs = slot_offset s (register_class r) in
-      `REAL8 PTR {emit_int ofs}[rsp]`
-  | { loc = Stack s; typ = _ } as r ->
-      let ofs = slot_offset s (register_class r) in
-      `QWORD PTR {emit_int ofs}[rsp]`
-  | { loc = Unknown } ->
-      assert false
-
-(* Output a reference to the lower 8, 16 or 32 bits of a register *)
-
-let reg_low_8_name =
-  [| "al"; "bl"; "dil"; "sil"; "dl"; "cl"; "r8b"; "r9b";
-     "r12b"; "r13b"; "r10b"; "r11b"; "bpl" |]
-let reg_low_16_name =
-  [| "ax"; "bx"; "di"; "si"; "dx"; "cx"; "r8w"; "r9w";
-     "r12w"; "r13w"; "r10w"; "r11w"; "bp" |]
-let reg_low_32_name =
-  [| "eax"; "ebx"; "edi"; "esi"; "edx"; "ecx"; "r8d"; "r9d";
-     "r12d"; "r13d"; "r10d"; "r11d"; "ebp" |]
-
-let emit_subreg tbl pref r =
-  match r.loc with
-    Reg r when r < 13 ->
-      emit_string tbl.(r)
-  | Stack s ->
-      let ofs = slot_offset s (register_class r) in
-      `{emit_string pref} PTR {emit_int ofs}[rsp]`
-  | _ ->
-      assert false
-
-let emit_reg8 r = emit_subreg reg_low_8_name "BYTE" r
-let emit_reg16 r = emit_subreg reg_low_16_name "WORD" r
-let emit_reg32 r = emit_subreg reg_low_32_name "DWORD" r
-
-(* Output an addressing mode *)
-
-let emit_signed_int d =
-  if d > 0 then emit_char '+';
-  if d <> 0 then emit_int d
-
-let emit_addressing addr r n =
-  match addr with
-    Ibased(s, d) ->
-      add_used_symbol s;
-      `{emit_symbol s}{emit_signed_int d}`
-  | Iindexed d ->
-      `[{emit_reg r.(n)}{emit_signed_int d}]`
-  | Iindexed2 d ->
-      `[{emit_reg r.(n)}+{emit_reg r.(n+1)}{emit_signed_int d}]`
-  | Iscaled(2, d) ->
-      `[{emit_reg r.(n)}+{emit_reg r.(n)}{emit_signed_int d}]`
-  | Iscaled(scale, d) ->
-      `[{emit_reg r.(n)}*{emit_int scale}{emit_signed_int d}]`
-  | Iindexed2scaled(scale, d) ->
-      `[{emit_reg r.(n)}+{emit_reg r.(n+1)}*{emit_int scale}{emit_signed_int d}]`
-
-(* Record live pointers at call points *)
-
-let record_frame_label live dbg =
-  let lbl = new_label() in
-  let live_offset = ref [] in
-  Reg.Set.iter
-    (function
-        {typ = Addr; loc = Reg r} ->
-          live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
-          live_offset := slot_offset s (register_class reg) :: !live_offset
-      | _ -> ())
-    live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_debuginfo = dbg } :: !frame_descriptors;
-  lbl
-
-let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:\n`
-
-(* Record calls to the GC -- we've moved them out of the way *)
-
-type gc_call =
-  { gc_lbl: label;                      (* Entry label *)
-    gc_return_lbl: label;               (* Where to branch after GC *)
-    gc_frame: label }                   (* Label of frame descriptor *)
-
-let call_gc_sites = ref ([] : gc_call list)
-
-let emit_call_gc gc =
-  `{emit_label gc.gc_lbl}:	call	{emit_symbol "caml_call_gc"}\n`;
-  `{emit_label gc.gc_frame}:	jmp	{emit_label gc.gc_return_lbl}\n`
-
-(* Record calls to caml_ml_array_bound_error.
-   In -g mode, we maintain one call to caml_ml_array_bound_error
-   per bound check site.  Without -g, we can share a single call. *)
-
-type bound_error_call =
-  { bd_lbl: label;                      (* Entry label *)
-    bd_frame: label }                   (* Label of frame descriptor *)
-
-let bound_error_sites = ref ([] : bound_error_call list)
-let bound_error_call = ref 0
-
-let bound_error_label dbg =
-  if !Clflags.debug then begin
-    let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame_label Reg.Set.empty dbg in
-    bound_error_sites :=
-     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
-   lbl_bound_error
- end else begin
-   if !bound_error_call = 0 then bound_error_call := new_label();
-   !bound_error_call
- end
-
-let emit_call_bound_error bd =
-  `{emit_label bd.bd_lbl}:	call	caml_ml_array_bound_error\n`;
-  `{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}:	call	caml_ml_array_bound_error\n`
-
-(* Names for instructions *)
-
-let instr_for_intop = function
-    Iadd -> "add"
-  | Isub -> "sub"
-  | Imul -> "imul"
-  | Iand -> "and"
-  | Ior -> "or"
-  | Ixor -> "xor"
-  | Ilsl -> "sal"
-  | Ilsr -> "shr"
-  | Iasr -> "sar"
-  | _ -> assert false
-
-let instr_for_floatop = function
-    Iaddf -> "addsd"
-  | Isubf -> "subsd"
-  | Imulf -> "mulsd"
-  | Idivf -> "divsd"
-  | _ -> assert false
-
-let instr_for_floatarithmem = function
-    Ifloatadd -> "addsd"
-  | Ifloatsub -> "subsd"
-  | Ifloatmul -> "mulsd"
-  | Ifloatdiv -> "divsd"
-
-let name_for_cond_branch = function
-    Isigned Ceq -> "e"     | Isigned Cne -> "ne"
-  | Isigned Cle -> "le"     | Isigned Cgt -> "g"
-  | Isigned Clt -> "l"     | Isigned Cge -> "ge"
-  | Iunsigned Ceq -> "e"   | Iunsigned Cne -> "ne"
-  | Iunsigned Cle -> "be"  | Iunsigned Cgt -> "a"
-  | Iunsigned Clt -> "b"  | Iunsigned Cge -> "ae"
-
-(* Output an = 0 or <> 0 test. *)
-
-let output_test_zero arg =
-  match arg.loc with
-    Reg r -> `	test	{emit_reg arg}, {emit_reg arg}\n`
-  | _     -> `	cmp	{emit_reg arg}, 0\n`
-
-(* Output a floating-point compare and branch *)
-
-let emit_float_test cmp neg arg lbl =
-  (* Effect of comisd on flags and conditional branches:
-                     ZF PF CF  cond. branches taken
-        unordered     1  1  1  je, jb, jbe, jp
-        >             0  0  0  jne, jae, ja
-        <             0  0  1  jne, jbe, jb
-        =             1  0  0  je, jae, jbe.
-     If FP traps are on (they are off by default),
-     comisd traps on QNaN and SNaN but ucomisd traps on SNaN only.
-  *)
-  match (cmp, neg) with
-  | (Ceq, false) | (Cne, true) ->
-      let next = new_label() in
-      `	ucomisd	{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
-      `	jp	{emit_label next}\n`;    (* skip if unordered *)
-      `	je	{emit_label lbl}\n`;     (* branch taken if x=y *)
-      `{emit_label next}:\n`
-  | (Cne, false) | (Ceq, true) ->
-      `	ucomisd	{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
-      `	jp	{emit_label lbl}\n`;     (* branch taken if unordered *)
-      `	jne	{emit_label lbl}\n`      (* branch taken if xy *)
-  | (Clt, _) ->
-      ` comisd	{emit_reg arg.(1)}, {emit_reg arg.(0)}\n`;  (* swap compare *)
-      if not neg then
-      `	ja	{emit_label lbl}\n`     (* branch taken if y>x i.e. x
-      ` comisd	{emit_reg arg.(1)}, {emit_reg arg.(0)}\n`;  (* swap compare *)
-      if not neg then
-      `	jae	{emit_label lbl}\n`     (* branch taken if y>=x i.e. x<=y *)
-      else
-      `	jb	{emit_label lbl}\n` (* taken if unordered or y
-      ` comisd	{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;
-      if not neg then
-      `	ja	{emit_label lbl}\n`     (* branch taken if x>y *)
-      else
-      `	jbe	{emit_label lbl}\n` (* taken if unordered or x<=y i.e. !(x>y) *)
-  | (Cge, _) ->
-      ` comisd	{emit_reg arg.(0)}, {emit_reg arg.(1)}\n`;  (* swap compare *)
-      if not neg then
-      `	jae	{emit_label lbl}\n`     (* branch taken if x>=y *)
-      else
-      `	jb	{emit_label lbl}\n` (* taken if unordered or x=y) *)
-
-(* Deallocate the stack frame before a return or tail call *)
-
-let output_epilogue () =
-  if frame_required() then begin
-    let n = frame_size() - 8 in
-    `	add	rsp, {emit_int n}\n`
-  end
-
-(* Floating-point constants *)
-
-let float_constants = ref ([] : (int64 * int) list)
-
-let add_float_constant cst =
-  let repr = Int64.bits_of_float cst in
-  try
-    List.assoc repr !float_constants
-  with
-    Not_found ->
-      let lbl = new_label() in
-      float_constants := (repr, lbl) :: !float_constants;
-      lbl
-
-let emit_float_constant (cst, lbl) =
-  `{emit_label lbl}	QWORD	{emit_int64 cst}\n`
-
-let emit_movabs reg n =
-  (* force ml64 to use mov reg, imm64 instruction *)
-  `	mov	{emit_reg reg}, {emit_printf "0%nxH" n}\n`
-
-(* Output the assembly code for an instruction *)
-
-(* Name of current function *)
-let function_name = ref ""
-(* Entry point for tail recursive calls *)
-let tailrec_entry_point = ref 0
-
-let emit_instr fallthrough i =
-    match i.desc with
-      Lend -> ()
-    | Lop(Imove | Ispill | Ireload) ->
-        let src = i.arg.(0) and dst = i.res.(0) in
-        if src.loc <> dst.loc then begin
-          match src.typ, src.loc, dst.loc with
-            Float, Reg _, Reg _ ->
-              `	movapd	{emit_reg dst}, {emit_reg src}\n`
-          | Float, _, _ ->
-              `	movsd	{emit_reg dst}, {emit_reg src}\n`
-          | _ ->
-              `	mov	{emit_reg dst}, {emit_reg src}\n`
-        end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
-        if n = 0n then begin
-          match i.res.(0).loc with
-            Reg n -> `	xor	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
-          | _     -> `	mov	{emit_reg i.res.(0)}, 0\n`
-        end else if n >= -0x80000000n && n <= 0x7FFFFFFFn then
-          `	mov	{emit_reg i.res.(0)}, {emit_nativeint n}\n`
-        else if n >= 0x80000000n && n <= 0xFFFFFFFFn  then
-	  (* work around bug in ml64 *)
-          `	mov	{emit_reg32 i.res.(0)}, {emit_nativeint n}\n`
-        else
-          emit_movabs i.res.(0) n
-    | Lop(Iconst_float f) ->
-        begin match Int64.bits_of_float f with
-        | 0x0000_0000_0000_0000L ->       (* +0.0 *)
-          `	xorpd	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
-        | _ ->
-          let lbl = add_float_constant f in
-          `	movsd	{emit_reg i.res.(0)}, {emit_label lbl}\n`
-        end
-    | Lop(Iconst_symbol s) ->
-        add_used_symbol s;
-        if !pic_code then
-          `	lea	{emit_reg i.res.(0)}, {emit_symbol s}\n`
-        else
-          `	mov	{emit_reg i.res.(0)}, OFFSET {emit_symbol s}\n`
-    | Lop(Icall_ind) ->
-        `	call	{emit_reg i.arg.(0)}\n`;
-        record_frame i.live i.dbg
-    | Lop(Icall_imm s) ->
-        add_used_symbol s;
-        `	call	{emit_symbol s}\n`;
-        record_frame i.live i.dbg
-    | Lop(Itailcall_ind) ->
-        output_epilogue();
-        `	jmp	{emit_reg i.arg.(0)}\n`
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then
-          `	jmp	{emit_label !tailrec_entry_point}\n`
-        else begin
-          add_used_symbol s;
-          output_epilogue();
-          `	jmp	{emit_symbol s}\n`
-        end
-    | Lop(Iextcall(s, alloc)) ->
-        add_used_symbol s;
-        if alloc then begin
-          `	lea	rax, {emit_symbol s}\n`;
-          `	call	{emit_symbol "caml_c_call"}\n`;
-          record_frame i.live i.dbg
-        end else begin
-          `	call	{emit_symbol s}\n`
-        end
-    | Lop(Istackoffset n) ->
-        if n < 0
-        then `	add	rsp, {emit_int(-n)}\n`
-        else `	sub	rsp, {emit_int(n)}\n`;
-        stack_offset := !stack_offset + n
-    | Lop(Iload(chunk, addr)) ->
-        let dest = i.res.(0) in
-        begin match chunk with
-          | Word ->
-              `	mov	{emit_reg dest}, QWORD PTR {emit_addressing addr i.arg 0}\n`
-          | Byte_unsigned ->
-              `	movzx	{emit_reg dest}, BYTE PTR {emit_addressing addr i.arg 0}\n`
-          | Byte_signed ->
-              `	movsx	{emit_reg dest}, BYTE PTR {emit_addressing addr i.arg 0}\n`
-          | Sixteen_unsigned ->
-              `	movzx	{emit_reg dest}, WORD PTR {emit_addressing addr i.arg 0}\n`
-          | Sixteen_signed ->
-              `	movsx	{emit_reg dest}, WORD PTR {emit_addressing addr i.arg 0}\n`
-          | Thirtytwo_unsigned ->
-              (* load to low 32 bits sets high 32 bits to 0 *)
-              `	mov	{emit_reg32 dest}, DWORD PTR {emit_addressing addr i.arg 0}\n`
-          | Thirtytwo_signed ->
-              `	movsxd	{emit_reg dest}, DWORD PTR {emit_addressing addr i.arg 0}\n`
-          | Single ->
-            `	cvtss2sd {emit_reg dest}, REAL4 PTR {emit_addressing addr i.arg 0}\n`
-          | Double | Double_u ->
-            `	movsd	{emit_reg dest}, REAL8 PTR {emit_addressing addr i.arg 0}\n`
-        end
-    | Lop(Istore(chunk, addr, _)) ->
-        begin match chunk with
-          | Word ->
-            `	mov	QWORD PTR {emit_addressing addr i.arg 1}, {emit_reg i.arg.(0)}\n`
-          | Byte_unsigned | Byte_signed ->
-            `	mov	BYTE PTR {emit_addressing addr i.arg 1}, {emit_reg8 i.arg.(0)}\n`
-          | Sixteen_unsigned | Sixteen_signed ->
-            `	mov	WORD PTR {emit_addressing addr i.arg 1}, {emit_reg16 i.arg.(0)}\n`
-          | Thirtytwo_signed | Thirtytwo_unsigned ->
-            `	mov	DWORD PTR {emit_addressing addr i.arg 1}, {emit_reg32 i.arg.(0)}\n`
-          | Single ->
-            `	cvtsd2ss xmm15, {emit_reg i.arg.(0)}\n`;
-            `	movss	REAL4 PTR {emit_addressing addr i.arg 1}, xmm15\n`
-          | Double | Double_u ->
-            `	movsd	REAL8 PTR {emit_addressing addr i.arg 1}, {emit_reg i.arg.(0)}\n`
-        end
-    | Lop(Ialloc n) ->
-        if !fastcode_flag then begin
-          let lbl_redo = new_label() in
-          `{emit_label lbl_redo}:	sub	r15, {emit_int n}\n`;
-          `	cmp	r15, {emit_symbol "caml_young_limit"}\n`;
-          let lbl_call_gc = new_label() in
-          let lbl_frame = record_frame_label i.live Debuginfo.none in
-          `	jb	{emit_label lbl_call_gc}\n`;
-          `	lea	{emit_reg i.res.(0)}, [r15+8]\n`;
-          call_gc_sites :=
-            { gc_lbl = lbl_call_gc;
-              gc_return_lbl = lbl_redo;
-              gc_frame = lbl_frame } :: !call_gc_sites
-        end else begin
-          begin match n with
-            16  -> `	call	{emit_symbol "caml_alloc1"}\n`
-          | 24 -> `	call	{emit_symbol "caml_alloc2"}\n`
-          | 32 -> `	call	{emit_symbol "caml_alloc3"}\n`
-          | _  -> `	mov	rax, {emit_int n}\n`;
-                  `	call	{emit_symbol "caml_allocN"}\n`
-          end;
-          `{record_frame i.live Debuginfo.none}	lea	{emit_reg i.res.(0)}, [r15+8]\n`
-        end
-    | Lop(Iintop(Icomp cmp)) ->
-        `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}	al\n`;
-        `	movzx	{emit_reg i.res.(0)}, al\n`
-    | Lop(Iintop_imm(Icomp cmp, n)) ->
-        `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}	al\n`;
-        `	movzx	{emit_reg i.res.(0)}, al\n`
-    | Lop(Iintop Icheckbound) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop_imm(Icheckbound, n)) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop(Idiv | Imod)) ->
-        `	cqo\n`;
-        `	idiv	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop(Ilsl | Ilsr | Iasr as op)) ->
-        (* We have i.arg.(0) = i.res.(0) and i.arg.(1) = %rcx *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.res.(0)}, cl\n`
-    | Lop(Iintop Imulh) ->
-        `	imul	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop op) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.res.(0)}, {emit_reg i.arg.(1)}\n`
-    | Lop(Iintop_imm(Iadd, n)) when i.arg.(0).loc <> i.res.(0).loc ->
-        `	lea	{emit_reg i.res.(0)}, {emit_int n}[{emit_reg i.arg.(0)}]\n`
-    | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
-        `	inc	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
-        `	dec	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(op, n)) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.res.(0)}, {emit_int n}\n`
-    | Lop(Inegf) ->
-        `	xorpd	{emit_reg i.res.(0)}, {emit_symbol "caml_negf_mask"}\n`
-    | Lop(Iabsf) ->
-        `	andpd	{emit_reg i.res.(0)}, {emit_symbol "caml_absf_mask"}\n`
-    | Lop(Iaddf | Isubf | Imulf | Idivf as floatop) ->
-        `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.res.(0)}, {emit_reg i.arg.(1)}\n`
-    | Lop(Ifloatofint) ->
-        `	cvtsi2sd	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`
-    | Lop(Iintoffloat) ->
-        `	cvttsd2si	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`
-    | Lop(Ispecific(Ilea addr)) ->
-        `	lea	{emit_reg i.res.(0)}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Istore_int(n, addr, _))) ->
-        `	mov	QWORD PTR {emit_addressing addr i.arg 0}, {emit_nativeint n}\n`
-    | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
-        assert (not !pic_code);
-	add_used_symbol s;
-        `	mov	QWORD PTR {emit_addressing addr i.arg 0}, OFFSET {emit_symbol s}\n`
-    | Lop(Ispecific(Ioffset_loc(n, addr))) ->
-        `	add	QWORD PTR {emit_addressing addr i.arg 0}, {emit_int n}\n`
-    | Lop(Ispecific(Ifloatarithmem(op, addr))) ->
-        `	{emit_string(instr_for_floatarithmem op)}	{emit_reg i.res.(0)}, REAL8 PTR {emit_addressing addr i.arg 1}\n`
-    | Lop(Ispecific(Ibswap size)) ->
-       begin match size with
-       | 16 ->
-        `	xchg	ah, al\n`;
-        `	movzx	{emit_reg i.res.(0)}, {emit_reg16 i.res.(0)}\n`
-       | 32 ->
-        `	bswap	{emit_reg32 i.res.(0)}\n`;
-        `	movsxd	{emit_reg i.res.(0)}, {emit_reg32 i.res.(0)}\n`
-       | 64 ->
-        `	bswap	{emit_reg i.res.(0)}\n`
-       | _ -> assert false
-       end
-    | Lop(Ispecific Isqrtf) ->
-        `	sqrtsd	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`
-    | Lop(Ispecific(Ifloatsqrtf addr)) ->
-        `	sqrtsd	{emit_reg i.res.(0)}, REAL8 PTR {emit_addressing addr i.arg 0}\n`
-    | Lreloadretaddr ->
-        ()
-    | Lreturn ->
-        output_epilogue();
-        `	ret\n`
-    | Llabel lbl ->
-        `{emit_Llabel fallthrough lbl}:\n`
-    | Lbranch lbl ->
-        `	jmp	{emit_label lbl}\n`
-    | Lcondbranch(tst, lbl) ->
-        begin match tst with
-          Itruetest ->
-            output_test_zero i.arg.(0);
-            `	jne	{emit_label lbl}\n`
-        | Ifalsetest ->
-            output_test_zero i.arg.(0);
-            `	je	{emit_label lbl}\n`
-        | Iinttest cmp ->
-            `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm((Isigned Ceq | Isigned Cne |
-                        Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
-            output_test_zero i.arg.(0);
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm(cmp, n) ->
-            `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Ifloattest(cmp, neg) ->
-            emit_float_test cmp neg i.arg lbl
-        | Ioddtest ->
-            `	test	{emit_reg8 i.arg.(0)}, 1\n`;
-            `	jne	{emit_label lbl}\n`
-        | Ieventest ->
-            `	test	{emit_reg8 i.arg.(0)}, 1\n`;
-            `	je	{emit_label lbl}\n`
-        end
-    | Lcondbranch3(lbl0, lbl1, lbl2) ->
-            `	cmp	{emit_reg i.arg.(0)}, 1\n`;
-            begin match lbl0 with
-              None -> ()
-            | Some lbl -> `	jb	{emit_label lbl}\n`
-            end;
-            begin match lbl1 with
-              None -> ()
-            | Some lbl -> `	je	{emit_label lbl}\n`
-            end;
-            begin match lbl2 with
-              None -> ()
-            | Some lbl -> `	jg	{emit_label lbl}\n`
-            end
-    | Lswitch jumptbl ->
-        let lbl = new_label() in
-        (* rax and rdx are clobbered by the Lswitch,
-           meaning that no variable that is live across the Lswitch
-           is assigned to rax or rdx.  However, the argument to Lswitch
-           can still be assigned to one of these two registers, so
-           we must be careful not to clobber it before use. *)
-        let (tmp1, tmp2) =
-          if i.arg.(0).loc = Reg 0 (* rax *)
-          then (phys_reg 4 (*rdx*), phys_reg 0 (*rax*))
-          else (phys_reg 0 (*rax*), phys_reg 4 (*rdx*)) in
-        `	lea	{emit_reg tmp1}, {emit_label lbl}\n`;
-        `	movsxd	{emit_reg tmp2}, DWORD PTR [{emit_reg tmp1}+{emit_reg i.arg.(0)}*4]\n`;
-        `	add	{emit_reg tmp1}, {emit_reg tmp2}\n`;
-        `	jmp	{emit_reg tmp1}\n`;
-        emit_align 4;
-        `{emit_label lbl}	LABEL DWORD\n`;
-        for i = 0 to Array.length jumptbl - 1 do
-          `	DWORD	{emit_label jumptbl.(i)} - {emit_label lbl}\n`
-        done
-    | Lsetuptrap lbl ->
-        `	call	{emit_label lbl}\n`
-    | Lpushtrap ->
-        `	push	r14\n`;
-        `	mov	r14, rsp\n`;
-        stack_offset := !stack_offset + 16
-    | Lpoptrap ->
-        `	pop	r14\n`;
-        `	add	rsp, 8\n`;
-        stack_offset := !stack_offset - 16
-    | Lraise k ->
-        begin match !Clflags.debug, k with
-        | true, Lambda.Raise_regular ->
-          `	call	caml_raise_exn\n`;
-          record_frame Reg.Set.empty i.dbg
-        | true, Lambda.Raise_reraise ->
-          `	call	caml_reraise_exn\n`;
-          record_frame Reg.Set.empty i.dbg
-        | false, _
-        | true, Lambda.Raise_notrace ->
-          `	mov	rsp, r14\n`;
-          `	pop	r14\n`;
-          `	ret\n`
-        end
-
-let rec emit_all fallthrough i =
-  match i.desc with
-  |  Lend -> ()
-  | _ ->
-      emit_instr fallthrough i;
-      emit_all (Linearize.has_fallthrough i.desc) i.next
-
-(* Emission of a function declaration *)
-
-let fundecl fundecl =
-  function_name := fundecl.fun_name;
-  fastcode_flag := fundecl.fun_fast;
-  tailrec_entry_point := new_label();
-  stack_offset := 0;
-  call_gc_sites := [];
-  bound_error_sites := [];
-  bound_error_call := 0;
-  `	.CODE\n`;
-  emit_align 16;
-  add_def_symbol fundecl.fun_name;
-  `	PUBLIC	{emit_symbol fundecl.fun_name}\n`;
-  `{emit_symbol fundecl.fun_name}:\n`;
-  if frame_required() then begin
-    let n = frame_size() - 8 in
-    `	sub	rsp, {emit_int n}\n`
-  end;
-  `{emit_label !tailrec_entry_point}:\n`;
-  emit_all true fundecl.fun_body;
-  List.iter emit_call_gc !call_gc_sites;
-  emit_call_bound_errors()
-
-(* Emission of data *)
-
-let emit_item = function
-    Cglobal_symbol s ->
-      `	PUBLIC	{emit_symbol s}\n`;
-  | Cdefine_symbol s ->
-      add_def_symbol s;
-      `{emit_symbol s} LABEL QWORD\n`
-  | Cdefine_label lbl ->
-      `{emit_data_label lbl} LABEL QWORD\n`
-  | Cint8 n ->
-      `	BYTE	{emit_int n}\n`
-  | Cint16 n ->
-      `	WORD	{emit_int n}\n`
-  | Cint32 n ->
-      `	DWORD	{emit_nativeint n}\n`
-  | Cint n ->
-      `	QWORD	{emit_nativeint n}\n`
-  | Csingle f ->
-      `	DWORD	{emit_int32 (Int32.bits_of_float f)}\n`
-  | Cdouble f ->
-      `	QWORD	{emit_int64 (Int64.bits_of_float f)}\n`
-  | Csymbol_address s ->
-      add_used_symbol s;
-      `	QWORD	{emit_symbol s}\n`
-  | Clabel_address lbl ->
-      `	QWORD	{emit_data_label lbl}\n`
-  | Cstring s ->
-      emit_bytes_directive "	BYTE	" s
-  | Cskip n ->
-      if n > 0 then `	BYTE	{emit_int n} DUP (?)\n`
-  | Calign n ->
-      emit_align n
-
-let data l =
-  `	.DATA\n`;
-  List.iter emit_item l
-
-(* Beginning / end of an assembly file *)
-
-let begin_assembly() =
-  float_constants := [];
-  `	EXTRN caml_young_ptr: QWORD\n`;
-  `	EXTRN caml_young_limit: QWORD\n`;
-  `	EXTRN caml_exception_pointer: QWORD\n`;
-  `	EXTRN caml_absf_mask: QWORD\n`;
-  `	EXTRN caml_negf_mask: QWORD\n`;
-  `	EXTRN caml_call_gc: NEAR\n`;
-  `	EXTRN caml_c_call: NEAR\n`;
-  `	EXTRN caml_allocN: NEAR\n`;
-  `	EXTRN caml_alloc1: NEAR\n`;
-  `	EXTRN caml_alloc2: NEAR\n`;
-  `	EXTRN caml_alloc3: NEAR\n`;
-  `	EXTRN caml_ml_array_bound_error: NEAR\n`;
-  `	EXTRN caml_raise_exn: NEAR\n`;
-  `	EXTRN caml_reraise_exn: NEAR\n`;
-  let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
-  add_def_symbol lbl_begin;
-  `	.DATA\n`;
-  `	PUBLIC	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin} LABEL QWORD\n`;
-  let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
-  add_def_symbol lbl_begin;
-  `	.CODE\n`;
-  `	PUBLIC	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin} LABEL QWORD\n`
-
-let end_assembly() =
-  if !float_constants <> [] then begin
-    `	.DATA\n`;
-    List.iter emit_float_constant !float_constants
-  end;
-  let lbl_end = Compilenv.make_symbol (Some "code_end") in
-  add_def_symbol lbl_end;
-  `	.CODE\n`;
-  `	PUBLIC	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end} LABEL QWORD\n`;
-  `	.DATA\n`;
-  let lbl_end = Compilenv.make_symbol (Some "data_end") in
-  add_def_symbol lbl_end;
-  `	PUBLIC	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end} LABEL QWORD\n`;
-  `	QWORD	0\n`;
-  let lbl = Compilenv.make_symbol (Some "frametable") in
-  add_def_symbol lbl;
-  `	PUBLIC	{emit_symbol lbl}\n`;
-  `{emit_symbol lbl} LABEL QWORD\n`;
-  emit_frames
-    { efa_label = (fun l -> `	QWORD	{emit_label l}\n`);
-      efa_16 = (fun n -> `	WORD	{emit_int n}\n`);
-      efa_32 = (fun n -> `	DWORD	{emit_int32 n}\n`);
-      efa_word = (fun n -> `	QWORD	{emit_int n}\n`);
-      efa_align = emit_align;
-      efa_label_rel = (fun lbl ofs ->
-                           `	DWORD	{emit_label lbl} - THIS BYTE + {emit_int32 ofs}\n`);
-      efa_def_label = (fun l -> `{emit_label l}	LABEL	QWORD\n`);
-      efa_string = (fun s -> emit_bytes_directive  "	BYTE	" (s ^ "\000")) };
-  `\n;External functions\n\n`;
-  StringSet.iter
-    (fun s ->
-      if not (StringSet.mem s !symbols_defined) then
-        `	EXTRN	{emit_symbol s}: NEAR\n`)
-    !symbols_used;
-  symbols_used := StringSet.empty;
-  symbols_defined := StringSet.empty;
-  `END\n`
diff --git a/asmcomp/amd64/proc.ml b/asmcomp/amd64/proc.ml
index 298e9290..3f18d50d 100644
--- a/asmcomp/amd64/proc.ml
+++ b/asmcomp/amd64/proc.ml
@@ -1,14 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2000 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+# 2 "asmcomp/amd64/proc.ml"
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2000 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the AMD64 processor *)
 
@@ -75,6 +79,8 @@ let masm =
      Linux's dynamic loader also destroys r10.
 *)
 
+let max_arguments_for_tailcalls = 10
+
 let int_reg_name =
   match Config.ccomp_type with
   | "msvc" ->
@@ -99,8 +105,7 @@ let num_register_classes = 2
 
 let register_class r =
   match r.typ with
-    Int -> 0
-  | Addr -> 0
+  | Val | Int | Addr -> 0
   | Float -> 1
 
 let num_available_registers = [| 13; 16 |]
@@ -155,7 +160,7 @@ let calling_conventions first_int last_int first_float last_float make_stack
   let ofs = ref 0 in
   for i = 0 to Array.length arg - 1 do
     match arg.(i).typ with
-      Int | Addr as ty ->
+    | Val | Int | Addr as ty ->
         if !int <= last_int then begin
           loc.(i) <- phys_reg !int;
           incr int
@@ -215,7 +220,7 @@ let win64_loc_external_arguments arg =
   and ofs = ref 32 in
   for i = 0 to Array.length arg - 1 do
     match arg.(i).typ with
-      Int | Addr as ty ->
+    | Val | Int | Addr as ty ->
         if !reg < 4 then begin
           loc.(i) <- phys_reg win64_int_external_arguments.(!reg);
           incr reg
@@ -234,8 +239,15 @@ let win64_loc_external_arguments arg =
   done;
   (loc, Misc.align !ofs 16)  (* keep stack 16-aligned *)
 
-let loc_external_arguments =
-  if win64 then win64_loc_external_arguments else unix_loc_external_arguments
+let loc_external_arguments arg =
+  let arg =
+    Array.map (fun regs -> assert (Array.length regs = 1); regs.(0)) arg
+  in
+  let loc, alignment =
+    if win64 then win64_loc_external_arguments arg
+    else unix_loc_external_arguments arg
+  in
+  Array.map (fun reg -> [|reg|]) loc, alignment
 
 let loc_exn_bucket = rax
 
@@ -317,13 +329,7 @@ let contains_calls = ref false
 (* Calling the assembler *)
 
 let assemble_file infile outfile =
-  if masm then
-    Ccomp.command (Config.asm ^
-                   Filename.quote outfile ^ " " ^ Filename.quote infile ^
-                   (if !Clflags.verbose then "" else ">NUL"))
-  else
-    Ccomp.command (Config.asm ^ " -o " ^
-                   Filename.quote outfile ^ " " ^ Filename.quote infile)
+  X86_proc.assemble_file infile outfile
 
 let init () =
   if fp then begin
diff --git a/asmcomp/amd64/reload.ml b/asmcomp/amd64/reload.ml
index 49070d29..9ea80d06 100644
--- a/asmcomp/amd64/reload.ml
+++ b/asmcomp/amd64/reload.ml
@@ -1,17 +1,19 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2000 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2000 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Cmm
-open Arch
 open Reg
 open Mach
 
@@ -93,7 +95,7 @@ method! reload_operation op arg res =
       then (arg, res)
       else super#reload_operation op arg res
   | Iconst_symbol _ ->
-      if !pic_code || !Clflags.dlcode
+      if !Clflags.pic_code || !Clflags.dlcode
       then super#reload_operation op arg res
       else (arg, res)
   | _ -> (* Other operations: all args and results in registers *)
diff --git a/asmcomp/amd64/scheduling.ml b/asmcomp/amd64/scheduling.ml
index e234431b..ad146c50 100644
--- a/asmcomp/amd64/scheduling.ml
+++ b/asmcomp/amd64/scheduling.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2000 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2000 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 let _ = let module M = Schedgen in () (* to create a dependency *)
 
diff --git a/asmcomp/amd64/selection.ml b/asmcomp/amd64/selection.ml
index fa7fe66c..3c1a344e 100644
--- a/asmcomp/amd64/selection.ml
+++ b/asmcomp/amd64/selection.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2000 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2000 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction selection for the AMD64 *)
 
@@ -30,11 +33,11 @@ let rec select_addr exp =
   match exp with
     Cconst_symbol s when not !Clflags.dlcode ->
       (Asymbol s, 0)
-  | Cop((Caddi | 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 | Csuba), [arg; Cconst_int m]) ->
+  | Cop(Csubi, [arg; Cconst_int m]) ->
       let (a, n) = select_addr arg in (a, n - m)
-  | Cop((Caddi | 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)]) ->
       begin match select_addr arg with
@@ -51,7 +54,7 @@ let rec select_addr exp =
         (Alinear e, n) -> (Ascale(e, mult), n * mult)
       | _ -> (Alinear exp, 0)
       end
-  | Cop((Caddi | 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)
@@ -162,7 +165,7 @@ 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 (!pic_code || !Clflags.dlcode) ->
+  | 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
@@ -170,8 +173,8 @@ method! select_store is_assign addr exp =
 method! select_operation op args =
   match op with
   (* Recognize the LEA instruction *)
-    Caddi | Cadda | Csubi | Csuba ->
-      begin match self#select_addressing Word (Cop(op, args)) with
+    Caddi | Caddv | Cadda | Csubi ->
+      begin match self#select_addressing Word_int (Cop(op, args)) with
         (Iindexed d, _) -> super#select_operation op args
       | (Iindexed2 0, _) -> super#select_operation op args
       | (addr, arg) -> (Ispecific(Ilea addr), [arg])
@@ -196,11 +199,11 @@ method! select_operation op args =
          assert false
      end
   (* Recognize store instructions *)
-  | Cstore Word ->
+  | Cstore ((Word_int|Word_val as chunk), _init) ->
       begin match args with
         [loc; Cop(Caddi, [Cop(Cload _, [loc']); Cconst_int n])]
         when loc = loc' && self#is_immediate n ->
-          let (addr, arg) = self#select_addressing Word loc in
+          let (addr, arg) = self#select_addressing chunk loc in
           (Ispecific(Ioffset_loc(n, addr)), [arg])
       | _ ->
           super#select_operation op args
diff --git a/asmcomp/arm/CSE.ml b/asmcomp/arm/CSE.ml
index bea333dc..3ab5a35d 100644
--- a/asmcomp/arm/CSE.ml
+++ b/asmcomp/arm/CSE.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* CSE for ARM *)
 
diff --git a/asmcomp/arm/NOTES.md b/asmcomp/arm/NOTES.md
new file mode 100644
index 00000000..7a8ae671
--- /dev/null
+++ b/asmcomp/arm/NOTES.md
@@ -0,0 +1,20 @@
+# Supported platforms
+
+A great many variants of the ARM 32-bit architecture:
+* Architecture versions: v4, v5, v5te, v6, v6t2, v7.
+  ARMv7 is the standard nowadays.
+* Instruction encoding: classic ARM or Thumb or Thumb-2.
+* Floating-point: software emulation, VFPv2, VFPv3-d16, VFP-v3.
+* ABI: the standard EABI (with floats passed in integer registers)
+  or the EABI-HF variant (with floats passed in VFP registers).
+
+Debian architecture names: `armel` and `armhf`.
+
+# Reference documents
+
+* Instruction set architecture:
+  _ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition_.
+  Alternatively:
+  _ARM Architecture Reference Manual, ARMv8_, restricted to the AArch32 subset.
+* Application binary interface:
+  _Procedure Call Standard for the ARM Architecture_
diff --git a/asmcomp/arm/arch.ml b/asmcomp/arm/arch.ml
index d93c1e0e..72f88a05 100644
--- a/asmcomp/arm/arch.ml
+++ b/asmcomp/arm/arch.ml
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 1998 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 1998 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Specific operations for the ARM processor *)
 
@@ -22,7 +25,7 @@ type fpu = Soft | VFPv2 | VFPv3_D16 | VFPv3
 let abi =
   match Config.system with
     "linux_eabi" | "freebsd" -> EABI
-  | "linux_eabihf" -> EABI_HF
+  | "linux_eabihf" | "netbsd" -> EABI_HF
   | _ -> assert false
 
 let string_of_arch = function
@@ -56,25 +59,25 @@ let (arch, fpu, thumb) =
     end in
   (ref def_arch, ref def_fpu, ref def_thumb)
 
-let pic_code = ref false
-
 let farch spec =
-  arch := (match spec with
+  arch := begin match spec with
              "armv4" when abi <> EABI_HF   -> ARMv4
            | "armv5" when abi <> EABI_HF   -> ARMv5
            | "armv5te" when abi <> EABI_HF -> ARMv5TE
            | "armv6"                       -> ARMv6
            | "armv6t2"                     -> ARMv6T2
            | "armv7"                       -> ARMv7
-           | spec -> raise (Arg.Bad spec))
+           | spec -> raise (Arg.Bad ("wrong '-farch' option: " ^ spec))
+  end
 
 let ffpu spec =
-  fpu := (match spec with
+  fpu := begin match spec with
             "soft" when abi <> EABI_HF     -> Soft
           | "vfpv2" when abi = EABI_HF     -> VFPv2
           | "vfpv3-d16" when abi = EABI_HF -> VFPv3_D16
           | "vfpv3" when abi = EABI_HF     -> VFPv3
-          | spec -> raise (Arg.Bad spec))
+          | spec -> raise (Arg.Bad ("wrong '-ffpu' option: " ^ spec))
+  end
 
 let command_line_options =
   [ "-farch", Arg.String farch,
@@ -83,9 +86,9 @@ let command_line_options =
     "-ffpu", Arg.String ffpu,
       "  Select the floating-point hardware"
       ^ " (default: " ^ (string_of_fpu !fpu) ^ ")";
-    "-fPIC", Arg.Set pic_code,
+    "-fPIC", Arg.Set Clflags.pic_code,
       " Generate position-independent machine code";
-    "-fno-PIC", Arg.Clear pic_code,
+    "-fno-PIC", Arg.Clear Clflags.pic_code,
       " Generate position-dependent machine code";
     "-fthumb", Arg.Set thumb,
       " Enable Thumb/Thumb-2 code generation"
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index 4948fb2b..a63f9e8b 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 1998 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 1998 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Emission of ARM assembly code *)
 
@@ -40,12 +43,12 @@ let emit_symbol s =
   Emitaux.emit_symbol '$' s
 
 let emit_call s =
-  if !Clflags.dlcode || !pic_code
+  if !Clflags.dlcode || !Clflags.pic_code
   then `bl	{emit_symbol s}(PLT)`
   else `bl	{emit_symbol s}`
 
 let emit_jump s =
-  if !Clflags.dlcode || !pic_code
+  if !Clflags.dlcode || !Clflags.pic_code
   then `b	{emit_symbol s}(PLT)`
   else `b	{emit_symbol s}`
 
@@ -103,10 +106,12 @@ let record_frame_label live dbg =
   let live_offset = ref [] in
   Reg.Set.iter
     (function
-        {typ = Addr; loc = Reg r} ->
+      | {typ = Val; loc = Reg r} ->
           live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
+      | {typ = Val; loc = Stack s} as reg ->
           live_offset := slot_offset s (register_class reg) :: !live_offset
+      | {typ = Addr} as r ->
+          Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
   frame_descriptors :=
@@ -283,13 +288,12 @@ let num_literals = ref 0
 
 (* Label a floating-point literal *)
 let float_literal f =
-  let repr = Int64.bits_of_float f in
   try
-    List.assoc repr !float_literals
+    List.assoc f !float_literals
   with Not_found ->
     let lbl = new_label() in
     num_literals := !num_literals + 2;
-    float_literals := (repr, lbl) :: !float_literals;
+    float_literals := (f, lbl) :: !float_literals;
     lbl
 
 (* Label a GOTREL literal *)
@@ -321,7 +325,7 @@ let emit_literals() =
   end;
   if !symbol_literals <> [] then begin
     let offset = if !thumb then 4 else 8 in
-    let suffix = if !pic_code then "(GOT)" else "" in
+    let suffix = if !Clflags.pic_code then "(GOT)" else "" in
     `	.align	2\n`;
     List.iter
       (fun (l, lbl) ->
@@ -339,7 +343,7 @@ let emit_literals() =
 (* Emit code to load the address of a symbol *)
 
 let emit_load_symbol_addr dst s =
-  if !pic_code then begin
+  if !Clflags.pic_code then begin
     let lbl_pic = new_label() in
     let lbl_got = gotrel_literal lbl_pic in
     let lbl_sym = symbol_literal s in
@@ -391,9 +395,8 @@ let emit_instr i =
     | Lop(Iconst_int n | Iconst_blockheader n) ->
         emit_intconst i.res.(0) (Nativeint.to_int32 n)
     | Lop(Iconst_float f) when !fpu = Soft ->
-        let bits = Int64.bits_of_float f in
-        let high_bits = Int64.to_int32 (Int64.shift_right_logical bits 32)
-        and low_bits = Int64.to_int32 bits in
+        let high_bits = Int64.to_int32 (Int64.shift_right_logical f 32)
+        and low_bits = Int64.to_int32 f in
         if is_immediate low_bits || is_immediate high_bits then begin
           let ninstr_low = emit_intconst i.res.(0) low_bits
           and ninstr_high = emit_intconst i.res.(1) high_bits in
@@ -425,7 +428,7 @@ let emit_instr i =
               let ex = ((ex + 3) land 0x07) lxor 0x04 in
               Some((sg lsl 7) lor (ex lsl 4) lor mn)
           end in
-        begin match encode (Int64.bits_of_float f) with
+        begin match encode f with
           None ->
             let lbl = float_literal f in
             `	fldd	{emit_reg i.res.(0)}, {emit_label lbl}\n`
@@ -651,7 +654,8 @@ let emit_instr i =
                      | Ishiftor     -> "orr"
                      | Ishiftxor    -> "eor") in
         let op = name_for_shift_operation shiftop in
-        `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_string op} #{emit_int n}\n`; 1
+        `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, \
+                                        {emit_reg i.arg.(1)}, {emit_string op} #{emit_int n}\n`; 1
     | Lop(Ispecific(Irevsubimm n)) ->
         `	rsb	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, #{emit_int n}\n`; 1
     | Lop(Ispecific(Imuladd | Imulsub as op)) ->
@@ -755,7 +759,7 @@ let emit_instr i =
             if tramtbl.(j) <> jumptbl.(j) then
               `{emit_label tramtbl.(j)}:	b	{emit_label jumptbl.(j)}\n`
           done
-        end else if not !pic_code then begin
+        end else if not !Clflags.pic_code then begin
           `	ldr	pc, [pc, {emit_reg i.arg.(0)}, lsl #2]\n`;
           `	nop\n`;
           for j = 0 to Array.length jumptbl - 1 do
@@ -820,7 +824,7 @@ let rec emit_all ninstr i =
 
 let emit_profile() =
   match Config.system with
-    "linux_eabi" | "linux_eabihf" ->
+    "linux_eabi" | "linux_eabihf" | "netbsd" ->
       `	push	\{lr}\n`;
       `	{emit_call "__gnu_mcount_nc"}\n`
   | _ -> ()
@@ -892,6 +896,7 @@ let data l =
 
 let begin_assembly() =
   reset_debug_info();
+  `	.file	\"\"\n`;  (* PR#7037 *)
   `	.syntax	unified\n`;
   begin match !arch with
   | ARMv4   -> `	.arch	armv4t\n`
@@ -947,7 +952,7 @@ let end_assembly () =
   `	.type	{emit_symbol lbl}, %object\n`;
   `	.size	{emit_symbol lbl}, .-{emit_symbol lbl}\n`;
   begin match Config.system with
-    "linux_eabihf" | "linux_eabi" ->
+    "linux_eabihf" | "linux_eabi" | "netbsd" ->
       (* Mark stack as non-executable *)
       `	.section	.note.GNU-stack,\"\",%progbits\n`
   | _ -> ()
diff --git a/asmcomp/arm/proc.ml b/asmcomp/arm/proc.ml
index 58bfa427..a204cfff 100644
--- a/asmcomp/arm/proc.ml
+++ b/asmcomp/arm/proc.ml
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 1998 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 1998 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the ARM processor *)
 
@@ -63,10 +66,10 @@ let num_register_classes = 3
 
 let register_class r =
   match (r.typ, !fpu) with
-    (Int | Addr), _  -> 0
-  | Float, VFPv2     -> 1
-  | Float, VFPv3_D16 -> 1
-  | Float, _         -> 2
+  | (Val | Int | Addr), _  -> 0
+  | Float, VFPv2         -> 1
+  | Float, VFPv3_D16     -> 1
+  | Float, _             -> 2
 
 let num_available_registers =
   [| 9; 16; 32 |]
@@ -106,33 +109,67 @@ let stack_slot slot ty =
 
 (* Calling conventions *)
 
-let calling_conventions
-    first_int last_int first_float last_float make_stack arg =
-  let loc = Array.make (Array.length arg) Reg.dummy in
+let calling_conventions first_int last_int first_float last_float make_stack
+      arg =
+  let loc = Array.make (Array.length arg) [| Reg.dummy |] in
   let int = ref first_int in
   let float = ref first_float in
   let ofs = ref 0 in
   for i = 0 to Array.length arg - 1 do
-    match arg.(i).typ with
-      Int | Addr as ty ->
-        if !int <= last_int then begin
-          loc.(i) <- phys_reg !int;
-          incr int
-        end else begin
-          loc.(i) <- stack_slot (make_stack !ofs) ty;
-          ofs := !ofs + size_int
-        end
-    | Float ->
-        assert (abi = EABI_HF);
-        assert (!fpu >= VFPv2);
-        if !float <= last_float then begin
-          loc.(i) <- phys_reg !float;
-          incr float
-        end else begin
-          ofs := Misc.align !ofs size_float;
-          loc.(i) <- stack_slot (make_stack !ofs) Float;
-          ofs := !ofs + size_float
-        end
+    match arg.(i) with
+    | [| arg |] ->
+      begin match arg.typ with
+      | Val | Int | Addr as ty ->
+          if !int <= last_int then begin
+            loc.(i) <- [| phys_reg !int |];
+            incr int
+          end else begin
+            loc.(i) <- [| stack_slot (make_stack !ofs) ty |];
+            ofs := !ofs + size_int
+          end
+      | Float ->
+          assert (abi = EABI_HF);
+          assert (!fpu >= VFPv2);
+          if !float <= last_float then begin
+            loc.(i) <- [| phys_reg !float |];
+            incr float
+          end else begin
+            ofs := Misc.align !ofs size_float;
+            loc.(i) <- [| stack_slot (make_stack !ofs) Float |];
+            ofs := !ofs + size_float
+          end
+      end
+    | [| arg1; arg2 |] ->
+      (* Passing of 64-bit quantities to external functions. *)
+      begin match arg1.typ, arg2.typ with
+      | Int, Int ->
+          (* 64-bit quantities split across two registers must either be in a
+             consecutive pair of registers where the lowest numbered is an
+             even-numbered register; or in a stack slot that is 8-byte
+             aligned. *)
+          int := Misc.align !int 2;
+          if !int <= last_int - 1 then begin
+            let reg_lower = phys_reg !int in
+            let reg_upper = phys_reg (1 + !int) in
+            loc.(i) <- [| reg_lower; reg_upper |];
+            int := !int + 2
+          end else begin
+            let size_int64 = size_int * 2 in
+            ofs := Misc.align !ofs size_int64;
+            let stack_lower = stack_slot (make_stack !ofs) Int in
+            let stack_upper = stack_slot (make_stack (size_int + !ofs)) Int in
+            loc.(i) <- [| stack_lower; stack_upper |];
+            ofs := !ofs + size_int64
+          end
+      | _, _ ->
+        let f = function Int -> "I" | Addr -> "A" | Val -> "V" | Float -> "F" in
+        fatal_error (Printf.sprintf "Proc.calling_conventions: bad register \
+            type(s) for multi-register argument: %s, %s"
+          (f arg1.typ) (f arg2.typ))
+      end
+    | _ ->
+      fatal_error "Proc.calling_conventions: bad number of registers for \
+        multi-register argument"
   done;
   (loc, Misc.align !ofs 8)  (* keep stack 8-aligned *)
 
@@ -146,12 +183,28 @@ let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
      remaining args on stack.
    Return values in r0...r7 or d0...d15. *)
 
+let max_arguments_for_tailcalls = 8
+
+let single_regs arg = Array.map (fun arg -> [| arg |]) arg
+let ensure_single_regs res =
+  Array.map (function
+      | [| res |] -> res
+      | _ -> failwith "Proc.ensure_single_regs")
+    res
+
 let loc_arguments arg =
-  calling_conventions 0 7 100 115 outgoing arg
+  let (loc, alignment) =
+    calling_conventions 0 7 100 115 outgoing (single_regs arg)
+  in
+  ensure_single_regs loc, alignment
 let loc_parameters arg =
-  let (loc, _) = calling_conventions 0 7 100 115 incoming arg in loc
+  let (loc, _) = calling_conventions 0 7 100 115 incoming (single_regs arg) in
+  ensure_single_regs loc
 let loc_results res =
-  let (loc, _) = calling_conventions 0 7 100 115 not_supported res in loc
+  let (loc, _) =
+    calling_conventions 0 7 100 115 not_supported (single_regs res)
+  in
+  ensure_single_regs loc
 
 (* C calling convention:
      first integer args in r0...r3
@@ -162,7 +215,10 @@ let loc_results res =
 let loc_external_arguments arg =
   calling_conventions 0 3 100 107 outgoing arg
 let loc_external_results res =
-  let (loc, _) = calling_conventions 0 1 100 100 not_supported res in loc
+  let (loc, _) =
+    calling_conventions 0 1 100 100 not_supported (single_regs res)
+  in
+  ensure_single_regs loc
 
 let loc_exn_bucket = phys_reg 0
 
@@ -203,7 +259,7 @@ let destroyed_at_oper = function
       destroyed_at_c_call
   | Iop(Ialloc _) ->
       destroyed_at_alloc
-  | Iop(Iconst_symbol _) when !pic_code ->
+  | Iop(Iconst_symbol _) when !Clflags.pic_code ->
       [| phys_reg 3; phys_reg 8 |]  (* r3 and r12 destroyed *)
   | Iop(Iintop Imulh) when !arch < ARMv6 ->
       [| phys_reg 8 |]              (* r12 destroyed *)
@@ -218,14 +274,14 @@ let destroyed_at_raise = all_phys_regs
 let safe_register_pressure = function
     Iextcall(_, _) -> if abi = EABI then 0 else 4
   | Ialloc _ -> if abi = EABI then 0 else 7
-  | Iconst_symbol _ when !pic_code -> 7
+  | Iconst_symbol _ when !Clflags.pic_code -> 7
   | Iintop Imulh when !arch < ARMv6 -> 8
   | _ -> 9
 
 let max_register_pressure = function
     Iextcall(_, _) -> if abi = EABI then [| 4; 0; 0 |] else [| 4; 8; 8 |]
   | Ialloc _ -> if abi = EABI then [| 7; 0; 0 |] else [| 7; 8; 8 |]
-  | Iconst_symbol _ when !pic_code -> [| 7; 16; 32 |]
+  | Iconst_symbol _ when !Clflags.pic_code -> [| 7; 16; 32 |]
   | Iintoffloat | Ifloatofint
   | Iload(Single, _) | Istore(Single, _, _) -> [| 9; 15; 31 |]
   | Iintop Imulh when !arch < ARMv6 -> [| 8; 16; 32 |]
diff --git a/asmcomp/arm/reload.ml b/asmcomp/arm/reload.ml
index bd783acb..f6d9b881 100644
--- a/asmcomp/arm/reload.ml
+++ b/asmcomp/arm/reload.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1998 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1998 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Reloading for the ARM *)
 
diff --git a/asmcomp/arm/scheduling.ml b/asmcomp/arm/scheduling.ml
index 0d6618ab..c89d628a 100644
--- a/asmcomp/arm/scheduling.ml
+++ b/asmcomp/arm/scheduling.ml
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 1998 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 1998 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Arch
 open Mach
diff --git a/asmcomp/arm/selection.ml b/asmcomp/arm/selection.ml
index 4725942b..d363c556 100644
--- a/asmcomp/arm/selection.ml
+++ b/asmcomp/arm/selection.ml
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 1998 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 1998 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction selection for the ARM processor *)
 
@@ -27,7 +30,7 @@ let is_offset chunk n =
   (* ARM load/store byte/word have -4095 to 4095 *)
   | Byte_unsigned | Byte_signed
   | Thirtytwo_unsigned | Thirtytwo_signed
-  | Word | Single
+  | Word_int | Word_val | Single
     when not !thumb ->
       n >= -4095 && n <= 4095
   (* Thumb-2 load/store have -255 to 4095 *)
@@ -89,6 +92,8 @@ inherit Selectgen.selector_generic as super
 method! regs_for tyv =
   Reg.createv (if !fpu = Soft then begin
                  (* Expand floats into pairs of integer registers *)
+                 (* CR mshinwell: we need to check this in conjunction with
+                    the unboxed external functionality *)
                  let rec expand = function
                    [] -> []
                  | Float :: tyl -> Int :: Int :: expand tyl
@@ -113,12 +118,12 @@ method! is_simple_expr = function
   | e -> super#is_simple_expr e
 
 method select_addressing chunk = function
-  | Cop(Cadda, [arg; Cconst_int n])
+  | Cop((Cadda | Caddv), [arg; Cconst_int n])
     when is_offset chunk n ->
       (Iindexed n, arg)
-  | Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int n])])
+  | Cop((Cadda | Caddv as op), [arg1; Cop(Caddi, [arg2; Cconst_int n])])
     when is_offset chunk n ->
-      (Iindexed n, Cop(Cadda, [arg1; arg2]))
+      (Iindexed n, Cop(op, [arg1; arg2]))
   | arg ->
       (Iindexed 0, arg)
 
@@ -163,18 +168,18 @@ method select_shift_arith op arithop arithrevop args =
 method! select_operation op args =
   match (op, args) with
   (* Recognize special shift arithmetic *)
-    ((Cadda | Caddi), [arg; Cconst_int n])
+    ((Caddv | Cadda | Caddi), [arg; Cconst_int n])
     when n < 0 && self#is_immediate (-n) ->
       (Iintop_imm(Isub, -n), [arg])
-  | ((Cadda | Caddi as op), args) ->
+  | ((Caddv | Cadda | Caddi as op), args) ->
       self#select_shift_arith op Ishiftadd Ishiftadd args
-  | ((Csuba | Csubi), [arg; Cconst_int n])
+  | (Csubi, [arg; Cconst_int n])
     when n < 0 && self#is_immediate (-n) ->
       (Iintop_imm(Iadd, -n), [arg])
-  | ((Csuba | Csubi), [Cconst_int n; arg])
+  | (Csubi, [Cconst_int n; arg])
     when self#is_immediate n ->
       (Ispecific(Irevsubimm n), [arg])
-  | ((Csuba | Csubi as op), args) ->
+  | (Csubi as op, args) ->
       self#select_shift_arith op Ishiftsub Ishiftsubrev args
   | (Cand as op, args) ->
       self#select_shift_arith op Ishiftand Ishiftand args
@@ -231,12 +236,12 @@ method private select_operation_softfp op args =
        [Cop(Cextcall(func, typ_int, false, Debuginfo.none), args)])
   (* Add coercions around loads and stores of 32-bit floats *)
   | (Cload Single, args) ->
-      (Iextcall("__aeabi_f2d", false), [Cop(Cload Word, args)])
-  | (Cstore Single, [arg1; arg2]) ->
+      (Iextcall("__aeabi_f2d", false), [Cop(Cload Word_int, args)])
+  | (Cstore (Single, init), [arg1; arg2]) ->
       let arg2' =
         Cop(Cextcall("__aeabi_d2f", typ_int, false, Debuginfo.none),
             [arg2]) in
-      self#select_operation (Cstore Word) [arg1; arg2']
+      self#select_operation (Cstore (Word_int, init)) [arg1; arg2']
   (* Other operations are regular *)
   | (op, args) -> super#select_operation op args
 
diff --git a/asmcomp/arm64/CSE.ml b/asmcomp/arm64/CSE.ml
index f9e03e48..7a8fc17f 100644
--- a/asmcomp/arm64/CSE.ml
+++ b/asmcomp/arm64/CSE.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* CSE for ARM64 *)
 
diff --git a/asmcomp/arm64/NOTES.md b/asmcomp/arm64/NOTES.md
new file mode 100644
index 00000000..e2134eb1
--- /dev/null
+++ b/asmcomp/arm64/NOTES.md
@@ -0,0 +1,12 @@
+# Supported platforms
+
+ARMv8 in 64-bit mode (AArch64).
+
+Debian architecture name: `arm64`.
+
+# Reference documents
+
+* Instruction set architecture:
+  _ARM Architecture Reference Manual, ARMv8_, restricted to the AArch64 subset.
+* Application binary interface:
+  _Procedure Call Standard for the ARM 64-bit Architecture (AArch64)_
diff --git a/asmcomp/arm64/arch.ml b/asmcomp/arm64/arch.ml
index 3e62da89..5c13957f 100644
--- a/asmcomp/arm64/arch.ml
+++ b/asmcomp/arm64/arch.ml
@@ -1,16 +1,19 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 2013 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 2013 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 let command_line_options = []
 
diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp
index 750c2b23..9cca60b2 100644
--- a/asmcomp/arm64/emit.mlp
+++ b/asmcomp/arm64/emit.mlp
@@ -1,16 +1,19 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 2013 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 2013 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Emission of ARM assembly code, 64-bit mode *)
 
@@ -123,10 +126,12 @@ let record_frame_label live dbg =
   let live_offset = ref [] in
   Reg.Set.iter
     (function
-        {typ = Addr; loc = Reg r} ->
+      | {typ = Val; loc = Reg r} ->
           live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
+      | {typ = Val; loc = Stack s} as reg ->
           live_offset := slot_offset s (register_class reg) :: !live_offset
+      | {typ = Addr} as r ->
+          Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
   frame_descriptors :=
@@ -563,13 +568,12 @@ let emit_instr i =
     | Lop(Iconst_int n | Iconst_blockheader n) ->
         emit_intconst i.res.(0) n
     | Lop(Iconst_float f) ->
-        let b = Int64.bits_of_float f in
-        if b = 0L then
+        if f = 0L then
           `	fmov	{emit_reg i.res.(0)}, xzr\n`
-        else if is_immediate_float b then
-          `	fmov	{emit_reg i.res.(0)}, #{emit_printf "0x%Lx" b}\n`
+        else if is_immediate_float f then
+          `	fmov	{emit_reg i.res.(0)}, #{emit_printf "0x%Lx" f}\n`
         else begin
-          let lbl = float_literal b in
+          let lbl = float_literal f in
           `	adrp	{emit_reg reg_tmp1}, {emit_label lbl}\n`;
           `	ldr	{emit_reg i.res.(0)}, [{emit_reg reg_tmp1}, #:lo12:{emit_label lbl}]\n`
         end
@@ -622,7 +626,7 @@ let emit_instr i =
         | Single ->
             `	ldr	s7, {emit_addressing addr base}\n`;
             `	fcvt	{emit_reg dst}, s7\n`
-        | Word | Double | Double_u ->
+        | Word_int | Word_val | Double | Double_u ->
             `	ldr	{emit_reg dst}, {emit_addressing addr base}\n`
         end
     | Lop(Istore(size, addr, _)) ->
@@ -643,7 +647,7 @@ let emit_instr i =
         | Single ->
             `	fcvt	s7, {emit_reg src}\n`;
             `	str	s7, {emit_addressing addr base}\n`;
-        | Word | Double | Double_u ->
+        | Word_int | Word_val | Double | Double_u ->
             `	str	{emit_reg src}, {emit_addressing addr base}\n`
         end
     | Lop(Ialloc n) ->
@@ -865,7 +869,7 @@ let rec emit_all i =
 let emit_profile() = ()   (* TODO *)
 (*
   match Config.system with
-    "linux_eabi" | "linux_eabihf" ->
+    "linux_eabi" | "linux_eabihf" | "netbsd" ->
       `	push	\{lr}\n`;
       `	{emit_call "__gnu_mcount_nc"}\n`
   | _ -> ()
@@ -942,6 +946,7 @@ let data l =
 
 let begin_assembly() =
   reset_debug_info();
+  `	.file	\"\"\n`;  (* PR#7037 *)
   let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
   `	.data\n`;
   `	.globl	{emit_symbol lbl_begin}\n`;
diff --git a/asmcomp/arm64/proc.ml b/asmcomp/arm64/proc.ml
index 0222b72a..86cfb51e 100644
--- a/asmcomp/arm64/proc.ml
+++ b/asmcomp/arm64/proc.ml
@@ -1,16 +1,19 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 2013 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 2013 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the ARM processor in 64-bit mode *)
 
@@ -59,8 +62,8 @@ let num_register_classes = 2
 
 let register_class r =
   match r.typ with
-  | (Int | Addr)  -> 0
-  | Float         -> 1
+  | Val | Int | Addr  -> 0
+  | Float -> 1
 
 let num_available_registers =
   [| 23; 32 |] (* first 23 int regs allocatable; all float regs allocatable *)
@@ -111,7 +114,7 @@ let calling_conventions
   let ofs = ref 0 in
   for i = 0 to Array.length arg - 1 do
     match arg.(i).typ with
-      Int | Addr as ty ->
+    | Val | Int | Addr as ty ->
         if !int <= last_int then begin
           loc.(i) <- phys_reg !int;
           incr int
@@ -140,6 +143,8 @@ let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
      remaining args on stack.
    Return values in r0...r15 or d0...d15. *)
 
+let max_arguments_for_tailcalls = 16
+
 let loc_arguments arg =
   calling_conventions 0 15 100 115 outgoing arg
 let loc_parameters arg =
@@ -154,7 +159,11 @@ let loc_results res =
    Return values in r0...r1 or d0. *)
 
 let loc_external_arguments arg =
-  calling_conventions 0 7 100 107 outgoing arg
+  let arg =
+    Array.map (fun regs -> assert (Array.length regs = 1); regs.(0)) arg
+  in
+  let loc, alignment = calling_conventions 0 7 100 107 outgoing arg in
+  Array.map (fun reg -> [|reg|]) loc, alignment
 let loc_external_results res =
   let (loc, _) = calling_conventions 0 1 100 100 not_supported res in loc
 
diff --git a/asmcomp/arm64/reload.ml b/asmcomp/arm64/reload.ml
index ff9214ef..0d6cacd0 100644
--- a/asmcomp/arm64/reload.ml
+++ b/asmcomp/arm64/reload.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2013 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2013 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Reloading for the ARM 64 bits *)
 
diff --git a/asmcomp/arm64/scheduling.ml b/asmcomp/arm64/scheduling.ml
index cc244be7..04f514e9 100644
--- a/asmcomp/arm64/scheduling.ml
+++ b/asmcomp/arm64/scheduling.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2013 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2013 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 let _ = let module M = Schedgen in () (* to create a dependency *)
 
diff --git a/asmcomp/arm64/selection.ml b/asmcomp/arm64/selection.ml
index e7ded8fb..d7d55a93 100644
--- a/asmcomp/arm64/selection.ml
+++ b/asmcomp/arm64/selection.ml
@@ -1,16 +1,19 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                  Benedikt Meurer, University of Siegen              *)
-(*                                                                     *)
-(*    Copyright 2013 Institut National de Recherche en Informatique    *)
-(*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    *)
-(*    reserved.  This file is distributed  under the terms of the Q    *)
-(*    Public License version 1.0.                                      *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                 Benedikt Meurer, University of Siegen                  *)
+(*                                                                        *)
+(*   Copyright 2013 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2012 Benedikt Meurer.                                      *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction selection for the ARM processor *)
 
@@ -28,7 +31,7 @@ let is_offset chunk n =
         n land 1 = 0 && n lsr 1 < 0x1000
     | Thirtytwo_unsigned | Thirtytwo_signed | Single ->
         n land 3 = 0 && n lsr 2 < 0x1000
-    | Word | Double | Double_u ->
+    | Word_int | Word_val | Double | Double_u ->
         n land 7 = 0 && n lsr 3 < 0x1000)
 
 (* An automaton to recognize ( 0+1+0* | 1+0+1* )
@@ -102,15 +105,15 @@ method! is_simple_expr = function
   | e -> super#is_simple_expr e
 
 method select_addressing chunk = function
-  | Cop(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(Cadda, [arg; Cconst_int n])
+  | Cop((Caddv | Cadda), [arg; Cconst_int n])
     when is_offset chunk n ->
       (Iindexed n, arg)
-  | Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int n])])
+  | Cop((Caddv | Cadda as op), [arg1; Cop(Caddi, [arg2; Cconst_int n])])
     when is_offset chunk n ->
-      (Iindexed n, Cop(Cadda, [arg1; arg2]))
+      (Iindexed n, Cop(op, [arg1; arg2]))
   | Cconst_symbol s
     when use_direct_addressing s ->
       (Ibased(s, 0), Ctuple [])
@@ -120,10 +123,13 @@ method select_addressing chunk = function
 method! select_operation op args =
   match op with
   (* Integer addition *)
-  | Caddi | Cadda ->
+  | Caddi | Caddv | Cadda ->
       begin match args with
       (* Add immediate *)
-      | [arg; Cconst_int n] | [Cconst_int n; arg] when self#is_immediate n ->
+      | [arg; Cconst_int n] when self#is_immediate n ->
+          ((if n >= 0 then Iintop_imm(Iadd, n) else Iintop_imm(Isub, -n)),
+           [arg])
+      | [Cconst_int n; arg] when self#is_immediate n ->
           ((if n >= 0 then Iintop_imm(Iadd, n) else Iintop_imm(Isub, -n)),
            [arg])
       (* Shift-add *)
@@ -149,7 +155,7 @@ method! select_operation op args =
           super#select_operation op args
       end
   (* Integer subtraction *)
-  | Csubi | Csuba ->
+  | Csubi ->
       begin match args with
       (* Sub immediate *)
       | [arg; Cconst_int n] when self#is_immediate n ->
diff --git a/asmcomp/asmgen.ml b/asmcomp/asmgen.ml
index 311bb029..b365e411 100644
--- a/asmcomp/asmgen.ml
+++ b/asmcomp/asmgen.ml
@@ -1,17 +1,22 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* From lambda to assembly code *)
 
+[@@@ocaml.warning "+a-4-9-40-41-42"]
+
 open Format
 open Config
 open Clflags
@@ -35,8 +40,40 @@ let pass_dump_linear_if ppf flag message phrase =
   if !flag then fprintf ppf "*** %s@.%a@." message Printlinear.fundecl phrase;
   phrase
 
-let clambda_dump_if ppf ulambda =
-  if !dump_clambda then Printclambda.clambda ppf ulambda; ulambda
+let flambda_raw_clambda_dump_if ppf
+      ({ Flambda_to_clambda. expr = ulambda; preallocated_blocks = _;
+        structured_constants; exported = _; } as input) =
+  if !dump_rawclambda then
+    begin
+      Format.fprintf ppf "@.clambda (before Un_anf):@.";
+      Printclambda.clambda ppf ulambda;
+      Symbol.Map.iter (fun sym cst ->
+          Format.fprintf ppf "%a:@ %a@."
+            Symbol.print sym
+            Printclambda.structured_constant cst)
+        structured_constants
+    end;
+  if !dump_cmm then Format.fprintf ppf "@.cmm:@.";
+  input
+
+type clambda_and_constants =
+  Clambda.ulambda *
+  Clambda.preallocated_block list *
+  Clambda.preallocated_constant list
+
+let raw_clambda_dump_if ppf
+      ((ulambda, _, structured_constants):clambda_and_constants) =
+  if !dump_rawclambda then
+    begin
+      Format.fprintf ppf "@.clambda (before Un_anf):@.";
+      Printclambda.clambda ppf ulambda;
+      List.iter (fun {Clambda.symbol; definition} ->
+          Format.fprintf ppf "%s:@ %a@."
+            symbol
+            Printclambda.structured_constant definition)
+        structured_constants
+    end;
+  if !dump_cmm then Format.fprintf ppf "@.cmm:@."
 
 let rec regalloc ppf round fd =
   if round > 50 then
@@ -59,28 +96,29 @@ let (++) x f = f x
 let compile_fundecl (ppf : formatter) fd_cmm =
   Proc.init ();
   Reg.reset();
+  let build = Compilenv.current_build () in
   fd_cmm
-  ++ Selection.fundecl
+  ++ Timings.(accumulate_time (Selection build)) Selection.fundecl
   ++ pass_dump_if ppf dump_selection "After instruction selection"
-  ++ Comballoc.fundecl
+  ++ Timings.(accumulate_time (Comballoc build)) Comballoc.fundecl
   ++ pass_dump_if ppf dump_combine "After allocation combining"
-  ++ CSE.fundecl
+  ++ Timings.(accumulate_time (CSE build)) CSE.fundecl
   ++ pass_dump_if ppf dump_cse "After CSE"
-  ++ liveness ppf
-  ++ Deadcode.fundecl
+  ++ Timings.(accumulate_time (Liveness build)) (liveness ppf)
+  ++ Timings.(accumulate_time (Deadcode build)) Deadcode.fundecl
   ++ pass_dump_if ppf dump_live "Liveness analysis"
-  ++ Spill.fundecl
-  ++ liveness ppf
+  ++ Timings.(accumulate_time (Spill build)) Spill.fundecl
+  ++ Timings.(accumulate_time (Liveness build)) (liveness ppf)
   ++ pass_dump_if ppf dump_spill "After spilling"
-  ++ Split.fundecl
+  ++ Timings.(accumulate_time (Split build)) Split.fundecl
   ++ pass_dump_if ppf dump_split "After live range splitting"
-  ++ liveness ppf
-  ++ regalloc ppf 1
-  ++ Linearize.fundecl
+  ++ Timings.(accumulate_time (Liveness build)) (liveness ppf)
+  ++ Timings.(accumulate_time (Regalloc build)) (regalloc ppf 1)
+  ++ Timings.(accumulate_time (Linearize build)) Linearize.fundecl
   ++ pass_dump_linear_if ppf dump_linear "Linearized code"
-  ++ Scheduling.fundecl
+  ++ Timings.(accumulate_time (Scheduling build)) Scheduling.fundecl
   ++ pass_dump_linear_if ppf dump_scheduling "After instruction scheduling"
-  ++ Emit.fundecl
+  ++ Timings.(accumulate_time (Emit build)) Emit.fundecl
 
 let compile_phrase ppf p =
   if !dump_cmm then fprintf ppf "%a@." Printcmm.phrase p;
@@ -99,43 +137,121 @@ let compile_genfuns ppf f =
        | _ -> ())
     (Cmmgen.generic_functions true [Compilenv.current_unit_infos ()])
 
-let compile_implementation ?toplevel prefixname ppf (size, lam) =
+let compile_unit ~source_provenance _output_prefix asm_filename keep_asm
+      obj_filename gen =
+  let create_asm = keep_asm || not !Emitaux.binary_backend_available in
+  Emitaux.create_asm_file := create_asm;
+  try
+    if create_asm then Emitaux.output_channel := open_out asm_filename;
+    begin try
+      gen ();
+      if create_asm then close_out !Emitaux.output_channel;
+    with exn when create_asm ->
+      close_out !Emitaux.output_channel;
+      if not keep_asm then remove_file asm_filename;
+      raise exn
+    end;
+    let assemble_result =
+      Timings.(time (Assemble source_provenance))
+        (Proc.assemble_file asm_filename) obj_filename
+    in
+    if assemble_result <> 0
+    then raise(Error(Assembler_error asm_filename));
+    if create_asm && not keep_asm then remove_file asm_filename
+  with exn ->
+    remove_file obj_filename;
+    raise exn
+
+let set_export_info (ulambda, prealloc, structured_constants, export) =
+  Compilenv.set_export_info export;
+  (ulambda, prealloc, structured_constants)
+
+let end_gen_implementation ?toplevel ~source_provenance ppf
+    (clambda:clambda_and_constants) =
+  Emit.begin_assembly ();
+  clambda
+  ++ Timings.(time (Cmm source_provenance)) Cmmgen.compunit
+  ++ Timings.(time (Compile_phrases source_provenance))
+       (List.iter (compile_phrase ppf))
+  ++ (fun () -> ());
+  (match toplevel with None -> () | Some f -> compile_genfuns ppf f);
+
+  (* We add explicit references to external primitive symbols.  This
+     is to ensure that the object files that define these symbols,
+     when part of a C library, won't be discarded by the linker.
+     This is important if a module that uses such a symbol is later
+     dynlinked. *)
+
+  compile_phrase ppf
+    (Cmmgen.reference_symbols
+       (List.filter (fun s -> s <> "" && s.[0] <> '%')
+          (List.map Primitive.native_name !Translmod.primitive_declarations))
+    );
+  Emit.end_assembly ()
+
+let flambda_gen_implementation ?toplevel ~source_provenance ~backend ppf
+    (program:Flambda.program) =
+  let export = Build_export_info.build_export_info ~backend program in
+  let (clambda, preallocated, constants) =
+    Timings.time (Flambda_pass ("backend", source_provenance)) (fun () ->
+      (program, export)
+      ++ Flambda_to_clambda.convert
+      ++ flambda_raw_clambda_dump_if ppf
+      ++ (fun { Flambda_to_clambda. expr; preallocated_blocks;
+                structured_constants; exported; } ->
+             (* "init_code" following the name used in
+                [Cmmgen.compunit_and_constants]. *)
+           Un_anf.apply expr ~what:"init_code", preallocated_blocks,
+           structured_constants, exported)
+      ++ set_export_info) ()
+  in
+  let constants =
+    List.map (fun (symbol, definition) ->
+        { Clambda.symbol = Linkage_name.to_string (Symbol.label symbol);
+          exported = true;
+          definition })
+      (Symbol.Map.bindings constants)
+  in
+  end_gen_implementation ?toplevel ~source_provenance ppf
+    (clambda, preallocated, constants)
+
+let lambda_gen_implementation ?toplevel ~source_provenance ppf
+    (lambda:Lambda.program) =
+  let clambda = Closure.intro lambda.main_module_block_size lambda.code in
+  let preallocated_block =
+    Clambda.{
+      symbol = Compilenv.make_symbol None;
+      exported = true;
+      tag = 0;
+      size = lambda.main_module_block_size;
+    }
+  in
+  let clambda_and_constants =
+    clambda, [preallocated_block], []
+  in
+  raw_clambda_dump_if ppf clambda_and_constants;
+  end_gen_implementation ?toplevel ~source_provenance ppf clambda_and_constants
+
+let compile_implementation_gen ?toplevel ~source_provenance prefixname
+    ppf gen_implementation program =
   let asmfile =
-    if !keep_asm_file
+    if !keep_asm_file || !Emitaux.binary_backend_available
     then prefixname ^ ext_asm
-    else Filename.temp_file "camlasm" ext_asm in
-  let oc = open_out asmfile in
-  begin try
-    Emitaux.output_channel := oc;
-    Emit.begin_assembly();
-    Closure.intro size lam
-    ++ clambda_dump_if ppf
-    ++ Cmmgen.compunit size
-    ++ List.iter (compile_phrase ppf) ++ (fun () -> ());
-    (match toplevel with None -> () | Some f -> compile_genfuns ppf f);
-
-    (* We add explicit references to external primitive symbols.  This
-       is to ensure that the object files that define these symbols,
-       when part of a C library, won't be discarded by the linker.
-       This is important if a module that uses such a symbol is later
-       dynlinked. *)
-
-    compile_phrase ppf
-      (Cmmgen.reference_symbols
-         (List.filter (fun s -> s <> "" && s.[0] <> '%')
-            (List.map Primitive.native_name !Translmod.primitive_declarations))
-      );
-
-    Emit.end_assembly();
-    close_out oc
-  with x ->
-    close_out oc;
-    if !keep_asm_file then () else remove_file asmfile;
-    raise x
-  end;
-  if Proc.assemble_file asmfile (prefixname ^ ext_obj) <> 0
-  then raise(Error(Assembler_error asmfile));
-  if !keep_asm_file then () else remove_file asmfile
+    else Filename.temp_file "camlasm" ext_asm
+  in
+  compile_unit ~source_provenance prefixname asmfile !keep_asm_file
+      (prefixname ^ ext_obj) (fun () ->
+        gen_implementation ?toplevel ~source_provenance ppf program)
+
+let compile_implementation_clambda ?toplevel ~source_provenance prefixname
+    ppf (program:Lambda.program) =
+  compile_implementation_gen ?toplevel ~source_provenance prefixname
+    ppf lambda_gen_implementation program
+
+let compile_implementation_flambda ?toplevel ~source_provenance prefixname
+    ~backend ppf (program:Flambda.program) =
+  compile_implementation_gen ?toplevel ~source_provenance prefixname
+    ppf (flambda_gen_implementation ~backend) program
 
 (* Error report *)
 
diff --git a/asmcomp/asmgen.mli b/asmcomp/asmgen.mli
index 33582af4..fc929878 100644
--- a/asmcomp/asmgen.mli
+++ b/asmcomp/asmgen.mli
@@ -1,23 +1,43 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* From lambda to assembly code *)
 
-val compile_implementation :
+val compile_implementation_flambda :
     ?toplevel:(string -> bool) ->
-    string -> Format.formatter -> int * Lambda.lambda -> unit
+    source_provenance:Timings.source_provenance ->
+    string ->
+    backend:(module Backend_intf.S) ->
+    Format.formatter -> Flambda.program -> unit
+
+val compile_implementation_clambda :
+    ?toplevel:(string -> bool) ->
+    source_provenance:Timings.source_provenance ->
+    string ->
+    Format.formatter -> Lambda.program -> unit
+
 val compile_phrase :
     Format.formatter -> Cmm.phrase -> unit
 
 type error = Assembler_error of string
 exception Error of error
 val report_error: Format.formatter -> error -> unit
+
+
+val compile_unit:
+  source_provenance:Timings.source_provenance ->
+  string(*prefixname*) ->
+  string(*asm file*) -> bool(*keep asm*) ->
+  string(*obj file*) -> (unit -> unit) -> unit
diff --git a/asmcomp/asmlibrarian.ml b/asmcomp/asmlibrarian.ml
index 968e1de7..b5002c18 100644
--- a/asmcomp/asmlibrarian.ml
+++ b/asmcomp/asmlibrarian.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Build libraries of .cmx files *)
 
@@ -22,6 +25,12 @@ type error =
 
 exception Error of error
 
+let default_ui_export_info =
+  if Config.flambda then
+    Cmx_format.Flambda Export_info.empty
+  else
+    Cmx_format.Clambda Clambda.Value_unknown
+
 let read_info name =
   let filename =
     try
@@ -34,7 +43,7 @@ let read_info name =
      since the compiler will go looking directly for .cmx files.
      The linker, which is the only one that reads .cmxa files, does not
      need the approximation. *)
-  info.ui_approx <- Clambda.Value_unknown;
+  info.ui_export_info <- default_ui_export_info;
   (Filename.chop_suffix filename ".cmx" ^ ext_obj, (info, crc))
 
 let create_archive file_list lib_name =
diff --git a/asmcomp/asmlibrarian.mli b/asmcomp/asmlibrarian.mli
index c1a6a478..4d66827c 100644
--- a/asmcomp/asmlibrarian.mli
+++ b/asmcomp/asmlibrarian.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Build libraries of .cmx files *)
 
diff --git a/asmcomp/asmlink.ml b/asmcomp/asmlink.ml
index cea7b568..254dec7b 100644
--- a/asmcomp/asmlink.ml
+++ b/asmcomp/asmlink.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Link a set of .cmx/.o files and produce an executable *)
 
@@ -94,7 +97,9 @@ let lib_ccopts = ref []
 let add_ccobjs origin l =
   if not !Clflags.no_auto_link then begin
     lib_ccobjs := l.lib_ccobjs @ !lib_ccobjs;
-    let replace_origin = Misc.replace_substring ~before:"$CAMLORIGIN" ~after:origin in
+    let replace_origin =
+      Misc.replace_substring ~before:"$CAMLORIGIN" ~after:origin
+    in
     lib_ccopts := List.map replace_origin l.lib_ccopts @ !lib_ccopts
   end
 
@@ -198,13 +203,12 @@ let scan_file obj_name tolink = match read_file obj_name with
 
 (* Second pass: generate the startup file and link it with everything else *)
 
-let make_startup_file ppf filename units_list =
+let make_startup_file ppf units_list =
   let compile_phrase p = Asmgen.compile_phrase ppf p in
-  let oc = open_out filename in
-  Emitaux.output_channel := oc;
   Location.input_name := "caml_startup"; (* set name of "current" input *)
-  Compilenv.reset "_startup"; (* set the name of the "current" compunit *)
-  Emit.begin_assembly();
+  Compilenv.reset ~source_provenance:Timings.Startup "_startup";
+  (* set the name of the "current" compunit *)
+  Emit.begin_assembly ();
   let name_list =
     List.flatten (List.map (fun (info,_,_) -> info.ui_defines) units_list) in
   compile_phrase (Cmmgen.entry_point name_list);
@@ -231,17 +235,13 @@ let make_startup_file ppf filename units_list =
   compile_phrase(Cmmgen.code_segment_table ("_startup" :: name_list));
   compile_phrase
     (Cmmgen.frame_table("_startup" :: "_system" :: name_list));
+  Emit.end_assembly ()
 
-  Emit.end_assembly();
-  close_out oc
-
-let make_shared_startup_file ppf units filename =
+let make_shared_startup_file ppf units =
   let compile_phrase p = Asmgen.compile_phrase ppf p in
-  let oc = open_out filename in
-  Emitaux.output_channel := oc;
   Location.input_name := "caml_startup";
-  Compilenv.reset "_shared_startup";
-  Emit.begin_assembly();
+  Compilenv.reset ~source_provenance:Timings.Startup "_shared_startup";
+  Emit.begin_assembly ();
   List.iter compile_phrase
     (Cmmgen.generic_functions true (List.map fst units));
   compile_phrase (Cmmgen.plugin_header units);
@@ -250,10 +250,7 @@ let make_shared_startup_file ppf units filename =
        (List.map (fun (ui,_) -> ui.ui_symbol) units));
   (* this is to force a reference to all units, otherwise the linker
      might drop some of them (in case of libraries) *)
-
-  Emit.end_assembly();
-  close_out oc
-
+  Emit.end_assembly ()
 
 let call_linker_shared file_list output_name =
   if not (Ccomp.call_linker Ccomp.Dll output_name file_list "")
@@ -270,15 +267,16 @@ let link_shared ppf objfiles output_name =
     (List.rev !Clflags.ccobjs) in
 
   let startup =
-    if !Clflags.keep_startup_file
+    if !Clflags.keep_startup_file || !Emitaux.binary_backend_available
     then output_name ^ ".startup" ^ ext_asm
     else Filename.temp_file "camlstartup" ext_asm in
-  make_shared_startup_file ppf
-    (List.map (fun (ui,_,crc) -> (ui,crc)) units_tolink) startup;
   let startup_obj = output_name ^ ".startup" ^ ext_obj in
-  if Proc.assemble_file startup startup_obj <> 0
-  then raise(Error(Assembler_error startup));
-  if not !Clflags.keep_startup_file then remove_file startup;
+  Asmgen.compile_unit ~source_provenance:Timings.Startup output_name
+    startup !Clflags.keep_startup_file startup_obj
+    (fun () ->
+       make_shared_startup_file ppf
+         (List.map (fun (ui,_,crc) -> (ui,crc)) units_tolink)
+    );
   call_linker_shared (startup_obj :: objfiles) output_name;
   remove_file startup_obj
 
@@ -291,7 +289,8 @@ let call_linker file_list startup_file output_name =
   let files, c_lib =
     if (not !Clflags.output_c_object) || main_dll || main_obj_runtime then
       files @ (List.rev !Clflags.ccobjs) @ runtime_lib (),
-      (if !Clflags.nopervasives || main_obj_runtime then "" else Config.native_c_libraries)
+      (if !Clflags.nopervasives || main_obj_runtime
+       then "" else Config.native_c_libraries)
     else
       files, ""
   in
@@ -327,19 +326,17 @@ let link ppf objfiles output_name =
   Clflags.all_ccopts := !lib_ccopts @ !Clflags.all_ccopts;
                                                (* put user's opts first *)
   let startup =
-    if !Clflags.keep_startup_file then output_name ^ ".startup" ^ ext_asm
+    if !Clflags.keep_startup_file || !Emitaux.binary_backend_available
+    then output_name ^ ".startup" ^ ext_asm
     else Filename.temp_file "camlstartup" ext_asm in
-  make_startup_file ppf startup units_tolink;
   let startup_obj = Filename.temp_file "camlstartup" ext_obj in
-  if Proc.assemble_file startup startup_obj <> 0 then
-    raise(Error(Assembler_error startup));
-  try
-    call_linker (List.map object_file_name objfiles) startup_obj output_name;
-    if not !Clflags.keep_startup_file then remove_file startup;
-    remove_file startup_obj
-  with x ->
-    remove_file startup_obj;
-    raise x
+  Asmgen.compile_unit ~source_provenance:Timings.Startup output_name
+    startup !Clflags.keep_startup_file startup_obj
+    (fun () -> make_startup_file ppf units_tolink);
+  Misc.try_finally
+    (fun () ->
+      call_linker (List.map object_file_name objfiles) startup_obj output_name)
+    (fun () -> remove_file startup_obj)
 
 (* Error report *)
 
diff --git a/asmcomp/asmlink.mli b/asmcomp/asmlink.mli
index 60a2111e..55310bd9 100644
--- a/asmcomp/asmlink.mli
+++ b/asmcomp/asmlink.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Link a set of .cmx/.o files and produce an executable or a plugin *)
 
diff --git a/asmcomp/asmpackager.ml b/asmcomp/asmpackager.ml
index d900df1e..9ecebef8 100644
--- a/asmcomp/asmpackager.ml
+++ b/asmcomp/asmpackager.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2002 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2002 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* "Package" a set of .cmx/.o files into one .cmx/.o file having the
    original compilation units as sub-modules. *)
@@ -38,7 +41,7 @@ type pack_member =
 
 let read_member_info pack_path file = (
   let name =
-    String.capitalize(Filename.basename(chop_extensions file)) in
+    String.capitalize_ascii(Filename.basename(chop_extensions file)) in
   let kind =
     if Filename.check_suffix file ".cmx" then begin
       let (info, crc) = Compilenv.read_unit_info file in
@@ -75,7 +78,8 @@ let check_units members =
 
 (* Make the .o file for the package *)
 
-let make_package_object ppf members targetobj targetname coercion =
+let make_package_object ppf members targetobj targetname coercion
+      ~backend =
   let objtemp =
     if !Clflags.keep_asm_file
     then chop_extension_if_any targetobj ^ ".pack" ^ Config.ext_obj
@@ -91,10 +95,33 @@ let make_package_object ppf members targetobj targetname coercion =
         | PM_intf -> None
         | PM_impl _ -> Some(Ident.create_persistent m.pm_name))
       members in
-  Asmgen.compile_implementation
-    (chop_extension_if_any objtemp) ppf
-    (Translmod.transl_store_package
-       components (Ident.create_persistent targetname) coercion);
+  let module_ident = Ident.create_persistent targetname in
+  let source_provenance = Timings.Pack targetname in
+  let prefixname = chop_extension_if_any objtemp in
+  if Config.flambda then begin
+    let size, lam =
+      Translmod.transl_package_flambda
+        components module_ident coercion
+    in
+    let flam =
+      Middle_end.middle_end ppf
+        ~source_provenance
+        ~prefixname
+        ~backend
+        ~size
+        ~filename:targetname
+        ~module_ident
+        ~module_initializer:lam
+    in
+    Asmgen.compile_implementation_flambda ~source_provenance
+      prefixname ~backend ppf flam;
+  end else begin
+    let main_module_block_size, code =
+      Translmod.transl_store_package
+        components (Ident.create_persistent targetname) coercion in
+    Asmgen.compile_implementation_clambda ~source_provenance
+      prefixname ppf { Lambda.code; main_module_block_size; }
+  end;
   let objfiles =
     List.map
       (fun m -> chop_extension_if_any m.pm_file ^ Config.ext_obj)
@@ -107,6 +134,18 @@ let make_package_object ppf members targetobj targetname coercion =
 
 (* Make the .cmx file for the package *)
 
+let get_export_info ui =
+  assert(Config.flambda);
+  match ui.ui_export_info with
+  | Clambda _ -> assert false
+  | Flambda info -> info
+
+let get_approx ui =
+  assert(not Config.flambda);
+  match ui.ui_export_info with
+  | Flambda _ -> assert false
+  | Clambda info -> info
+
 let build_package_cmx members cmxfile =
   let unit_names =
     List.map (fun m -> m.pm_name) members in
@@ -122,7 +161,42 @@ let build_package_cmx members cmxfile =
       (fun m accu ->
         match m.pm_kind with PM_intf -> accu | PM_impl info -> info :: accu)
       members [] in
+  let pack_units =
+    List.fold_left
+      (fun set info ->
+         let unit_id = Compilenv.unit_id_from_name info.ui_name in
+         Compilation_unit.Set.add
+           (Compilenv.unit_for_global unit_id) set)
+      Compilation_unit.Set.empty units in
+  let units =
+    if Config.flambda then
+      List.map (fun info ->
+          { info with
+            ui_export_info =
+              Flambda
+                (Export_info_for_pack.import_for_pack ~pack_units
+                   ~pack:(Compilenv.current_unit ())
+                   (get_export_info info)) })
+        units
+    else
+      units
+  in
   let ui = Compilenv.current_unit_infos() in
+  let ui_export_info =
+    if Config.flambda then
+      let ui_export_info =
+        List.fold_left (fun acc info ->
+            Export_info.merge acc (get_export_info info))
+          (Export_info_for_pack.import_for_pack ~pack_units
+             ~pack:(Compilenv.current_unit ())
+             (get_export_info ui))
+          units
+      in
+      Flambda ui_export_info
+    else
+      Clambda (get_approx ui)
+  in
+  Export_info_for_pack.clear_import_state ();
   let pkg_infos =
     { ui_name = ui.ui_name;
       ui_symbol = ui.ui_symbol;
@@ -134,7 +208,6 @@ let build_package_cmx members cmxfile =
           filter(Asmlink.extract_crc_interfaces());
       ui_imports_cmx =
           filter(Asmlink.extract_crc_implementations());
-      ui_approx = ui.ui_approx;
       ui_curry_fun =
           union(List.map (fun info -> info.ui_curry_fun) units);
       ui_apply_fun =
@@ -143,25 +216,26 @@ let build_package_cmx members cmxfile =
           union(List.map (fun info -> info.ui_send_fun) units);
       ui_force_link =
           List.exists (fun info -> info.ui_force_link) units;
+      ui_export_info;
     } in
   Compilenv.write_unit_info pkg_infos cmxfile
 
 (* Make the .cmx and the .o for the package *)
 
 let package_object_files ppf files targetcmx
-                         targetobj targetname coercion =
+                         targetobj targetname coercion ~backend =
   let pack_path =
     match !Clflags.for_package with
     | None -> targetname
     | Some p -> p ^ "." ^ targetname in
   let members = map_left_right (read_member_info pack_path) files in
   check_units members;
-  make_package_object ppf members targetobj targetname coercion;
+  make_package_object ppf members targetobj targetname coercion ~backend;
   build_package_cmx members targetcmx
 
 (* The entry point *)
 
-let package_files ppf initial_env files targetcmx =
+let package_files ppf initial_env files targetcmx ~backend =
   let files =
     List.map
       (fun f ->
@@ -171,15 +245,17 @@ let package_files ppf initial_env files targetcmx =
   let prefix = chop_extensions targetcmx in
   let targetcmi = prefix ^ ".cmi" in
   let targetobj = chop_extension_if_any targetcmx ^ Config.ext_obj in
-  let targetname = String.capitalize(Filename.basename prefix) in
+  let targetname = String.capitalize_ascii(Filename.basename prefix) in
   (* Set the name of the current "input" *)
   Location.input_name := targetcmx;
   (* Set the name of the current compunit *)
-  Compilenv.reset ?packname:!Clflags.for_package targetname;
+  Compilenv.reset ~source_provenance:(Timings.Pack targetname)
+    ?packname:!Clflags.for_package targetname;
   try
     let coercion =
       Typemod.package_units initial_env files targetcmi targetname in
     package_object_files ppf files targetcmx targetobj targetname coercion
+      ~backend
   with x ->
     remove_file targetcmx; remove_file targetobj;
     raise x
diff --git a/asmcomp/asmpackager.mli b/asmcomp/asmpackager.mli
index 4d47f5c2..203fc301 100644
--- a/asmcomp/asmpackager.mli
+++ b/asmcomp/asmpackager.mli
@@ -1,19 +1,28 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2002 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2002 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* "Package" a set of .cmx/.o files into one .cmx/.o file having the
    original compilation units as sub-modules. *)
 
-val package_files: Format.formatter -> Env.t -> string list -> string -> unit
+val package_files
+   : Format.formatter
+  -> Env.t
+  -> string list
+  -> string
+  -> backend:(module Backend_intf.S)
+  -> unit
 
 type error =
     Illegal_renaming of string * string * string
diff --git a/asmcomp/branch_relaxation.ml b/asmcomp/branch_relaxation.ml
index d4609e4a..4ef09865 100644
--- a/asmcomp/branch_relaxation.ml
+++ b/asmcomp/branch_relaxation.ml
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                   Mark Shinwell, Jane Street Europe                 *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                    Mark Shinwell, Jane Street Europe                   *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Mach
 open Linearize
diff --git a/asmcomp/branch_relaxation.mli b/asmcomp/branch_relaxation.mli
index e2a93f83..170f306d 100644
--- a/asmcomp/branch_relaxation.mli
+++ b/asmcomp/branch_relaxation.mli
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                   Mark Shinwell, Jane Street Europe                 *)
-(*                                                                     *)
-(*  Copyright 2015 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                    Mark Shinwell, Jane Street Europe                   *)
+(*                                                                        *)
+(*   Copyright 2015 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Fix up conditional branches that exceed hardware-allowed ranges. *)
 
diff --git a/asmcomp/branch_relaxation_intf.ml b/asmcomp/branch_relaxation_intf.ml
index 0812c7c1..0bfab4f7 100644
--- a/asmcomp/branch_relaxation_intf.ml
+++ b/asmcomp/branch_relaxation_intf.ml
@@ -1,15 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                   Mark Shinwell, Jane Street Europe                 *)
-(*                                                                     *)
-(*  Copyright 2015 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                    Mark Shinwell, Jane Street Europe                   *)
+(*                                                                        *)
+(*   Copyright 2015 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 module type S = sig
   (* The distance between two instructions, in arbitrary units (typically
diff --git a/asmcomp/build_export_info.ml b/asmcomp/build_export_info.ml
new file mode 100644
index 00000000..99d47039
--- /dev/null
+++ b/asmcomp/build_export_info.ml
@@ -0,0 +1,551 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+module Env : sig
+  type t
+
+  val new_descr : t -> Export_info.descr -> Export_id.t
+  val record_descr : t -> Export_id.t -> Export_info.descr -> unit
+  val get_descr : t -> Export_info.approx -> Export_info.descr option
+
+  val add_approx : t -> Variable.t -> Export_info.approx -> t
+  val add_approx_maps : t -> Export_info.approx Variable.Map.t list -> t
+  val find_approx : t -> Variable.t -> Export_info.approx
+
+  val get_symbol_descr : t -> Symbol.t -> Export_info.descr option
+
+  val new_unit_descr : t -> Export_id.t
+
+  module Global : sig
+    (* "Global" as in "without local variable bindings". *)
+    type t
+
+    val create_empty : unit -> t
+
+    val add_symbol : t -> Symbol.t -> Export_id.t -> t
+    val new_symbol : t -> Symbol.t -> Export_id.t * t
+
+    val symbol_to_export_id_map : t -> Export_id.t Symbol.Map.t
+    val export_id_to_descr_map : t -> Export_info.descr Export_id.Map.t
+  end
+
+  (** Creates a new environment, sharing the mapping from export IDs to
+      export descriptions with the given global environment. *)
+  val empty_of_global : Global.t -> t
+end = struct
+  let fresh_id () = Export_id.create (Compilenv.current_unit ())
+
+  module Global = struct
+    type t =
+      { sym : Export_id.t Symbol.Map.t;
+        (* Note that [ex_table]s themselves are shared (hence [ref] and not
+           [mutable]). *)
+        ex_table : Export_info.descr Export_id.Map.t ref;
+      }
+
+    let create_empty () =
+      { sym = Symbol.Map.empty;
+        ex_table = ref Export_id.Map.empty;
+      }
+
+    let add_symbol t sym export_id =
+      if Symbol.Map.mem sym t.sym then begin
+        Misc.fatal_errorf "Build_export_info.Env.Global.add_symbol: cannot \
+            rebind symbol %a in environment"
+          Symbol.print sym
+      end;
+      { t with sym = Symbol.Map.add sym export_id t.sym }
+
+    let new_symbol t sym =
+      let export_id = fresh_id () in
+      export_id, add_symbol t sym export_id
+
+    let symbol_to_export_id_map t = t.sym
+    let export_id_to_descr_map t = !(t.ex_table)
+  end
+
+  (* CR-someday mshinwell: The half-mutable nature of [t] with sharing of
+     the [ex_table] is kind of nasty.  Consider making it immutable. *)
+  type t =
+    { var : Export_info.approx Variable.Map.t;
+      sym : Export_id.t Symbol.Map.t;
+      ex_table : Export_info.descr Export_id.Map.t ref;
+    }
+
+  let empty_of_global (env : Global.t) =
+    { var = Variable.Map.empty;
+      sym = env.sym;
+      ex_table = env.ex_table;
+    }
+
+  let extern_id_descr export_id =
+    let export = Compilenv.approx_env () in
+    try Some (Export_info.find_description export export_id)
+    with Not_found -> None
+
+  let extern_symbol_descr sym =
+    if Compilenv.is_predefined_exception sym
+    then None
+    else
+      let export = Compilenv.approx_for_global (Symbol.compilation_unit sym) in
+      try
+        let id = Symbol.Map.find sym export.symbol_id in
+        let descr = Export_info.find_description export id in
+        Some descr
+      with
+      | Not_found -> None
+
+  let get_id_descr t export_id =
+    try Some (Export_id.Map.find export_id !(t.ex_table))
+    with Not_found -> extern_id_descr export_id
+
+  let get_symbol_descr t sym =
+    try
+      let export_id = Symbol.Map.find sym t.sym in
+      Some (Export_id.Map.find export_id !(t.ex_table))
+    with
+    | Not_found -> extern_symbol_descr sym
+
+  let get_descr t (approx : Export_info.approx) =
+    match approx with
+    | Value_unknown -> None
+    | Value_id export_id -> get_id_descr t export_id
+    | Value_symbol sym -> get_symbol_descr t sym
+
+  let record_descr t id (descr : Export_info.descr) =
+    if Export_id.Map.mem id !(t.ex_table) then begin
+      Misc.fatal_errorf "Build_export_info.Env.record_descr: cannot rebind \
+          export ID %a in environment"
+        Export_id.print id
+    end;
+    t.ex_table := Export_id.Map.add id descr !(t.ex_table)
+
+  let new_descr t (descr : Export_info.descr) =
+    let id = fresh_id () in
+    record_descr t id descr;
+    id
+
+  let new_unit_descr t =
+    new_descr t (Value_constptr 0)
+
+  let add_approx t var approx =
+    if Variable.Map.mem var t.var then begin
+      Misc.fatal_errorf "Build_export_info.Env.add_approx: cannot rebind \
+          variable %a in environment"
+        Variable.print var
+    end;
+    { t with var = Variable.Map.add var approx t.var; }
+
+  let add_approx_map t vars_to_approxs =
+    Variable.Map.fold (fun var approx t -> add_approx t var approx)
+      vars_to_approxs
+      t
+
+  let add_approx_maps t vars_to_approxs_list =
+    List.fold_left add_approx_map t vars_to_approxs_list
+
+  let find_approx t var : Export_info.approx =
+    try Variable.Map.find var t.var with
+    | Not_found -> Value_unknown
+end
+
+let descr_of_constant (c : Flambda.const) : Export_info.descr =
+  match c with
+  (* [Const_pointer] is an immediate value of a type whose values may be
+     boxed (typically a variant type with both constant and non-constant
+     constructors). *)
+  | Int i -> Value_int i
+  | Char c -> Value_char c
+  | Const_pointer i -> Value_constptr i
+
+let descr_of_allocated_constant (c : Allocated_const.t) : Export_info.descr =
+  match c with
+  | Float f -> Value_float f
+  | Int32 i -> Value_boxed_int (Int32, i)
+  | Int64 i -> Value_boxed_int (Int64, i)
+  | Nativeint i -> Value_boxed_int (Nativeint, i)
+  | String s ->
+    let v_string : Export_info.value_string =
+      { size = String.length s; contents = Unknown_or_mutable; }
+    in
+    Value_string v_string
+  | Immutable_string s ->
+    let v_string : Export_info.value_string =
+      { size = String.length s; contents = Contents s; }
+    in
+    Value_string v_string
+  | Immutable_float_array fs ->
+    Value_float_array {
+      contents = Contents (Array.map (fun x -> Some x) (Array.of_list fs));
+      size = List.length fs;
+    }
+  | Float_array fs ->
+    Value_float_array {
+      contents = Unknown_or_mutable;
+      size = List.length fs;
+    }
+
+let rec approx_of_expr (env : Env.t) (flam : Flambda.t) : Export_info.approx =
+  match flam with
+  | Var var -> Env.find_approx env var
+  | Let { var; defining_expr; body; _ } ->
+    let approx = descr_of_named env defining_expr in
+    let env = Env.add_approx env var approx in
+    approx_of_expr env body
+  | Let_mutable (_mut_var, _var, body) ->
+    approx_of_expr env body
+  | Let_rec (defs, body) ->
+    let env =
+      List.fold_left (fun env (var, defining_expr) ->
+          let approx = descr_of_named env defining_expr in
+          Env.add_approx env var approx)
+        env defs
+    in
+    approx_of_expr env body
+  | Apply { func; kind; _ } ->
+    begin match kind with
+    | Indirect -> Value_unknown
+    | Direct closure_id' ->
+      match Env.get_descr env (Env.find_approx env func) with
+      | Some (Value_closure
+          { closure_id; set_of_closures = { results; _ }; }) ->
+        assert (Closure_id.equal closure_id closure_id');
+        assert (Closure_id.Map.mem closure_id results);
+        Closure_id.Map.find closure_id results
+      | _ -> Value_unknown
+    end
+  | Assign _ -> Value_id (Env.new_unit_descr env)
+  | For _ -> Value_id (Env.new_unit_descr env)
+  | While _ -> Value_id (Env.new_unit_descr env)
+  | Static_raise _ | Static_catch _ | Try_with _ | If_then_else _
+  | Switch _ | String_switch _ | Send _ | Proved_unreachable ->
+    Value_unknown
+
+and descr_of_named (env : Env.t) (named : Flambda.named)
+      : Export_info.approx =
+  match named with
+  | Expr expr -> approx_of_expr env expr
+  | Symbol sym -> Value_symbol sym
+  | Read_mutable _ -> Value_unknown
+  | Read_symbol_field (sym, i) ->
+    begin match Env.get_symbol_descr env sym with
+    | Some (Value_block (_, fields)) when Array.length fields > i -> fields.(i)
+    | _ -> Value_unknown
+    end
+  | Const const ->
+    Value_id (Env.new_descr env (descr_of_constant const))
+  | Allocated_const const ->
+    Value_id (Env.new_descr env (descr_of_allocated_constant const))
+  | Prim (Pmakeblock (tag, Immutable), args, _dbg) ->
+    let approxs = List.map (Env.find_approx env) args in
+    let descr : Export_info.descr =
+      Value_block (Tag.create_exn tag, Array.of_list approxs)
+    in
+    Value_id (Env.new_descr env descr)
+  | Prim (Pfield i, [arg], _) ->
+    begin match Env.get_descr env (Env.find_approx env arg) with
+    | Some (Value_block (_, fields)) when Array.length fields > i -> fields.(i)
+    | _ -> Value_unknown
+    end
+  | Prim (Pgetglobal id, _, _) ->
+    Value_symbol (Compilenv.symbol_for_global' id)
+  | Prim _ -> Value_unknown
+  | Set_of_closures set ->
+    let descr : Export_info.descr =
+      Value_set_of_closures (describe_set_of_closures env set)
+    in
+    Value_id (Env.new_descr env descr)
+  | Project_closure { set_of_closures; closure_id; } ->
+    begin match Env.get_descr env (Env.find_approx env set_of_closures) with
+    | Some (Value_set_of_closures set_of_closures) ->
+      if not (Closure_id.Map.mem closure_id set_of_closures.results) then begin
+        Misc.fatal_errorf "Could not build export description for \
+            [Project_closure]: closure ID %a not in set of closures"
+          Closure_id.print closure_id
+      end;
+      let descr : Export_info.descr =
+        Value_closure { closure_id = closure_id; set_of_closures; }
+      in
+      Value_id (Env.new_descr env descr)
+    | _ ->
+      (* It would be nice if this were [assert false], but owing to the fact
+         that this pass may propagate less information than for example
+         [Inline_and_simplify], we might end up here. *)
+      Value_unknown
+    end
+  | Move_within_set_of_closures { closure; start_from; move_to; } ->
+    begin match Env.get_descr env (Env.find_approx env closure) with
+    | Some (Value_closure { set_of_closures; closure_id; }) ->
+      assert (Closure_id.equal closure_id start_from);
+      let descr : Export_info.descr =
+        Value_closure { closure_id = move_to; set_of_closures; }
+      in
+      Value_id (Env.new_descr env descr)
+    | _ -> Value_unknown
+    end
+  | Project_var { closure; closure_id = closure_id'; var; } ->
+    begin match Env.get_descr env (Env.find_approx env closure) with
+    | Some (Value_closure
+        { set_of_closures = { bound_vars; _ }; closure_id; }) ->
+      assert (Closure_id.equal closure_id closure_id');
+      if not (Var_within_closure.Map.mem var bound_vars) then begin
+        Misc.fatal_errorf "Project_var from %a (closure ID %a) of \
+            variable %a that is not bound by the closure.  \
+            Variables bound by the closure are: %a"
+          Variable.print closure
+          Closure_id.print closure_id
+          Var_within_closure.print var
+          (Var_within_closure.Map.print (fun _ _ -> ())) bound_vars
+      end;
+      Var_within_closure.Map.find var bound_vars
+    | _ -> Value_unknown
+    end
+
+and describe_set_of_closures env (set : Flambda.set_of_closures)
+      : Export_info.value_set_of_closures =
+  let bound_vars_approx =
+    Variable.Map.map (fun (external_var : Flambda.specialised_to) ->
+        Env.find_approx env external_var.var)
+      set.free_vars
+  in
+  let specialised_args_approx =
+    Variable.Map.map (fun (spec_to : Flambda.specialised_to) ->
+        Env.find_approx env spec_to.var)
+      set.specialised_args
+  in
+  let closures_approx =
+    (* To build an approximation of the results, we need an
+       approximation of the functions. The first one we can build is
+       one where every function returns something unknown.
+    *)
+    (* CR-someday pchambart: we could improve a bit on that by building a
+       recursive approximation of the closures: The value_closure
+       description contains a [value_set_of_closures]. We could replace
+       this field by a [Expr_id.t] or an [approx].
+       mshinwell: Deferred for now.
+    *)
+    let initial_value_set_of_closures =
+      { Export_info.
+        set_of_closures_id = set.function_decls.set_of_closures_id;
+        bound_vars = Var_within_closure.wrap_map bound_vars_approx;
+        results =
+          Closure_id.wrap_map
+            (Variable.Map.map (fun _ -> Export_info.Value_unknown)
+              set.function_decls.funs);
+        aliased_symbol = None;
+      }
+    in
+    Variable.Map.mapi (fun fun_var _function_decl ->
+        let descr : Export_info.descr =
+          Value_closure
+            { closure_id = Closure_id.wrap fun_var;
+              set_of_closures = initial_value_set_of_closures;
+            }
+        in
+        Export_info.Value_id (Env.new_descr env descr))
+      set.function_decls.funs
+  in
+  let closure_env =
+    Env.add_approx_maps env
+      [closures_approx; bound_vars_approx; specialised_args_approx]
+  in
+  let results =
+    let result_approx _var (function_decl : Flambda.function_declaration) =
+      approx_of_expr closure_env function_decl.body
+    in
+    Variable.Map.mapi result_approx set.function_decls.funs
+  in
+  { set_of_closures_id = set.function_decls.set_of_closures_id;
+    bound_vars = Var_within_closure.wrap_map bound_vars_approx;
+    results = Closure_id.wrap_map results;
+    aliased_symbol = None;
+  }
+
+let approx_of_constant_defining_value_block_field env
+      (c : Flambda.constant_defining_value_block_field) : Export_info.approx =
+  match c with
+  | Symbol s -> Value_symbol s
+  | Const c -> Value_id (Env.new_descr env (descr_of_constant c))
+
+let describe_constant_defining_value env export_id symbol
+      (const : Flambda.constant_defining_value) =
+  let env =
+    (* Assignments of variables to export IDs are local to each constant
+       defining value. *)
+    Env.empty_of_global env
+  in
+  match const with
+  | Allocated_const alloc_const ->
+    let descr = descr_of_allocated_constant alloc_const in
+    Env.record_descr env export_id descr
+  | Block (tag, fields) ->
+    let approxs =
+      List.map (approx_of_constant_defining_value_block_field env) fields
+    in
+    Env.record_descr env export_id (Value_block (tag, Array.of_list approxs))
+  | Set_of_closures set_of_closures ->
+    let descr : Export_info.descr =
+      Value_set_of_closures
+        { (describe_set_of_closures env set_of_closures) with
+          aliased_symbol = Some symbol;
+        }
+    in
+    Env.record_descr env export_id descr
+  | Project_closure (sym, closure_id) ->
+    begin match Env.get_symbol_descr env sym with
+    | Some (Value_set_of_closures set_of_closures) ->
+      if not (Closure_id.Map.mem closure_id set_of_closures.results) then begin
+        Misc.fatal_errorf "Could not build export description for \
+            [Project_closure] constant defining value: closure ID %a not in \
+            set of closures"
+          Closure_id.print closure_id
+      end;
+      let descr =
+        Export_info.Value_closure
+          { closure_id = closure_id; set_of_closures; }
+      in
+      Env.record_descr env export_id descr
+    | None ->
+      Misc.fatal_errorf
+        "Cannot project symbol %a to closure_id %a.  \
+          No available export description@."
+        Symbol.print sym
+        Closure_id.print closure_id
+    | Some (Value_closure _) ->
+      Misc.fatal_errorf
+        "Cannot project symbol %a to closure_id %a.  \
+          The symbol is a closure instead of a set of closures.@."
+        Symbol.print sym
+        Closure_id.print closure_id
+    | Some _ ->
+      Misc.fatal_errorf
+        "Cannot project symbol %a to closure_id %a.  \
+          The symbol is not a set of closures.@."
+        Symbol.print sym
+        Closure_id.print closure_id
+    end
+
+let describe_program (env : Env.Global.t) (program : Flambda.program) =
+  let rec loop env (program : Flambda.program_body) =
+    match program with
+    | Let_symbol (symbol, constant_defining_value, program) ->
+      let id, env = Env.Global.new_symbol env symbol in
+      describe_constant_defining_value env id symbol constant_defining_value;
+      loop env program
+    | Let_rec_symbol (defs, program) ->
+      let env, defs =
+        List.fold_left (fun (env, defs) (symbol, def) ->
+            let id, env = Env.Global.new_symbol env symbol in
+            env, ((id, symbol, def) :: defs))
+          (env, []) defs
+      in
+      (* [Project_closure]s are separated to be handled last.  They are the
+         only values that need a description for their argument. *)
+      let project_closures, other_constants =
+        List.partition (function
+            | _, _, Flambda.Project_closure _ -> true
+            | _ -> false)
+          defs
+      in
+      List.iter (fun (id, symbol, def) ->
+          describe_constant_defining_value env id symbol def)
+        other_constants;
+      List.iter (fun (id, symbol, def) ->
+          describe_constant_defining_value env id symbol def)
+        project_closures;
+      loop env program
+    | Initialize_symbol (symbol, tag, fields, program) ->
+      let id =
+        let env =
+          (* Assignments of variables to export IDs are local to each
+             [Initialize_symbol] construction. *)
+          Env.empty_of_global env
+        in
+        let field_approxs = List.map (approx_of_expr env) fields in
+        let descr : Export_info.descr =
+          Value_block (tag, Array.of_list field_approxs)
+        in
+        Env.new_descr env descr
+      in
+      let env = Env.Global.add_symbol env symbol id in
+      loop env program
+    | Effect (_expr, program) -> loop env program
+    | End symbol -> symbol, env
+  in
+  loop env program.program_body
+
+let build_export_info ~(backend : (module Backend_intf.S))
+      (program : Flambda.program) : Export_info.t =
+  if !Clflags.opaque then
+    Export_info.empty
+  else
+    (* CR-soon pchambart: Should probably use that instead of the ident of
+       the module as global identifier.
+       mshinwell: Is "that" the variable "_global_symbol"?
+       Yes it is.  We are just assuming that the symbol produced from
+       the identifier of the module is the right one. *)
+    let _global_symbol, env =
+      describe_program (Env.Global.create_empty ()) program
+    in
+    let sets_of_closures =
+      Flambda_utils.all_function_decls_indexed_by_set_of_closures_id program
+    in
+    let closures =
+      Flambda_utils.all_function_decls_indexed_by_closure_id program
+    in
+    let invariant_params =
+      Set_of_closures_id.Map.map
+        (fun { Flambda. function_decls; _ } ->
+           Invariant_params.invariant_params_in_recursion
+             ~backend function_decls)
+        (Flambda_utils.all_sets_of_closures_map program)
+    in
+    let unnested_values =
+      Env.Global.export_id_to_descr_map env
+    in
+    let invariant_params =
+      let export = Compilenv.approx_env () in
+      Export_id.Map.fold (fun _eid (descr:Export_info.descr)
+                           (invariant_params) ->
+          match descr with
+          | Value_closure { set_of_closures }
+          | Value_set_of_closures set_of_closures ->
+            let { Export_info.set_of_closures_id } = set_of_closures in
+            begin match
+              Set_of_closures_id.Map.find set_of_closures_id
+                export.invariant_params
+            with
+            | exception Not_found ->
+              invariant_params
+            | (set:Variable.Set.t Variable.Map.t) ->
+              Set_of_closures_id.Map.add set_of_closures_id set invariant_params
+            end
+          | _ ->
+            invariant_params)
+        unnested_values invariant_params
+    in
+    let values =
+      Export_info.nest_eid_map unnested_values
+    in
+    Export_info.create ~values
+      ~symbol_id:(Env.Global.symbol_to_export_id_map env)
+      ~offset_fun:Closure_id.Map.empty
+      ~offset_fv:Var_within_closure.Map.empty
+      ~sets_of_closures ~closures
+      ~constant_sets_of_closures:Set_of_closures_id.Set.empty
+      ~invariant_params
diff --git a/asmcomp/build_export_info.mli b/asmcomp/build_export_info.mli
new file mode 100644
index 00000000..2a824ea3
--- /dev/null
+++ b/asmcomp/build_export_info.mli
@@ -0,0 +1,25 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+(** Construct export information, for emission into .cmx files, from an
+    Flambda program. *)
+
+val build_export_info :
+  backend:(module Backend_intf.S) ->
+  Flambda.program ->
+  Export_info.t
diff --git a/asmcomp/clambda.ml b/asmcomp/clambda.ml
index ed96f218..673bf8c8 100644
--- a/asmcomp/clambda.ml
+++ b/asmcomp/clambda.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* A variant of the "lambda" code with direct / indirect calls explicit
    and closures explicit too *)
@@ -26,13 +29,14 @@ type ustructured_constant =
   | Uconst_block of int * uconstant list
   | Uconst_float_array of float list
   | Uconst_string of string
+  | Uconst_closure of ufunction list * string * uconstant list
 
 and uconstant =
-  | Uconst_ref of string * ustructured_constant
+  | Uconst_ref of string * ustructured_constant option
   | Uconst_int of int
   | Uconst_ptr of int
 
-type ulambda =
+and ulambda =
     Uvar of Ident.t
   | Uconst of uconstant
   | Udirect_apply of function_label * ulambda list * Debuginfo.t
@@ -53,6 +57,7 @@ type ulambda =
   | Ufor of Ident.t * ulambda * ulambda * direction_flag * ulambda
   | Uassign of Ident.t * ulambda
   | Usend of meth_kind * ulambda * ulambda * ulambda list * Debuginfo.t
+  | Uunreachable
 
 and ufunction = {
   label  : function_label;
@@ -87,6 +92,21 @@ type value_approximation =
   | Value_const of uconstant
   | Value_global_field of string * int
 
+(* Preallocated globals *)
+
+type preallocated_block = {
+  symbol : string;
+  exported : bool;
+  tag : int;
+  size : int;
+}
+
+type preallocated_constant = {
+  symbol : string;
+  exported : bool;
+  definition : ustructured_constant;
+}
+
 (* Comparison functions for constants.  We must not use Pervasives.compare
    because it compares "0.0" and "-0.0" equal.  (PR#6442) *)
 
@@ -133,6 +153,7 @@ let rank_structured_constant = function
   | Uconst_block _ -> 4
   | Uconst_float_array _ -> 5
   | Uconst_string _ -> 6
+  | Uconst_closure _ -> 7
 
 let compare_structured_constants c1 c2 =
   match c1, c2 with
@@ -140,11 +161,14 @@ let compare_structured_constants c1 c2 =
   | Uconst_int32 x1, Uconst_int32 x2 -> Int32.compare x1 x2
   | Uconst_int64 x1, Uconst_int64 x2 -> Int64.compare x1 x2
   | Uconst_nativeint x1, Uconst_nativeint x2 -> Nativeint.compare x1 x2
-  | Uconst_block(t1, l1), Uconst_block(t2, l2) -> 
+  | Uconst_block(t1, l1), Uconst_block(t2, l2) ->
       let c = t1 - t2 (* no overflow possible here *) in
       if c <> 0 then c else compare_constant_lists l1 l2
   | Uconst_float_array l1, Uconst_float_array l2 ->
       compare_float_lists l1 l2
   | Uconst_string s1, Uconst_string s2 -> String.compare s1 s2
-  | _, _ -> rank_structured_constant c1 - rank_structured_constant c2
-                (* no overflow possible here *)
+  | Uconst_closure (_,lbl1,_), Uconst_closure (_,lbl2,_) ->
+      String.compare lbl1 lbl2
+  | _, _ ->
+    (* no overflow possible here *)
+    rank_structured_constant c1 - rank_structured_constant c2
diff --git a/asmcomp/clambda.mli b/asmcomp/clambda.mli
index fc7a14d1..f506c7b3 100644
--- a/asmcomp/clambda.mli
+++ b/asmcomp/clambda.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* A variant of the "lambda" code with direct / indirect calls explicit
    and closures explicit too *)
@@ -26,13 +29,14 @@ type ustructured_constant =
   | Uconst_block of int * uconstant list
   | Uconst_float_array of float list
   | Uconst_string of string
+  | Uconst_closure of ufunction list * string * uconstant list
 
 and uconstant =
-  | Uconst_ref of string * ustructured_constant
+  | Uconst_ref of string * ustructured_constant option
   | Uconst_int of int
   | Uconst_ptr of int
 
-type ulambda =
+and ulambda =
     Uvar of Ident.t
   | Uconst of uconstant
   | Udirect_apply of function_label * ulambda list * Debuginfo.t
@@ -53,6 +57,7 @@ type ulambda =
   | Ufor of Ident.t * ulambda * ulambda * direction_flag * ulambda
   | Uassign of Ident.t * ulambda
   | Usend of meth_kind * ulambda * ulambda * ulambda list * Debuginfo.t
+  | Uunreachable
 
 and ufunction = {
   label  : function_label;
@@ -93,3 +98,16 @@ val compare_structured_constants:
         ustructured_constant -> ustructured_constant -> int
 val compare_constants:
         uconstant -> uconstant -> int
+
+type preallocated_block = {
+  symbol : string;
+  exported : bool;
+  tag : int;
+  size : int;
+}
+
+type preallocated_constant = {
+  symbol : string;
+  exported : bool;
+  definition : ustructured_constant;
+}
diff --git a/asmcomp/closure.ml b/asmcomp/closure.ml
index 249e67c4..d06e4c6f 100644
--- a/asmcomp/closure.ml
+++ b/asmcomp/closure.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Introduction of closures, uncurrying, recognition of direct calls *)
 
@@ -83,6 +86,7 @@ let occurs_var var u =
     | Uassign(id, u) -> id = var || occurs u
     | Usend(_, met, obj, args, _) ->
         occurs met || occurs obj || List.exists occurs args
+    | Uunreachable -> false
   and occurs_array a =
     try
       for i = 0 to Array.length a - 1 do
@@ -93,52 +97,6 @@ let occurs_var var u =
       true
   in occurs u
 
-(* Split a function with default parameters into a wrapper and an
-   inner function.  The wrapper fills in missing optional parameters
-   with their default value and tail-calls the inner function.  The
-   wrapper can then hopefully be inlined on most call sites to avoid
-   the overhead associated with boxing an optional argument with a
-   'Some' constructor, only to deconstruct it immediately in the
-   function's body. *)
-
-let split_default_wrapper fun_id kind params body =
-  let rec aux map = function
-    | Llet(Strict, id, (Lifthenelse(Lvar optparam, _, _) as def), rest) when
-        Ident.name optparam = "*opt*" && List.mem optparam params
-          && not (List.mem_assoc optparam map)
-      ->
-        let wrapper_body, inner = aux ((optparam, id) :: map) rest in
-        Llet(Strict, id, def, wrapper_body), inner
-    | _ when map = [] -> raise Exit
-    | body ->
-        (* Check that those *opt* identifiers don't appear in the remaining
-           body. This should not appear, but let's be on the safe side. *)
-        let fv = Lambda.free_variables body in
-        List.iter (fun (id, _) -> if IdentSet.mem id fv then raise Exit) map;
-
-        let inner_id = Ident.create (Ident.name fun_id ^ "_inner") in
-        let map_param p = try List.assoc p map with Not_found -> p in
-        let args = List.map (fun p -> Lvar (map_param p)) params in
-        let wrapper_body = Lapply (Lvar inner_id, args, Location.none) in
-
-        let inner_params = List.map map_param params in
-        let new_ids = List.map Ident.rename inner_params in
-        let subst = List.fold_left2
-            (fun s id new_id ->
-               Ident.add id (Lvar new_id) s)
-            Ident.empty inner_params new_ids
-        in
-        let body = Lambda.subst_lambda subst body in
-        let inner_fun = Lfunction(Curried, new_ids, body) in
-        (wrapper_body, (inner_id, inner_fun))
-  in
-  try
-    let wrapper_body, inner = aux [] body in
-    [(fun_id, Lfunction(kind, params, wrapper_body)); inner]
-  with Exit ->
-    [(fun_id, Lfunction(kind, params, body))]
-
-
 (* Determine whether the estimated size of a clambda term is below
    some threshold *)
 
@@ -149,15 +107,22 @@ let prim_size prim args =
   | Psetglobal id -> 1
   | Pmakeblock(tag, mut) -> 5 + List.length args
   | Pfield f -> 1
-  | Psetfield(f, isptr) -> if isptr then 4 else 1
+  | Psetfield(f, isptr, init) ->
+    begin match init with
+    | Initialization -> 1  (* never causes a write barrier hit *)
+    | Assignment ->
+      match isptr with
+      | Pointer -> 4
+      | Immediate -> 1
+    end
   | Pfloatfield f -> 1
-  | Psetfloatfield f -> 1
+  | Psetfloatfield (f, _) -> 1
   | Pduprecord _ -> 10 + List.length args
   | Pccall p -> (if p.prim_alloc then 10 else 4) + List.length args
   | Praise _ -> 4
   | Pstringlength -> 5
   | Pstringrefs | Pstringsets -> 6
-  | Pmakearray kind -> 5 + List.length args
+  | Pmakearray _ -> 5 + List.length args
   | Parraylength kind -> if kind = Pgenarray then 6 else 2
   | Parrayrefu kind -> if kind = Pgenarray then 12 else 2
   | Parraysetu kind -> if kind = Pgenarray then 16 else 4
@@ -226,6 +191,7 @@ let lambda_smaller lam threshold =
     | Usend(_, met, obj, args, _) ->
         size := !size + 8;
         lambda_size met; lambda_size obj; lambda_list_size args
+    | Uunreachable -> ()
   and lambda_list_size l = List.iter lambda_size l
   and lambda_array_size a = Array.iter lambda_size a in
   try
@@ -249,7 +215,8 @@ let rec is_pure_clambda = function
 
 let make_const c = (Uconst c, Value_const c)
 let make_const_ref c =
-  make_const(Uconst_ref(Compilenv.new_structured_constant ~shared:true c, c))
+  make_const(Uconst_ref(Compilenv.new_structured_constant ~shared:true c,
+    Some c))
 let make_const_int n = make_const (Uconst_int n)
 let make_const_ptr n = make_const (Uconst_ptr n)
 let make_const_bool b = make_const_ptr(if b then 1 else 0)
@@ -311,7 +278,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* float *)
-  | [Value_const(Uconst_ref(_, Uconst_float n1))] when fpc ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_float n1)))] when fpc ->
       begin match p with
       | Pintoffloat -> make_const_int (int_of_float n1)
       | Pnegfloat -> make_const_float (-. n1)
@@ -319,8 +286,8 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* float, float *)
-  | [Value_const(Uconst_ref(_, Uconst_float n1));
-     Value_const(Uconst_ref(_, Uconst_float n2))] when fpc ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_float n1)));
+     Value_const(Uconst_ref(_, Some (Uconst_float n2)))] when fpc ->
       begin match p with
       | Paddfloat -> make_const_float (n1 +. n2)
       | Psubfloat -> make_const_float (n1 -. n2)
@@ -330,7 +297,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* nativeint *)
-  | [Value_const(Uconst_ref(_, Uconst_nativeint n))] ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_nativeint n)))] ->
       begin match p with
       | Pintofbint Pnativeint -> make_const_int (Nativeint.to_int n)
       | Pcvtbint(Pnativeint, Pint32) -> make_const_int32 (Nativeint.to_int32 n)
@@ -339,8 +306,8 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* nativeint, nativeint *)
-  | [Value_const(Uconst_ref(_, Uconst_nativeint n1));
-     Value_const(Uconst_ref(_, Uconst_nativeint n2))] ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_nativeint n1)));
+     Value_const(Uconst_ref(_, Some (Uconst_nativeint n2)))] ->
       begin match p with
       | Paddbint Pnativeint -> make_const_natint (Nativeint.add n1 n2)
       | Psubbint Pnativeint -> make_const_natint (Nativeint.sub n1 n2)
@@ -356,7 +323,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* nativeint, int *)
-  | [Value_const(Uconst_ref(_, Uconst_nativeint n1));
+  | [Value_const(Uconst_ref(_, Some (Uconst_nativeint n1)));
      Value_const(Uconst_int n2)] ->
       begin match p with
       | Plslbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
@@ -368,7 +335,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* int32 *)
-  | [Value_const(Uconst_ref(_, Uconst_int32 n))] ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_int32 n)))] ->
       begin match p with
       | Pintofbint Pint32 -> make_const_int (Int32.to_int n)
       | Pcvtbint(Pint32, Pnativeint) -> make_const_natint (Nativeint.of_int32 n)
@@ -377,8 +344,8 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* int32, int32 *)
-  | [Value_const(Uconst_ref(_, Uconst_int32 n1));
-     Value_const(Uconst_ref(_, Uconst_int32 n2))] ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_int32 n1)));
+     Value_const(Uconst_ref(_, Some (Uconst_int32 n2)))] ->
       begin match p with
       | Paddbint Pint32 -> make_const_int32 (Int32.add n1 n2)
       | Psubbint Pint32 -> make_const_int32 (Int32.sub n1 n2)
@@ -392,7 +359,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* int32, int *)
-  | [Value_const(Uconst_ref(_, Uconst_int32 n1));
+  | [Value_const(Uconst_ref(_, Some (Uconst_int32 n1)));
      Value_const(Uconst_int n2)] ->
       begin match p with
       | Plslbint Pint32 when 0 <= n2 && n2 < 32 ->
@@ -404,7 +371,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* int64 *)
-  | [Value_const(Uconst_ref(_, Uconst_int64 n))] ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_int64 n)))] ->
       begin match p with
       | Pintofbint Pint64 -> make_const_int (Int64.to_int n)
       | Pcvtbint(Pint64, Pint32) -> make_const_int32 (Int64.to_int32 n)
@@ -413,8 +380,8 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* int64, int64 *)
-  | [Value_const(Uconst_ref(_, Uconst_int64 n1));
-     Value_const(Uconst_ref(_, Uconst_int64 n2))] ->
+  | [Value_const(Uconst_ref(_, Some (Uconst_int64 n1)));
+     Value_const(Uconst_ref(_, Some (Uconst_int64 n2)))] ->
       begin match p with
       | Paddbint Pint64 -> make_const_int64 (Int64.add n1 n2)
       | Psubbint Pint64 -> make_const_int64 (Int64.sub n1 n2)
@@ -428,7 +395,7 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
       | _ -> default
       end
   (* int64, int *)
-  | [Value_const(Uconst_ref(_, Uconst_int64 n1));
+  | [Value_const(Uconst_ref(_, Some (Uconst_int64 n1)));
      Value_const(Uconst_int n2)] ->
       begin match p with
       | Plslbint Pint64 when 0 <= n2 && n2 < 64 ->
@@ -446,7 +413,8 @@ let simplif_arith_prim_pure fpc p (args, approxs) dbg =
 
 let field_approx n = function
   | Value_tuple a when n < Array.length a -> a.(n)
-  | Value_const (Uconst_ref(_, Uconst_block(_, l))) when n < List.length l ->
+  | Value_const (Uconst_ref(_, Some (Uconst_block(_, l))))
+    when n < List.length l ->
       Value_const (List.nth l n)
   | _ -> Value_unknown
 
@@ -463,19 +431,19 @@ let simplif_prim_pure fpc p (args, approxs) dbg =
         let name =
           Compilenv.new_structured_constant cst ~shared:true
         in
-        make_const (Uconst_ref (name, cst))
+        make_const (Uconst_ref (name, Some cst))
       with Exit ->
         (Uprim(p, args, dbg), Value_tuple (Array.of_list approxs))
       end
   (* Field access *)
-  | Pfield n, _, [ Value_const(Uconst_ref(_, Uconst_block(_, l))) ]
+  | Pfield n, _, [ Value_const(Uconst_ref(_, Some (Uconst_block(_, l)))) ]
     when n < List.length l ->
       make_const (List.nth l n)
   | Pfield n, [ Uprim(Pmakeblock _, ul, _) ], [approx]
     when n < List.length ul ->
       (List.nth ul n, field_approx n approx)
   (* Strings *)
-  | Pstringlength, _, [ Value_const(Uconst_ref(_, Uconst_string s)) ] ->
+  | Pstringlength, _, [ Value_const(Uconst_ref(_, Some (Uconst_string s))) ] ->
       make_const_int (String.length s)
   (* Identity *)
   | Pidentity, [arg1], [app1] ->
@@ -493,6 +461,8 @@ let simplif_prim_pure fpc p (args, approxs) dbg =
       begin match c with
         | Big_endian -> make_const_bool Arch.big_endian
         | Word_size -> make_const_int (8*Arch.size_int)
+        | Int_size -> make_const_int (8*Arch.size_int - 1)
+        | Max_wosize -> make_const_int ((1 lsl ((8*Arch.size_int) - 10)) - 1 )
         | Ostype_unix -> make_const_bool (Sys.os_type = "Unix")
         | Ostype_win32 -> make_const_bool (Sys.os_type = "Win32")
         | Ostype_cygwin -> make_const_bool (Sys.os_type = "Cygwin")
@@ -528,6 +498,16 @@ let approx_ulam = function
     Uconst c -> Value_const c
   | _ -> Value_unknown
 
+let find_action idxs acts tag =
+  if 0 <= tag && tag < Array.length idxs then begin
+    let idx = idxs.(tag) in
+    assert(0 <= idx && idx < Array.length acts);
+    Some acts.(idx)
+  end else
+    (* Can this happen? *)
+    None
+
+
 let rec substitute fpc sb ulam =
   match ulam with
     Uvar v ->
@@ -572,13 +552,32 @@ let rec substitute fpc sb ulam =
         simplif_prim fpc p (sargs, List.map approx_ulam sargs) dbg in
       res
   | Uswitch(arg, sw) ->
-      Uswitch(substitute fpc sb arg,
-              { sw with
-                us_actions_consts =
-                  Array.map (substitute fpc sb) sw.us_actions_consts;
-                us_actions_blocks =
-                  Array.map (substitute fpc sb) sw.us_actions_blocks;
-               })
+      let sarg = substitute fpc sb arg in
+      let action =
+        (* Unfortunately, we cannot easily deal with the
+           case of a constructed block (makeblock) bound to a local
+           identifier.  This would require to keep track of
+           local let bindings (at least their approximations)
+           in this substitute function.
+        *)
+        match sarg with
+        | Uconst (Uconst_ref (_,  Some (Uconst_block (tag, _)))) ->
+            find_action sw.us_index_blocks sw.us_actions_blocks tag
+        | Uconst (Uconst_ptr tag) ->
+            find_action sw.us_index_consts sw.us_actions_consts tag
+        | _ -> None
+      in
+      begin match action with
+      | Some u -> substitute fpc sb u
+      | None ->
+          Uswitch(sarg,
+                  { sw with
+                    us_actions_consts =
+                      Array.map (substitute fpc sb) sw.us_actions_consts;
+                    us_actions_blocks =
+                      Array.map (substitute fpc sb) sw.us_actions_blocks;
+                  })
+      end
   | Ustringswitch(arg,sw,d) ->
       Ustringswitch
         (substitute fpc sb arg,
@@ -587,7 +586,13 @@ let rec substitute fpc sb ulam =
   | Ustaticfail (nfail, args) ->
       Ustaticfail (nfail, List.map (substitute fpc sb) args)
   | Ucatch(nfail, ids, u1, u2) ->
-      Ucatch(nfail, ids, substitute fpc sb u1, substitute fpc sb u2)
+      let ids' = List.map Ident.rename ids in
+      let sb' =
+        List.fold_right2
+          (fun id id' s -> Tbl.add id (Uvar id') s)
+          ids ids' sb
+      in
+      Ucatch(nfail, ids', substitute fpc sb u1, substitute fpc sb' u2)
   | Utrywith(u1, id, u2) ->
       let id' = Ident.rename id in
       Utrywith(substitute fpc sb u1, id',
@@ -619,6 +624,8 @@ let rec substitute fpc sb ulam =
   | Usend(k, u1, u2, ul, dbg) ->
       Usend(k, substitute fpc sb u1, substitute fpc sb u2,
             List.map (substitute fpc sb) ul, dbg)
+  | Uunreachable ->
+      Uunreachable
 
 (* Perform an inline expansion *)
 
@@ -671,17 +678,24 @@ let rec is_pure = function
   | Levent(lam, ev) -> is_pure lam
   | _ -> false
 
+let warning_if_forced_inline ~loc ~attribute warning =
+  if attribute = Always_inline then
+    Location.prerr_warning loc (Warnings.Inlining_impossible warning)
+
 (* Generate a direct application *)
 
-let direct_apply fundesc funct ufunct uargs =
+let direct_apply fundesc funct ufunct uargs ~loc ~attribute =
   let app_args =
     if fundesc.fun_closed then uargs else uargs @ [ufunct] in
   let app =
-    match fundesc.fun_inline with
-    | None ->
+    match fundesc.fun_inline, attribute with
+    | _, Never_inline | None, _ ->
+        warning_if_forced_inline ~loc ~attribute
+          "Function information unavailable";
         Udirect_apply(fundesc.fun_label, app_args, Debuginfo.none)
-    | Some(params, body) ->
-        bind_params fundesc.fun_float_const_prop params app_args body in
+    | Some(params, body), _  ->
+        bind_params fundesc.fun_float_const_prop params app_args body
+  in
   (* If ufunct can contain side-effects or function definitions,
      we must make sure that it is evaluated exactly once.
      If the function is not closed, we evaluate ufunct as part of the
@@ -786,7 +800,7 @@ let rec close fenv cenv = function
         let name =
           Compilenv.new_structured_constant cst ~shared
         in
-        Uconst_ref (name, cst)
+        Uconst_ref (name, Some cst)
       in
       let rec transl = function
         | Const_base(Const_int n) -> Uconst_int n
@@ -809,22 +823,23 @@ let rec close fenv cenv = function
         | Const_base(Const_nativeint x) -> str (Uconst_nativeint x)
       in
       make_const (transl cst)
-  | Lfunction(kind, params, body) as funct ->
+  | Lfunction{kind; params; body} 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]
        when fun_arity > nargs *)
-  | Lapply(funct, args, loc) ->
+  | Lapply{ap_func = funct; ap_args = args; ap_loc = loc;
+        ap_inlined = attribute} ->
       let nargs = List.length args in
       begin match (close fenv cenv funct, close_list fenv cenv args) with
         ((ufunct, Value_closure(fundesc, approx_res)),
          [Uprim(Pmakeblock(_, _), uargs, _)])
         when List.length uargs = - fundesc.fun_arity ->
-          let app = direct_apply fundesc funct ufunct uargs in
+          let app = direct_apply ~loc ~attribute fundesc funct ufunct uargs in
           (app, strengthen_approx app approx_res)
       | ((ufunct, Value_closure(fundesc, approx_res)), uargs)
         when nargs = fundesc.fun_arity ->
-          let app = direct_apply fundesc funct ufunct uargs in
+          let app = direct_apply ~loc ~attribute fundesc funct ufunct uargs in
           (app, strengthen_approx app approx_res)
 
       | ((ufunct, Value_closure(fundesc, approx_res)), uargs)
@@ -846,19 +861,30 @@ let rec close fenv cenv = function
           @ (List.map (fun arg -> Lvar arg ) final_args)
         in
         let (new_fun, approx) = close fenv cenv
-          (Lfunction(
-            Curried, final_args, Lapply(funct, internal_args, loc)))
+          (Lfunction{
+               kind = Curried;
+               params = final_args;
+               body = Lapply{ap_should_be_tailcall=false;
+                             ap_loc=loc;
+                             ap_func=funct;
+                             ap_args=internal_args;
+                             ap_inlined=Default_inline;
+                             ap_specialised=Default_specialise};
+               attr = default_function_attribute})
         in
         let new_fun = iter first_args 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
-          (Ugeneric_apply(direct_apply fundesc funct ufunct first_args,
-                          rem_args, Debuginfo.none),
+          warning_if_forced_inline ~loc ~attribute "Over-application";
+          (Ugeneric_apply(direct_apply ~loc ~attribute fundesc funct ufunct
+                          first_args, rem_args, Debuginfo.none),
            Value_unknown)
       | ((ufunct, _), uargs) ->
+          warning_if_forced_inline ~loc ~attribute "Unknown function";
           (Ugeneric_apply(ufunct, uargs, Debuginfo.none), Value_unknown)
       end
   | Lsend(kind, met, obj, args, _) ->
@@ -881,7 +907,7 @@ let rec close fenv cenv = function
       end
   | Lletrec(defs, body) ->
       if List.for_all
-           (function (id, Lfunction(_, _, _)) -> true | _ -> false)
+           (function (id, Lfunction _) -> true | _ -> false)
            defs
       then begin
         (* Simple case: only function definitions *)
@@ -913,7 +939,12 @@ let rec close fenv cenv = function
       end
   | Lprim(Pdirapply loc,[funct;arg])
   | Lprim(Prevapply loc,[arg;funct]) ->
-      close fenv cenv (Lapply(funct, [arg], loc))
+      close fenv cenv (Lapply{ap_should_be_tailcall=false;
+                              ap_loc=loc;
+                              ap_func=funct;
+                              ap_args=[arg];
+                              ap_inlined=Default_inline;
+                              ap_specialised=Default_specialise})
   | Lprim(Pgetglobal id, []) as lam ->
       check_constant_result lam
                             (getglobal id)
@@ -922,11 +953,11 @@ let rec close fenv cenv = function
       let (ulam, approx) = close fenv cenv lam in
       check_constant_result lam (Uprim(Pfield n, [ulam], Debuginfo.none))
                             (field_approx n approx)
-  | Lprim(Psetfield(n, _), [Lprim(Pgetglobal id, []); lam]) ->
+  | Lprim(Psetfield(n, is_ptr, init), [Lprim(Pgetglobal id, []); lam]) ->
       let (ulam, approx) = close fenv cenv lam in
       if approx <> Value_unknown then
         (!global_approx).(n) <- approx;
-      (Uprim(Psetfield(n, false), [getglobal id; ulam], Debuginfo.none),
+      (Uprim(Psetfield(n, is_ptr, init), [getglobal id; ulam], Debuginfo.none),
        Value_unknown)
   | Lprim(Praise k, [Levent(arg, ev)]) ->
       let (ulam, approx) = close fenv cenv arg in
@@ -1035,7 +1066,7 @@ and close_list_approx fenv cenv = function
       (ulam :: ulams, approx :: approxs)
 
 and close_named fenv cenv id = function
-    Lfunction(kind, params, body) as funct ->
+    Lfunction{kind; params; body} as funct ->
       close_one_function fenv cenv id funct
   | lam ->
       close fenv cenv lam
@@ -1047,12 +1078,16 @@ and close_functions fenv cenv fun_defs =
     List.flatten
       (List.map
          (function
-           | (id, Lfunction(kind, params, body)) ->
-               split_default_wrapper id kind params body
+           | (id, Lfunction{kind; params; body; attr}) ->
+               Simplif.split_default_wrapper id kind params body attr
            | _ -> assert false
          )
          fun_defs)
   in
+  let inline_attribute = match fun_defs with
+    | [_, Lfunction{kind; params; body; attr = { inline }}] -> inline
+    | _ -> Default_inline (* recursive functions can't be inlined *)
+  in
 
   (* Update and check nesting depth *)
   incr function_nesting_depth;
@@ -1067,7 +1102,7 @@ and close_functions fenv cenv fun_defs =
   let uncurried_defs =
     List.map
       (function
-          (id, Lfunction(kind, params, body)) ->
+          (id, Lfunction{kind; params; body}) ->
             let label = Compilenv.make_symbol (Some (Ident.unique_name id)) in
             let arity = List.length params in
             let fundesc =
@@ -1131,8 +1166,19 @@ and close_functions fenv cenv fun_defs =
         0
         fun_params
     in
-    if lambda_smaller ubody
-        (!Clflags.inline_threshold + n)
+    let threshold =
+      match inline_attribute with
+      | Default_inline ->
+          let inline_threshold =
+            Clflags.Float_arg_helper.get ~key:0 !Clflags.inline_threshold
+          in
+          let magic_scale_constant = 8. in
+          int_of_float (inline_threshold *. magic_scale_constant) + n
+      | Always_inline -> max_int
+      | Never_inline -> min_int
+      | Unroll _ -> assert false
+    in
+    if lambda_smaller ubody threshold
     then fundesc.fun_inline <- Some(fun_params, ubody);
 
     (f, (id, env_pos, Value_closure(fundesc, approx))) in
@@ -1238,15 +1284,17 @@ let collect_exported_structured_constants a =
     | Value_const c -> const c
     | Value_unknown | Value_global_field _ -> ()
   and const = function
-    | Uconst_ref (s, c) ->
+    | Uconst_ref (s, (Some c)) ->
         Compilenv.add_exported_constant s;
         structured_constant c
+    | Uconst_ref (s, None) -> assert false (* Cannot be generated *)
     | Uconst_int _ | Uconst_ptr _ -> ()
   and structured_constant = function
     | Uconst_block (_, ul) -> List.iter const ul
     | Uconst_float _ | Uconst_int32 _
     | Uconst_int64 _ | Uconst_nativeint _
     | Uconst_float_array _ | Uconst_string _ -> ()
+    | Uconst_closure _ -> assert false (* Cannot be generated *)
   and ulam = function
     | Uvar _ -> ()
     | Uconst c -> const c
@@ -1276,6 +1324,7 @@ let collect_exported_structured_constants a =
     | Ufor (_, u1, u2, _, u3) -> ulam u1; ulam u2; ulam u3
     | Uassign (_, u) -> ulam u
     | Usend (_, u1, u2, ul, _) -> ulam u1; ulam u2; List.iter ulam ul
+    | Uunreachable -> ()
   in
   approx a
 
@@ -1291,7 +1340,11 @@ let intro size lam =
   global_approx := Array.init size (fun i -> Value_global_field (id, i));
   Compilenv.set_global_approx(Value_tuple !global_approx);
   let (ulam, approx) = close Tbl.empty Tbl.empty lam in
-  if !Clflags.opaque
+  let opaque =
+    !Clflags.opaque
+    || Env.is_imported_opaque (Compilenv.current_unit_name ())
+  in
+  if opaque
   then Compilenv.set_global_approx(Value_unknown)
   else collect_exported_structured_constants (Value_tuple !global_approx);
   global_approx := [||];
diff --git a/asmcomp/closure.mli b/asmcomp/closure.mli
index 2db6e163..f930e0fe 100644
--- a/asmcomp/closure.mli
+++ b/asmcomp/closure.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Introduction of closures, uncurrying, recognition of direct calls *)
 
diff --git a/asmcomp/closure_offsets.ml b/asmcomp/closure_offsets.ml
new file mode 100644
index 00000000..94eb4a1f
--- /dev/null
+++ b/asmcomp/closure_offsets.ml
@@ -0,0 +1,138 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+type result = {
+  function_offsets : int Closure_id.Map.t;
+  free_variable_offsets : int Var_within_closure.Map.t;
+}
+
+let add_closure_offsets
+      { function_offsets; free_variable_offsets }
+      ({ function_decls; free_vars } : Flambda.set_of_closures) =
+  (* Build the table mapping the functions declared by the set of closures
+     to the positions of their individual "infix" closures inside the runtime
+     closure block.  (All of the environment entries will come afterwards.) *)
+  let assign_function_offset id function_decl (map, env_pos) =
+    let pos = env_pos + 1 in
+    let env_pos =
+      let arity = Flambda_utils.function_arity function_decl in
+      env_pos
+        + 1  (* GC header; either [Closure_tag] or [Infix_tag] *)
+        + 1  (* full application code pointer *)
+        + 1  (* arity *)
+        + (if arity > 1 then 1 else 0)  (* partial application code pointer *)
+    in
+    let closure_id = Closure_id.wrap id in
+    if Closure_id.Map.mem closure_id map then begin
+      Misc.fatal_errorf "Closure_offsets.add_closure_offsets: function \
+          offset for %a would be defined multiple times"
+        Closure_id.print closure_id
+    end;
+    let map = Closure_id.Map.add closure_id pos map in
+    (map, env_pos)
+  in
+  let function_offsets, free_variable_pos =
+    Variable.Map.fold assign_function_offset
+      function_decls.funs (function_offsets, -1)
+  in
+  (* Adds the mapping of free variables to their offset.  Recall that
+     projections of [Var_within_closure]s are only currently used when
+     compiling accesses to the closure of a function from outside that
+     function (in particular, as a result of inlining).  Accesses to
+     a function's own closure are compiled directly via normal [Var]
+     accesses. *)
+  (* CR-someday mshinwell: As discussed with lwhite, maybe this isn't
+     ideal, and the self accesses should be explicitly marked too. *)
+  let assign_free_variable_offset var _ (map, pos) =
+    let var_within_closure = Var_within_closure.wrap var in
+    if Var_within_closure.Map.mem var_within_closure map then begin
+      Misc.fatal_errorf "Closure_offsets.add_closure_offsets: free variable \
+          offset for %a would be defined multiple times"
+        Var_within_closure.print var_within_closure
+    end;
+    let map = Var_within_closure.Map.add var_within_closure pos map in
+    (map, pos + 1)
+  in
+  let free_variable_offsets, _ =
+    Variable.Map.fold assign_free_variable_offset
+      free_vars (free_variable_offsets, free_variable_pos)
+  in
+  { function_offsets;
+    free_variable_offsets;
+  }
+
+let compute (program:Flambda.program) =
+  let init : result =
+    { function_offsets = Closure_id.Map.empty;
+      free_variable_offsets = Var_within_closure.Map.empty;
+    }
+  in
+  let r =
+    List.fold_left add_closure_offsets
+      init (Flambda_utils.all_sets_of_closures program)
+  in
+  r
+
+let compute_reexported_offsets program
+      ~current_unit_offset_fun ~current_unit_offset_fv
+      ~imported_units_offset_fun ~imported_units_offset_fv =
+  let offset_fun = ref current_unit_offset_fun in
+  let offset_fv = ref current_unit_offset_fv in
+  let used_closure_id closure_id =
+    match Closure_id.Map.find closure_id imported_units_offset_fun with
+    | offset ->
+      assert (not (Closure_id.Map.mem closure_id current_unit_offset_fun));
+      begin match Closure_id.Map.find closure_id !offset_fun with
+      | exception Not_found ->
+        offset_fun := Closure_id.Map.add closure_id offset !offset_fun
+      | offset' -> assert (offset = offset')
+      end
+    | exception Not_found ->
+      assert (Closure_id.Map.mem closure_id current_unit_offset_fun)
+  in
+  let used_var_within_closure var =
+    match Var_within_closure.Map.find var imported_units_offset_fv with
+    | offset ->
+      assert (not (Var_within_closure.Map.mem var current_unit_offset_fv));
+      begin match Var_within_closure.Map.find var !offset_fv with
+      | exception Not_found ->
+        offset_fv := Var_within_closure.Map.add var offset !offset_fv
+      | offset' -> assert (offset = offset')
+      end
+    | exception Not_found ->
+      assert (Var_within_closure.Map.mem var current_unit_offset_fv)
+  in
+  Flambda_iterators.iter_named_of_program program
+    ~f:(fun (named : Flambda.named) ->
+      match named with
+      | Project_closure { closure_id; _ } ->
+        used_closure_id closure_id
+      | Move_within_set_of_closures { start_from; move_to; _ } ->
+        used_closure_id start_from;
+        used_closure_id move_to
+      | Project_var { closure_id; var; _ } ->
+        used_closure_id closure_id;
+        used_var_within_closure var
+      | Symbol _ | Const _ | Allocated_const _ | Read_mutable _
+      | Read_symbol_field _ | Set_of_closures _ | Prim _ | Expr _ -> ());
+  Flambda_iterators.iter_constant_defining_values_on_program program
+    ~f:(fun (const : Flambda.constant_defining_value) ->
+      match const with
+      | Project_closure (_, closure_id) -> used_closure_id closure_id
+      | Allocated_const _ | Block _ | Set_of_closures _ -> ());
+  !offset_fun, !offset_fv
diff --git a/asmcomp/closure_offsets.mli b/asmcomp/closure_offsets.mli
new file mode 100644
index 00000000..7acb8449
--- /dev/null
+++ b/asmcomp/closure_offsets.mli
@@ -0,0 +1,44 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+(** Assign numerical offsets, within closure blocks, for code pointers and
+    environment entries. *)
+
+type result = private {
+  function_offsets : int Closure_id.Map.t;
+  free_variable_offsets : int Var_within_closure.Map.t;
+}
+
+val compute : Flambda.program -> result
+
+(** If compilation unit [C] references [B], which contains functions inlined
+    from another compilation unit [A], then we may need to know the layout of
+    closures inside (or constructed by code inside) a.cmx in order to
+    compile c.cmx.  Unfortunately a.cmx is permitted to be absent during such
+    compilation; c.cmx will be compiled using just b.cmx.  As such, when
+    building the .cmx export information for a given compilation unit, we
+    also include information about the layout of any closures that it depends
+    on from other compilation units.  This means that when situations as just
+    describe arise, we always have access to the necessary closure offsets. *)
+val compute_reexported_offsets
+   : Flambda.program
+  -> current_unit_offset_fun:int Closure_id.Map.t
+  -> current_unit_offset_fv:int Var_within_closure.Map.t
+  -> imported_units_offset_fun:int Closure_id.Map.t
+  -> imported_units_offset_fv:int Var_within_closure.Map.t
+  -> int Closure_id.Map.t * int Var_within_closure.Map.t
diff --git a/asmcomp/cmm.ml b/asmcomp/cmm.ml
index 67ee3445..9243cb47 100644
--- a/asmcomp/cmm.ml
+++ b/asmcomp/cmm.ml
@@ -1,32 +1,87 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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 machtype_component =
-    Addr
+  | Val
+  | Addr
   | Int
   | Float
 
 type machtype = machtype_component array
 
 let typ_void = ([||] : machtype_component array)
+let typ_val = [|Val|]
 let typ_addr = [|Addr|]
 let typ_int = [|Int|]
 let typ_float = [|Float|]
 
 let size_component = function
-    Addr -> Arch.size_addr
+  | Val | Addr -> Arch.size_addr
   | Int -> Arch.size_int
   | Float -> Arch.size_float
 
+(** [machtype_component]s are partially ordered as follows:
+
+      Addr     Float
+       ^
+       |
+      Val
+       ^
+       |
+      Int
+
+  In particular, [Addr] must be above [Val], to ensure that if there is
+  a join point between a code path yielding [Addr] and one yielding [Val]
+  then the result is treated as a derived pointer into the heap (i.e. [Addr]).
+  (Such a result may not be live across any call site or a fatal compiler
+  error will result.)
+*)
+
+let lub_component comp1 comp2 =
+  match comp1, comp2 with
+  | Int, Int -> Int
+  | Int, Val -> Val
+  | Int, Addr -> Addr
+  | Val, Int -> Val
+  | Val, Val -> Val
+  | Val, Addr -> Addr
+  | Addr, Int -> Addr
+  | Addr, Addr -> Addr
+  | Addr, Val -> Addr
+  | Float, Float -> Float
+  | (Int | Addr | Val), Float
+  | Float, (Int | Addr | Val) ->
+    (* Float unboxing code must be sure to avoid this case. *)
+    assert false
+
+let ge_component comp1 comp2 =
+  match comp1, comp2 with
+  | Int, Int -> true
+  | Int, Addr -> false
+  | Int, Val -> false
+  | Val, Int -> true
+  | Val, Val -> true
+  | Val, Addr -> false
+  | Addr, Int -> true
+  | Addr, Addr -> true
+  | Addr, Val -> true
+  | Float, Float -> true
+  | (Int | Addr | Val), Float
+  | Float, (Int | Addr | Val) ->
+    assert false
+
 let size_machtype mty =
   let size = ref 0 in
   for i = 0 to Array.length mty - 1 do
@@ -59,7 +114,8 @@ type memory_chunk =
   | Sixteen_signed
   | Thirtytwo_unsigned
   | Thirtytwo_signed
-  | Word
+  | Word_int
+  | Word_val
   | Single
   | Double
   | Double_u
@@ -69,11 +125,11 @@ type operation =
   | Cextcall of string * machtype * bool * Debuginfo.t
   | Cload of memory_chunk
   | Calloc
-  | Cstore of memory_chunk
+  | Cstore of memory_chunk * Lambda.initialization_or_assignment
   | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi
   | Cand | Cor | Cxor | Clsl | Clsr | Casr
   | Ccmpi of comparison
-  | Cadda | Csuba
+  | Caddv | Cadda
   | Ccmpa of comparison
   | Cnegf | Cabsf
   | Caddf | Csubf | Cmulf | Cdivf
diff --git a/asmcomp/cmm.mli b/asmcomp/cmm.mli
index 97b8d409..31c222cf 100644
--- a/asmcomp/cmm.mli
+++ b/asmcomp/cmm.mli
@@ -1,30 +1,75 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Second intermediate language (machine independent) *)
 
 type machtype_component =
-    Addr
+  | Val
+  | Addr
   | Int
   | Float
 
+(* - [Val] denotes a valid OCaml value: either a pointer to the beginning
+     of a heap block, an infix pointer if it is preceded by the correct
+     infix header, or a 2n+1 encoded integer.
+   - [Int] is for integers (not necessarily 2n+1 encoded) and for
+     pointers outside the heap.
+   - [Addr] denotes pointers that are neither [Val] nor [Int], i.e.
+     pointers into the heap that point in the middle of a heap block.
+     Such derived pointers are produced by e.g. array indexing.
+   - [Float] is for unboxed floating-point numbers.
+
+The purpose of these types is twofold.  First, they guide register
+allocation: type [Float] goes in FP registers, the other types go
+into integer registers.  Second, they determine how local variables are
+tracked by the GC:
+   - Variables of type [Val] are GC roots.  If they are pointers, the
+     GC will not deallocate the addressed heap block, and will update
+     the local variable if the heap block moves.
+   - Variables of type [Int] and [Float] are ignored by the GC.
+     The GC does not change their values.
+   - Variables of type [Addr] must never be live across an allocation
+     point or function call.  They cannot be given as roots to the GC
+     because they don't point after a well-formed block header of the
+     kind that the GC needs.  However, the GC may move the block pointed
+     into, invalidating the value of the [Addr] variable.
+*)
+
 type machtype = machtype_component array
 
 val typ_void: machtype
+val typ_val: machtype
 val typ_addr: machtype
 val typ_int: machtype
 val typ_float: machtype
 
 val size_component: machtype_component -> int
+
+(** Least upper bound of two [machtype_component]s. *)
+val lub_component
+   : machtype_component
+  -> machtype_component
+  -> machtype_component
+
+(** Returns [true] iff the first supplied [machtype_component] is greater than
+    or equal to the second under the relation used by [lub_component]. *)
+val ge_component
+   : machtype_component
+  -> machtype_component
+  -> bool
+
 val size_machtype: machtype -> int
 
 type comparison =
@@ -45,21 +90,23 @@ type memory_chunk =
   | Sixteen_signed
   | Thirtytwo_unsigned
   | Thirtytwo_signed
-  | Word
+  | Word_int                           (* integer or pointer outside heap *)
+  | Word_val                           (* pointer inside heap or encoded int *)
   | Single
-  | Double                              (* 64-bit-aligned 64-bit float *)
-  | Double_u                            (* word-aligned 64-bit float *)
+  | Double                             (* 64-bit-aligned 64-bit float *)
+  | Double_u                           (* word-aligned 64-bit float *)
 
 type operation =
     Capply of machtype * Debuginfo.t
   | Cextcall of string * machtype * bool * Debuginfo.t
   | Cload of memory_chunk
   | Calloc
-  | Cstore of memory_chunk
+  | Cstore of memory_chunk * Lambda.initialization_or_assignment
   | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi
   | Cand | Cor | Cxor | Clsl | Clsr | Casr
   | Ccmpi of comparison
-  | Cadda | Csuba
+  | Caddv (* pointer addition that produces a [Val] (well-formed Caml value) *)
+  | Cadda (* pointer addition that produces a [Addr] (derived heap pointer) *)
   | Ccmpa of comparison
   | Cnegf | Cabsf
   | Caddf | Csubf | Cmulf | Cdivf
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index 83149660..78a39ddb 100644
--- a/asmcomp/cmmgen.ml
+++ b/asmcomp/cmmgen.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Translation from closed lambda to C-- *)
 
@@ -31,6 +34,11 @@ let bind name arg fn =
   | Cconst_blockheader _ -> fn arg
   | _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
 
+let bind_load name arg fn =
+  match arg with
+  | Cop(Cload _, [Cvar _]) -> fn arg
+  | _ -> bind name arg fn
+
 let bind_nonvar name arg fn =
   match arg with
     Cconst_int _ | Cconst_natint _ | Cconst_symbol _
@@ -64,7 +72,6 @@ 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_block_header tag sz = Cconst_blockheader(block_header tag sz)
 let alloc_float_header = Cconst_blockheader(float_header)
 let alloc_floatarray_header len = Cconst_blockheader(floatarray_header len)
 let alloc_closure_header sz = Cconst_blockheader(white_closure_header sz)
@@ -84,74 +91,86 @@ let int_const n =
   else Cconst_natint
           (Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
 
+let cint_const n =
+  Cint(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
+
+let add_no_overflow n x c =
+  let d = n + x in
+  if d = 0 then c else Cop(Caddi, [c; Cconst_int d])
+
 let rec add_const c n =
   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])
+    when no_overflow_add n x ->
+      add_no_overflow n x c
+  | 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])
 
-let incr_int = function
-    Cconst_int n when n < max_int -> Cconst_int(n+1)
-  | Cop(Caddi, [c; Cconst_int n]) when n < max_int -> add_const c (n + 1)
-  | c -> add_const c 1
+let incr_int c = add_const c 1
+let decr_int c = add_const c (-1)
 
-let decr_int = function
-    Cconst_int n when n > min_int -> Cconst_int(n-1)
-  | Cop(Caddi, [c; Cconst_int n]) when n > min_int -> add_const c (n - 1)
-  | c -> add_const c (-1)
-
-let add_int c1 c2 =
+let rec add_int c1 c2 =
   match (c1, c2) with
-    (Cop(Caddi, [c1; Cconst_int n1]),
-     Cop(Caddi, [c2; Cconst_int n2])) when no_overflow_add n1 n2 ->
-      add_const (Cop(Caddi, [c1; c2])) (n1 + n2)
+  | (Cconst_int n, c) | (c, Cconst_int n) ->
+      add_const c n
   | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
-      add_const (Cop(Caddi, [c1; c2])) n1
+      add_const (add_int c1 c2) n1
   | (c1, Cop(Caddi, [c2; Cconst_int n2])) ->
-      add_const (Cop(Caddi, [c1; c2])) n2
-  | (Cconst_int _, _) ->
-      Cop(Caddi, [c2; c1])
+      add_const (add_int c1 c2) n2
   | (_, _) ->
       Cop(Caddi, [c1; c2])
 
-let sub_int c1 c2 =
+let rec sub_int c1 c2 =
   match (c1, c2) with
-    (Cop(Caddi, [c1; Cconst_int n1]),
-     Cop(Caddi, [c2; Cconst_int n2])) when no_overflow_sub n1 n2 ->
-      add_const (Cop(Csubi, [c1; c2])) (n1 - n2)
-  | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
-      add_const (Cop(Csubi, [c1; c2])) n1
+  | (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 (Cop(Csubi, [c1; c2])) (-n2)
-  | (c1, Cconst_int n) when n <> min_int ->
-      add_const c1 (-n)
+      add_const (sub_int c1 c2) (-n2)
+  | (Cop(Caddi, [c1; Cconst_int n1]), c2) ->
+      add_const (sub_int c1 c2) n1
   | (c1, c2) ->
       Cop(Csubi, [c1; c2])
 
-let mul_int c1 c2 =
+let rec lsl_int c1 c2 =
+  match (c1, c2) with
+  | (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)
+    when no_overflow_lsl n1 n2 ->
+      add_const (lsl_int c1 c2) (n1 lsl n2)
+  | (_, _) ->
+      Cop(Clsl, [c1; c2])
+
+let is_power2 n = n = 1 lsl Misc.log2 n
+
+and mult_power2 c n = lsl_int c (Cconst_int (Misc.log2 n))
+
+let rec mul_int c1 c2 =
   match (c1, c2) with
-    (c, Cconst_int 0) | (Cconst_int 0, c) ->
+  | (c, Cconst_int 0) | (Cconst_int 0, 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) | (Cconst_int n, c) when n = 1 lsl Misc.log2 n->
-      Cop(Clsl, [c; Cconst_int(Misc.log2 n)])
+  | (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]))
+    when no_overflow_mul n k ->
+      add_const (mul_int c (Cconst_int k)) (n * k)
   | (c1, c2) ->
       Cop(Cmuli, [c1; c2])
 
-let lsl_int c1 c2 =
-  match (c1, c2) with
-    (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(Clsl, [c1; c2])
 
 let ignore_low_bit_int = function
     Cop(Caddi, [(Cop(Clsl, [_; Cconst_int n]) as c); Cconst_int 1]) when n > 0
@@ -205,6 +224,13 @@ let untag_int = function
   | Cop(Cor, [c; Cconst_int 1]) -> Cop(Casr, [c; Cconst_int 1])
   | c -> Cop(Casr, [c; Cconst_int 1])
 
+let if_then_else (cond, ifso, ifnot) =
+  match cond with
+  | Cconst_int 0 -> ifnot
+  | Cconst_int 1 -> ifso
+  | _ ->
+    Cifthenelse(cond, ifso, ifnot)
+
 (* Turning integer divisions into multiply-high then shift.
    The [division_parameters] function is used in module Emit for
    those target platforms that support this optimization. *)
@@ -411,7 +437,11 @@ let safe_mod_bi =
 
 let test_bool = function
     Cop(Caddi, [Cop(Clsl, [c; Cconst_int 1]); Cconst_int 1]) -> c
-  | Cop(Clsl, [c; 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])
 
 (* Float *)
@@ -472,14 +502,15 @@ let field_address ptr n =
   then ptr
   else Cop(Cadda, [ptr; Cconst_int(n * size_addr)])
 
+
 let get_field ptr n =
-  Cop(Cload Word, [field_address ptr n])
+  Cop(Cload Word_val, [field_address ptr n])
 
-let set_field ptr n newval =
-  Cop(Cstore Word, [field_address ptr n; newval])
+let set_field ptr n newval init =
+  Cop(Cstore (Word_val, init), [field_address ptr n; newval])
 
 let header ptr =
-  Cop(Cload Word, [Cop(Cadda, [ptr; Cconst_int(-size_int)])])
+  Cop(Cload Word_int, [Cop(Cadda, [ptr; Cconst_int(-size_int)])])
 
 let tag_offset =
   if big_endian then -1 else -size_int
@@ -512,24 +543,44 @@ 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 lsl_const c n =
-  Cop(Clsl, [c; Cconst_int n])
-
-let array_indexing log2size ptr ofs =
+  if n = 0 then c
+  else Cop(Clsl, [c; Cconst_int n])
+
+(* 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
+   tagged int expression.
+   The optional ?typ argument is the C-- type of the result.
+   By default, it is Addr, meaning we are constructing a derived pointer
+   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 add =
+    match typ with
+    | None | Some Addr -> Cadda
+    | Some Int -> Caddi
+    | _ -> assert false in
   match ofs with
     Cconst_int n ->
       let i = n asr 1 in
-      if i = 0 then ptr else Cop(Cadda, [ptr; Cconst_int(i lsl log2size)])
+      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(Cadda, [ptr; lsl_const c log2size])
+      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(Cadda, [Cop(Cadda, [ptr; lsl_const c (log2size - 1)]);
+      Cop(add, [Cop(add, [ptr; lsl_const c (log2size - 1)]);
                    Cconst_int((n-1) lsl (log2size - 1))])
+  | _ when log2size = 0 ->
+      Cop(add, [ptr; untag_int ofs])
   | _ ->
-      Cop(Cadda, [Cop(Cadda, [ptr; lsl_const ofs (log2size - 1)]);
+      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, [array_indexing log2_size_addr 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])
 let float_array_ref arr ofs =
@@ -539,9 +590,11 @@ let addr_array_set arr ofs newval =
   Cop(Cextcall("caml_modify", typ_void, false, Debuginfo.none),
       [array_indexing log2_size_addr arr ofs; newval])
 let int_array_set arr ofs newval =
-  Cop(Cstore Word, [array_indexing log2_size_addr arr ofs; newval])
+  Cop(Cstore (Word_int, Assignment),
+    [array_indexing log2_size_addr arr ofs; newval])
 let float_array_set arr ofs newval =
-  Cop(Cstore Double_u, [array_indexing log2_size_float arr ofs; newval])
+  Cop(Cstore (Double_u, Assignment),
+    [array_indexing log2_size_float arr ofs; newval])
 
 (* String length *)
 
@@ -565,19 +618,19 @@ let string_length exp =
 
 let lookup_tag obj tag =
   bind "tag" tag (fun tag ->
-    Cop(Cextcall("caml_get_public_method", typ_addr, false, Debuginfo.none),
+    Cop(Cextcall("caml_get_public_method", typ_val, false, Debuginfo.none),
         [obj; tag]))
 
 let lookup_label obj lab =
   bind "lab" lab (fun lab ->
-    let table = Cop (Cload Word, [obj]) in
+    let table = Cop (Cload Word_val, [obj]) in
     addr_array_ref table lab)
 
 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
   Compilenv.need_send_fun arity;
-  Cop(Capply (typ_addr, dbg),
+  Cop(Capply (typ_val, dbg),
       Cconst_symbol("caml_send" ^ string_of_int arity) ::
       obj :: tag :: cache :: args)
 
@@ -593,7 +646,7 @@ let make_alloc_generic set_fn tag wordsize args =
     | e1::el -> Csequence(set_fn (Cvar id) (Cconst_int idx) e1,
                           fill_fields (idx + 2) el) in
     Clet(id,
-         Cop(Cextcall("caml_alloc", typ_addr, true, Debuginfo.none),
+         Cop(Cextcall("caml_alloc", typ_val, true, Debuginfo.none),
                  [Cconst_int wordsize; Cconst_int tag]),
          fill_fields 1 args)
   end
@@ -617,7 +670,18 @@ let make_checkbound dbg = function
 let fundecls_size fundecls =
   let sz = ref (-1) in
   List.iter
-    (fun f -> sz := !sz + 1 + (if f.arity = 1 then 2 else 3))
+    (fun f ->
+       let indirect_call_code_pointer_size =
+         match f.arity with
+         | 0 | 1 -> 0
+           (* arity 1 does not need an indirect call handler.
+              arity 0 cannot be indirect called *)
+         | _ -> 1
+           (* For other arities there is an indirect call handler.
+              if arity >= 2 it is caml_curry...
+              if arity < 0 it is caml_tuplify... *)
+       in
+       sz := !sz + 1 + 2 + indirect_call_code_pointer_size)
     fundecls;
   !sz
 
@@ -637,14 +701,20 @@ let rec expr_size env = function
       expr_size env body
   | Uprim(Pmakeblock(tag, mut), args, _) ->
       RHS_block (List.length args)
-  | Uprim(Pmakearray(Paddrarray | Pintarray), args, _) ->
+  | Uprim(Pmakearray((Paddrarray | Pintarray), _), args, _) ->
       RHS_block (List.length args)
-  | Uprim(Pmakearray(Pfloatarray), args, _) ->
+  | Uprim(Pmakearray(Pfloatarray, _), args, _) ->
       RHS_floatblock (List.length args)
-  | Uprim (Pduprecord (Record_regular, sz), _, _) ->
+  | Uprim (Pduprecord ((Record_regular | Record_inlined _), sz), _, _) ->
       RHS_block sz
+  | Uprim (Pduprecord (Record_extension, sz), _, _) ->
+      RHS_block (sz + 1)
   | Uprim (Pduprecord (Record_float, sz), _, _) ->
       RHS_floatblock sz
+  | Uprim (Pccall { prim_name; _ }, closure::_, _)
+        when prim_name = "caml_check_value_is_closure" ->
+      (* Used for "-clambda-checks". *)
+      expr_size env closure
   | Usequence(exp, exp') ->
       expr_size env exp'
   | _ -> RHS_nonrec
@@ -688,8 +758,10 @@ let transl_structured_constant cst =
 
 (* Translate constant closures *)
 
+type is_global = Global | Not_global
+
 let constant_closures =
-  ref ([] : (string * ufunction list) list)
+  ref ([] : ((string * is_global) * ufunction list * uconstant list) list)
 
 (* Boxed integers *)
 
@@ -726,6 +798,13 @@ let box_int bi arg =
                    Cconst_symbol(operations_boxed_int bi);
                    arg'])
 
+let split_int64_for_32bit_target arg =
+  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 rec unbox_int bi arg =
   match arg with
     Cop(Calloc, [hdr; ops; Cop(Clsl, [contents; Cconst_int 32])])
@@ -746,14 +825,47 @@ let rec unbox_int bi arg =
   | 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)
   | _ ->
-      Cop(Cload(if bi = Pint32 then Thirtytwo_signed else Word),
-          [Cop(Cadda, [arg; Cconst_int size_addr])])
+      if size_int = 4 && bi = Pint64 then
+        split_int64_for_32bit_target arg
+      else
+        Cop(Cload(if bi = Pint32 then Thirtytwo_signed else Word_int),
+            [Cop(Cadda, [arg; Cconst_int size_addr])])
 
 let make_unsigned_int bi arg =
   if bi = Pint32 && size_int = 8
   then Cop(Cand, [arg; Cconst_natint 0xFFFFFFFFn])
   else arg
 
+(* Boxed numbers *)
+
+type boxed_number =
+  | Boxed_float
+  | Boxed_integer of boxed_integer
+
+let box_number bn arg =
+  match bn with
+  | Boxed_float -> box_float arg
+  | Boxed_integer bi -> box_int 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
@@ -771,22 +883,40 @@ let bigarray_elt_size = function
   | Pbigarray_complex32 -> 8
   | Pbigarray_complex64 -> 16
 
+(* Produces a pointer to the element of the bigarray [b] on the position
+   [args].  [args] is given as a list of tagged int expressions, one per array
+   dimension. *)
 let bigarray_indexing unsafe elt_kind layout b args dbg =
-  let check_bound a1 a2 k =
-    if unsafe then k else Csequence(make_checkbound dbg [a1;a2], k) in
+  let check_ba_bound bound idx v =
+    Csequence(make_checkbound dbg [bound;idx], v) in
+  (* Validates the given multidimensional offset against the array bounds and
+     transforms it into a one dimensional offset.  The offsets are expressions
+     evaluating to tagged int. *)
   let rec ba_indexing dim_ofs delta_ofs = function
     [] -> assert false
   | [arg] ->
-      bind "idx" (untag_int arg)
-        (fun idx ->
-           check_bound (Cop(Cload Word,[field_address b dim_ofs])) idx idx)
+      if unsafe then arg
+      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
+          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
-      bind "idx" (untag_int arg1)
-        (fun idx ->
-          bind "bound" (Cop(Cload Word, [field_address b dim_ofs]))
-          (fun bound ->
-            check_bound bound idx (add_int (mul_int rem bound) idx))) 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
+      else
+        bind "idx" arg1 (fun idx ->
+          bind "bound" bound (fun bound ->
+            let idxn = untag_int idx in
+            (* [offset = rem * (tag_int bound) + idx] *)
+            let offset = add_int (mul_int (decr_int rem) bound) idx in
+            check_ba_bound bound idxn offset)) in
+  (* The offset as an expression evaluating to int *)
   let offset =
     match layout with
       Pbigarray_unknown_layout ->
@@ -797,11 +927,9 @@ let bigarray_indexing unsafe elt_kind layout b args dbg =
         ba_indexing 5 1 (List.map (fun idx -> sub_int idx (Cconst_int 2)) args)
   and elt_size =
     bigarray_elt_size elt_kind in
-  let byte_offset =
-    if elt_size = 1
-    then offset
-    else Cop(Clsl, [offset; Cconst_int(log2 elt_size)]) in
-  Cop(Cadda, [Cop(Cload Word, [field_address b 1]); byte_offset])
+  (* [array_indexing] can simplify the given expressions *)
+  array_indexing ~typ:Int (log2 elt_size)
+                 (Cop(Cload Word_int, [field_address b 1])) offset
 
 let bigarray_word_kind = function
     Pbigarray_unknown -> assert false
@@ -812,9 +940,9 @@ let bigarray_word_kind = function
   | Pbigarray_sint16 -> Sixteen_signed
   | Pbigarray_uint16 -> Sixteen_unsigned
   | Pbigarray_int32 -> Thirtytwo_signed
-  | Pbigarray_int64 -> Word
-  | Pbigarray_caml_int -> Word
-  | Pbigarray_native_int -> Word
+  | Pbigarray_int64 -> Word_int
+  | Pbigarray_caml_int -> Word_int
+  | Pbigarray_native_int -> Word_int
   | Pbigarray_complex32 -> Single
   | Pbigarray_complex64 -> Double
 
@@ -843,11 +971,11 @@ 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, [addr; complex_re newv]),
-            Cop(Cstore kind,
+            Cop(Cstore (kind, Assignment), [addr; complex_re newv]),
+            Cop(Cstore (kind, Assignment),
                 [Cop(Cadda, [addr; Cconst_int sz]); complex_im newv]))))
     | _ ->
-        Cop(Cstore (bigarray_word_kind elt_kind),
+        Cop(Cstore (bigarray_word_kind elt_kind, Assignment),
             [bigarray_indexing unsafe elt_kind layout b args dbg; newval]))
 
 let unaligned_load_16 ptr idx =
@@ -862,14 +990,14 @@ let unaligned_load_16 ptr idx =
 
 let unaligned_set_16 ptr idx newval =
   if Arch.allow_unaligned_access
-  then Cop(Cstore Sixteen_unsigned, [add_int ptr idx; newval])
+  then Cop(Cstore (Sixteen_unsigned, Assignment), [add_int ptr idx; newval])
   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 b1, b2 = if Arch.big_endian then v1, v2 else v2, v1 in
     Csequence(
-        Cop(Cstore Byte_unsigned, [add_int ptr idx; b1]),
-        Cop(Cstore Byte_unsigned,
+        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]))
 
 let unaligned_load_32 ptr idx =
@@ -893,7 +1021,7 @@ let unaligned_load_32 ptr idx =
 
 let unaligned_set_32 ptr idx newval =
   if Arch.allow_unaligned_access
-  then Cop(Cstore Thirtytwo_unsigned, [add_int ptr idx; newval])
+  then Cop(Cstore (Thirtytwo_unsigned, Assignment), [add_int ptr idx; newval])
   else
     let v1 =
       Cop(Cand, [Cop(Clsr, [newval; Cconst_int 24]); Cconst_int 0xFF]) in
@@ -908,19 +1036,19 @@ let unaligned_set_32 ptr idx newval =
       else v4, v3, v2, v1 in
     Csequence(
         Csequence(
-            Cop(Cstore Byte_unsigned, [add_int ptr idx; b1]),
-            Cop(Cstore Byte_unsigned,
+            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])),
         Csequence(
-            Cop(Cstore Byte_unsigned,
+            Cop(Cstore (Byte_unsigned, Assignment),
                 [add_int (add_int ptr idx) (Cconst_int 2); b3]),
-            Cop(Cstore Byte_unsigned,
+            Cop(Cstore (Byte_unsigned, Assignment),
                 [add_int (add_int ptr idx) (Cconst_int 3); b4])))
 
 let unaligned_load_64 ptr idx =
   assert(size_int = 8);
   if Arch.allow_unaligned_access
-  then Cop(Cload Word, [add_int ptr idx])
+  then Cop(Cload Word_int, [add_int ptr idx])
   else
     let v1 = Cop(Cload Byte_unsigned, [add_int ptr idx]) in
     let v2 = Cop(Cload Byte_unsigned,
@@ -956,7 +1084,7 @@ let unaligned_load_64 ptr idx =
 let unaligned_set_64 ptr idx newval =
   assert(size_int = 8);
   if Arch.allow_unaligned_access
-  then Cop(Cstore Word, [add_int ptr idx; newval])
+  then Cop(Cstore (Word_int, Assignment), [add_int ptr idx; newval])
   else
     let v1 =
       Cop(Cand, [Cop(Clsr, [newval; Cconst_int (8*7)]); Cconst_int 0xFF]) in
@@ -979,24 +1107,24 @@ let unaligned_set_64 ptr idx newval =
     Csequence(
         Csequence(
             Csequence(
-                Cop(Cstore Byte_unsigned, [add_int ptr idx; b1]),
-                Cop(Cstore Byte_unsigned,
+                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])),
             Csequence(
-                Cop(Cstore Byte_unsigned,
+                Cop(Cstore (Byte_unsigned, Assignment),
                     [add_int (add_int ptr idx) (Cconst_int 2); b3]),
-                Cop(Cstore Byte_unsigned,
+                Cop(Cstore (Byte_unsigned, Assignment),
                     [add_int (add_int ptr idx) (Cconst_int 3); b4]))),
         Csequence(
             Csequence(
-                Cop(Cstore Byte_unsigned,
+                Cop(Cstore (Byte_unsigned, Assignment),
                     [add_int (add_int ptr idx) (Cconst_int 4); b5]),
-                Cop(Cstore Byte_unsigned,
+                Cop(Cstore (Byte_unsigned, Assignment),
                     [add_int (add_int ptr idx) (Cconst_int 5); b6])),
             Csequence(
-                Cop(Cstore Byte_unsigned,
+                Cop(Cstore (Byte_unsigned, Assignment),
                     [add_int (add_int ptr idx) (Cconst_int 6); b7]),
-                Cop(Cstore Byte_unsigned,
+                Cop(Cstore (Byte_unsigned, Assignment),
                     [add_int (add_int ptr idx) (Cconst_int 7); b8]))))
 
 let max_or_zero a =
@@ -1019,8 +1147,7 @@ let check_bound unsafe dbg a1 a2 k =
 (* Simplification of some primitives into C calls *)
 
 let default_prim name =
-  { prim_name = name; prim_arity = 0 (*ignored*);
-    prim_alloc = true; prim_native_name = ""; prim_native_float = false }
+  Primitive.simple ~name ~arity:0(*ignored*) ~alloc:true
 
 let simplif_primitive_32bits = function
     Pbintofint Pint64 -> Pccall (default_prim "caml_int64_of_int")
@@ -1094,7 +1221,6 @@ struct
 
   type act = expression
 
-  let default = Cexit (0,[])
   let make_const i =  Cconst_int i
   let make_prim p args = Cop (p,args)
   let make_offset arg n = add_const arg n
@@ -1191,99 +1317,96 @@ let transl_int_switch arg low high cases default = match cases with
 
 type unboxed_number_kind =
     No_unboxing
-  | Boxed_float
-  | Boxed_integer of boxed_integer
+  | Boxed of boxed_number
+  | No_result (* expression never returns a result *)
+
+let unboxed_number_kind_of_unbox = function
+  | Same_as_ocaml_repr -> No_unboxing
+  | Unboxed_float -> Boxed Boxed_float
+  | Unboxed_integer bi -> Boxed (Boxed_integer bi)
+  | Untagged_int -> No_unboxing
+
+let rec is_unboxed_number env e =
+  (* Given unboxed_number_kind from two branches of the code, returns the
+     resulting unboxed_number_kind *)
+  let join k1 e =
+    match k1, is_unboxed_number env e with
+    | Boxed b1, Boxed b2 when b1 = b2 -> Boxed b1
+    | No_result, k | k, No_result ->
+        k (* if a branch never returns, it is safe to unbox it *)
+    | _, _ -> No_unboxing
+  in
+  match e with
+  | Uvar id ->
+      begin match is_unboxed_id id env with
+      | None -> No_unboxing
+      | Some (_, bn) -> Boxed bn
+      end
 
-let rec is_unboxed_number = function
-    Uconst(Uconst_ref(_, Uconst_float _)) ->
-      Boxed_float
+  | Uconst(Uconst_ref(_, Some (Uconst_float _))) ->
+      Boxed Boxed_float
+  | Uconst(Uconst_ref(_, Some (Uconst_int32 _))) ->
+      Boxed (Boxed_integer Pint32)
+  | Uconst(Uconst_ref(_, Some (Uconst_int64 _))) ->
+      Boxed (Boxed_integer Pint64)
+  | Uconst(Uconst_ref(_, Some (Uconst_nativeint _))) ->
+      Boxed (Boxed_integer Pnativeint)
   | Uprim(p, _, _) ->
       begin match simplif_primitive p with
-          Pccall p -> if p.prim_native_float then Boxed_float else No_unboxing
-        | Pfloatfield _ -> Boxed_float
-        | Pfloatofint -> Boxed_float
-        | Pnegfloat -> Boxed_float
-        | Pabsfloat -> Boxed_float
-        | Paddfloat -> Boxed_float
-        | Psubfloat -> Boxed_float
-        | Pmulfloat -> Boxed_float
-        | Pdivfloat -> Boxed_float
-        | Parrayrefu Pfloatarray -> Boxed_float
-        | Parrayrefs Pfloatarray -> Boxed_float
-        | Pbintofint bi -> Boxed_integer bi
-        | Pcvtbint(src, dst) -> Boxed_integer dst
-        | Pnegbint bi -> Boxed_integer bi
-        | Paddbint bi -> Boxed_integer bi
-        | Psubbint bi -> Boxed_integer bi
-        | Pmulbint bi -> Boxed_integer bi
-        | Pdivbint bi -> Boxed_integer bi
-        | Pmodbint bi -> Boxed_integer bi
-        | Pandbint bi -> Boxed_integer bi
-        | Porbint bi -> Boxed_integer bi
-        | Pxorbint bi -> Boxed_integer bi
-        | Plslbint bi -> Boxed_integer bi
-        | Plsrbint bi -> Boxed_integer bi
-        | Pasrbint bi -> Boxed_integer bi
+        | Pccall p -> unboxed_number_kind_of_unbox p.prim_native_repr_res
+        | Pfloatfield _ -> Boxed Boxed_float
+        | Pfloatofint -> Boxed Boxed_float
+        | Pnegfloat -> Boxed Boxed_float
+        | Pabsfloat -> Boxed Boxed_float
+        | Paddfloat -> Boxed Boxed_float
+        | Psubfloat -> Boxed Boxed_float
+        | Pmulfloat -> Boxed Boxed_float
+        | Pdivfloat -> Boxed Boxed_float
+        | Parrayrefu Pfloatarray -> Boxed Boxed_float
+        | Parrayrefs Pfloatarray -> Boxed Boxed_float
+        | Pbintofint bi -> Boxed (Boxed_integer bi)
+        | Pcvtbint(src, dst) -> Boxed (Boxed_integer dst)
+        | Pnegbint bi -> Boxed (Boxed_integer bi)
+        | Paddbint bi -> Boxed (Boxed_integer bi)
+        | Psubbint bi -> Boxed (Boxed_integer bi)
+        | Pmulbint bi -> Boxed (Boxed_integer bi)
+        | Pdivbint bi -> Boxed (Boxed_integer bi)
+        | Pmodbint bi -> Boxed (Boxed_integer bi)
+        | Pandbint bi -> Boxed (Boxed_integer bi)
+        | Porbint bi -> Boxed (Boxed_integer bi)
+        | Pxorbint bi -> Boxed (Boxed_integer bi)
+        | Plslbint bi -> Boxed (Boxed_integer bi)
+        | Plsrbint bi -> Boxed (Boxed_integer bi)
+        | Pasrbint bi -> Boxed (Boxed_integer bi)
         | Pbigarrayref(_, _, (Pbigarray_float32 | Pbigarray_float64), _) ->
-            Boxed_float
-        | Pbigarrayref(_, _, Pbigarray_int32, _) -> Boxed_integer Pint32
-        | Pbigarrayref(_, _, Pbigarray_int64, _) -> Boxed_integer Pint64
-        | Pbigarrayref(_, _, Pbigarray_native_int,_) -> Boxed_integer Pnativeint
-        | Pstring_load_32(_) -> Boxed_integer Pint32
-        | Pstring_load_64(_) -> Boxed_integer Pint64
-        | Pbigstring_load_32(_) -> Boxed_integer Pint32
-        | Pbigstring_load_64(_) -> Boxed_integer Pint64
-        | Pbbswap bi -> Boxed_integer bi
+            Boxed Boxed_float
+        | Pbigarrayref(_, _, Pbigarray_int32, _) -> Boxed (Boxed_integer Pint32)
+        | Pbigarrayref(_, _, Pbigarray_int64, _) -> Boxed (Boxed_integer Pint64)
+        | Pbigarrayref(_, _, Pbigarray_native_int,_) ->
+            Boxed (Boxed_integer Pnativeint)
+        | Pstring_load_32(_) -> Boxed (Boxed_integer Pint32)
+        | Pstring_load_64(_) -> Boxed (Boxed_integer Pint64)
+        | Pbigstring_load_32(_) -> Boxed (Boxed_integer Pint32)
+        | Pbigstring_load_64(_) -> Boxed (Boxed_integer Pint64)
+        | Pbbswap bi -> Boxed (Boxed_integer bi)
+        | Praise _ -> No_result
         | _ -> No_unboxing
       end
-  | Ulet (_, _, e) | Usequence (_, e) -> is_unboxed_number e
-  | _ -> No_unboxing
-
-let subst_boxed_number unbox_fn boxed_id unboxed_id box_chunk box_offset exp =
-  let need_boxed = ref false in
-  let assigned = ref false in
-  let rec subst = function
-      Cvar id as e ->
-        if Ident.same id boxed_id then need_boxed := true; e
-    | Clet(id, arg, body) -> Clet(id, subst arg, subst body)
-    | Cassign(id, arg) ->
-        if Ident.same id boxed_id then begin
-          assigned := true;
-          Cassign(unboxed_id, subst(unbox_fn arg))
-        end else
-          Cassign(id, subst arg)
-    | Ctuple argv -> Ctuple(List.map subst argv)
-    | Cop(Cload chunk, [Cvar id]) as e ->
-      if not (Ident.same id boxed_id) then e
-      else if chunk = box_chunk && box_offset = 0 then
-        Cvar unboxed_id
-      else begin
-        need_boxed := true;
-        e
+  | Ulet (_, _, e) | Uletrec (_, e) | Usequence (_, e) ->
+      is_unboxed_number env e
+  | Uswitch (_, switch) ->
+      let k = Array.fold_left join No_result switch.us_actions_consts in
+      Array.fold_left join k switch.us_actions_blocks
+  | Ustringswitch (_, actions, default_opt) ->
+      let k = List.fold_left (fun k (_, e) -> join k e) No_result actions in
+      begin match default_opt with
+        None -> k
+      | Some default -> join k default
       end
-    | Cop(Cload chunk, [Cop(Cadda, [Cvar id; Cconst_int ofs])]) as e ->
-      if not (Ident.same id boxed_id) then e
-      else if chunk = box_chunk && ofs = box_offset then
-        Cvar unboxed_id
-      else begin
-        need_boxed := true;
-        e
-      end
-    | Cop(op, argv) -> Cop(op, List.map subst argv)
-    | Csequence(e1, e2) -> Csequence(subst e1, subst e2)
-    | Cifthenelse(e1, e2, e3) -> Cifthenelse(subst e1, subst e2, subst e3)
-    | Cswitch(arg, index, cases) ->
-        Cswitch(subst arg, index, Array.map subst cases)
-    | Cloop e -> Cloop(subst e)
-    | Ccatch(nfail, ids, e1, e2) -> Ccatch(nfail, ids, subst e1, subst e2)
-    | Cexit (nfail, el) -> Cexit (nfail, List.map subst el)
-    | Ctrywith(e1, id, e2) -> Ctrywith(subst e1, id, subst e2)
-    | Cconst_int _ | Cconst_natint _ | Cconst_float _ | Cconst_symbol _
-    | Cconst_pointer _ | Cconst_natpointer _
-    | Cconst_blockheader _ as e -> e
-  in
-  let res = subst exp in
-  (res, !need_boxed, !assigned)
+  | Ustaticfail _ -> No_result
+  | Uifthenelse (_, e1, e2) | Ucatch (_, _, e1, e2) | Utrywith (e1, _, e2) ->
+      join (is_unboxed_number env e1) e2
+  | _ -> No_unboxing
 
 (* Translate an expression *)
 
@@ -1298,14 +1421,19 @@ let strmatch_compile =
       end) in
   S.compile
 
-let rec transl = function
+let rec transl env e =
+  match e with
     Uvar id ->
-      Cvar id
+      begin match is_unboxed_id id env with
+      | None -> Cvar id
+      | Some (unboxed_id, bn) -> box_number bn (Cvar unboxed_id)
+      end
   | Uconst sc ->
       transl_constant sc
   | Uclosure(fundecls, []) ->
       let lbl = Compilenv.new_const_symbol() in
-      constant_closures := (lbl, fundecls) :: !constant_closures;
+      constant_closures :=
+        ((lbl, Not_global), fundecls, []) :: !constant_closures;
       List.iter (fun f -> Queue.add f functions) fundecls;
       Cconst_symbol lbl
   | Uclosure(fundecls, clos_vars) ->
@@ -1313,17 +1441,17 @@ let rec transl = function
         fundecls_size fundecls + List.length clos_vars in
       let rec transl_fundecls pos = function
           [] ->
-            List.map transl clos_vars
+            List.map (transl env) clos_vars
         | f :: rem ->
             Queue.add f functions;
             let header =
               if pos = 0
               then alloc_closure_header block_size
               else alloc_infix_header pos in
-            if f.arity = 1 then
+            if f.arity = 1 || f.arity = 0 then
               header ::
               Cconst_symbol f.label ::
-              int_const 1 ::
+              int_const f.arity ::
               transl_fundecls (pos + 3) rem
             else
               header ::
@@ -1333,52 +1461,45 @@ let rec transl = function
               transl_fundecls (pos + 4) rem in
       Cop(Calloc, transl_fundecls 0 fundecls)
   | Uoffset(arg, offset) ->
-      field_address (transl 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)])
   | Udirect_apply(lbl, args, dbg) ->
-      Cop(Capply(typ_addr, dbg), Cconst_symbol lbl :: List.map transl args)
+      Cop(Capply(typ_val, dbg), Cconst_symbol lbl :: List.map (transl env) args)
   | Ugeneric_apply(clos, [arg], dbg) ->
-      bind "fun" (transl clos) (fun clos ->
-        Cop(Capply(typ_addr, dbg), [get_field clos 0; transl arg; clos]))
+      bind "fun" (transl env clos) (fun clos ->
+        Cop(Capply(typ_val, dbg), [get_field clos 0; transl env arg; clos]))
   | Ugeneric_apply(clos, args, dbg) ->
       let arity = List.length args in
       let cargs = Cconst_symbol(apply_function arity) ::
-        List.map transl (args @ [clos]) in
-      Cop(Capply(typ_addr, dbg), cargs)
+        List.map (transl env) (args @ [clos]) in
+      Cop(Capply(typ_val, dbg), cargs)
   | Usend(kind, met, obj, args, dbg) ->
       let call_met obj args clos =
         if args = [] then
-          Cop(Capply(typ_addr, dbg), [get_field clos 0;obj;clos])
+          Cop(Capply(typ_val, dbg), [get_field clos 0;obj;clos])
         else
           let arity = List.length args + 1 in
           let cargs = Cconst_symbol(apply_function arity) :: obj ::
-            (List.map transl args) @ [clos] in
-          Cop(Capply(typ_addr, dbg), cargs)
+            (List.map (transl env) args) @ [clos] in
+          Cop(Capply(typ_val, dbg), cargs)
       in
-      bind "obj" (transl obj) (fun obj ->
+      bind "obj" (transl env obj) (fun obj ->
         match kind, args with
           Self, _ ->
-            bind "met" (lookup_label obj (transl met)) (call_met obj args)
+            bind "met" (lookup_label obj (transl env met)) (call_met obj args)
         | Cached, cache :: pos :: args ->
-            call_cached_method obj (transl met) (transl cache) (transl pos)
-              (List.map transl args) dbg
+            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 met)) (call_met obj args))
+            bind "met" (lookup_tag obj (transl env met)) (call_met obj args))
   | Ulet(id, exp, body) ->
-      begin match is_unboxed_number exp with
-        No_unboxing ->
-          Clet(id, transl exp, transl body)
-      | Boxed_float ->
-          transl_unbox_let box_float unbox_float transl_unbox_float
-                           Double_u 0
-                           id exp body
-      | Boxed_integer bi ->
-          transl_unbox_let (box_int bi) (unbox_int bi) (transl_unbox_int bi)
-                           (if bi = Pint32 then Thirtytwo_signed else Word)
-                           size_addr
-                           id exp body
-      end
+      transl_let env id exp body
   | Uletrec(bindings, body) ->
-      transl_letrec bindings (transl body)
+      transl_letrec env bindings (transl env body)
 
   (* Primitives *)
   | Uprim(prim, args, dbg) ->
@@ -1388,33 +1509,34 @@ let rec transl = function
       | (Pmakeblock(tag, mut), []) ->
           assert false
       | (Pmakeblock(tag, mut), args) ->
-          make_alloc tag (List.map transl args)
+          make_alloc tag (List.map (transl env) args)
       | (Pccall prim, args) ->
-          if prim.prim_native_float then
-            box_float
-              (Cop(Cextcall(prim.prim_native_name, typ_float, false, dbg),
-                   List.map transl_unbox_float args))
-          else
-            Cop(Cextcall(Primitive.native_name prim, typ_addr, prim.prim_alloc,
-                         dbg),
-                List.map transl args)
-      | (Pmakearray kind, []) ->
+          transl_ccall env prim args dbg
+      | (Pduparray (kind, _), [Uprim (Pmakearray (kind', _), args, _dbg)]) ->
+          (* We arrive here in two cases:
+             1. When using Closure, all the time.
+             2. When using Flambda, if a float array longer than
+             [Translcore.use_dup_for_constant_arrays_bigger_than] turns out
+             to be non-constant.
+             If for some reason Flambda fails to lift a constant array we
+             could in theory also end up here.
+             Note that [kind] above is unconstrained, but with the current
+             state of [Translcore], we will in fact only get here with
+             [Pfloatarray]s. *)
+          assert (kind = kind');
+          transl_make_array env kind args
+      | (Pduparray _, [arg]) ->
+          let prim_obj_dup =
+            Primitive.simple ~name:"caml_obj_dup" ~arity:1 ~alloc:true
+          in
+          transl_ccall env prim_obj_dup [arg] dbg
+      | (Pmakearray (kind, _), []) ->
           transl_structured_constant (Uconst_block(0, []))
-      | (Pmakearray kind, args) ->
-          begin match kind with
-            Pgenarray ->
-              Cop(Cextcall("caml_make_array", typ_addr, true, Debuginfo.none),
-                  [make_alloc 0 (List.map transl args)])
-          | Paddrarray | Pintarray ->
-              make_alloc 0 (List.map transl args)
-          | Pfloatarray ->
-              make_float_alloc Obj.double_array_tag
-                              (List.map transl_unbox_float args)
-          end
+      | (Pmakearray (kind, _), args) -> transl_make_array env kind args
       | (Pbigarrayref(unsafe, num_dims, elt_kind, layout), arg1 :: argl) ->
           let elt =
             bigarray_get unsafe elt_kind layout
-              (transl arg1) (List.map transl argl) dbg in
+              (transl env arg1) (List.map (transl env) argl) dbg in
           begin match elt_kind with
             Pbigarray_float32 | Pbigarray_float64 -> box_float elt
           | Pbigarray_complex32 | Pbigarray_complex64 -> elt
@@ -1427,26 +1549,26 @@ let rec transl = function
       | (Pbigarrayset(unsafe, num_dims, elt_kind, layout), arg1 :: argl) ->
           let (argidx, argnewval) = split_last argl in
           return_unit(bigarray_set unsafe elt_kind layout
-            (transl arg1)
-            (List.map transl argidx)
+            (transl env arg1)
+            (List.map (transl env) argidx)
             (match elt_kind with
               Pbigarray_float32 | Pbigarray_float64 ->
-                transl_unbox_float argnewval
-            | Pbigarray_complex32 | Pbigarray_complex64 -> transl argnewval
-            | Pbigarray_int32 -> transl_unbox_int Pint32 argnewval
-            | Pbigarray_int64 -> transl_unbox_int Pint64 argnewval
-            | Pbigarray_native_int -> transl_unbox_int Pnativeint argnewval
-            | _ -> untag_int (transl argnewval))
+                transl_unbox_float 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))
             dbg)
       | (Pbigarraydim(n), [b]) ->
           let dim_ofs = 4 + n in
-          tag_int (Cop(Cload Word, [field_address (transl b) dim_ofs]))
+          tag_int (Cop(Cload Word_int, [field_address (transl env b) dim_ofs]))
       | (p, [arg]) ->
-          transl_prim_1 p arg dbg
+          transl_prim_1 env p arg dbg
       | (p, [arg1; arg2]) ->
-          transl_prim_2 p arg1 arg2 dbg
+          transl_prim_2 env p arg1 arg2 dbg
       | (p, [arg1; arg2; arg3]) ->
-          transl_prim_3 p arg1 arg2 arg3 dbg
+          transl_prim_3 env p arg1 arg2 arg3 dbg
       | (_, _) ->
           fatal_error "Cmmgen.transl:prim"
       end
@@ -1457,73 +1579,75 @@ let rec transl = function
          can be checked *)
       if Array.length s.us_index_blocks = 0 then
         Cswitch
-          (untag_int (transl arg),
+          (untag_int (transl env arg),
            s.us_index_consts,
-           Array.map transl s.us_actions_consts)
+           Array.map (transl env) s.us_actions_consts)
       else if Array.length s.us_index_consts = 0 then
-        transl_switch (get_tag (transl arg))
+        transl_switch env (get_tag (transl env arg))
           s.us_index_blocks s.us_actions_blocks
       else
-        bind "switch" (transl arg) (fun arg ->
+        bind "switch" (transl env arg) (fun arg ->
           Cifthenelse(
           Cop(Cand, [arg; Cconst_int 1]),
-          transl_switch
+          transl_switch env
             (untag_int arg) s.us_index_consts s.us_actions_consts,
-          transl_switch
+          transl_switch env
             (get_tag arg) s.us_index_blocks s.us_actions_blocks))
   | Ustringswitch(arg,sw,d) ->
-      bind "switch" (transl arg)
+      bind "switch" (transl env arg)
         (fun arg ->
-          strmatch_compile arg (Misc.may_map transl d)
-            (List.map (fun (s,act) -> s,transl act) sw))
+          strmatch_compile 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 args)
+      Cexit (nfail, List.map (transl env) args)
   | Ucatch(nfail, [], body, handler) ->
-      make_catch nfail (transl body) (transl handler)
+      make_catch nfail (transl env body) (transl env handler)
   | Ucatch(nfail, ids, body, handler) ->
-      Ccatch(nfail, ids, transl body, transl handler)
+      Ccatch(nfail, ids, transl env body, transl env handler)
   | Utrywith(body, exn, handler) ->
-      Ctrywith(transl body, exn, transl handler)
+      Ctrywith(transl env body, exn, transl env handler)
   | Uifthenelse(Uprim(Pnot, [arg], _), ifso, ifnot) ->
-      transl (Uifthenelse(arg, ifnot, ifso))
+      transl env (Uifthenelse(arg, ifnot, ifso))
   | Uifthenelse(cond, ifso, Ustaticfail (nfail, [])) ->
-      exit_if_false cond (transl ifso) nfail
+      exit_if_false env cond (transl env ifso) nfail
   | Uifthenelse(cond, Ustaticfail (nfail, []), ifnot) ->
-      exit_if_true cond nfail (transl ifnot)
+      exit_if_true env cond nfail (transl env ifnot)
   | Uifthenelse(Uprim(Psequand, _, _) as cond, ifso, ifnot) ->
       let raise_num = next_raise_count () in
       make_catch
         raise_num
-        (exit_if_false cond (transl ifso) raise_num)
-        (transl ifnot)
+        (exit_if_false env cond (transl env ifso) raise_num)
+        (transl env ifnot)
   | Uifthenelse(Uprim(Psequor, _, _) as cond, ifso, ifnot) ->
       let raise_num = next_raise_count () in
       make_catch
         raise_num
-        (exit_if_true cond raise_num (transl ifnot))
-        (transl ifso)
+        (exit_if_true env cond raise_num (transl env ifnot))
+        (transl env ifso)
   | Uifthenelse (Uifthenelse (cond, condso, condnot), ifso, ifnot) ->
       let num_true = next_raise_count () in
       make_catch
         num_true
         (make_catch2
            (fun shared_false ->
-             Cifthenelse
-               (test_bool (transl cond),
-                exit_if_true condso num_true shared_false,
-                exit_if_true condnot num_true shared_false))
-           (transl ifnot))
-        (transl ifso)
+             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))
+           (transl env ifnot))
+        (transl env ifso)
   | Uifthenelse(cond, ifso, ifnot) ->
-      Cifthenelse(test_bool(transl cond), transl ifso, transl ifnot)
+      if_then_else(test_bool(transl env cond), transl env ifso,
+        transl env ifnot)
   | Usequence(exp1, exp2) ->
-      Csequence(remove_unit(transl exp1), transl exp2)
+      Csequence(remove_unit(transl env exp1), transl env exp2)
   | Uwhile(cond, body) ->
       let raise_num = next_raise_count () in
       return_unit
         (Ccatch
            (raise_num, [],
-            Cloop(exit_if_false cond (remove_unit(transl body)) raise_num),
+            Cloop(exit_if_false env cond
+                    (remove_unit(transl env body)) raise_num),
             Ctuple []))
   | Ufor(id, low, high, dir, body) ->
       let tst = match dir with Upto -> Cgt   | Downto -> Clt in
@@ -1532,15 +1656,15 @@ let rec transl = function
       let id_prev = Ident.rename id in
       return_unit
         (Clet
-           (id, transl low,
-            bind_nonvar "bound" (transl high) (fun high ->
+           (id, transl env low,
+            bind_nonvar "bound" (transl env high) (fun high ->
               Ccatch
                 (raise_num, [],
                  Cifthenelse
                    (Cop(Ccmpi tst, [Cvar id; high]), Cexit (raise_num, []),
                     Cloop
                       (Csequence
-                         (remove_unit(transl body),
+                         (remove_unit(transl env body),
                          Clet(id_prev, Cvar id,
                           Csequence
                             (Cassign(id,
@@ -1550,98 +1674,151 @@ let rec transl = function
                                 Cexit (raise_num,[]), Ctuple [])))))),
                  Ctuple []))))
   | Uassign(id, exp) ->
-      return_unit(Cassign(id, transl exp))
+      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))
+      end
+  | Uunreachable ->
+      Cop(Cload Word_int, [Cconst_int 0])
+
+and transl_make_array env kind args =
+  match kind with
+  | Pgenarray ->
+      Cop(Cextcall("caml_make_array", typ_val, true, Debuginfo.none),
+          [make_alloc 0 (List.map (transl env) args)])
+  | Paddrarray | Pintarray ->
+      make_alloc 0 (List.map (transl env) args)
+  | Pfloatarray ->
+      make_float_alloc Obj.double_array_tag
+                      (List.map (transl_unbox_float 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)
+  in
+  let rec transl_args native_repr_args args =
+    match native_repr_args, args with
+    | [], args ->
+        (* We don't require the two lists to be of the same length as
+           [default_prim] always sets the arity to [0]. *)
+        List.map (transl env) args
+    | _, [] -> assert false
+    | native_repr :: native_repr_args, arg :: args ->
+        transl_arg native_repr arg :: transl_args native_repr_args args
+  in
+  let typ_res, wrap_result =
+    match prim.prim_native_repr_res with
+    | Same_as_ocaml_repr -> (typ_val, fun x -> x)
+    | Unboxed_float -> (typ_float, box_float)
+    | Unboxed_integer Pint64 when size_int = 4 -> ([|Int; Int|], box_int Pint64)
+    | Unboxed_integer bi -> (typ_int, box_int bi)
+    | Untagged_int -> (typ_int, tag_int)
+  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), args))
 
-and transl_prim_1 p arg dbg =
+and transl_prim_1 env p arg dbg =
   match p with
   (* Generic operations *)
-    Pidentity ->
-      transl arg
+    Pidentity | Popaque ->
+      transl env arg
   | Pignore ->
-      return_unit(remove_unit (transl arg))
+      return_unit(remove_unit (transl env arg))
   (* Heap operations *)
   | Pfield n ->
-      get_field (transl arg) n
+      get_field (transl env arg) n
   | Pfloatfield n ->
-      let ptr = transl arg in
+      let ptr = transl env arg in
       box_float(
         Cop(Cload Double_u,
             [if n = 0 then ptr
                        else Cop(Cadda, [ptr; Cconst_int(n * size_float)])]))
   | Pint_as_pointer ->
-     Cop(Cadda, [transl arg; Cconst_int (-1)])
+     Cop(Caddi, [transl env arg; Cconst_int (-1)])
+     (* always a pointer outside the heap *)
   (* Exceptions *)
   | Praise k ->
-      Cop(Craise (k, dbg), [transl arg])
+      Cop(Craise (k, dbg), [transl env arg])
   (* Integer operations *)
   | Pnegint ->
-      Cop(Csubi, [Cconst_int 2; transl arg])
+      Cop(Csubi, [Cconst_int 2; transl env arg])
   | Pctconst c ->
       let const_of_bool b = tag_int (Cconst_int (if b then 1 else 0)) 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))
+        | Max_wosize ->
+            tag_int (Cconst_int ((1 lsl ((8*Arch.size_int) - 10)) - 1 ))
         | 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")
       end
   | Poffsetint n ->
-      if no_overflow_lsl n then
-        add_const (transl arg) (n lsl 1)
+      if no_overflow_lsl n 1 then
+        add_const (transl env arg) (n lsl 1)
       else
-        transl_prim_2 Paddint arg (Uconst (Uconst_int n))
+        transl_prim_2 env Paddint arg (Uconst (Uconst_int n))
                       Debuginfo.none
   | Poffsetref n ->
       return_unit
-        (bind "ref" (transl arg) (fun arg ->
-          Cop(Cstore Word,
-              [arg; add_const (Cop(Cload Word, [arg])) (n lsl 1)])))
+        (bind "ref" (transl env arg) (fun arg ->
+          Cop(Cstore (Word_int, Assignment),
+              [arg; add_const (Cop(Cload Word_int, [arg])) (n lsl 1)])))
   (* Floating-point operations *)
   | Pfloatofint ->
-      box_float(Cop(Cfloatofint, [untag_int(transl arg)]))
+      box_float(Cop(Cfloatofint, [untag_int(transl env arg)]))
   | Pintoffloat ->
-     tag_int(Cop(Cintoffloat, [transl_unbox_float arg]))
+     tag_int(Cop(Cintoffloat, [transl_unbox_float env arg]))
   | Pnegfloat ->
-      box_float(Cop(Cnegf, [transl_unbox_float arg]))
+      box_float(Cop(Cnegf, [transl_unbox_float env arg]))
   | Pabsfloat ->
-      box_float(Cop(Cabsf, [transl_unbox_float arg]))
+      box_float(Cop(Cabsf, [transl_unbox_float env arg]))
   (* String operations *)
   | Pstringlength ->
-      tag_int(string_length (transl arg))
+      tag_int(string_length (transl env arg))
   (* Array operations *)
   | Parraylength kind ->
       begin match kind with
         Pgenarray ->
           let len =
             if wordsize_shift = numfloat_shift then
-              Cop(Clsr, [header(transl arg); Cconst_int wordsize_shift])
+              Cop(Clsr, [header(transl env arg); Cconst_int wordsize_shift])
             else
-              bind "header" (header(transl arg)) (fun hdr ->
+              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])
       | Paddrarray | Pintarray ->
-          Cop(Cor, [addr_array_length(header(transl arg)); Cconst_int 1])
+          Cop(Cor, [addr_array_length(header(transl env arg)); Cconst_int 1])
       | Pfloatarray ->
-          Cop(Cor, [float_array_length(header(transl arg)); Cconst_int 1])
+          Cop(Cor, [float_array_length(header(transl env arg)); Cconst_int 1])
       end
   (* Boolean operations *)
   | Pnot ->
-      Cop(Csubi, [Cconst_int 4; transl arg]) (* 1 -> 3, 3 -> 1 *)
+      Cop(Csubi, [Cconst_int 4; transl env arg]) (* 1 -> 3, 3 -> 1 *)
   (* Test integer/block *)
   | Pisint ->
-      tag_int(Cop(Cand, [transl arg; Cconst_int 1]))
+      tag_int(Cop(Cand, [transl env arg; Cconst_int 1]))
   (* Boxed integers *)
   | Pbintofint bi ->
-      box_int bi (untag_int (transl arg))
+      box_int bi (untag_int (transl env arg))
   | Pintofbint bi ->
-      force_tag_int (transl_unbox_int bi arg)
+      force_tag_int (transl_unbox_int env bi arg)
   | Pcvtbint(bi1, bi2) ->
-      box_int bi2 (transl_unbox_int bi1 arg)
+      box_int bi2 (transl_unbox_int env bi1 arg)
   | Pnegbint bi ->
-      box_int bi (Cop(Csubi, [Cconst_int 0; transl_unbox_int bi arg]))
+      box_int bi (Cop(Csubi, [Cconst_int 0; transl_unbox_int env bi arg]))
   | Pbbswap bi ->
       let prim = match bi with
         | Pnativeint -> "nativeint"
@@ -1649,145 +1826,169 @@ and transl_prim_1 p arg dbg =
         | Pint64 -> "int64" in
       box_int bi (Cop(Cextcall(Printf.sprintf "caml_%s_direct_bswap" prim,
                                typ_int, false, Debuginfo.none),
-                      [transl_unbox_int bi arg]))
+                      [transl_unbox_int env bi arg]))
   | Pbswap16 ->
       tag_int (Cop(Cextcall("caml_bswap16_direct", typ_int, false,
                             Debuginfo.none),
-                   [untag_int (transl arg)]))
-  | _ ->
-      fatal_error "Cmmgen.transl_prim_1"
+                   [untag_int (transl env arg)]))
+  | prim ->
+      fatal_errorf "Cmmgen.transl_prim_1: %a" Printlambda.primitive prim
 
-and transl_prim_2 p arg1 arg2 dbg =
+and transl_prim_2 env p arg1 arg2 dbg =
   match p with
   (* Heap operations *)
-    Psetfield(n, ptr) ->
-      if ptr then
+    Psetfield(n, ptr, init) ->
+      begin match init, ptr with
+      | Assignment, Pointer ->
         return_unit(Cop(Cextcall("caml_modify", typ_void, false,Debuginfo.none),
-                        [field_address (transl arg1) n; transl arg2]))
-      else
-        return_unit(set_field (transl arg1) n (transl arg2))
-  | Psetfloatfield n ->
-      let ptr = transl arg1 in
+                        [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)
+      end
+  | Psetfloatfield (n, init) ->
+      let ptr = transl env arg1 in
       return_unit(
-        Cop(Cstore Double_u,
+        Cop(Cstore (Double_u, init),
             [if n = 0 then ptr
                        else Cop(Cadda, [ptr; Cconst_int(n * size_float)]);
-                   transl_unbox_float arg2]))
+                   transl_unbox_float env arg2]))
 
   (* Boolean operations *)
   | Psequand ->
-      Cifthenelse(test_bool(transl arg1), transl arg2, Cconst_int 1)
+      if_then_else(test_bool(transl env arg1), transl env arg2, Cconst_int 1)
       (* let id = Ident.create "res1" in
-      Clet(id, transl arg1,
-           Cifthenelse(test_bool(Cvar id), transl arg2, Cvar id)) *)
+      Clet(id, transl env arg1,
+           Cifthenelse(test_bool(Cvar id), transl env arg2, Cvar id)) *)
   | Psequor ->
-      Cifthenelse(test_bool(transl arg1), Cconst_int 3, transl arg2)
+      if_then_else(test_bool(transl env arg1), Cconst_int 3, transl env arg2)
 
   (* Integer operations *)
   | Paddint ->
-      decr_int(add_int (transl arg1) (transl arg2))
+      decr_int(add_int (transl env arg1) (transl env arg2))
   | Psubint ->
-      incr_int(sub_int (transl arg1) (transl arg2))
+      incr_int(sub_int (transl env arg1) (transl env arg2))
   | Pmulint ->
-      incr_int(mul_int (decr_int(transl arg1)) (untag_int(transl arg2)))
+     begin
+       (* decrementing the non-constant part helps when the multiplication is
+          followed by an addition;
+          for example, using this trick compiles (100 * a + 7) into
+            (+ ( * a 100) -85)
+          rather than
+            (+ ( * 200 (>>s a 1)) 15)
+        *)
+       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))
+     end
   | Pdivint ->
-      tag_int(div_int (untag_int(transl arg1)) (untag_int(transl arg2)) dbg)
+      tag_int(div_int (untag_int(transl env arg1))
+        (untag_int(transl env arg2)) dbg)
   | Pmodint ->
-      tag_int(mod_int (untag_int(transl arg1)) (untag_int(transl arg2)) dbg)
+      tag_int(mod_int (untag_int(transl env arg1))
+        (untag_int(transl env arg2)) dbg)
   | Pandint ->
-      Cop(Cand, [transl arg1; transl arg2])
+      Cop(Cand, [transl env arg1; transl env arg2])
   | Porint ->
-      Cop(Cor, [transl arg1; transl arg2])
+      Cop(Cor, [transl env arg1; transl env arg2])
   | Pxorint ->
-      Cop(Cor, [Cop(Cxor, [ignore_low_bit_int(transl arg1);
-                           ignore_low_bit_int(transl arg2)]);
+      Cop(Cor, [Cop(Cxor, [ignore_low_bit_int(transl env arg1);
+                           ignore_low_bit_int(transl env arg2)]);
                 Cconst_int 1])
   | Plslint ->
-      incr_int(lsl_int (decr_int(transl arg1)) (untag_int(transl arg2)))
+      incr_int(lsl_int (decr_int(transl env arg1)) (untag_int(transl env arg2)))
   | Plsrint ->
-      Cop(Cor, [lsr_int (transl arg1) (untag_int(transl arg2));
+      Cop(Cor, [lsr_int (transl env arg1) (untag_int(transl env arg2));
                 Cconst_int 1])
   | Pasrint ->
-      Cop(Cor, [asr_int (transl arg1) (untag_int(transl arg2));
+      Cop(Cor, [asr_int (transl env arg1) (untag_int(transl env arg2));
                 Cconst_int 1])
   | Pintcomp cmp ->
-      tag_int(Cop(Ccmpi(transl_comparison cmp), [transl arg1; transl arg2]))
+      tag_int(Cop(Ccmpi(transl_comparison cmp),
+                  [transl env arg1; transl env arg2]))
   | Pisout ->
-      transl_isout (transl arg1) (transl arg2)
+      transl_isout (transl env arg1) (transl env arg2)
   (* Float operations *)
   | Paddfloat ->
       box_float(Cop(Caddf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Psubfloat ->
       box_float(Cop(Csubf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Pmulfloat ->
       box_float(Cop(Cmulf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Pdivfloat ->
       box_float(Cop(Cdivf,
-                    [transl_unbox_float arg1; transl_unbox_float arg2]))
+                    [transl_unbox_float env arg1; transl_unbox_float env arg2]))
   | Pfloatcomp cmp ->
       tag_int(Cop(Ccmpf(transl_comparison cmp),
-                  [transl_unbox_float arg1; transl_unbox_float arg2]))
+                  [transl_unbox_float env arg1; transl_unbox_float env arg2]))
 
   (* String operations *)
   | Pstringrefu ->
       tag_int(Cop(Cload Byte_unsigned,
-                  [add_int (transl arg1) (untag_int(transl arg2))]))
+                  [add_int (transl env arg1) (untag_int(transl env arg2))]))
   | Pstringrefs ->
       tag_int
-        (bind "str" (transl arg1) (fun str ->
-          bind "index" (untag_int (transl arg2)) (fun idx ->
+        (bind "str" (transl env arg1) (fun str ->
+          bind "index" (untag_int (transl env arg2)) (fun idx ->
             Csequence(
               make_checkbound dbg [string_length str; idx],
               Cop(Cload Byte_unsigned, [add_int str idx])))))
 
   | Pstring_load_16(unsafe) ->
      tag_int
-       (bind "str" (transl arg1) (fun str ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
+       (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))))
 
   | Pbigstring_load_16(unsafe) ->
      tag_int
-       (bind "ba" (transl arg1) (fun ba ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+       (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]))
+         (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)))))
 
   | Pstring_load_32(unsafe) ->
      box_int Pint32
-       (bind "str" (transl arg1) (fun str ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
+       (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))))
 
   | Pbigstring_load_32(unsafe) ->
      box_int Pint32
-       (bind "ba" (transl arg1) (fun ba ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+       (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]))
+         (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)))))
 
   | Pstring_load_64(unsafe) ->
      box_int Pint64
-       (bind "str" (transl arg1) (fun str ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
+       (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))))
 
   | Pbigstring_load_64(unsafe) ->
      box_int Pint64
-       (bind "ba" (transl arg1) (fun ba ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+       (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]))
+         (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)))))
 
@@ -1795,21 +1996,23 @@ and transl_prim_2 p arg1 arg2 dbg =
   | Parrayrefu kind ->
       begin match kind with
         Pgenarray ->
-          bind "arr" (transl arg1) (fun arr ->
-            bind "index" (transl arg2) (fun idx ->
+          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,
                           float_array_ref arr idx)))
-      | Paddrarray | Pintarray ->
-          addr_array_ref (transl arg1) (transl arg2)
+      | Paddrarray ->
+          addr_array_ref (transl env arg1) (transl env arg2)
+      | Pintarray ->
+          int_array_ref (transl env arg1) (transl env arg2)
       | Pfloatarray ->
-          float_array_ref (transl arg1) (transl arg2)
+          float_array_ref (transl env arg1) (transl env arg2)
       end
   | Parrayrefs kind ->
       begin match kind with
       | Pgenarray ->
-          bind "index" (transl arg2) (fun idx ->
-          bind "arr" (transl arg1) (fun arr ->
+          bind "index" (transl env arg2) (fun idx ->
+          bind "arr" (transl env arg1) (fun arr ->
           bind "header" (header arr) (fun hdr ->
             if wordsize_shift = numfloat_shift then
               Csequence(make_checkbound dbg [addr_array_length hdr; idx],
@@ -1822,15 +2025,20 @@ and transl_prim_2 p arg1 arg2 dbg =
                           addr_array_ref arr idx),
                 Csequence(make_checkbound dbg [float_array_length hdr; idx],
                           float_array_ref arr idx)))))
-      | Paddrarray | Pintarray ->
-          bind "index" (transl arg2) (fun idx ->
-          bind "arr" (transl arg1) (fun arr ->
+      | 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)))
+      | 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)))
       | Pfloatarray ->
           box_float(
-            bind "index" (transl arg2) (fun idx ->
-            bind "arr" (transl arg1) (fun arr ->
+            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))))
@@ -1838,10 +2046,10 @@ and transl_prim_2 p arg1 arg2 dbg =
 
   (* Operations on bitvects *)
   | Pbittest ->
-      bind "index" (untag_int(transl arg2)) (fun idx ->
+      bind "index" (untag_int(transl env arg2)) (fun idx ->
         tag_int(
           Cop(Cand, [Cop(Clsr, [Cop(Cload Byte_unsigned,
-                                    [add_int (transl arg1)
+                                    [add_int (transl env arg1)
                                       (Cop(Clsr, [idx; Cconst_int 3]))]);
                                 Cop(Cand, [idx; Cconst_int 7])]);
                      Cconst_int 1])))
@@ -1849,85 +2057,97 @@ and transl_prim_2 p arg1 arg2 dbg =
   (* Boxed integers *)
   | Paddbint bi ->
       box_int bi (Cop(Caddi,
-                      [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+                      [transl_unbox_int env bi arg1;
+                       transl_unbox_int env bi arg2]))
   | Psubbint bi ->
       box_int bi (Cop(Csubi,
-                      [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+                      [transl_unbox_int env bi arg1;
+                       transl_unbox_int env bi arg2]))
   | Pmulbint bi ->
       box_int bi (Cop(Cmuli,
-                      [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+                      [transl_unbox_int env bi arg1;
+                       transl_unbox_int env bi arg2]))
   | Pdivbint bi ->
       box_int bi (safe_div_bi
-                      (transl_unbox_int bi arg1) (transl_unbox_int bi arg2)
+                      (transl_unbox_int env bi arg1)
+                      (transl_unbox_int env bi arg2)
                       bi dbg)
   | Pmodbint bi ->
       box_int bi (safe_mod_bi
-                      (transl_unbox_int bi arg1) (transl_unbox_int bi arg2)
+                      (transl_unbox_int env bi arg1)
+                      (transl_unbox_int env bi arg2)
                       bi dbg)
   | Pandbint bi ->
       box_int bi (Cop(Cand,
-                     [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+                     [transl_unbox_int env bi arg1;
+                      transl_unbox_int env bi arg2]))
   | Porbint bi ->
       box_int bi (Cop(Cor,
-                     [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+                     [transl_unbox_int env bi arg1;
+                      transl_unbox_int env bi arg2]))
   | Pxorbint bi ->
       box_int bi (Cop(Cxor,
-                     [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
+                     [transl_unbox_int env bi arg1;
+                      transl_unbox_int env bi arg2]))
   | Plslbint bi ->
       box_int bi (Cop(Clsl,
-                     [transl_unbox_int bi arg1; untag_int(transl arg2)]))
+                     [transl_unbox_int env bi arg1;
+                      untag_int(transl env arg2)]))
   | Plsrbint bi ->
       box_int bi (Cop(Clsr,
-                     [make_unsigned_int bi (transl_unbox_int bi arg1);
-                      untag_int(transl arg2)]))
+                     [make_unsigned_int bi (transl_unbox_int env bi arg1);
+                      untag_int(transl env arg2)]))
   | Pasrbint bi ->
       box_int bi (Cop(Casr,
-                     [transl_unbox_int bi arg1; untag_int(transl arg2)]))
+                     [transl_unbox_int env bi arg1;
+                      untag_int(transl env arg2)]))
   | Pbintcomp(bi, cmp) ->
       tag_int (Cop(Ccmpi(transl_comparison cmp),
-                     [transl_unbox_int bi arg1; transl_unbox_int bi arg2]))
-  | _ ->
-      fatal_error "Cmmgen.transl_prim_2"
+                     [transl_unbox_int env bi arg1;
+                      transl_unbox_int env bi arg2]))
+  | prim ->
+      fatal_errorf "Cmmgen.transl_prim_2: %a" Printlambda.primitive prim
 
-and transl_prim_3 p arg1 arg2 arg3 dbg =
+and transl_prim_3 env p arg1 arg2 arg3 dbg =
   match p with
   (* String operations *)
     Pstringsetu ->
-      return_unit(Cop(Cstore Byte_unsigned,
-                      [add_int (transl arg1) (untag_int(transl arg2));
-                        untag_int(transl arg3)]))
+      return_unit(Cop(Cstore (Byte_unsigned, Assignment),
+                      [add_int (transl env arg1) (untag_int(transl env arg2));
+                        untag_int(transl env arg3)]))
   | Pstringsets ->
       return_unit
-        (bind "str" (transl arg1) (fun str ->
-          bind "index" (untag_int (transl arg2)) (fun idx ->
+        (bind "str" (transl env arg1) (fun str ->
+          bind "index" (untag_int (transl env arg2)) (fun idx ->
             Csequence(
               make_checkbound dbg [string_length str; idx],
-              Cop(Cstore Byte_unsigned,
-                  [add_int str idx; untag_int(transl arg3)])))))
+              Cop(Cstore (Byte_unsigned, Assignment),
+                  [add_int str idx; untag_int(transl env arg3)])))))
 
   (* Array operations *)
   | Parraysetu kind ->
       return_unit(begin match kind with
         Pgenarray ->
-          bind "newval" (transl arg3) (fun newval ->
-            bind "index" (transl arg2) (fun index ->
-              bind "arr" (transl arg1) (fun arr ->
+          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)))))
       | Paddrarray ->
-          addr_array_set (transl arg1) (transl arg2) (transl arg3)
+          addr_array_set (transl env arg1) (transl env arg2) (transl env arg3)
       | Pintarray ->
-          int_array_set (transl arg1) (transl arg2) (transl arg3)
+          int_array_set (transl env arg1) (transl env arg2) (transl env arg3)
       | Pfloatarray ->
-          float_array_set (transl arg1) (transl arg2) (transl_unbox_float arg3)
+          float_array_set (transl env arg1) (transl env arg2)
+            (transl_unbox_float env arg3)
       end)
   | Parraysets kind ->
       return_unit(begin match kind with
       | Pgenarray ->
-          bind "newval" (transl arg3) (fun newval ->
-          bind "index" (transl arg2) (fun idx ->
-          bind "arr" (transl arg1) (fun arr ->
+          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 ->
             if wordsize_shift = numfloat_shift then
               Csequence(make_checkbound dbg [addr_array_length hdr; idx],
@@ -1943,110 +2163,127 @@ and transl_prim_3 p arg1 arg2 arg3 dbg =
                           float_array_set arr idx
                                           (unbox_float newval)))))))
       | Paddrarray ->
-          bind "newval" (transl arg3) (fun newval ->
-          bind "index" (transl arg2) (fun idx ->
-          bind "arr" (transl arg1) (fun arr ->
+          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))))
       | Pintarray ->
-          bind "newval" (transl arg3) (fun newval ->
-          bind "index" (transl arg2) (fun idx ->
-          bind "arr" (transl arg1) (fun arr ->
+          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))))
       | Pfloatarray ->
-          bind "newval" (transl_unbox_float arg3) (fun newval ->
-          bind "index" (transl arg2) (fun idx ->
-          bind "arr" (transl arg1) (fun arr ->
+          bind_load "newval" (transl_unbox_float 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))))
       end)
 
   | Pstring_set_16(unsafe) ->
      return_unit
-       (bind "str" (transl arg1) (fun str ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "newval" (untag_int (transl arg3)) (fun newval ->
+       (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)))))
 
   | Pbigstring_set_16(unsafe) ->
      return_unit
-       (bind "ba" (transl arg1) (fun ba ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "newval" (untag_int (transl arg3)) (fun newval ->
-        bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+       (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]))
+             (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))))))
 
   | Pstring_set_32(unsafe) ->
      return_unit
-       (bind "str" (transl arg1) (fun str ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int Pint32 arg3) (fun newval ->
+       (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)))))
 
   | Pbigstring_set_32(unsafe) ->
      return_unit
-       (bind "ba" (transl arg1) (fun ba ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int Pint32 arg3) (fun newval ->
-        bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+       (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]))
+             (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))))))
 
   | Pstring_set_64(unsafe) ->
      return_unit
-       (bind "str" (transl arg1) (fun str ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int Pint64 arg3) (fun newval ->
+       (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)))))
 
   | Pbigstring_set_64(unsafe) ->
      return_unit
-       (bind "ba" (transl arg1) (fun ba ->
-        bind "index" (untag_int (transl arg2)) (fun idx ->
-        bind "newval" (transl_unbox_int Pint64 arg3) (fun newval ->
-        bind "ba_data" (Cop(Cload Word, [field_address ba 1])) (fun ba_data ->
-          check_bound unsafe dbg (sub_int (Cop(Cload Word,[field_address ba 5]))
+       (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]))
+             (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))))))
 
-  | _ ->
-    fatal_error "Cmmgen.transl_prim_3"
+  | prim ->
+      fatal_errorf "Cmmgen.transl_prim_3: %a" Printlambda.primitive prim
 
-and transl_unbox_float = function
-    Uconst(Uconst_ref(_, Uconst_float f)) -> Cconst_float f
-  | exp -> unbox_float(transl exp)
+and transl_unbox_float env = function
+    Uconst(Uconst_ref(_, Some (Uconst_float f))) -> Cconst_float f
+  | exp -> unbox_float(transl env exp)
 
-and transl_unbox_int bi = function
-    Uconst(Uconst_ref(_, Uconst_int32 n)) ->
+and transl_unbox_int env bi = function
+    Uconst(Uconst_ref(_, Some (Uconst_int32 n))) ->
       Cconst_natint (Nativeint.of_int32 n)
-  | Uconst(Uconst_ref(_, Uconst_nativeint n)) ->
+  | Uconst(Uconst_ref(_, Some (Uconst_nativeint n))) ->
       Cconst_natint n
-  | Uconst(Uconst_ref(_, Uconst_int64 n)) ->
-      assert (size_int = 8); Cconst_natint (Int64.to_nativeint n)
+  | Uconst(Uconst_ref(_, Some (Uconst_int64 n))) ->
+      if size_int = 8 then
+        Cconst_natint (Int64.to_nativeint n)
+      else begin
+        let low = Int64.to_nativeint n in
+        let high = Int64.to_nativeint (Int64.shift_right_logical n 32) in
+        if big_endian then Ctuple [Cconst_natint high; Cconst_natint low]
+        else Ctuple [Cconst_natint low; Cconst_natint high]
+      end
   | Uprim(Pbintofint bi',[Uconst(Uconst_int i)],_) when bi = bi' ->
       Cconst_int i
-  | exp -> unbox_int bi (transl exp)
-
-and transl_unbox_let box_fn unbox_fn transl_unbox_fn box_chunk box_offset
-                     id exp body =
-  let unboxed_id = Ident.create (Ident.name id) in
-  let trbody1 = transl body in
-  let (trbody2, need_boxed, is_assigned) =
-    subst_boxed_number unbox_fn id unboxed_id box_chunk box_offset trbody1 in
-  if need_boxed && is_assigned then
-    Clet(id, transl exp, trbody1)
-  else
-    Clet(unboxed_id, transl_unbox_fn exp,
-         if need_boxed
-         then Clet(id, box_fn(Cvar unboxed_id), trbody2)
-         else trbody2)
+  | exp -> unbox_int bi (transl env exp)
+
+and transl_unbox_number env bn arg =
+  match bn with
+  | Boxed_float -> transl_unbox_float env arg
+  | Boxed_integer bi -> transl_unbox_int env bi arg
+
+and transl_let env id exp body =
+  match is_unboxed_number env exp with
+  |  No_unboxing ->
+      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 ->
+      let unboxed_id = Ident.create (Ident.name id) in
+      Clet(unboxed_id, transl_unbox_number 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
@@ -2062,71 +2299,75 @@ and make_catch2 mk_body handler = match handler with
       (mk_body (Cexit (nfail,[])))
       handler
 
-and exit_if_true cond nfail otherwise =
+and exit_if_true 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 arg1 nfail (exit_if_true arg2 nfail otherwise)
+      exit_if_true env arg1 nfail (exit_if_true env arg2 nfail otherwise)
+  | Uifthenelse (_, _, Uconst (Uconst_ptr 0))
   | Uprim(Psequand, _, _) ->
       begin match otherwise with
       | Cexit (raise_num,[]) ->
-          exit_if_false cond (Cexit (nfail,[])) raise_num
+          exit_if_false env cond (Cexit (nfail,[])) raise_num
       | _ ->
           let raise_num = next_raise_count () in
           make_catch
             raise_num
-            (exit_if_false cond (Cexit (nfail,[])) raise_num)
+            (exit_if_false env cond (Cexit (nfail,[])) raise_num)
             otherwise
       end
   | Uprim(Pnot, [arg], _) ->
-      exit_if_false arg otherwise nfail
+      exit_if_false env arg otherwise nfail
   | Uifthenelse (cond, ifso, ifnot) ->
       make_catch2
         (fun shared ->
-          Cifthenelse
-            (test_bool (transl cond),
-             exit_if_true ifso nfail shared,
-             exit_if_true ifnot nfail shared))
+          if_then_else
+            (test_bool (transl env cond),
+             exit_if_true env ifso nfail shared,
+             exit_if_true env ifnot nfail shared))
         otherwise
   | _ ->
-      Cifthenelse(test_bool(transl cond), Cexit (nfail, []), otherwise)
+      if_then_else(test_bool(transl env cond), Cexit (nfail, []), otherwise)
 
-and exit_if_false cond otherwise nfail =
+and exit_if_false 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 arg1 (exit_if_false arg2 otherwise nfail) nfail
+      exit_if_false env arg1 (exit_if_false env arg2 otherwise nfail) nfail
+  | Uifthenelse (_, Uconst (Uconst_ptr 1), _)
   | Uprim(Psequor, _, _) ->
       begin match otherwise with
       | Cexit (raise_num,[]) ->
-          exit_if_true cond raise_num (Cexit (nfail,[]))
+          exit_if_true env cond raise_num (Cexit (nfail,[]))
       | _ ->
           let raise_num = next_raise_count () in
           make_catch
             raise_num
-            (exit_if_true cond raise_num (Cexit (nfail,[])))
+            (exit_if_true env cond raise_num (Cexit (nfail,[])))
             otherwise
       end
   | Uprim(Pnot, [arg], _) ->
-      exit_if_true arg nfail otherwise
+      exit_if_true env arg nfail otherwise
   | Uifthenelse (cond, ifso, ifnot) ->
       make_catch2
         (fun shared ->
-          Cifthenelse
-            (test_bool (transl cond),
-             exit_if_false ifso shared nfail,
-             exit_if_false ifnot shared nfail))
+          if_then_else
+            (test_bool (transl env cond),
+             exit_if_false env ifso shared nfail,
+             exit_if_false env ifnot shared nfail))
         otherwise
   | _ ->
-      Cifthenelse(test_bool(transl cond), otherwise, Cexit (nfail, []))
+      if_then_else(test_bool(transl env cond), otherwise, Cexit (nfail, []))
 
-and transl_switch arg index cases = match Array.length cases with
+and transl_switch env arg index cases = match Array.length cases with
 | 0 -> fatal_error "Cmmgen.transl_switch"
-| 1 -> transl cases.(0)
+| 1 -> transl env cases.(0)
 | _ ->
-    let cases = Array.map transl cases in
+    let cases = Array.map (transl env) cases in
     let store = StoreExp.mk_store () in
     let index =
       Array.map
@@ -2159,11 +2400,11 @@ and transl_switch arg index cases = match Array.length cases with
               a
               (Array.of_list inters) store)
 
-and transl_letrec bindings cont =
+and transl_letrec env bindings cont =
   let bsz =
     List.map (fun (id, exp) -> (id, exp, expr_size Ident.empty exp)) bindings in
   let op_alloc prim sz =
-    Cop(Cextcall(prim, typ_addr, true, Debuginfo.none), [int_const sz]) in
+    Cop(Cextcall(prim, typ_val, true, Debuginfo.none), [int_const sz]) in
   let rec init_blocks = function
     | [] -> fill_nonrec bsz
     | (id, exp, RHS_block sz) :: rem ->
@@ -2177,13 +2418,13 @@ and transl_letrec bindings cont =
     | (id, exp, (RHS_block _ | RHS_floatblock _)) :: rem ->
         fill_nonrec rem
     | (id, exp, RHS_nonrec) :: rem ->
-        Clet (id, transl exp, fill_nonrec rem)
+        Clet(id, transl env exp, fill_nonrec rem)
   and fill_blocks = function
     | [] -> cont
     | (id, exp, (RHS_block _ | RHS_floatblock _)) :: rem ->
         let op =
           Cop(Cextcall("caml_update_dummy", typ_void, false, Debuginfo.none),
-              [Cvar id; transl exp]) in
+              [Cvar id; transl env exp]) in
         Csequence(op, fill_blocks rem)
     | (id, exp, RHS_nonrec) :: rem ->
         fill_blocks rem
@@ -2192,9 +2433,15 @@ and transl_letrec bindings cont =
 (* Translate a function definition *)
 
 let transl_function f =
+  let body =
+    if Config.flambda then
+      Un_anf.apply f.body ~what:f.label
+    else
+      f.body
+  in
   Cfunction {fun_name = f.label;
-             fun_args = List.map (fun id -> (id, typ_addr)) f.params;
-             fun_body = transl f.body;
+             fun_args = List.map (fun id -> (id, typ_val)) f.params;
+             fun_body = transl empty_env body;
              fun_fast = !Clflags.optimize_for_speed;
              fun_dbg  = f.dbg; }
 
@@ -2217,7 +2464,12 @@ let rec transl_all_functions already_translated cont =
         (transl_function f :: cont)
     end
   with Queue.Empty ->
-    cont
+    cont, already_translated
+
+let cdefine_symbol (symb, global) =
+  match global with
+  | Global -> [Cglobal_symbol symb; Cdefine_symbol symb]
+  | Not_global -> [Cdefine_symbol symb]
 
 (* Emit structured constants *)
 
@@ -2226,7 +2478,7 @@ let rec emit_structured_constant symb cst cont =
     (* Headers for structured constants must be marked black in case we
        are in no-naked-pointers mode.  See [caml_darken]. *)
     let black_header = Nativeint.logor white_header caml_black in
-    Cint black_header :: Cdefine_symbol symb :: cont
+    Cint black_header :: cdefine_symbol symb @ cont
   in
   match cst with
   | Uconst_float s->
@@ -2249,11 +2501,16 @@ let rec emit_structured_constant symb cst cont =
   | Uconst_float_array fields ->
       emit_block (floatarray_header (List.length fields)) symb
         (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;
+      List.iter (fun f -> Queue.add f functions) fundecls;
+      cont
 
 and emit_constant cst cont =
   match cst with
   | Uconst_int n | Uconst_ptr n ->
-      Cint(Nativeint.add (Nativeint.shift_left (Nativeint.of_int n) 1) 1n)
+      cint_const n
       :: cont
   | Uconst_ref (label, _) ->
       Csymbol_address label :: cont
@@ -2286,66 +2543,101 @@ and emit_boxed_int64_constant n cont =
 
 (* Emit constant closures *)
 
-let emit_constant_closure symb fundecls cont =
+let emit_constant_closure ((_, global_symb) as symb) fundecls clos_vars cont =
+  let closure_symbol f =
+    if Config.flambda then
+      cdefine_symbol (f.label ^ "_closure", global_symb)
+    else
+      []
+  in
   match fundecls with
-    [] -> assert false
+    [] ->
+      (* This should probably not happen: dead code has normally been
+         eliminated and a closure cannot be accessed without going through
+         a [Project_closure], which depends on the function. *)
+      assert (clos_vars = []);
+      cdefine_symbol symb @
+        List.fold_right emit_constant clos_vars cont
   | f1 :: remainder ->
       let rec emit_others pos = function
-        [] -> cont
+          [] ->
+            List.fold_right emit_constant clos_vars cont
       | f2 :: rem ->
-          if f2.arity = 1 then
+          if f2.arity = 1 || f2.arity = 0 then
             Cint(infix_header pos) ::
+            (closure_symbol f2) @
             Csymbol_address f2.label ::
-            Cint 3n ::
+            cint_const f2.arity ::
             emit_others (pos + 3) rem
           else
             Cint(infix_header pos) ::
+            (closure_symbol f2) @
             Csymbol_address(curry_function f2.arity) ::
-            Cint(Nativeint.of_int (f2.arity lsl 1 + 1)) ::
+            cint_const f2.arity ::
             Csymbol_address f2.label ::
             emit_others (pos + 4) rem in
-      Cint(black_closure_header (fundecls_size fundecls)) ::
-      Cdefine_symbol symb ::
-      if f1.arity = 1 then
+      Cint(black_closure_header (fundecls_size fundecls
+                                 + List.length clos_vars)) ::
+      cdefine_symbol symb @
+      (closure_symbol f1) @
+      if f1.arity = 1 || f1.arity = 0 then
         Csymbol_address f1.label ::
-        Cint 3n ::
+        cint_const f1.arity ::
         emit_others 3 remainder
       else
         Csymbol_address(curry_function f1.arity) ::
-        Cint(Nativeint.of_int (f1.arity lsl 1 + 1)) ::
+        cint_const f1.arity ::
         Csymbol_address f1.label ::
         emit_others 4 remainder
 
 (* Emit all structured constants *)
 
-let emit_all_constants cont =
+let emit_constants cont (constants:Clambda.preallocated_constant list) =
   let c = ref cont in
   List.iter
-    (fun (lbl, global, cst) ->
-       let cst = emit_structured_constant lbl cst [] in
-       let cst = if global then
-         Cglobal_symbol lbl :: cst
-       else cst in
+    (fun { symbol = lbl; exported; definition = cst } ->
+       let global = if exported then Global else Not_global in
+       let cst = emit_structured_constant (lbl, global) cst [] in
          c:= Cdata(cst):: !c)
-    (Compilenv.structured_constants());
+    constants;
   List.iter
-    (fun (symb, fundecls) ->
-        c := Cdata(emit_constant_closure symb fundecls []) :: !c)
+    (fun (symb, fundecls, clos_vars) ->
+        c := Cdata(emit_constant_closure symb fundecls clos_vars []) :: !c)
     !constant_closures;
   constant_closures := [];
   !c
 
-(* Translate a compilation unit *)
+let emit_all_constants cont =
+  let constants = Compilenv.structured_constants () in
+  Compilenv.clear_structured_constants ();
+  emit_constants cont constants
+
+let transl_all_functions_and_emit_all_constants cont =
+  let rec aux already_translated cont =
+    if Compilenv.structured_constants () = [] &&
+       Queue.is_empty functions
+    then cont
+    else
+      let cont, set = transl_all_functions already_translated cont in
+      let cont = emit_all_constants cont in
+      aux already_translated cont
+  in
+  aux StringSet.empty cont
 
-let compunit size ulam =
-  let glob = Compilenv.make_symbol None in
-  let init_code = transl ulam in
-  let c1 = [Cfunction {fun_name = Compilenv.make_symbol (Some "entry");
-                       fun_args = [];
-                       fun_body = init_code; fun_fast = false;
-                       fun_dbg  = Debuginfo.none }] in
-  let c2 = transl_all_functions StringSet.empty c1 in
-  let c3 = emit_all_constants c2 in
+(* Build the NULL terminated array of gc roots *)
+
+let emit_gc_roots_table ~symbols cont =
+  let table_symbol = Compilenv.make_symbol (Some "gc_roots") in
+  Cdata(Cglobal_symbol table_symbol ::
+        Cdefine_symbol table_symbol ::
+        List.map (fun s -> Csymbol_address s) symbols @
+        [Cint 0n])
+  :: cont
+
+(* Build preallocated blocks (used for Flambda [Initialize_symbol]
+   constructs, and Clambda global module) *)
+
+let preallocate_block cont { Clambda.symbol; exported; tag; size } =
   let space =
     (* These words will be registered as roots and as such must contain
        valid values, in case we are in no-naked-pointers mode.  Likewise
@@ -2355,9 +2647,35 @@ let compunit size ulam =
       (Array.init size (fun _index ->
         Cint (Nativeint.of_int 1 (* Val_unit *))))
   in
-  Cdata ([Cint(black_block_header 0 size);
-         Cglobal_symbol glob;
-         Cdefine_symbol glob] @ space) :: c3
+  let data =
+    Cint(black_block_header tag size) ::
+    if exported then
+      Cglobal_symbol symbol ::
+      Cdefine_symbol symbol :: space
+    else
+      Cdefine_symbol symbol :: space
+  in
+  Cdata data :: cont
+
+let emit_preallocated_blocks preallocated_blocks cont =
+  let symbols =
+    List.map (fun ({ Clambda.symbol }:Clambda.preallocated_block) -> symbol)
+      preallocated_blocks
+  in
+  let c1 = emit_gc_roots_table ~symbols cont in
+  List.fold_left preallocate_block c1 preallocated_blocks
+
+(* Translate a compilation unit *)
+
+let compunit (ulam, preallocated_blocks, constants) =
+  let init_code = transl empty_env ulam in
+  let c1 = [Cfunction {fun_name = Compilenv.make_symbol (Some "entry");
+                       fun_args = [];
+                       fun_body = init_code; fun_fast = false;
+                       fun_dbg  = Debuginfo.none }] in
+  let c2 = emit_constants c1 constants in
+  let c3 = transl_all_functions_and_emit_all_constants c2 in
+  emit_preallocated_blocks preallocated_blocks c3
 
 (*
 CAMLprim value caml_cache_public_method (value meths, value tag, value *cache)
@@ -2380,7 +2698,7 @@ let cache_public_method meths tag cache =
   Clet (
   li, Cconst_int 3,
   Clet (
-  hi, Cop(Cload Word, [meths]),
+  hi, Cop(Cload Word_int, [meths]),
   Csequence(
   Ccatch
     (raise_num, [],
@@ -2394,7 +2712,7 @@ let cache_public_method meths tag cache =
         Cifthenelse
           (Cop (Ccmpi Clt,
                 [tag;
-                 Cop(Cload Word,
+                 Cop(Cload Word_int,
                      [Cop(Cadda,
                           [meths; lsl_const (Cvar mi) log2_size_addr])])]),
            Cassign(hi, Cop(Csubi, [Cvar mi; Cconst_int 2])),
@@ -2406,7 +2724,7 @@ let cache_public_method meths tag cache =
   Clet (
   tagged, Cop(Cadda, [lsl_const (Cvar li) log2_size_addr;
                       Cconst_int(1 - 3 * size_addr)]),
-  Csequence(Cop (Cstore Word, [cache; Cvar tagged]),
+  Csequence(Cop (Cstore (Word_int, Assignment), [cache; Cvar tagged]),
             Cvar tagged)))))
 
 (* Generate an application function:
@@ -2426,12 +2744,12 @@ let apply_function_body arity =
   let clos = Ident.create "clos" in
   let rec app_fun clos n =
     if n = arity-1 then
-      Cop(Capply(typ_addr, Debuginfo.none),
+      Cop(Capply(typ_val, Debuginfo.none),
           [get_field (Cvar clos) 0; Cvar arg.(n); Cvar clos])
     else begin
       let newclos = Ident.create "clos" in
       Clet(newclos,
-           Cop(Capply(typ_addr, Debuginfo.none),
+           Cop(Capply(typ_val, Debuginfo.none),
                [get_field (Cvar clos) 0; Cvar arg.(n); Cvar clos]),
            app_fun newclos (n+1))
     end in
@@ -2441,7 +2759,7 @@ let apply_function_body arity =
    if arity = 1 then app_fun clos 0 else
    Cifthenelse(
    Cop(Ccmpi Ceq, [get_field (Cvar clos) 1; int_const arity]),
-   Cop(Capply(typ_addr, Debuginfo.none),
+   Cop(Capply(typ_val, Debuginfo.none),
        get_field (Cvar clos) 2 :: List.map (fun s -> Cvar s) all_args),
    app_fun clos 0))
 
@@ -2458,24 +2776,24 @@ let send_function arity =
     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, [tag_pos]) in
+    let tag' = Cop(Cload Word_int, [tag_pos]) in
     Clet (
-    meths, Cop(Cload Word, [obj]),
+    meths, Cop(Cload Word_val, [obj]),
     Clet (
-    cached, Cop(Cand, [Cop(Cload Word, [cache]); mask]),
+    cached, Cop(Cand, [Cop(Cload Word_int, [cache]); mask]),
     Clet (
     real,
     Cifthenelse(Cop(Ccmpa Cne, [tag'; tag]),
                 cache_public_method (Cvar meths) tag cache,
                 cached_pos),
-    Cop(Cload Word, [Cop(Cadda, [Cop (Cadda, [Cvar real; Cvar meths]);
-                                 Cconst_int(2*size_addr-1)])]))))
+    Cop(Cload Word_val, [Cop(Cadda, [Cop (Cadda, [Cvar real; Cvar meths]);
+                                     Cconst_int(2*size_addr-1)])]))))
 
   in
   let body = Clet(clos', clos, body) in
   let fun_args =
-    [obj, typ_addr; tag, typ_int; cache, typ_addr]
-    @ List.map (fun id -> (id, typ_addr)) (List.tl args) in
+    [obj, typ_val; tag, typ_int; cache, typ_val]
+    @ List.map (fun id -> (id, typ_val)) (List.tl args) in
   Cfunction
    {fun_name = "caml_send" ^ string_of_int arity;
     fun_args = fun_args;
@@ -2488,7 +2806,7 @@ let apply_function arity =
   let all_args = args @ [clos] in
   Cfunction
    {fun_name = "caml_apply" ^ string_of_int arity;
-    fun_args = List.map (fun id -> (id, typ_addr)) all_args;
+    fun_args = List.map (fun id -> (id, typ_val)) all_args;
     fun_body = body;
     fun_fast = true;
     fun_dbg  = Debuginfo.none }
@@ -2506,9 +2824,9 @@ let tuplify_function arity =
     else get_field (Cvar arg) i :: access_components(i+1) in
   Cfunction
    {fun_name = "caml_tuplify" ^ string_of_int arity;
-    fun_args = [arg, typ_addr; clos, typ_addr];
+    fun_args = [arg, typ_val; clos, typ_val];
     fun_body =
-      Cop(Capply(typ_addr, Debuginfo.none),
+      Cop(Capply(typ_val, Debuginfo.none),
           get_field (Cvar clos) 2 :: access_components 0 @ [Cvar clos]);
     fun_fast = true;
     fun_dbg  = Debuginfo.none }
@@ -2547,7 +2865,7 @@ let final_curry_function arity =
   let last_clos = Ident.create "clos" in
   let rec curry_fun args clos n =
     if n = 0 then
-      Cop(Capply(typ_addr, Debuginfo.none),
+      Cop(Capply(typ_val, Debuginfo.none),
           get_field (Cvar clos) 2 ::
           args @ [Cvar last_arg; Cvar clos])
     else
@@ -2567,7 +2885,7 @@ let final_curry_function arity =
   Cfunction
    {fun_name = "caml_curry" ^ string_of_int arity ^
                "_" ^ string_of_int (arity-1);
-    fun_args = [last_arg, typ_addr; last_clos, typ_addr];
+    fun_args = [last_arg, typ_val; last_clos, typ_val];
     fun_body = curry_fun [] last_clos (arity-1);
     fun_fast = true;
     fun_dbg  = Debuginfo.none }
@@ -2581,7 +2899,7 @@ let rec intermediate_curry_functions arity num =
     let arg = Ident.create "arg" and clos = Ident.create "clos" in
     Cfunction
      {fun_name = name2;
-      fun_args = [arg, typ_addr; clos, typ_addr];
+      fun_args = [arg, typ_val; clos, typ_val];
       fun_body =
          if arity - num > 2 && arity <= max_arity_optimized then
            Cop(Calloc,
@@ -2602,13 +2920,13 @@ let rec intermediate_curry_functions arity num =
           let rec iter i =
             if i <= arity then
               let arg = Ident.create (Printf.sprintf "arg%d" i) in
-              (arg, typ_addr) :: iter (i+1)
+              (arg, typ_val) :: iter (i+1)
             else []
           in
           let direct_args = iter (num+2) in
           let rec iter i args clos =
             if i = 0 then
-              Cop(Capply(typ_addr, Debuginfo.none),
+              Cop(Capply(typ_val, Debuginfo.none),
                   (get_field (Cvar clos) 2) :: args @ [Cvar clos])
             else
               let newclos = Ident.create "clos" in
@@ -2619,7 +2937,7 @@ let rec intermediate_curry_functions arity num =
           let cf =
             Cfunction
               {fun_name = name1 ^ "_" ^ string_of_int (num+1) ^ "_app";
-               fun_args = direct_args @ [clos, typ_addr];
+               fun_args = direct_args @ [clos, typ_val];
                fun_body = iter (num+1)
                   (List.map (fun (arg,_) -> Cvar arg) direct_args) clos;
                fun_fast = true;
@@ -2631,7 +2949,9 @@ let rec intermediate_curry_functions arity num =
   end
 
 let curry_function arity =
-  if arity >= 0
+  assert(arity <> 0);
+  (* Functions with arity = 0 does not have a curry_function *)
+  if arity > 0
   then intermediate_curry_functions arity 0
   else [tuplify_function (-arity)]
 
@@ -2664,9 +2984,9 @@ let generic_functions shared units =
 
 let entry_point namelist =
   let incr_global_inited =
-    Cop(Cstore Word,
+    Cop(Cstore (Word_int, Assignment),
         [Cconst_symbol "caml_globals_inited";
-         Cop(Caddi, [Cop(Cload Word, [Cconst_symbol "caml_globals_inited"]);
+         Cop(Caddi, [Cop(Cload Word_int, [Cconst_symbol "caml_globals_inited"]);
                      Cconst_int 1])]) in
   let body =
     List.fold_right
@@ -2688,7 +3008,7 @@ let cint_zero = Cint 0n
 
 let global_table namelist =
   let mksym name =
-    Csymbol_address (Compilenv.make_symbol ~unitname:name None)
+    Csymbol_address (Compilenv.make_symbol ~unitname:name (Some "gc_roots"))
   in
   Cdata(Cglobal_symbol "caml_globals" ::
         Cdefine_symbol "caml_globals" ::
@@ -2700,8 +3020,7 @@ let reference_symbols namelist =
   Cdata(List.map mksym namelist)
 
 let global_data name v =
-  Cdata(Cglobal_symbol name ::
-          emit_structured_constant name
+  Cdata(emit_structured_constant (name, Global)
           (Uconst_string (Marshal.to_string v [])) [])
 
 let globals_map v = global_data "caml_globals_map" v
@@ -2741,19 +3060,16 @@ let predef_exception i name =
   let symname = "caml_exn_" ^ name in
   let cst = Uconst_string name in
   let label = Compilenv.new_const_symbol () in
-  let cont = emit_structured_constant label cst [] in
-  Cdata(Cglobal_symbol symname ::
-        emit_structured_constant symname
+  let cont = emit_structured_constant (label, Not_global) cst [] in
+  Cdata(emit_structured_constant (symname, Global)
           (Uconst_block(Obj.object_tag,
                        [
-                         Uconst_ref(label, cst);
+                         Uconst_ref(label, Some cst);
                          Uconst_int (-i-1);
                        ])) cont)
 
 (* Header for a plugin *)
 
-let mapflat f l = List.flatten (List.map f l)
-
 let plugin_header units =
   let mk (ui,crc) =
     { dynu_name = ui.ui_name;
diff --git a/asmcomp/cmmgen.mli b/asmcomp/cmmgen.mli
index 46f94966..1843fac5 100644
--- a/asmcomp/cmmgen.mli
+++ b/asmcomp/cmmgen.mli
@@ -1,18 +1,25 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Translation from closed lambda to C-- *)
 
-val compunit: int -> Clambda.ulambda -> Cmm.phrase list
+val compunit:
+    Clambda.ulambda
+    * Clambda.preallocated_block list
+    * Clambda.preallocated_constant list
+  -> Cmm.phrase list
 
 val apply_function: int -> Cmm.phrase
 val send_function: int -> Cmm.phrase
diff --git a/asmcomp/cmx_format.mli b/asmcomp/cmx_format.mli
index 51aa0440..0e3cf285 100644
--- a/asmcomp/cmx_format.mli
+++ b/asmcomp/cmx_format.mli
@@ -1,14 +1,21 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, 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 Q Public License version 1.0.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2010 Institut National de Recherche en Informatique et     *)
+(*     en Automatique                                                     *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Format of .cmx, .cmxa and .cmxs files *)
 
@@ -22,6 +29,10 @@
    The .cmx file contains these infos (as an externed record) plus a MD5
    of these infos *)
 
+type export_info =
+  | Clambda of Clambda.value_approximation
+  | Flambda of Export_info.t
+
 type unit_infos =
   { mutable ui_name: string;                    (* Name of unit implemented *)
     mutable ui_symbol: string;            (* Prefix for symbols *)
@@ -29,10 +40,10 @@ type unit_infos =
     mutable ui_imports_cmi:
               (string * Digest.t option) list; (* Interfaces imported *)
     mutable ui_imports_cmx:(string * Digest.t option) list; (* Infos imported *)
-    mutable ui_approx: Clambda.value_approximation; (* Approx of the structure*)
     mutable ui_curry_fun: int list;             (* Currying functions needed *)
     mutable ui_apply_fun: int list;             (* Apply functions needed *)
     mutable ui_send_fun: int list;              (* Send functions needed *)
+    mutable ui_export_info: export_info;
     mutable ui_force_link: bool }               (* Always linked *)
 
 (* Each .a library has a matching .cmxa file that provides the following
diff --git a/asmcomp/codegen.ml b/asmcomp/codegen.ml
deleted file mode 100644
index a3182462..00000000
--- a/asmcomp/codegen.ml
+++ /dev/null
@@ -1,95 +0,0 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-(* From C-- to assembly code *)
-
-open Format
-open Cmm
-
-let dump_cmm = ref false
-let dump_selection = ref false
-let dump_live = ref false
-let dump_spill = ref false
-let dump_split = ref false
-let dump_interf = ref false
-let dump_prefer = ref false
-let dump_regalloc = ref false
-let dump_reload = ref false
-let dump_linear = ref false
-
-let rec regalloc fd =
-  if !dump_live then Printmach.phase "Liveness analysis" fd;
-  Interf.build_graph fd;
-  if !dump_interf then Printmach.interferences();
-  if !dump_prefer then Printmach.preferences();
-  Coloring.allocate_registers();
-  if !dump_regalloc then
-    Printmach.phase "After register allocation" fd;
-  let (newfd, redo_regalloc) = Reload.fundecl fd in
-  if !dump_reload then
-    Printmach.phase "After insertion of reloading code" newfd;
-  if redo_regalloc
-  then begin Reg.reinit(); Liveness.fundecl newfd; regalloc newfd end
-  else newfd
-
-let fundecl ppf fd_cmm =
-  if !dump_cmm then begin
-    fprintf ppf "*** C-- code@.";
-    fprintf ppf "%a@." Printcmm.fundecl fd_cmm
-  end;
-  Reg.reset();
-  let fd_sel = Sequence.fundecl fd_cmm in
-  if !dump_selection then
-    Printmach.phase "After instruction selection" fd_sel;
-  Liveness.fundecl fd_sel;
-  if !dump_live then Printmach.phase "Liveness analysis" fd_sel;
-  let fd_spill = Spill.fundecl fd_sel in
-  Liveness.fundecl fd_spill;
-  if !dump_spill then
-    Printmach.phase "After spilling" fd_spill;
-  let fd_split = Split.fundecl fd_spill in
-  Liveness.fundecl fd_split;
-  if !dump_split then
-    Printmach.phase "After live range splitting" fd_split;
-  let fd_reload = regalloc fd_split in
-  let fd_linear = Linearize.fundecl fd_reload in
-  if !dump_linear then begin
-    printf "*** Linearized code@.";
-    Printlinear.fundecl fd_linear; print_newline()
-  end;
-  Emit.fundecl fd_linear
-
-let phrase = function
-    Cfunction fd -> fundecl fd
-  | Cdata dl -> Emit.data dl
-
-let file filename =
-  let ic = open_in filename in
-  let lb = Lexing.from_channel ic in
-  try
-    while true do
-      phrase(Parsecmm.phrase Lexcmm.token lb)
-    done
-  with
-      End_of_file ->
-        close_in ic
-    | 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()
-    | Parsecmmaux.Error msg ->
-        close_in ic; Parsecmmaux.report_error msg
-    | x ->
-        close_in ic; raise x
diff --git a/asmcomp/codegen.mli b/asmcomp/codegen.mli
deleted file mode 100644
index 5dab12fc..00000000
--- a/asmcomp/codegen.mli
+++ /dev/null
@@ -1,27 +0,0 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-(* From C-- to assembly code *)
-
-val phrase: Cmm.phrase -> unit
-val file: string -> unit
-
-val dump_cmm: bool ref
-val dump_selection: bool ref
-val dump_live: bool ref
-val dump_spill: bool ref
-val dump_split: bool ref
-val dump_interf: bool ref
-val dump_prefer: bool ref
-val dump_regalloc: bool ref
-val dump_reload: bool ref
-val dump_linear: bool ref
diff --git a/asmcomp/coloring.ml b/asmcomp/coloring.ml
index aff4ad62..62a9b0da 100644
--- a/asmcomp/coloring.ml
+++ b/asmcomp/coloring.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Register allocation by coloring of the interference graph *)
 
diff --git a/asmcomp/coloring.mli b/asmcomp/coloring.mli
index b0cd0437..874a6f98 100644
--- a/asmcomp/coloring.mli
+++ b/asmcomp/coloring.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Register allocation by coloring of the interference graph *)
 
diff --git a/asmcomp/comballoc.ml b/asmcomp/comballoc.ml
index 820b1b3f..094cdb89 100644
--- a/asmcomp/comballoc.ml
+++ b/asmcomp/comballoc.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 Q Public License version 1.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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Combine heap allocations occurring in the same basic block *)
 
diff --git a/asmcomp/comballoc.mli b/asmcomp/comballoc.mli
index ee04c16b..19d8fdee 100644
--- a/asmcomp/comballoc.mli
+++ b/asmcomp/comballoc.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                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 Q Public License version 1.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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Combine heap allocations occurring in the same basic block *)
 
diff --git a/asmcomp/compilenv.ml b/asmcomp/compilenv.ml
index a313b972..8133c396 100644
--- a/asmcomp/compilenv.ml
+++ b/asmcomp/compilenv.ml
@@ -1,20 +1,28 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2010 Institut National de Recherche en Informatique et     *)
+(*     en Automatique                                                     *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Compilation environments for compilation units *)
 
+[@@@ocaml.warning "+a-4-9-40-41-42"]
+
 open Config
 open Misc
-open Clambda
 open Cmx_format
 
 type error =
@@ -26,6 +34,14 @@ exception Error of error
 
 let global_infos_table =
   (Hashtbl.create 17 : (string, unit_infos option) Hashtbl.t)
+let export_infos_table =
+  (Hashtbl.create 10 : (string, Export_info.t) Hashtbl.t)
+
+let imported_sets_of_closures_table =
+  (Set_of_closures_id.Tbl.create 10
+   : Flambda.function_declarations Set_of_closures_id.Tbl.t)
+
+let sourcefile = ref None
 
 module CstMap =
   Map.Make(struct
@@ -52,17 +68,25 @@ let structured_constants = ref structured_constants_empty
 
 let exported_constants = Hashtbl.create 17
 
+let merged_environment = ref Export_info.empty
+
+let default_ui_export_info =
+  if Config.flambda then
+    Cmx_format.Flambda Export_info.empty
+  else
+    Cmx_format.Clambda Value_unknown
+
 let current_unit =
   { ui_name = "";
     ui_symbol = "";
     ui_defines = [];
     ui_imports_cmi = [];
     ui_imports_cmx = [];
-    ui_approx = Value_unknown;
     ui_curry_fun = [];
     ui_apply_fun = [];
     ui_send_fun = [];
-    ui_force_link = false }
+    ui_force_link = false;
+    ui_export_info = default_ui_export_info }
 
 let symbolname_for_pack pack name =
   match pack with
@@ -78,10 +102,25 @@ let symbolname_for_pack pack name =
       Buffer.add_string b name;
       Buffer.contents b
 
+let unit_id_from_name name = Ident.create_persistent name
+
+let concat_symbol unitname id =
+  unitname ^ "__" ^ id
 
-let reset ?packname name =
+let make_symbol ?(unitname = current_unit.ui_symbol) idopt =
+  let prefix = "caml" ^ unitname in
+  match idopt with
+  | None -> prefix
+  | Some id -> concat_symbol prefix id
+
+let current_unit_linkage_name () =
+  Linkage_name.create (make_symbol ~unitname:current_unit.ui_symbol None)
+
+let reset ?packname ~source_provenance:file name =
   Hashtbl.clear global_infos_table;
+  Set_of_closures_id.Tbl.clear imported_sets_of_closures_table;
   let symbol = symbolname_for_pack packname name in
+  sourcefile := Some file;
   current_unit.ui_name <- name;
   current_unit.ui_symbol <- symbol;
   current_unit.ui_defines <- [symbol];
@@ -92,7 +131,16 @@ let reset ?packname name =
   current_unit.ui_send_fun <- [];
   current_unit.ui_force_link <- false;
   Hashtbl.clear exported_constants;
-  structured_constants := structured_constants_empty
+  structured_constants := structured_constants_empty;
+  current_unit.ui_export_info <- default_ui_export_info;
+  merged_environment := Export_info.empty;
+  Hashtbl.clear export_infos_table;
+  let compilation_unit =
+    Compilation_unit.create
+      (Ident.create_persistent name)
+      (current_unit_linkage_name ())
+  in
+  Compilation_unit.set_current compilation_unit
 
 let current_unit_infos () =
   current_unit
@@ -100,6 +148,11 @@ let current_unit_infos () =
 let current_unit_name () =
   current_unit.ui_name
 
+let current_build () =
+  match !sourcefile with
+  | None -> assert false
+  | Some v -> v
+
 let make_symbol ?(unitname = current_unit.ui_symbol) idopt =
   let prefix = "caml" ^ unitname in
   match idopt with
@@ -152,15 +205,21 @@ let get_global_info global_ident = (
       Hashtbl.find global_infos_table modname
     with Not_found ->
       let (infos, crc) =
-        try
-          let filename =
-            find_in_path_uncap !load_path (modname ^ ".cmx") in
-          let (ui, crc) = read_unit_info filename in
-          if ui.ui_name <> modname then
-            raise(Error(Illegal_renaming(modname, ui.ui_name, filename)));
-          (Some ui, Some crc)
-        with Not_found ->
-          (None, None) in
+        if Env.is_imported_opaque modname then (None, None)
+        else begin
+          try
+            let filename =
+              find_in_path_uncap !load_path (modname ^ ".cmx") in
+            let (ui, crc) = read_unit_info filename in
+            if ui.ui_name <> modname then
+              raise(Error(Illegal_renaming(modname, ui.ui_name, filename)));
+            (Some ui, Some crc)
+          with Not_found ->
+            let warn = Warnings.No_cmx_file modname in
+              Location.prerr_warning Location.none warn;
+              (None, None)
+          end
+      in
       current_unit.ui_imports_cmx <-
         (modname, crc) :: current_unit.ui_imports_cmx;
       Hashtbl.add global_infos_table modname infos;
@@ -173,18 +232,26 @@ let cache_unit_info ui =
 
 (* Return the approximation of a global identifier *)
 
-let toplevel_approx = Hashtbl.create 16
+let get_clambda_approx ui =
+  assert(not Config.flambda);
+  match ui.ui_export_info with
+  | Flambda _ -> assert false
+  | Clambda approx -> approx
+
+let toplevel_approx :
+  (string, Clambda.value_approximation) Hashtbl.t = Hashtbl.create 16
 
-let record_global_approx_toplevel id =
-  Hashtbl.add toplevel_approx current_unit.ui_name current_unit.ui_approx
+let record_global_approx_toplevel () =
+  Hashtbl.add toplevel_approx current_unit.ui_name
+    (get_clambda_approx current_unit)
 
 let global_approx id =
-  if Ident.is_predef_exn id then Value_unknown
+  if Ident.is_predef_exn id then Clambda.Value_unknown
   else try Hashtbl.find toplevel_approx (Ident.name id)
   with Not_found ->
     match get_global_info id with
-      | None -> Value_unknown
-      | Some ui -> ui.ui_approx
+      | None -> Clambda.Value_unknown
+      | Some ui -> get_clambda_approx ui
 
 (* Return the symbol used to refer to a global identifier *)
 
@@ -192,15 +259,72 @@ let symbol_for_global id =
   if Ident.is_predef_exn id then
     "caml_exn_" ^ Ident.name id
   else begin
-    match get_global_info id with
+    let unitname = Ident.name id in
+    match
+      try ignore (Hashtbl.find toplevel_approx unitname); None
+      with Not_found -> get_global_info id
+    with
     | None -> make_symbol ~unitname:(Ident.name id) None
     | Some ui -> make_symbol ~unitname:ui.ui_symbol None
   end
 
 (* Register the approximation of the module being compiled *)
 
+let unit_for_global id =
+  let sym_label = Linkage_name.create (symbol_for_global id) in
+  Compilation_unit.create id sym_label
+
+let predefined_exception_compilation_unit =
+  Compilation_unit.create (Ident.create_persistent "__dummy__")
+    (Linkage_name.create "__dummy__")
+
+let is_predefined_exception sym =
+  Compilation_unit.equal
+    predefined_exception_compilation_unit
+    (Symbol.compilation_unit sym)
+
+let symbol_for_global' id =
+  let sym_label = Linkage_name.create (symbol_for_global id) in
+  if Ident.is_predef_exn id then
+    Symbol.unsafe_create predefined_exception_compilation_unit sym_label
+  else
+    Symbol.unsafe_create (unit_for_global id) sym_label
+
 let set_global_approx approx =
-  current_unit.ui_approx <- approx
+  assert(not Config.flambda);
+  current_unit.ui_export_info <- Clambda approx
+
+(* Exporting and importing cross module information *)
+
+let get_flambda_export_info ui =
+  assert(Config.flambda);
+  match ui.ui_export_info with
+  | Clambda _ -> assert false
+  | Flambda ei -> ei
+
+let set_export_info export_info =
+  assert(Config.flambda);
+  current_unit.ui_export_info <- Flambda export_info
+
+let approx_for_global comp_unit =
+  let id = Compilation_unit.get_persistent_ident comp_unit in
+  if (Compilation_unit.equal
+      predefined_exception_compilation_unit
+      comp_unit)
+     || Ident.is_predef_exn id
+     || not (Ident.global id)
+  then invalid_arg (Format.asprintf "approx_for_global %a" Ident.print id);
+  let modname = Ident.name id in
+  try Hashtbl.find export_infos_table modname with
+  | Not_found ->
+    let exported = match get_global_info id with
+      | None -> Export_info.empty
+      | Some ui -> get_flambda_export_info ui in
+    Hashtbl.add export_infos_table modname exported;
+    merged_environment := Export_info.merge !merged_environment exported;
+    exported
+
+let approx_env () = !merged_environment
 
 (* Record that a currying function or application function is needed *)
 
@@ -209,6 +333,7 @@ let need_curry_fun n =
     current_unit.ui_curry_fun <- n :: current_unit.ui_curry_fun
 
 let need_apply_fun n =
+  assert(n > 0);
   if not (List.mem n current_unit.ui_apply_fun) then
     current_unit.ui_apply_fun <- n :: current_unit.ui_apply_fun
 
@@ -231,13 +356,18 @@ let save_unit_info filename =
   current_unit.ui_imports_cmi <- Env.imports();
   write_unit_info current_unit filename
 
+let current_unit_linkage_name () =
+  Linkage_name.create (make_symbol ~unitname:current_unit.ui_symbol None)
 
+let current_unit () =
+  match Compilation_unit.get_current () with
+  | Some current_unit -> current_unit
+  | None -> Misc.fatal_error "Compilenv.current_unit"
 
-let const_label = ref 0
+let current_unit_symbol () =
+  Symbol.unsafe_create (current_unit ()) (current_unit_linkage_name ())
 
-let new_const_label () =
-  incr const_label;
-  !const_label
+let const_label = ref 0
 
 let new_const_symbol () =
   incr const_label;
@@ -271,11 +401,36 @@ let new_structured_constant cst ~shared =
 let add_exported_constant s =
   Hashtbl.replace exported_constants s ()
 
+let clear_structured_constants () =
+  structured_constants := structured_constants_empty
+
 let structured_constants () =
   List.map
-    (fun (lbl, cst) ->
-       (lbl, Hashtbl.mem exported_constants lbl, cst)
-    ) (!structured_constants).strcst_all
+    (fun (symbol, definition) ->
+       {
+         Clambda.symbol;
+         exported = Hashtbl.mem exported_constants symbol;
+         definition;
+       })
+    (!structured_constants).strcst_all
+
+let closure_symbol fv =
+  let compilation_unit = Closure_id.get_compilation_unit fv in
+  let unitname =
+    Linkage_name.to_string (Compilation_unit.get_linkage_name compilation_unit)
+  in
+  let linkage_name =
+    concat_symbol unitname ((Closure_id.unique_name fv) ^ "_closure")
+  in
+  Symbol.unsafe_create compilation_unit (Linkage_name.create linkage_name)
+
+let function_label fv =
+  let compilation_unit = Closure_id.get_compilation_unit fv in
+  let unitname =
+    Linkage_name.to_string
+      (Compilation_unit.get_linkage_name compilation_unit)
+  in
+  (concat_symbol unitname (Closure_id.unique_name fv))
 
 (* Error report *)
 
diff --git a/asmcomp/compilenv.mli b/asmcomp/compilenv.mli
index 7fae3bad..2974eae0 100644
--- a/asmcomp/compilenv.mli
+++ b/asmcomp/compilenv.mli
@@ -1,28 +1,62 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2010 Institut National de Recherche en Informatique et     *)
+(*     en Automatique                                                     *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Compilation environments for compilation units *)
 
 open Cmx_format
 
-val reset: ?packname:string -> string -> unit
+(* CR-soon mshinwell: this is a bit ugly
+   mshinwell: deferred CR, this has been addressed in the export info
+   improvement feature.
+*)
+val imported_sets_of_closures_table
+  : Flambda.function_declarations Set_of_closures_id.Tbl.t
+        (* flambda-only *)
+
+val reset: ?packname:string -> source_provenance:Timings.source_provenance ->
+        string -> unit
         (* Reset the environment and record the name of the unit being
            compiled (arg).  Optional argument is [-for-pack] prefix. *)
 
+val unit_id_from_name: string -> Ident.t
+        (* flambda-only *)
+
 val current_unit_infos: unit -> unit_infos
         (* Return the infos for the unit being compiled *)
 
 val current_unit_name: unit -> string
-        (* Return the name of the unit being compiled *)
+        (* Return the name of the unit being compiled
+           clambda-only *)
+
+val current_unit_linkage_name: unit -> Linkage_name.t
+        (* Return the linkage_name of the unit being compiled.
+           flambda-only *)
+
+val current_build: unit -> Timings.source_provenance
+        (* Return the kind of build source being compiled. If it is a
+           file compilation it also provides the filename. *)
+
+val current_unit: unit -> Compilation_unit.t
+        (* flambda-only *)
+
+val current_unit_symbol: unit -> Symbol.t
+        (* flambda-only *)
 
 val make_symbol: ?unitname:string -> string option -> string
         (* [make_symbol ~unitname:u None] returns the asm symbol that
@@ -35,16 +69,36 @@ val symbol_in_current_unit: string -> bool
         (* Return true if the given asm symbol belongs to the
            current compilation unit, false otherwise. *)
 
-val symbol_for_global: Ident.t -> string
-        (* Return the asm symbol that refers to the given global identifier *)
+val is_predefined_exception: Symbol.t -> bool
+        (* flambda-only *)
+
+val unit_for_global: Ident.t -> Compilation_unit.t
+        (* flambda-only *)
 
+val symbol_for_global: Ident.t -> string
+        (* Return the asm symbol that refers to the given global identifier
+           flambda-only *)
+val symbol_for_global': Ident.t -> Symbol.t
+        (* flambda-only *)
 val global_approx: Ident.t -> Clambda.value_approximation
-        (* Return the approximation for the given global identifier *)
+        (* Return the approximation for the given global identifier
+           clambda-only *)
 val set_global_approx: Clambda.value_approximation -> unit
-        (* Record the approximation of the unit being compiled *)
+        (* Record the approximation of the unit being compiled
+           clambda-only *)
 val record_global_approx_toplevel: unit -> unit
-        (* Record the current approximation for the current toplevel phrase *)
-
+        (* Record the current approximation for the current toplevel phrase
+           clambda-only *)
+
+val set_export_info: Export_info.t -> unit
+        (* Record the informations of the unit being compiled
+           flambda-only *)
+val approx_env: unit -> Export_info.t
+        (* Returns all the information loaded from extenal compilation units
+           flambda-only *)
+val approx_for_global: Compilation_unit.t -> Export_info.t
+        (* Loads the exported information declaring the compilation_unit
+           flambda-only *)
 
 val need_curry_fun: int -> unit
 val need_apply_fun: int -> unit
@@ -53,20 +107,29 @@ val need_send_fun: int -> unit
            message sending) function with the given arity *)
 
 val new_const_symbol : unit -> string
-val new_const_label : unit -> int
+val closure_symbol : Closure_id.t -> Symbol.t
+        (* Symbol of a function if the function is
+           closed (statically allocated)
+           flambda-only *)
+val function_label : Closure_id.t -> string
+        (* linkage name of the code of a function
+           flambda-only *)
 
 val new_structured_constant:
   Clambda.ustructured_constant ->
   shared:bool -> (* can be shared with another structually equal constant *)
   string
 val structured_constants:
-  unit -> (string * bool * Clambda.ustructured_constant) list
+  unit -> Clambda.preallocated_constant list
+val clear_structured_constants: unit -> unit
 val add_exported_constant: string -> unit
-
+        (* clambda-only *)
 type structured_constants
+        (* clambda-only *)
 val snapshot: unit -> structured_constants
+        (* clambda-only *)
 val backtrack: structured_constants -> unit
-
+        (* clambda-only *)
 
 val read_unit_info: string -> unit_infos * Digest.t
         (* Read infos and MD5 from a [.cmx] file. *)
diff --git a/asmcomp/deadcode.ml b/asmcomp/deadcode.ml
index cb93c286..4570d8ef 100644
--- a/asmcomp/deadcode.ml
+++ b/asmcomp/deadcode.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Dead code elimination: remove pure instructions whose results are
    not used. *)
diff --git a/asmcomp/deadcode.mli b/asmcomp/deadcode.mli
index 6aafae05..c566cfbd 100644
--- a/asmcomp/deadcode.mli
+++ b/asmcomp/deadcode.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Dead code elimination: remove pure instructions whose results are
    not used. *)
diff --git a/asmcomp/debuginfo.ml b/asmcomp/debuginfo.ml
deleted file mode 100644
index 3f96049e..00000000
--- a/asmcomp/debuginfo.ml
+++ /dev/null
@@ -1,56 +0,0 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2006 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-open Lexing
-open Location
-
-type kind = Dinfo_call | Dinfo_raise
-
-type t = {
-  dinfo_kind: kind;
-  dinfo_file: string;
-  dinfo_line: int;
-  dinfo_char_start: int;
-  dinfo_char_end: int
-}
-
-let none = {
-  dinfo_kind = Dinfo_call;
-  dinfo_file = "";
-  dinfo_line = 0;
-  dinfo_char_start = 0;
-  dinfo_char_end = 0
-}
-
-(* PR#5643: cannot use (==) because Debuginfo values are marshalled *)
-let is_none t =
-  t = none
-
-let to_string d =
-  if d = none
-  then ""
-  else Printf.sprintf "{%s:%d,%d-%d}"
-           d.dinfo_file d.dinfo_line d.dinfo_char_start d.dinfo_char_end
-
-let from_location kind loc =
-  if loc == Location.none then none else
-  { dinfo_kind = kind;
-    dinfo_file = loc.loc_start.pos_fname;
-    dinfo_line = loc.loc_start.pos_lnum;
-    dinfo_char_start = loc.loc_start.pos_cnum - loc.loc_start.pos_bol;
-    dinfo_char_end =
-      if loc.loc_end.pos_fname = loc.loc_start.pos_fname
-      then loc.loc_end.pos_cnum - loc.loc_start.pos_bol
-      else loc.loc_start.pos_cnum - loc.loc_start.pos_bol }
-
-let from_call ev = from_location Dinfo_call ev.Lambda.lev_loc
-let from_raise ev = from_location Dinfo_raise ev.Lambda.lev_loc
diff --git a/asmcomp/debuginfo.mli b/asmcomp/debuginfo.mli
deleted file mode 100644
index ef4d55ad..00000000
--- a/asmcomp/debuginfo.mli
+++ /dev/null
@@ -1,32 +0,0 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2006 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-type kind = Dinfo_call | Dinfo_raise
-
-type t = private {
-  dinfo_kind: kind;
-  dinfo_file: string;
-  dinfo_line: int;
-  dinfo_char_start: int;
-  dinfo_char_end: int
-}
-
-val none: t
-
-val is_none: t -> bool
-
-val to_string: t -> string
-
-val from_location: kind -> Location.t -> t
-
-val from_call: Lambda.lambda_event -> t
-val from_raise: Lambda.lambda_event -> t
diff --git a/asmcomp/emit.mli b/asmcomp/emit.mli
index ab9442ef..cab50833 100644
--- a/asmcomp/emit.mli
+++ b/asmcomp/emit.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Generation of assembly code *)
 
diff --git a/asmcomp/emitaux.ml b/asmcomp/emitaux.ml
index ec2e8f06..4ba28d2a 100644
--- a/asmcomp/emitaux.ml
+++ b/asmcomp/emitaux.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Common functions for emitting assembly code *)
 
@@ -220,28 +223,41 @@ let reset_debug_info () =
 
 (* We only diplay .file if the file has not been seen before. We
    display .loc for every instruction. *)
-let emit_debug_info dbg =
+let emit_debug_info_gen dbg file_emitter loc_emitter =
   if is_cfi_enabled () &&
     (!Clflags.debug || Config.with_frame_pointers)
      && dbg.Debuginfo.dinfo_line > 0 (* PR#6243 *)
   then begin
-    let line = dbg.Debuginfo.dinfo_line in
-    let file_name = dbg.Debuginfo.dinfo_file in
+    let { Debuginfo.
+          dinfo_line = line;
+          dinfo_char_start = col;
+          dinfo_file = file_name;
+        } = dbg in
     let file_num =
       try List.assoc file_name !file_pos_nums
       with Not_found ->
         let file_num = !file_pos_num_cnt in
         incr file_pos_num_cnt;
-        emit_string "\t.file\t";
-        emit_int file_num; emit_char '\t';
-        emit_string_literal file_name; emit_char '\n';
+        file_emitter ~file_num ~file_name;
         file_pos_nums := (file_name,file_num) :: !file_pos_nums;
         file_num in
-    emit_string "\t.loc\t";
-    emit_int file_num; emit_char '\t';
-    emit_int line; emit_char '\n'
+    loc_emitter ~file_num ~line ~col;
   end
 
+let emit_debug_info dbg =
+  emit_debug_info_gen dbg (fun ~file_num ~file_name ->
+      emit_string "\t.file\t";
+      emit_int file_num; emit_char '\t';
+      emit_string_literal file_name; emit_char '\n';
+    )
+    (fun ~file_num ~line ~col:_ ->
+       emit_string "\t.loc\t";
+       emit_int file_num; emit_char '\t';
+       emit_int line; emit_char '\n')
+
 let reset () =
   reset_debug_info ();
   frame_descriptors := []
+
+let binary_backend_available = ref false
+let create_asm_file = ref true
diff --git a/asmcomp/emitaux.mli b/asmcomp/emitaux.mli
index e943da38..093b589f 100644
--- a/asmcomp/emitaux.mli
+++ b/asmcomp/emitaux.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Common functions for emitting assembly code *)
 
@@ -30,6 +33,10 @@ val emit_float32_directive: string -> int32 -> unit
 val reset : unit -> unit
 val reset_debug_info: unit -> unit
 val emit_debug_info: Debuginfo.t -> unit
+val emit_debug_info_gen :
+  Debuginfo.t ->
+  (file_num:int -> file_name:string -> unit) ->
+  (file_num:int -> line:int -> col:int -> unit) -> unit
 
 type frame_descr =
   { fd_lbl: int;                        (* Return address *)
@@ -57,3 +64,12 @@ val cfi_startproc : unit -> unit
 val cfi_endproc : unit -> unit
 val cfi_adjust_cfa_offset : int -> unit
 val cfi_offset : reg:int -> offset:int -> unit
+
+
+val binary_backend_available: bool ref
+    (** Is a binary backend available.  If yes, we don't need
+        to generate the textual assembly file (unless the user
+        request it with -S). *)
+
+val create_asm_file: bool ref
+    (** Are we actually generating the textual assembly file? *)
diff --git a/asmcomp/export_info.ml b/asmcomp/export_info.ml
new file mode 100644
index 00000000..b67998bb
--- /dev/null
+++ b/asmcomp/export_info.ml
@@ -0,0 +1,354 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+type value_string_contents =
+  | Contents of string
+  | Unknown_or_mutable
+
+type value_string = {
+  contents : value_string_contents;
+  size : int;
+}
+
+type value_float_array_contents =
+  | Contents of float option array
+  | Unknown_or_mutable
+
+type value_float_array = {
+  contents : value_float_array_contents;
+  size : int;
+}
+
+type descr =
+  | Value_block of Tag.t * approx array
+  | Value_mutable_block of Tag.t * int
+  | Value_int of int
+  | Value_char of char
+  | Value_constptr of int
+  | Value_float of float
+  | Value_float_array of value_float_array
+  | Value_boxed_int : 'a Simple_value_approx.boxed_int * 'a -> descr
+  | Value_string of value_string
+  | Value_closure of value_closure
+  | Value_set_of_closures of value_set_of_closures
+
+and value_closure = {
+  closure_id : Closure_id.t;
+  set_of_closures : value_set_of_closures;
+}
+
+and value_set_of_closures = {
+  set_of_closures_id : Set_of_closures_id.t;
+  bound_vars : approx Var_within_closure.Map.t;
+  results : approx Closure_id.Map.t;
+  aliased_symbol : Symbol.t option;
+}
+
+and approx =
+  | Value_unknown
+  | Value_id of Export_id.t
+  | Value_symbol of Symbol.t
+
+let equal_approx (a1:approx) (a2:approx) =
+  match a1, a2 with
+  | Value_unknown, Value_unknown ->
+    true
+  | Value_id id1, Value_id id2 ->
+    Export_id.equal id1 id2
+  | Value_symbol s1, Value_symbol s2 ->
+    Symbol.equal s1 s2
+  | (Value_unknown | Value_symbol _ | Value_id _),
+    (Value_unknown | Value_symbol _ | Value_id _) ->
+    false
+
+let equal_array eq a1 a2 =
+  Array.length a1 = Array.length a2 &&
+  try
+    Array.iteri (fun i v1 -> if not (eq a2.(i) v1) then raise Exit) a1;
+    true
+  with Exit -> false
+
+let equal_option eq o1 o2 =
+  match o1, o2 with
+  | None, None -> true
+  | Some v1, Some v2 -> eq v1 v2
+  | Some _, None | None, Some _ -> false
+
+let equal_set_of_closures (s1:value_set_of_closures)
+      (s2:value_set_of_closures) =
+  Set_of_closures_id.equal s1.set_of_closures_id s2.set_of_closures_id &&
+  Var_within_closure.Map.equal equal_approx s1.bound_vars s2.bound_vars &&
+  Closure_id.Map.equal equal_approx s1.results s2.results &&
+  equal_option Symbol.equal s1.aliased_symbol s2.aliased_symbol
+
+let equal_descr (d1:descr) (d2:descr) : bool =
+  match d1, d2 with
+  | Value_block (t1, f1), Value_block (t2, f2) ->
+    Tag.equal t1 t2 && equal_array equal_approx f1 f2
+  | Value_mutable_block (t1, s1), Value_mutable_block (t2, s2) ->
+    Tag.equal t1 t2 &&
+    s1 = s2
+  | Value_int i1, Value_int i2 ->
+    i1 = i2
+  | Value_char c1, Value_char c2 ->
+    c1 = c2
+  | Value_constptr i1, Value_constptr i2 ->
+    i1 = i2
+  | Value_float f1, Value_float f2 ->
+    f1 = f2
+  | Value_float_array s1, Value_float_array s2 ->
+    s1 = s2
+  | Value_boxed_int (t1, v1), Value_boxed_int (t2, v2) ->
+    Simple_value_approx.equal_boxed_int t1 v1 t2 v2
+  | Value_string s1, Value_string s2 ->
+    s1 = s2
+  | Value_closure c1, Value_closure c2 ->
+    Closure_id.equal c1.closure_id c2.closure_id &&
+    equal_set_of_closures c1.set_of_closures c2.set_of_closures
+  | Value_set_of_closures s1, Value_set_of_closures s2 ->
+    equal_set_of_closures s1 s2
+  | ( Value_block (_, _) | Value_mutable_block (_, _) | Value_int _
+    | Value_char _ | Value_constptr _ | Value_float _ | Value_float_array _
+    | Value_boxed_int _ | Value_string _ | Value_closure _
+    | Value_set_of_closures _ ),
+    ( Value_block (_, _) | Value_mutable_block (_, _) | Value_int _
+    | Value_char _ | Value_constptr _ | Value_float _ | Value_float_array _
+    | Value_boxed_int _ | Value_string _ | Value_closure _
+    | Value_set_of_closures _ ) ->
+    false
+
+type t = {
+  sets_of_closures : Flambda.function_declarations Set_of_closures_id.Map.t;
+  closures : Flambda.function_declarations Closure_id.Map.t;
+  values : descr Export_id.Map.t Compilation_unit.Map.t;
+  symbol_id : Export_id.t Symbol.Map.t;
+  offset_fun : int Closure_id.Map.t;
+  offset_fv : int Var_within_closure.Map.t;
+  constant_sets_of_closures : Set_of_closures_id.Set.t;
+  invariant_params : Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t;
+}
+
+let empty : t = {
+  sets_of_closures = Set_of_closures_id.Map.empty;
+  closures = Closure_id.Map.empty;
+  values = Compilation_unit.Map.empty;
+  symbol_id = Symbol.Map.empty;
+  offset_fun = Closure_id.Map.empty;
+  offset_fv = Var_within_closure.Map.empty;
+  constant_sets_of_closures = Set_of_closures_id.Set.empty;
+  invariant_params = Set_of_closures_id.Map.empty;
+}
+
+let create ~sets_of_closures ~closures ~values ~symbol_id
+      ~offset_fun ~offset_fv ~constant_sets_of_closures
+      ~invariant_params =
+  { sets_of_closures;
+    closures;
+    values;
+    symbol_id;
+    offset_fun;
+    offset_fv;
+    constant_sets_of_closures;
+    invariant_params;
+  }
+
+let add_clambda_info t ~offset_fun ~offset_fv ~constant_sets_of_closures =
+  assert (Closure_id.Map.cardinal t.offset_fun = 0);
+  assert (Var_within_closure.Map.cardinal t.offset_fv = 0);
+  assert (Set_of_closures_id.Set.cardinal t.constant_sets_of_closures = 0);
+  { t with offset_fun; offset_fv; constant_sets_of_closures; }
+
+let merge (t1 : t) (t2 : t) : t =
+  let eidmap_disjoint_union ?eq map1 map2 =
+    Compilation_unit.Map.merge (fun _id map1 map2 ->
+        match map1, map2 with
+        | None, None -> None
+        | None, Some map
+        | Some map, None -> Some map
+        | Some map1, Some map2 ->
+          Some (Export_id.Map.disjoint_union ?eq map1 map2))
+      map1 map2
+  in
+  let int_eq (i : int) j = i = j in
+  { values = eidmap_disjoint_union ~eq:equal_descr t1.values t2.values;
+    sets_of_closures =
+      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;
+    offset_fun = Closure_id.Map.disjoint_union
+        ~eq:int_eq t1.offset_fun t2.offset_fun;
+    offset_fv = Var_within_closure.Map.disjoint_union
+        ~eq:int_eq t1.offset_fv t2.offset_fv;
+    constant_sets_of_closures =
+      Set_of_closures_id.Set.union t1.constant_sets_of_closures
+        t2.constant_sets_of_closures;
+    invariant_params =
+      Set_of_closures_id.Map.disjoint_union
+        ~eq:(Variable.Map.equal Variable.Set.equal)
+        t1.invariant_params t2.invariant_params;
+  }
+
+let find_value eid map =
+  let unit_map =
+    Compilation_unit.Map.find (Export_id.get_compilation_unit eid) map
+  in
+  Export_id.Map.find eid unit_map
+
+let find_description (t : t) eid =
+  find_value eid t.values
+
+let nest_eid_map map =
+  let add_map eid v map =
+    let unit = Export_id.get_compilation_unit eid in
+    let m =
+      try Compilation_unit.Map.find unit map
+      with Not_found -> Export_id.Map.empty
+    in
+    Compilation_unit.Map.add unit (Export_id.Map.add eid v m) map
+  in
+  Export_id.Map.fold add_map map Compilation_unit.Map.empty
+
+let print_approx ppf (t : t) =
+  let values = t.values in
+  let fprintf = Format.fprintf in
+  let printed = ref Export_id.Set.empty in
+  let recorded_symbol = ref Symbol.Set.empty in
+  let symbols_to_print = Queue.create () in
+  let printed_set_of_closures = ref Set_of_closures_id.Set.empty in
+  let rec print_approx ppf (approx : approx) =
+    match approx with
+    | Value_unknown -> fprintf ppf "?"
+    | Value_id id ->
+      if Export_id.Set.mem id !printed then
+        fprintf ppf "(%a: _)" Export_id.print id
+      else begin
+        try
+          let descr = find_value id values in
+          printed := Export_id.Set.add id !printed;
+          fprintf ppf "@[(%a:@ %a)@]"
+            Export_id.print id print_descr descr
+        with Not_found ->
+          fprintf ppf "(%a: Not available)" Export_id.print id
+      end
+    | Value_symbol sym ->
+      if not (Symbol.Set.mem sym !recorded_symbol) then begin
+        recorded_symbol := Symbol.Set.add sym !recorded_symbol;
+        Queue.push sym symbols_to_print;
+      end;
+      Symbol.print ppf sym
+  and print_descr ppf (descr : descr) =
+    match descr with
+    | Value_int i -> Format.pp_print_int ppf i
+    | Value_char c -> fprintf ppf "%c" c
+    | Value_constptr i -> fprintf ppf "%ip" i
+    | Value_block (tag, fields) ->
+      fprintf ppf "[%a:%a]" Tag.print tag print_fields fields
+    | Value_mutable_block (tag, size) ->
+      fprintf ppf "[mutable %a:%i]" Tag.print tag size
+    | Value_closure {closure_id; set_of_closures} ->
+      fprintf ppf "(closure %a, %a)" Closure_id.print closure_id
+        print_set_of_closures set_of_closures
+    | Value_set_of_closures set_of_closures ->
+      fprintf ppf "(set_of_closures %a)" print_set_of_closures set_of_closures
+    | Value_string { contents; size } ->
+      begin match contents with
+      | Unknown_or_mutable -> Format.fprintf ppf "string %i" size
+      | Contents s ->
+        let s =
+          if size > 10
+          then String.sub s 0 8 ^ "..."
+          else s
+        in
+        Format.fprintf ppf "string %i %S" size s
+      end
+    | Value_float f -> Format.pp_print_float ppf f
+    | Value_float_array float_array ->
+      Format.fprintf ppf "float_array%s %i"
+        (match float_array.contents with
+          | Unknown_or_mutable -> ""
+          | Contents _ -> "_imm")
+        float_array.size
+    | Value_boxed_int (t, i) ->
+      let module A = Simple_value_approx in
+      match t with
+      | A.Int32 -> Format.fprintf ppf "%li" i
+      | A.Int64 -> Format.fprintf ppf "%Li" i
+      | A.Nativeint -> Format.fprintf ppf "%ni" i
+  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 } =
+    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
+      printed_set_of_closures :=
+        Set_of_closures_id.Set.add set_of_closures_id !printed_set_of_closures;
+      let print_alias ppf = function
+        | None -> ()
+        | Some symbol ->
+          Format.fprintf ppf "@ (alias: %a)" Symbol.print symbol
+      in
+      fprintf ppf "{%a: %a%a}"
+        Set_of_closures_id.print set_of_closures_id
+        print_binding bound_vars
+        print_alias aliased_symbol
+    end
+  and print_binding ppf bound_vars =
+    Var_within_closure.Map.iter (fun clos_id approx ->
+        fprintf ppf "%a -> %a,@ "
+          Var_within_closure.print clos_id
+          print_approx approx)
+      bound_vars
+  in
+  let rec print_recorded_symbols () =
+    if not (Queue.is_empty symbols_to_print) then begin
+      let sym = Queue.pop symbols_to_print in
+      begin match Symbol.Map.find sym t.symbol_id with
+      | exception Not_found -> ()
+      | id ->
+        fprintf ppf "@[%a:@ %a@];@ "
+          Symbol.print sym
+          print_approx (Value_id id)
+      end;
+      print_recorded_symbols ();
+    end
+  in
+  fprintf ppf "@[Globals:@ ";
+  fprintf ppf "@]@ @[Symbols:@ ";
+  print_recorded_symbols ();
+  fprintf ppf "@]"
+
+let print_offsets ppf (t : t) =
+  Format.fprintf ppf "@[offset_fun:@ ";
+  Closure_id.Map.iter (fun cid off ->
+      Format.fprintf ppf "%a -> %i@ "
+        Closure_id.print cid off) t.offset_fun;
+  Format.fprintf ppf "@]@ @[offset_fv:@ ";
+  Var_within_closure.Map.iter (fun vid off ->
+      Format.fprintf ppf "%a -> %i@ "
+        Var_within_closure.print vid off) t.offset_fv;
+  Format.fprintf ppf "@]@ "
+
+let print_all ppf (t : t) =
+  let fprintf = Format.fprintf in
+  fprintf ppf "approxs@ %a@.@."
+    print_approx t;
+  fprintf ppf "functions@ %a@.@."
+    (Set_of_closures_id.Map.print Flambda.print_function_declarations)
+    t.sets_of_closures
diff --git a/asmcomp/export_info.mli b/asmcomp/export_info.mli
new file mode 100644
index 00000000..9d6bc0f6
--- /dev/null
+++ b/asmcomp/export_info.mli
@@ -0,0 +1,148 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+(** Exported information (that is to say, information written into a .cmx
+    file) about a compilation unit. *)
+
+type value_string_contents =
+  | Contents of string
+  | Unknown_or_mutable
+
+type value_string = {
+  contents : value_string_contents;
+  size : int;
+}
+
+type value_float_array_contents =
+  | Contents of float option array
+  | Unknown_or_mutable
+
+type value_float_array = {
+  contents : value_float_array_contents;
+  size : int;
+}
+
+type descr =
+  | Value_block of Tag.t * approx array
+  | Value_mutable_block of Tag.t * int
+  | Value_int of int
+  | Value_char of char
+  | Value_constptr of int
+  | Value_float of float
+  | Value_float_array of value_float_array
+  | Value_boxed_int : 'a Simple_value_approx.boxed_int * 'a -> descr
+  | Value_string of value_string
+  | Value_closure of value_closure
+  | Value_set_of_closures of value_set_of_closures
+
+and value_closure = {
+  closure_id : Closure_id.t;
+  set_of_closures : value_set_of_closures;
+}
+
+and value_set_of_closures = {
+  set_of_closures_id : Set_of_closures_id.t;
+  bound_vars : approx Var_within_closure.Map.t;
+  results : approx Closure_id.Map.t;
+  aliased_symbol : Symbol.t option;
+}
+
+(* CR-soon mshinwell: Fix the export information so we can correctly
+   propagate "unresolved due to..." in the manner of [Simple_value_approx].
+   Unfortunately this seems to be complicated by the fact that, during
+   [Import_approx], resolution can fail not only due to missing symbols but
+   also due to missing export IDs.  The argument type of
+   [Simple_value_approx.t] may need updating to reflect this (make the
+   symbol optional?  It's only for debugging anyway.) *)
+and approx =
+  | Value_unknown
+  | Value_id of Export_id.t
+  | Value_symbol of Symbol.t
+
+(** A structure that describes what a single compilation unit exports. *)
+type t = private {
+  sets_of_closures : Flambda.function_declarations Set_of_closures_id.Map.t;
+  (** Code of exported functions indexed by set of closures IDs. *)
+  closures : Flambda.function_declarations Closure_id.Map.t;
+  (** Code of exported functions indexed by closure IDs. *)
+  values : descr Export_id.Map.t Compilation_unit.Map.t;
+  (** Structure of exported values. *)
+  symbol_id : Export_id.t Symbol.Map.t;
+  (** Associates symbols and values. *)
+  offset_fun : int Closure_id.Map.t;
+  (** Positions of function pointers in their closures. *)
+  offset_fv : int Var_within_closure.Map.t;
+  (** Positions of value pointers in their closures. *)
+  constant_sets_of_closures : Set_of_closures_id.Set.t;
+  (* CR-soon mshinwell for pchambart: Add comment *)
+  invariant_params : Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t;
+  (* Function parameters known to be invariant (see [Invariant_params])
+     indexed by set of closures ID. *)
+}
+
+(** Export information for a compilation unit that exports nothing. *)
+val empty : t
+
+(** Create a new export information structure. *)
+val create
+   : sets_of_closures:Flambda.function_declarations Set_of_closures_id.Map.t
+  -> closures:Flambda.function_declarations Closure_id.Map.t
+  -> values:descr Export_id.Map.t Compilation_unit.Map.t
+  -> symbol_id:Export_id.t Symbol.Map.t
+  -> offset_fun:int Closure_id.Map.t
+  -> offset_fv:int Var_within_closure.Map.t
+  -> constant_sets_of_closures:Set_of_closures_id.Set.t
+  -> invariant_params:Variable.Set.t Variable.Map.t Set_of_closures_id.Map.t
+  -> t
+
+(* CR-someday pchambart: Should we separate [t] in 2 types: one created by the
+   current [create] function, returned by [Build_export_info]. And
+   another built using t and offset_informations returned by
+   [flambda_to_clambda] ?
+   mshinwell: I think we should, but after we've done the first release.
+*)
+(** Record information about the layout of closures and which sets of
+    closures are constant.  These are all worked out during the
+    [Flambda_to_clambda] pass. *)
+val add_clambda_info
+   : t
+  -> offset_fun:int Closure_id.Map.t
+  -> offset_fv:int Var_within_closure.Map.t
+  -> constant_sets_of_closures:Set_of_closures_id.Set.t
+  -> t
+
+(** Union of export information.  Verifies that there are no identifier
+    clashes. *)
+val merge : t -> t -> t
+
+(** Look up the description of an exported value given its export ID. *)
+val find_description
+   : t
+  -> Export_id.t
+  -> descr
+
+(** Partition a mapping from export IDs by compilation unit. *)
+val nest_eid_map
+   : 'a Export_id.Map.t
+  -> 'a Export_id.Map.t Compilation_unit.Map.t
+
+(**/**)
+(* Debug printing functions. *)
+val print_approx : Format.formatter -> t -> unit
+val print_offsets : Format.formatter -> t -> unit
+val print_all : Format.formatter -> t -> unit
diff --git a/asmcomp/export_info_for_pack.ml b/asmcomp/export_info_for_pack.ml
new file mode 100644
index 00000000..25ef70c6
--- /dev/null
+++ b/asmcomp/export_info_for_pack.ml
@@ -0,0 +1,138 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+let rename_id_state = Export_id.Tbl.create 100
+
+(* Rename export identifiers' compilation units to denote that they now
+   live within a pack. *)
+let import_eid_for_pack units pack id =
+  try Export_id.Tbl.find rename_id_state id
+  with Not_found ->
+    let unit_id = Export_id.get_compilation_unit id in
+    let id' =
+      if Compilation_unit.Set.mem unit_id units
+      then Export_id.create ?name:(Export_id.name id) pack
+      else id
+    in
+    Export_id.Tbl.add rename_id_state id id';
+    id'
+
+(* Similar to [import_eid_for_pack], but for symbols. *)
+let import_symbol_for_pack units pack symbol =
+  let compilation_unit = Symbol.compilation_unit symbol in
+  if Compilation_unit.Set.mem compilation_unit units
+  then Symbol.import_for_pack ~pack symbol
+  else symbol
+
+let import_approx_for_pack units pack (approx : Export_info.approx)
+      : Export_info.approx =
+  match approx with
+  | Value_symbol sym -> Value_symbol (import_symbol_for_pack units pack sym)
+  | Value_id eid -> Value_id (import_eid_for_pack units pack eid)
+  | Value_unknown -> Value_unknown
+
+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;
+    bound_vars =
+      Var_within_closure.Map.map (import_approx_for_pack units pack)
+        set_of_closures.bound_vars;
+    results =
+      Closure_id.Map.map (import_approx_for_pack units pack)
+        set_of_closures.results;
+    aliased_symbol =
+      Misc.may_map
+        (import_symbol_for_pack units pack)
+        set_of_closures.aliased_symbol;
+  }
+
+let import_descr_for_pack units pack (descr : Export_info.descr)
+      : Export_info.descr =
+  match descr with
+  | Value_int _
+  | Value_char _
+  | Value_constptr _
+  | Value_string _
+  | Value_float _
+  | Value_float_array _
+  | Export_info.Value_boxed_int _
+  | Value_mutable_block _ as desc -> desc
+  | Value_block (tag, fields) ->
+    Value_block (tag, Array.map (import_approx_for_pack units pack) fields)
+  | Value_closure { closure_id; set_of_closures } ->
+    Value_closure {
+      closure_id;
+      set_of_closures = import_set_of_closures units pack set_of_closures;
+    }
+  | 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 =
+  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)
+      | e -> e)
+    expr
+
+let import_function_declarations_for_pack units pack
+      (function_decls : Flambda.function_declarations) =
+  let funs =
+    Variable.Map.map (fun (function_decl : Flambda.function_declaration) ->
+        Flambda.create_function_declaration ~params:function_decl.params
+          ~body:(import_code_for_pack units pack function_decl.body)
+          ~stub:function_decl.stub ~dbg:function_decl.dbg
+          ~inline:function_decl.inline
+          ~specialise:function_decl.specialise
+          ~is_a_functor:function_decl.is_a_functor)
+      function_decls.funs
+  in
+  Flambda.update_function_declarations function_decls ~funs
+
+let import_eidmap_for_pack units pack f map =
+  Export_info.nest_eid_map
+    (Compilation_unit.Map.fold
+      (fun _ map acc -> Export_id.Map.disjoint_union map acc)
+      (Compilation_unit.Map.map (fun map ->
+          Export_id.Map.map_keys (import_eid_for_pack units pack)
+            (Export_id.Map.map f map))
+        map)
+      Export_id.Map.empty)
+
+let import_for_pack ~pack_units ~pack (exp : Export_info.t) =
+  let import_sym = import_symbol_for_pack pack_units pack in
+  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 sets_of_closures =
+    Set_of_closures_id.Map.map
+      (import_function_declarations_for_pack pack_units pack)
+      exp.sets_of_closures
+  in
+  Export_info.create ~sets_of_closures
+    ~closures:(Flambda_utils.make_closure_map' sets_of_closures)
+    ~offset_fun:exp.offset_fun
+    ~offset_fv:exp.offset_fv
+    ~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
+
+let clear_import_state () = Export_id.Tbl.clear rename_id_state
diff --git a/asmcomp/export_info_for_pack.mli b/asmcomp/export_info_for_pack.mli
new file mode 100644
index 00000000..2ba3a35d
--- /dev/null
+++ b/asmcomp/export_info_for_pack.mli
@@ -0,0 +1,34 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+(** Transformations on export information that are only used for the
+    building of packs. *)
+
+(** Transform the information from [exported] to be
+    suitable to be reexported as the information for a pack named [pack]
+    containing units [pack_units].
+    It mainly changes symbols of units [pack_units] to refer to
+    [pack] instead. *)
+val import_for_pack
+   : pack_units:Compilation_unit.Set.t
+  -> pack:Compilation_unit.t
+  -> Export_info.t
+  -> Export_info.t
+
+(** Drops the state after importing several units in the same pack. *)
+val clear_import_state : unit -> unit
diff --git a/asmcomp/flambda_to_clambda.ml b/asmcomp/flambda_to_clambda.ml
new file mode 100644
index 00000000..a5a0bd76
--- /dev/null
+++ b/asmcomp/flambda_to_clambda.ml
@@ -0,0 +1,711 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+type for_one_or_more_units = {
+  fun_offset_table : int Closure_id.Map.t;
+  fv_offset_table : int Var_within_closure.Map.t;
+  closures : Flambda.function_declarations Closure_id.Map.t;
+  constant_sets_of_closures : Set_of_closures_id.Set.t;
+}
+
+type t = {
+  current_unit : for_one_or_more_units;
+  imported_units : for_one_or_more_units;
+}
+
+type ('a, 'b) declaration_position =
+  | Current_unit of 'a
+  | Imported_unit of 'b
+  | Not_declared
+
+let get_fun_offset t closure_id =
+  let fun_offset_table =
+    if Closure_id.in_compilation_unit closure_id (Compilenv.current_unit ())
+    then t.current_unit.fun_offset_table
+    else t.imported_units.fun_offset_table
+  in
+  try Closure_id.Map.find closure_id fun_offset_table
+  with Not_found ->
+    Misc.fatal_errorf "Flambda_to_clambda: missing offset for closure %a"
+      Closure_id.print closure_id
+
+let get_fv_offset t var_within_closure =
+  let fv_offset_table =
+    if Var_within_closure.in_compilation_unit var_within_closure
+        (Compilenv.current_unit ())
+    then t.current_unit.fv_offset_table
+    else t.imported_units.fv_offset_table
+  in
+  try Var_within_closure.Map.find var_within_closure fv_offset_table
+  with Not_found ->
+    Misc.fatal_errorf "Flambda_to_clambda: missing offset for variable %a"
+      Var_within_closure.print var_within_closure
+
+let function_declaration_position t closure_id =
+  try
+    Current_unit (Closure_id.Map.find closure_id t.current_unit.closures)
+  with Not_found ->
+    try
+      Imported_unit (Closure_id.Map.find closure_id t.imported_units.closures)
+    with Not_found -> Not_declared
+
+let is_function_constant t closure_id =
+  match function_declaration_position t closure_id with
+  | Current_unit { set_of_closures_id } ->
+    Set_of_closures_id.Set.mem set_of_closures_id
+      t.current_unit.constant_sets_of_closures
+  | Imported_unit { set_of_closures_id } ->
+    Set_of_closures_id.Set.mem set_of_closures_id
+      t.imported_units.constant_sets_of_closures
+  | Not_declared ->
+    Misc.fatal_errorf "Flambda_to_clambda: missing closure %a"
+      Closure_id.print closure_id
+
+(* Instrumentation of closure and field accesses to try to catch compiler
+   bugs. *)
+
+let check_closure ulam named : Clambda.ulambda =
+  if not !Clflags.clambda_checks then ulam
+  else
+    let desc =
+      Primitive.simple ~name:"caml_check_value_is_closure"
+        ~arity:2 ~alloc:false
+    in
+    let str = Format.asprintf "%a" Flambda.print_named named in
+    let str_const =
+      Compilenv.new_structured_constant (Uconst_string str) ~shared:true
+    in
+    Uprim (Pccall desc,
+           [ulam; Clambda.Uconst (Uconst_ref (str_const, None))],
+           Debuginfo.none)
+
+let check_field ulam pos named_opt : Clambda.ulambda =
+  if not !Clflags.clambda_checks then ulam
+  else
+    let desc =
+      Primitive.simple ~name:"caml_check_field_access"
+        ~arity:3 ~alloc:false
+    in
+    let str =
+      match named_opt with
+      | None -> ""
+      | Some named -> Format.asprintf "%a" Flambda.print_named named
+    in
+    let str_const =
+      Compilenv.new_structured_constant (Uconst_string str) ~shared:true
+    in
+    Uprim (Pccall desc, [ulam; Clambda.Uconst (Uconst_int pos);
+        Clambda.Uconst (Uconst_ref (str_const, None))],
+      Debuginfo.none)
+
+module Env : sig
+  type t
+
+  val empty : t
+
+  val add_subst : t -> Variable.t -> Clambda.ulambda -> t
+  val find_subst_exn : t -> Variable.t -> Clambda.ulambda
+
+  val add_fresh_ident : t -> Variable.t -> Ident.t * t
+  val ident_for_var_exn : t -> Variable.t -> Ident.t
+
+  val add_fresh_mutable_ident : t -> Mutable_variable.t -> Ident.t * t
+  val ident_for_mutable_var_exn : t -> Mutable_variable.t -> Ident.t
+
+  val add_allocated_const : t -> Symbol.t -> Allocated_const.t -> t
+  val allocated_const_for_symbol : t -> Symbol.t -> Allocated_const.t option
+
+  val keep_only_symbols : t -> t
+end = struct
+  type t =
+    { subst : Clambda.ulambda Variable.Map.t;
+      var : Ident.t Variable.Map.t;
+      mutable_var : Ident.t Mutable_variable.Map.t;
+      toplevel : bool;
+      allocated_constant_for_symbol : Allocated_const.t Symbol.Map.t;
+    }
+
+  let empty =
+    { subst = Variable.Map.empty;
+      var = Variable.Map.empty;
+      mutable_var = Mutable_variable.Map.empty;
+      toplevel = false;
+      allocated_constant_for_symbol = Symbol.Map.empty;
+    }
+
+  let add_subst t id subst =
+    { t with subst = Variable.Map.add id subst t.subst }
+
+  let find_subst_exn t id = Variable.Map.find id t.subst
+
+  let ident_for_var_exn t id = Variable.Map.find id t.var
+
+  let add_fresh_ident t var =
+    let id = Ident.create (Variable.unique_name var) in
+    id, { t with var = Variable.Map.add var id t.var }
+
+  let ident_for_mutable_var_exn t mut_var =
+    Mutable_variable.Map.find mut_var t.mutable_var
+
+  let add_fresh_mutable_ident t mut_var =
+    let id = Mutable_variable.unique_ident mut_var in
+    let mutable_var = Mutable_variable.Map.add mut_var id t.mutable_var in
+    id, { t with mutable_var; }
+
+  let add_allocated_const t sym cons =
+    { t with
+      allocated_constant_for_symbol =
+        Symbol.Map.add sym cons t.allocated_constant_for_symbol;
+    }
+
+  let allocated_const_for_symbol t sym =
+    try
+      Some (Symbol.Map.find sym t.allocated_constant_for_symbol)
+    with Not_found -> None
+
+  let keep_only_symbols t =
+    { empty with
+      allocated_constant_for_symbol = t.allocated_constant_for_symbol;
+    }
+end
+
+let subst_var env var : Clambda.ulambda =
+  try Env.find_subst_exn env var
+  with Not_found ->
+    try Uvar (Env.ident_for_var_exn env var)
+    with Not_found ->
+      Misc.fatal_errorf "Flambda_to_clambda: unbound variable %a@."
+        Variable.print var
+
+let subst_vars env vars = List.map (subst_var env) vars
+
+let build_uoffset ulam offset : Clambda.ulambda =
+  if offset = 0 then ulam
+  else Uoffset (ulam, offset)
+
+let to_clambda_allocated_constant (const : Allocated_const.t)
+      : Clambda.ustructured_constant =
+  match const with
+  | Float f -> Uconst_float f
+  | Int32 i -> Uconst_int32 i
+  | Int64 i -> Uconst_int64 i
+  | Nativeint i -> Uconst_nativeint i
+  | Immutable_string s | String s -> Uconst_string s
+  | Immutable_float_array a | Float_array a -> Uconst_float_array a
+
+let to_uconst_symbol env symbol : Clambda.ustructured_constant option =
+  match Env.allocated_const_for_symbol env symbol with
+  | Some ((Float _ | Int32 _ | Int64 _ | Nativeint _) as const) ->
+    Some (to_clambda_allocated_constant const)
+  | None  (* CR-soon mshinwell: Try to make this an error. *)
+  | Some _ -> None
+
+let to_clambda_symbol' env sym : Clambda.uconstant =
+  let lbl = Linkage_name.to_string (Symbol.label sym) in
+  Uconst_ref (lbl, to_uconst_symbol env sym)
+
+let to_clambda_symbol env sym : Clambda.ulambda =
+  Uconst (to_clambda_symbol' env sym)
+
+let to_clambda_const env (const : Flambda.constant_defining_value_block_field)
+      : Clambda.uconstant =
+  match const with
+  | Symbol symbol -> to_clambda_symbol' env symbol
+  | Const (Int i) -> Uconst_int i
+  | Const (Char c) -> Uconst_int (Char.code c)
+  | Const (Const_pointer i) -> Uconst_ptr i
+
+(* CR-someday mshinwell: We should improve debug info / location handling
+   so that we don't need to do this. *)
+(* Erase debug info created with high probability by [Debuginfo.from_filename]
+   (currently only used for emission of warning 59, which happens prior to
+   this pass).  Failure to do this will cause erroneous empty frames in
+   backtraces. *)
+let erase_empty_debuginfo (dbg : Debuginfo.t) =
+  if dbg.dinfo_kind = Debuginfo.Dinfo_call
+    && dbg.dinfo_line = 0
+    && dbg.dinfo_char_start = 0
+    && dbg.dinfo_char_end = 0
+  then
+    Debuginfo.none
+  else
+    dbg
+
+let rec to_clambda t env (flam : Flambda.t) : Clambda.ulambda =
+  match flam with
+  | Var var -> subst_var env var
+  | Let { var; defining_expr; body; _ } ->
+    let id, env_body = Env.add_fresh_ident env var in
+    Ulet (id, to_clambda_named t env var defining_expr,
+      to_clambda t env_body body)
+  | Let_mutable (mut_var, var, body) ->
+    let id, env_body = Env.add_fresh_mutable_ident env mut_var in
+    let def = subst_var env var in
+    Ulet (id, def, to_clambda t env_body body)
+  | Let_rec (defs, body) ->
+    let env, defs =
+      List.fold_right (fun (var, def) (env, defs) ->
+          let id, env = Env.add_fresh_ident env var in
+          env, (id, var, def) :: defs)
+        defs (env, [])
+    in
+    let defs =
+      List.map (fun (id, var, def) -> id, to_clambda_named t env var def) defs
+    in
+    Uletrec (defs, to_clambda t env body)
+  | Apply { func; args; kind = Direct direct_func; dbg = dbg } ->
+    (* The closure _parameter_ of the function is added by cmmgen.
+       At the call site, for a direct call, the closure argument must be
+       explicitly added (by [to_clambda_direct_apply]); there is no special
+       handling of such in the direct call primitive.
+       For an indirect call, we do not need to do anything here; Cmmgen will
+       do the equivalent of the previous paragraph when it generates a direct
+       call to [caml_apply]. *)
+    to_clambda_direct_apply t func args direct_func dbg env
+  | Apply { func; args; kind = Indirect; dbg = dbg } ->
+    let callee = subst_var env func in
+    Ugeneric_apply (check_closure callee (Flambda.Expr (Var func)),
+      subst_vars env args, dbg)
+  | Switch (arg, sw) ->
+    let aux () : Clambda.ulambda =
+      let const_index, const_actions =
+        to_clambda_switch t env sw.consts sw.numconsts sw.failaction
+      in
+      let block_index, block_actions =
+        to_clambda_switch t env sw.blocks sw.numblocks sw.failaction
+      in
+      Uswitch (subst_var env arg,
+        { us_index_consts = const_index;
+          us_actions_consts = const_actions;
+          us_index_blocks = block_index;
+          us_actions_blocks = block_actions;
+        })
+    in
+    (* Check that the [failaction] may be duplicated.  If this is not the
+       case, share it through a static raise / static catch. *)
+    (* CR-someday pchambart for pchambart: This is overly simplified.
+       We should verify that this does not generates too bad code.
+       If it the case, handle some let cases.
+    *)
+    begin match sw.failaction with
+    | None -> aux ()
+    | Some (Static_raise _) -> aux ()
+    | Some failaction ->
+      let exn = Static_exception.create () in
+      let sw =
+        { sw with
+          failaction = Some (Flambda.Static_raise (exn, []));
+        }
+      in
+      let expr : Flambda.t =
+        Static_catch (exn, [], Switch (arg, sw), failaction)
+      in
+      to_clambda t env expr
+    end
+  | String_switch (arg, sw, def) ->
+    let arg = subst_var env arg in
+    let sw = List.map (fun (s, e) -> s, to_clambda t env e) sw in
+    let def = Misc.may_map (to_clambda t env) def in
+    Ustringswitch (arg, sw, def)
+  | Static_raise (static_exn, args) ->
+    Ustaticfail (Static_exception.to_int static_exn,
+      List.map (subst_var env) args)
+  | Static_catch (static_exn, vars, body, handler) ->
+    let env_handler, ids =
+      List.fold_right (fun var (env, ids) ->
+          let id, env = Env.add_fresh_ident env var in
+          env, id :: ids)
+        vars (env, [])
+    in
+    Ucatch (Static_exception.to_int static_exn, ids,
+      to_clambda t env body, to_clambda t env_handler handler)
+  | Try_with (body, var, handler) ->
+    let id, env_handler = Env.add_fresh_ident env var in
+    Utrywith (to_clambda t env body, id, to_clambda t env_handler handler)
+  | If_then_else (arg, ifso, ifnot) ->
+    Uifthenelse (subst_var env arg, to_clambda t env ifso,
+      to_clambda t env ifnot)
+  | While (cond, body) ->
+    Uwhile (to_clambda t env cond, to_clambda t env body)
+  | For { bound_var; from_value; to_value; direction; body } ->
+    let id, env_body = Env.add_fresh_ident env bound_var in
+    Ufor (id, subst_var env from_value, subst_var env to_value,
+      direction, to_clambda t env_body body)
+  | Assign { being_assigned; new_value } ->
+    let id =
+      try Env.ident_for_mutable_var_exn env being_assigned
+      with Not_found ->
+        Misc.fatal_errorf "Unbound mutable variable %a in [Assign]: %a"
+          Mutable_variable.print being_assigned
+          Flambda.print flam
+    in
+    Uassign (id, subst_var env new_value)
+  | Send { kind; meth; obj; args; dbg } ->
+    Usend (kind, subst_var env meth, subst_var env obj,
+      subst_vars env args, dbg)
+  | Proved_unreachable -> Uunreachable
+
+and to_clambda_named t env var (named : Flambda.named) : Clambda.ulambda =
+  match named with
+  | Symbol sym -> to_clambda_symbol env sym
+  | Const (Const_pointer n) -> Uconst (Uconst_ptr n)
+  | Const (Int n) -> Uconst (Uconst_int n)
+  | Const (Char c) -> Uconst (Uconst_int (Char.code c))
+  | Allocated_const _ ->
+    Misc.fatal_errorf "[Allocated_const] should have been lifted to a \
+        [Let_symbol] construction before [Flambda_to_clambda]: %a = %a"
+      Variable.print var
+      Flambda.print_named named
+  | Read_mutable mut_var ->
+    begin try Uvar (Env.ident_for_mutable_var_exn env mut_var)
+    with Not_found ->
+      Misc.fatal_errorf "Unbound mutable variable %a in [Read_mutable]: %a"
+        Mutable_variable.print mut_var
+        Flambda.print_named named
+    end
+  | Read_symbol_field (symbol, field) ->
+    Uprim (Pfield field, [to_clambda_symbol env symbol], Debuginfo.none)
+  | Set_of_closures set_of_closures ->
+    to_clambda_set_of_closures t env set_of_closures
+  | Project_closure { set_of_closures; closure_id } ->
+    (* Note that we must use [build_uoffset] to ensure that we do not generate
+       a [Uoffset] construction in the event that the offset is zero, otherwise
+       we might break pattern matches in Cmmgen (in particular for the
+       compilation of "let rec"). *)
+    check_closure (
+      build_uoffset
+        (check_closure (subst_var env set_of_closures)
+           (Flambda.Expr (Var set_of_closures)))
+        (get_fun_offset t closure_id))
+      named
+  | Move_within_set_of_closures { closure; start_from; move_to } ->
+    check_closure (build_uoffset
+      (check_closure (subst_var env closure)
+         (Flambda.Expr (Var closure)))
+      ((get_fun_offset t move_to) - (get_fun_offset t start_from)))
+      named
+  | Project_var { closure; var; closure_id } ->
+    let ulam = subst_var env closure in
+    let fun_offset = get_fun_offset t closure_id in
+    let var_offset = get_fv_offset t var in
+    let pos = var_offset - fun_offset in
+    Uprim (Pfield pos,
+      [check_field (check_closure ulam (Expr (Var closure))) pos (Some named)],
+      Debuginfo.none)
+  | Prim (Pfield index, [block], dbg) ->
+    let dbg = erase_empty_debuginfo dbg in
+    Uprim (Pfield index, [check_field (subst_var env block) index None], dbg)
+  | Prim (Psetfield (index, maybe_ptr, init), [block; new_value], dbg) ->
+    let dbg = erase_empty_debuginfo dbg in
+    Uprim (Psetfield (index, maybe_ptr, init), [
+        check_field (subst_var env block) index None;
+        subst_var env new_value;
+      ], dbg)
+  | Prim (Popaque, args, dbg) ->
+    let dbg = erase_empty_debuginfo dbg in
+    Uprim (Pidentity, subst_vars env args, dbg)
+  | Prim (p, args, dbg) ->
+    let dbg = erase_empty_debuginfo dbg in
+    Uprim (p, subst_vars env args, dbg)
+  | Expr expr -> to_clambda t env expr
+
+and to_clambda_switch t env cases num_keys default =
+  let num_keys =
+    if Numbers.Int.Set.cardinal num_keys = 0 then 0
+    else Numbers.Int.Set.max_elt num_keys + 1
+  in
+  let index = Array.make num_keys 0 in
+  let store = Flambda_utils.Switch_storer.mk_store () in
+  begin match default with
+  | Some def when List.length cases < num_keys -> ignore (store.act_store def)
+  | _ -> ()
+  end;
+  List.iter (fun (key, lam) -> index.(key) <- store.act_store lam) cases;
+  let actions = Array.map (to_clambda t env) (store.act_get ()) in
+  match actions with
+  | [| |] -> [| |], [| |]  (* May happen when [default] is [None]. *)
+  | _ -> index, actions
+
+and to_clambda_direct_apply t func args direct_func dbg env : Clambda.ulambda =
+  let closed = is_function_constant t direct_func in
+  let label = Compilenv.function_label direct_func in
+  let uargs =
+    let uargs = subst_vars env args in
+    (* Remove the closure argument if the closure is closed.  (Note that the
+       closure argument is always a variable, so we can be sure we are not
+       dropping any side effects.) *)
+    if closed then uargs else uargs @ [subst_var env func]
+  in
+  Udirect_apply (label, uargs, dbg)
+
+(* Describe how to build a runtime closure block that corresponds to the
+   given Flambda set of closures.
+
+   For instance the closure for the following set of closures:
+
+     let rec fun_a x =
+       if x <= 0 then 0 else fun_b (x-1) v1
+     and fun_b x y =
+       if x <= 0 then 0 else v1 + v2 + y + fun_a (x-1)
+
+   will be represented in memory as:
+
+     [ closure header; fun_a;
+       1; infix header; fun caml_curry_2;
+       2; fun_b; v1; v2 ]
+
+   fun_a and fun_b will take an additional parameter 'env' to
+   access their closure.  It will be arranged such that in the body
+   of each function the env parameter points to its own code
+   pointer.  For example, in fun_b it will be shifted by 3 words.
+
+   Hence accessing v1 in the body of fun_a is accessing the
+   6th field of 'env' and in the body of fun_b the 1st field.
+*)
+and to_clambda_set_of_closures t env
+      (({ function_decls; free_vars } : Flambda.set_of_closures)
+        as set_of_closures) : Clambda.ulambda =
+  let all_functions = Variable.Map.bindings function_decls.funs in
+  let env_var = Ident.create "env" in
+  let to_clambda_function
+        (closure_id, (function_decl : Flambda.function_declaration))
+        : Clambda.ufunction =
+    let closure_id = Closure_id.wrap closure_id in
+    let fun_offset =
+      Closure_id.Map.find closure_id t.current_unit.fun_offset_table
+    in
+    let env =
+      (* Inside the body of the function, we cannot access variables
+         declared outside, so start with a suitably clean environment.
+         Note that we must not forget the information about which allocated
+         constants contain which unboxed values. *)
+      let env = Env.keep_only_symbols env in
+      (* Add the Clambda expressions for the free variables of the function
+         to the environment. *)
+      let add_env_free_variable id _ env =
+        let var_offset =
+          try
+            Var_within_closure.Map.find
+              (Var_within_closure.wrap id) t.current_unit.fv_offset_table
+          with Not_found ->
+            Misc.fatal_errorf "Clambda.to_clambda_set_of_closures: offset for \
+                free variable %a is unknown.  Set of closures: %a"
+              Variable.print id
+              Flambda.print_set_of_closures set_of_closures
+        in
+        let pos = var_offset - fun_offset in
+        Env.add_subst env id
+          (Uprim (Pfield pos, [Clambda.Uvar env_var], Debuginfo.none))
+      in
+      let env = Variable.Map.fold add_env_free_variable free_vars env in
+      (* Add the Clambda expressions for all functions defined in the current
+         set of closures to the environment.  The various functions may be
+         retrieved by moving within the runtime closure, starting from the
+         current function's closure. *)
+      let add_env_function pos env (id, _) =
+        let offset =
+          Closure_id.Map.find (Closure_id.wrap id)
+            t.current_unit.fun_offset_table
+        in
+        let exp : Clambda.ulambda = Uoffset (Uvar env_var, offset - pos) in
+        Env.add_subst env id exp
+      in
+      List.fold_left (add_env_function fun_offset) env all_functions
+    in
+    let env_body, params =
+      List.fold_right (fun var (env, params) ->
+          let id, env = Env.add_fresh_ident env var in
+          env, id :: params)
+        function_decl.params (env, [])
+    in
+    { label = Compilenv.function_label closure_id;
+      arity = Flambda_utils.function_arity function_decl;
+      params = params @ [env_var];
+      body = to_clambda t env_body function_decl.body;
+      dbg = function_decl.dbg;
+    }
+  in
+  let funs = List.map to_clambda_function all_functions in
+  let free_vars =
+    Variable.Map.bindings (Variable.Map.map (
+      fun (free_var : Flambda.specialised_to) ->
+        subst_var env free_var.var) free_vars)
+  in
+  Uclosure (funs, List.map snd free_vars)
+
+and to_clambda_closed_set_of_closures t env symbol
+      ({ function_decls; } : Flambda.set_of_closures)
+      : Clambda.ustructured_constant =
+  let functions = Variable.Map.bindings function_decls.funs in
+  let to_clambda_function (id, (function_decl : Flambda.function_declaration))
+        : Clambda.ufunction =
+    (* All that we need in the environment, for translating one closure from
+       a closed set of closures, is the substitutions for variables bound to
+       the various closures in the set.  Such closures will always be
+       referenced via symbols. *)
+    let env =
+      List.fold_left (fun env (var, _) ->
+          let closure_id = Closure_id.wrap var in
+          let symbol = Compilenv.closure_symbol closure_id in
+          Env.add_subst env var (to_clambda_symbol env symbol))
+        (Env.keep_only_symbols env)
+        functions
+    in
+    let env_body, params =
+      List.fold_right (fun var (env, params) ->
+          let id, env = Env.add_fresh_ident env var in
+          env, id :: params)
+        function_decl.params (env, [])
+    in
+    { label = Compilenv.function_label (Closure_id.wrap id);
+      arity = Flambda_utils.function_arity function_decl;
+      params;
+      body = to_clambda t env_body function_decl.body;
+      dbg = function_decl.dbg;
+    }
+  in
+  let ufunct = List.map to_clambda_function functions in
+  let closure_lbl = Linkage_name.to_string (Symbol.label symbol) in
+  Uconst_closure (ufunct, closure_lbl, [])
+
+let to_clambda_initialize_symbol t env symbol fields : Clambda.ulambda =
+  let fields =
+    List.mapi (fun index expr -> index, to_clambda t env expr) fields
+  in
+  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),
+      [to_clambda_symbol env symbol; field],
+      Debuginfo.none)
+  in
+  match fields with
+  | [] -> Uconst (Uconst_ptr 0)
+  | h :: t ->
+    List.fold_left (fun acc (p, field) ->
+        Clambda.Usequence (build_setfield (p, field), acc))
+      (build_setfield h) t
+
+let accumulate_structured_constants t env symbol
+      (c : Flambda.constant_defining_value) acc =
+  match c with
+  | Allocated_const c ->
+    Symbol.Map.add symbol (to_clambda_allocated_constant c) acc
+  | Block (tag, fields) ->
+    let fields = List.map (to_clambda_const env) fields in
+    Symbol.Map.add symbol (Clambda.Uconst_block (Tag.to_int tag, fields)) acc
+  | Set_of_closures set_of_closures ->
+    let to_clambda_set_of_closures =
+      to_clambda_closed_set_of_closures t env symbol set_of_closures
+    in
+    Symbol.Map.add symbol to_clambda_set_of_closures acc
+  | Project_closure _ -> acc
+
+let to_clambda_program t env constants (program : Flambda.program) =
+  let rec loop env constants (program : Flambda.program_body)
+        : Clambda.ulambda * Clambda.ustructured_constant Symbol.Map.t =
+    match program with
+    | Let_symbol (symbol, alloc, program) ->
+      (* Useful only for unboxing. Since floats and boxed integers will
+         never be part of a Let_rec_symbol, handling only the Let_symbol
+         is sufficient. *)
+      let env =
+        match alloc with
+        | Allocated_const const -> Env.add_allocated_const env symbol const
+        | _ -> env
+      in
+      let constants =
+        accumulate_structured_constants t env symbol alloc constants
+      in
+      loop env constants program
+    | Let_rec_symbol (defs, program) ->
+      let constants =
+        List.fold_left (fun constants (symbol, alloc) ->
+            accumulate_structured_constants t env symbol alloc constants)
+          constants defs
+      in
+      loop env constants program
+    | Initialize_symbol (symbol, _tag, fields, program) ->
+      (* The tag is ignored here: It is used separately to generate the
+         preallocated block. Only the initialisation code is generated
+         here. *)
+      let e1 = to_clambda_initialize_symbol t env symbol fields in
+      let e2, constants = loop env constants program in
+      Usequence (e1, e2), constants
+    | Effect (expr, program) ->
+      let e1 = to_clambda t env expr in
+      let e2, constants = loop env constants program in
+      Usequence (e1, e2), constants
+    | End _ ->
+      Uconst (Uconst_ptr 0), constants
+  in
+  loop env constants program.program_body
+
+type result = {
+  expr : Clambda.ulambda;
+  preallocated_blocks : Clambda.preallocated_block list;
+  structured_constants : Clambda.ustructured_constant Symbol.Map.t;
+  exported : Export_info.t;
+}
+
+let convert (program, exported) : result =
+  let current_unit =
+    let offsets = Closure_offsets.compute program in
+    { fun_offset_table = offsets.function_offsets;
+      fv_offset_table = offsets.free_variable_offsets;
+      closures = Flambda_utils.make_closure_map program;
+      constant_sets_of_closures =
+        Flambda_utils.all_lifted_constant_sets_of_closures program;
+    }
+  in
+  let imported_units =
+    let imported = Compilenv.approx_env () in
+    { fun_offset_table = imported.offset_fun;
+      fv_offset_table = imported.offset_fv;
+      closures = imported.closures;
+      constant_sets_of_closures = imported.constant_sets_of_closures;
+    }
+  in
+  let t = { current_unit; imported_units; } in
+  let preallocated_blocks =
+    List.map (fun (symbol, tag, fields) ->
+        { Clambda.
+          symbol = Linkage_name.to_string (Symbol.label symbol);
+          exported = true;
+          tag = Tag.to_int tag;
+          size = List.length fields;
+        })
+      (Flambda_utils.initialize_symbols program)
+  in
+  let expr, structured_constants =
+    to_clambda_program t Env.empty Symbol.Map.empty program
+  in
+  let offset_fun, offset_fv =
+    Closure_offsets.compute_reexported_offsets program
+      ~current_unit_offset_fun:current_unit.fun_offset_table
+      ~current_unit_offset_fv:current_unit.fv_offset_table
+      ~imported_units_offset_fun:imported_units.fun_offset_table
+      ~imported_units_offset_fv:imported_units.fv_offset_table
+  in
+  let exported =
+    Export_info.add_clambda_info exported
+      ~offset_fun
+      ~offset_fv
+      ~constant_sets_of_closures:current_unit.constant_sets_of_closures
+  in
+  { expr; preallocated_blocks; structured_constants; exported; }
diff --git a/asmcomp/flambda_to_clambda.mli b/asmcomp/flambda_to_clambda.mli
new file mode 100644
index 00000000..39cbc40f
--- /dev/null
+++ b/asmcomp/flambda_to_clambda.mli
@@ -0,0 +1,38 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+type result = {
+  expr : Clambda.ulambda;
+  preallocated_blocks : Clambda.preallocated_block list;
+  structured_constants : Clambda.ustructured_constant Symbol.Map.t;
+  exported : Export_info.t;
+}
+
+(** Convert an Flambda program, with associated proto-export information,
+    to Clambda.
+    This yields a Clambda expression together with augmented export
+    information and details about required statically-allocated values
+    (preallocated blocks, for [Initialize_symbol], and structured
+    constants).
+
+    It is during this process that accesses to variables within
+    closures are transformed to field accesses within closure values.
+    For direct calls, the hidden closure parameter is added.  Switch
+    tables are also built.
+*)
+val convert : Flambda.program * Export_info.t -> result
diff --git a/asmcomp/i386/CSE.ml b/asmcomp/i386/CSE.ml
index 6bea76f1..85c7223f 100644
--- a/asmcomp/i386/CSE.ml
+++ b/asmcomp/i386/CSE.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* CSE for the i386 *)
 
diff --git a/asmcomp/i386/NOTES.md b/asmcomp/i386/NOTES.md
new file mode 100644
index 00000000..6f1e1839
--- /dev/null
+++ b/asmcomp/i386/NOTES.md
@@ -0,0 +1,22 @@
+# Supported platforms
+
+Intel and AMD x86 processors in 32-bit mode.
+The baseline is the 80486, also known as `i486`.
+(Debian's baseline is now the Pentium 1.)
+
+Floating-point architecture: x87.
+(SSE2 not available in Debian's baseline.)
+
+Operating systems: Linux, BSD, MacOS X, MS Windows.
+
+Debian architecture name: `i386`
+
+# Reference documents
+
+* Instruction set architecture:
+  any Intel or AMD manual of the last 20 years.
+* ELF application binary interface:
+  _System V Application Binary Interface,
+   Intel386 Architecture Processor Supplement_
+* MacOS X application binary interface:
+  _OS X ABI Function Call Guide: IA-32 Function Calling Conventions_
diff --git a/asmcomp/i386/arch.ml b/asmcomp/i386/arch.ml
index 1d486db3..b17188af 100644
--- a/asmcomp/i386/arch.ml
+++ b/asmcomp/i386/arch.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Machine-specific command-line options *)
 
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index 98df5f95..2a261fb6 100644
--- a/asmcomp/i386/emit.mlp
+++ b/asmcomp/i386/emit.mlp
@@ -1,20 +1,21 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+#2 "asmcomp/i386/emit.mlp"
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Emission of Intel 386 assembly code *)
 
-module StringSet =
-  Set.Make(struct type t = string let compare (x:t) y = compare x y end)
-
 open Misc
 open Cmm
 open Arch
@@ -24,6 +25,29 @@ open Mach
 open Linearize
 open Emitaux
 
+open X86_ast
+open X86_proc
+open X86_dsl
+
+let _label s = D.label ~typ:DWORD s
+
+let mem_sym typ ?(ofs = 0) sym =
+  mem32 typ ~scale:0 ?base:None ~sym ofs RAX (*ignored since scale=0*)
+
+(* CFI directives *)
+
+let cfi_startproc () =
+  if Config.asm_cfi_supported then D.cfi_startproc ()
+
+let cfi_endproc () =
+  if Config.asm_cfi_supported then D.cfi_endproc ()
+
+let cfi_adjust_cfa_offset n =
+  if Config.asm_cfi_supported then D.cfi_adjust_cfa_offset n
+
+let emit_debug_info dbg =
+  emit_debug_info_gen dbg D.file D.loc
+
 (* Tradeoff between code size and code speed *)
 
 let fastcode_flag = ref true
@@ -39,7 +63,7 @@ let frame_size () =                     (* includes return address *)
 
 let slot_offset loc cl =
   match loc with
-    Incoming n ->
+  | Incoming n ->
       assert (n >= 0);
       frame_size() + n
   | Local n ->
@@ -50,129 +74,122 @@ let slot_offset loc cl =
       assert (n >= 0);
       n
 
+(* Record symbols used and defined - at the end generate extern for those
+   used but not defined *)
+
+let symbols_defined = ref StringSet.empty
+let symbols_used = ref StringSet.empty
+
+let add_def_symbol s = symbols_defined := StringSet.add s !symbols_defined
+let add_used_symbol s = symbols_used := StringSet.add s !symbols_used
+
 let trap_frame_size = Misc.align 8 stack_alignment
 
 (* Prefixing of symbols with "_" *)
 
 let symbol_prefix =
-  match Config.system with
-    "linux_elf" -> ""
-  | "bsd_elf" -> ""
-  | "solaris" -> ""
-  | "beos" -> ""
-  | "gnu" -> ""
-  | _ -> "_"
+  match system with
+  | S_linux_elf -> ""
+  | S_bsd_elf -> ""
+  | S_solaris -> ""
+  | S_beos -> ""
+  | S_gnu -> ""
+  | _ -> "_" (* win32 & others *)
 
-let emit_symbol s =
-  emit_string symbol_prefix; Emitaux.emit_symbol '$' s
+let emit_symbol s = string_of_symbol symbol_prefix s
+
+let immsym s = sym (emit_symbol s)
+
+let emit_call s = I.call (immsym s)
 
 (* Output a label *)
 
 let label_prefix =
-  match Config.system with
-    "linux_elf" -> ".L"
-  | "bsd_elf" -> ".L"
-  | "solaris" -> ".L"
-  | "beos" -> ".L"
-  | "gnu" -> ".L"
+  match system with
+  | S_linux_elf -> ".L"
+  | S_bsd_elf -> ".L"
+  | S_solaris -> ".L"
+  | S_beos -> ".L"
+  | S_gnu -> ".L"
   | _ -> "L"
 
 let emit_label lbl =
-  emit_string label_prefix; emit_int lbl
+  Printf.sprintf "%s%d" label_prefix lbl
 
 let emit_data_label lbl =
-  emit_string label_prefix; emit_string "d"; emit_int lbl
-
-
-(* Some data directives have different names under Solaris *)
-
-let word_dir =
-  match Config.system with
-    "solaris" -> ".value"
-  | _ -> ".word"
-let skip_dir =
-  match Config.system with
-    "solaris" -> ".zero"
-  | _ -> ".space"
-let use_ascii_dir =
-  match Config.system with
-    "solaris" -> false
-  | _ -> true
-
-(* MacOSX has its own way to reference symbols potentially defined in
-   shared objects *)
-
-let macosx =
-  match Config.system with
-  | "macosx" -> true
-  | _ -> false
-
-(* Output a .align directive.
-   The numerical argument to .align is log2 of alignment size, except
-   under ELF, where it is the alignment size... *)
-
-let emit_align =
-  match Config.system with
-    "linux_elf" | "bsd_elf" | "solaris" | "beos" | "cygwin" | "mingw" | "gnu" ->
-      (fun n -> `	.align	{emit_int n}\n`)
-  | _ ->
-      (fun n -> `	.align	{emit_int(Misc.log2 n)}\n`)
+  Printf.sprintf "%sd%d" label_prefix lbl
+
+let label s = sym (emit_label s)
+
+let def_label s = D.label (emit_label s)
 
 let emit_Llabel fallthrough lbl =
-  if not fallthrough && !fastcode_flag then
-    emit_align 16 ;
-  emit_label lbl
+  if not fallthrough && !fastcode_flag then D.align 16 ;
+  def_label lbl
 
 (* Output a pseudo-register *)
 
-let emit_reg = function
-    { loc = Reg r } ->
-      emit_string (register_name r)
+let int_reg_name =  [| RAX; RBX; RCX; RDX; RSI; RDI; RBP  |]
+
+let float_reg_name = [| TOS |]
+
+let register_name r =
+  if r < 100 then Reg32 (int_reg_name.(r))
+  else Regf (float_reg_name.(r - 100))
+
+let sym32 ?ofs s = mem_sym ?ofs DWORD (emit_symbol s)
+
+let reg = function
+  | { loc = Reg r } -> register_name r
   | { loc = Stack(Incoming n | Outgoing n) } when n < 0 ->
-      `{emit_symbol "caml_extra_params"} + {emit_int (n + 64)}`
+      sym32 "caml_extra_params" ~ofs:(n + 64)
+  | { loc = Stack s; typ = Float } as r ->
+      let ofs = slot_offset s (register_class r) in
+      mem32 REAL8 ofs RSP
   | { loc = Stack s } as r ->
       let ofs = slot_offset s (register_class r) in
-      `{emit_int ofs}(%esp)`
+      mem32 DWORD ofs RSP
   | { loc = Unknown } ->
-      fatal_error "Emit_i386.emit_reg"
+      fatal_error "Emit_i386.reg"
 
 (* Output a reference to the lower 8 bits or lower 16 bits of a register *)
 
-let reg_low_byte_name = [| "%al"; "%bl"; "%cl"; "%dl" |]
-let reg_low_half_name = [| "%ax"; "%bx"; "%cx"; "%dx"; "%si"; "%di"; "%bp" |]
+let reg_low_8_name  = Array.map (fun r -> Reg8L r) int_reg_name
+let reg_low_16_name = Array.map (fun r -> Reg16 r) int_reg_name
 
-let emit_reg8 r =
+let reg8 r =
   match r.loc with
-    Reg r when r < 4 -> emit_string (reg_low_byte_name.(r))
-  | _ -> fatal_error "Emit_i386.emit_reg8"
+  | Reg r when r < 4 -> reg_low_8_name.(r)
+  | _ -> fatal_error "Emit_i386.reg8"
 
-let emit_reg16 r =
+let reg16 r =
   match r.loc with
-    Reg r when r < 7 -> emit_string (reg_low_half_name.(r))
-  | _ -> fatal_error "Emit_i386.emit_reg16"
+  | Reg r when r < 7 -> reg_low_16_name.(r)
+  | _ -> fatal_error "Emit_i386.reg16"
+
+let reg32 = function
+  | { loc = Reg.Reg r } -> int_reg_name.(r)
+  | _ -> assert false
+
+let arg32 i n = reg32 i.arg.(n)
 
 (* Output an addressing mode *)
 
-let emit_addressing addr r n =
+let addressing addr typ i n =
   match addr with
-    Ibased(s, d) ->
-      `{emit_symbol s}`;
-      if d <> 0 then ` + {emit_int d}`
+  | Ibased(s, ofs) ->
+      add_used_symbol s;
+      mem_sym typ (emit_symbol s) ~ofs
   | Iindexed d ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)})`
+      mem32 typ d (arg32 i n)
   | Iindexed2 d ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)}, {emit_reg r.(n+1)})`
+      mem32 typ ~base:(arg32 i n) d (arg32 i (n+1))
   | Iscaled(2, d) ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)}, {emit_reg r.(n)})`
+      mem32 typ ~base:(arg32 i n) d (arg32 i n)
   | Iscaled(scale, d) ->
-      if d <> 0 then emit_int d;
-      `(, {emit_reg r.(n)}, {emit_int scale})`
+      mem32 typ ~scale d (arg32 i n)
   | Iindexed2scaled(scale, d) ->
-      if d <> 0 then emit_int d;
-      `({emit_reg r.(n)}, {emit_reg r.(n+1)}, {emit_int scale})`
+      mem32 typ ~scale ~base:(arg32 i n) d (arg32 i (n+1))
 
 (* Record live pointers at call points *)
 
@@ -181,10 +198,12 @@ let record_frame_label live dbg =
   let live_offset = ref [] in
   Reg.Set.iter
     (function
-        {typ = Addr; loc = Reg r} ->
+      | {typ = Val; loc = Reg r} ->
           live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
+      | {typ = Val; loc = Stack s} as reg ->
           live_offset := slot_offset s (register_class reg) :: !live_offset
+      | {typ = Addr} as r ->
+          Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
   frame_descriptors :=
@@ -195,7 +214,8 @@ let record_frame_label live dbg =
   lbl
 
 let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:\n`
+  let lbl = record_frame_label live dbg in
+  def_label lbl
 
 (* Record calls to the GC -- we've moved them out of the way *)
 
@@ -207,8 +227,10 @@ type gc_call =
 let call_gc_sites = ref ([] : gc_call list)
 
 let emit_call_gc gc =
-  `{emit_label gc.gc_lbl}:	call	{emit_symbol "caml_call_gc"}\n`;
-  `{emit_label gc.gc_frame}:	jmp	{emit_label gc.gc_return_lbl}\n`
+  def_label gc.gc_lbl;
+  emit_call "caml_call_gc";
+  def_label gc.gc_frame;
+  I.jmp (label gc.gc_return_lbl)
 
 (* Record calls to caml_ml_array_bound_error.
    In -g mode, we maintain one call to caml_ml_array_bound_error
@@ -226,100 +248,107 @@ let bound_error_label dbg =
     let lbl_bound_error = new_label() in
     let lbl_frame = record_frame_label Reg.Set.empty dbg in
     bound_error_sites :=
-     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
-   lbl_bound_error
- end else begin
-   if !bound_error_call = 0 then bound_error_call := new_label();
-   !bound_error_call
- end
+      { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
+    lbl_bound_error
+  end else begin
+    if !bound_error_call = 0 then bound_error_call := new_label();
+    !bound_error_call
+  end
 
 let emit_call_bound_error bd =
-  `{emit_label bd.bd_lbl}:	call	{emit_symbol "caml_ml_array_bound_error"}\n`;
-  `{emit_label bd.bd_frame}:\n`
+  def_label bd.bd_lbl;
+  emit_call "caml_ml_array_bound_error";
+  def_label bd.bd_frame
 
 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}:	call	{emit_symbol "caml_ml_array_bound_error"}\n`
+  if !bound_error_call > 0 then begin
+    def_label !bound_error_call;
+    emit_call "caml_ml_array_bound_error"
+  end
 
 (* Names for instructions *)
 
 let instr_for_intop = function
-    Iadd -> "addl"
-  | Isub -> "subl"
-  | Imul -> "imull"
-  | Iand -> "andl"
-  | Ior -> "orl"
-  | Ixor -> "xorl"
-  | Ilsl -> "sall"
-  | Ilsr -> "shrl"
-  | Iasr -> "sarl"
+  | Iadd -> I.add
+  | Isub -> I.sub
+  | Imul -> (fun arg1 arg2 ->  I.imul arg1 (Some arg2))
+  | Iand -> I.and_
+  | Ior -> I.or_
+  | Ixor -> I.xor
+  | Ilsl -> I.sal
+  | Ilsr -> I.shr
+  | Iasr -> I.sar
   | _ -> fatal_error "Emit_i386: instr_for_intop"
 
+let unary_instr_for_floatop = function
+  | Inegf -> I.fchs ()
+  | Iabsf -> I.fabs ()
+  | _ -> fatal_error "Emit_i386: unary_instr_for_floatop"
+
 let instr_for_floatop = function
-    Inegf -> "fchs"
-  | Iabsf -> "fabs"
-  | Iaddf -> "faddl"
-  | Isubf -> "fsubl"
-  | Imulf -> "fmull"
-  | Idivf -> "fdivl"
-  | Ispecific Isubfrev -> "fsubrl"
-  | Ispecific Idivfrev -> "fdivrl"
+  | Iaddf -> I.fadd
+  | Isubf -> I.fsub
+  | Imulf -> I.fmul
+  | Idivf -> I.fdiv
+  | Ispecific Isubfrev -> I.fsubr
+  | Ispecific Idivfrev -> I.fdivr
   | _ -> fatal_error "Emit_i386: instr_for_floatop"
 
 let instr_for_floatop_reversed = function
-    Iaddf -> "faddl"
-  | Isubf -> "fsubrl"
-  | Imulf -> "fmull"
-  | Idivf -> "fdivrl"
-  | Ispecific Isubfrev -> "fsubl"
-  | Ispecific Idivfrev -> "fdivl"
+  | Iaddf -> I.fadd
+  | Isubf -> I.fsubr
+  | Imulf -> I.fmul
+  | Idivf -> I.fdivr
+  | Ispecific Isubfrev -> I.fsub
+  | Ispecific Idivfrev -> I.fdiv
   | _ -> fatal_error "Emit_i386: instr_for_floatop_reversed"
 
-let instr_for_floatop_pop = function
-    Iaddf -> "faddp"
-  | Isubf -> "fsubp"
-  | Imulf -> "fmulp"
-  | Idivf -> "fdivp"
-  | Ispecific Isubfrev -> "fsubrp"
-  | Ispecific Idivfrev -> "fdivrp"
-  | _ -> fatal_error "Emit_i386: instr_for_floatop_pop"
-
-let instr_for_floatarithmem double = function
-    Ifloatadd -> if double then "faddl" else "fadds"
-  | Ifloatsub -> if double then "fsubl" else "fsubs"
-  | Ifloatsubrev -> if double then "fsubrl" else "fsubrs"
-  | Ifloatmul -> if double then "fmull" else "fmuls"
-  | Ifloatdiv -> if double then "fdivl" else "fdivs"
-  | Ifloatdivrev -> if double then "fdivrl" else "fdivrs"
-
-let name_for_cond_branch = function
-    Isigned Ceq -> "e"     | Isigned Cne -> "ne"
-  | Isigned Cle -> "le"     | Isigned Cgt -> "g"
-  | Isigned Clt -> "l"     | Isigned Cge -> "ge"
-  | Iunsigned Ceq -> "e"   | Iunsigned Cne -> "ne"
-  | Iunsigned Cle -> "be"  | Iunsigned Cgt -> "a"
-  | Iunsigned Clt -> "b"  | Iunsigned Cge -> "ae"
+
+let instr_for_floatop_reversed_pop = function
+  | Iaddf -> I.faddp
+  | Isubf -> I.fsubrp
+  | Imulf -> I.fmulp
+  | Idivf -> I.fdivrp
+  | Ispecific Isubfrev -> I.fsubp
+  | Ispecific Idivfrev -> I.fdivp
+  | _ -> fatal_error "Emit_i386: instr_for_floatop_reversed_pop"
+
+let instr_for_floatarithmem = function
+  | Ifloatadd -> I.fadd
+  | Ifloatsub -> I.fsub
+  | Ifloatsubrev -> I.fsubr
+  | Ifloatmul -> I.fmul
+  | Ifloatdiv -> I.fdiv
+  | Ifloatdivrev -> I.fdivr
+
+let cond = function
+  | Isigned Ceq   -> E   | Isigned Cne   -> NE
+  | Isigned Cle   -> LE  | Isigned Cgt   -> G
+  | Isigned Clt   -> L   | Isigned Cge   -> GE
+  | Iunsigned Ceq -> E   | Iunsigned Cne -> NE
+  | Iunsigned Cle -> BE  | Iunsigned Cgt -> A
+  | Iunsigned Clt -> B   | Iunsigned Cge -> AE
 
 (* Output an = 0 or <> 0 test. *)
 
 let output_test_zero arg =
   match arg.loc with
-    Reg r -> `	testl	{emit_reg arg}, {emit_reg arg}\n`
-  | _     -> `	cmpl	$0, {emit_reg arg}\n`
+  | Reg.Reg _ -> I.test (reg arg) (reg arg)
+  | _  -> I.cmp (int 0) (reg arg)
 
 (* Deallocate the stack frame before a return or tail call *)
 
 let output_epilogue f =
   let n = frame_size() - 4 in
   if n > 0 then
-  begin
-    `	addl	${emit_int n}, %esp\n`;
-    cfi_adjust_cfa_offset (-n);
-    f ();
-    (* reset CFA back cause function body may continue *)
-    cfi_adjust_cfa_offset n
-  end
+    begin
+      I.add (int n) esp;
+      cfi_adjust_cfa_offset (-n);
+      f ();
+      (* reset CFA back cause function body may continue *)
+      cfi_adjust_cfa_offset n
+    end
   else
     f ()
 
@@ -332,82 +361,80 @@ let is_tos = function { loc = Reg _; typ = Float } -> true | _ -> false
 let emit_float_test cmp neg arg lbl =
   let actual_cmp =
     match (is_tos arg.(0), is_tos arg.(1)) with
-      (true, true) ->
-      (* both args on top of FP stack *)
-      `	fcompp\n`;
-      cmp
+    | (true, true) ->
+        (* both args on top of FP stack *)
+        I.fcompp ();
+        cmp
     | (true, false) ->
-      (* first arg on top of FP stack *)
-      `	fcompl	{emit_reg arg.(1)}\n`;
-      cmp
+        (* first arg on top of FP stack *)
+        I.fcomp (reg arg.(1));
+        cmp
     | (false, true) ->
-      (* second arg on top of FP stack *)
-      `	fcompl	{emit_reg arg.(0)}\n`;
-      Cmm.swap_comparison cmp
+        (* second arg on top of FP stack *)
+        I.fcomp (reg arg.(0));
+        Cmm.swap_comparison cmp
     | (false, false) ->
-      `	fldl	{emit_reg arg.(0)}\n`;
-      `	fcompl	{emit_reg arg.(1)}\n`;
-      cmp
-    in
-  `	fnstsw	%ax\n`;
-  begin match actual_cmp with
-    Ceq ->
+        I.fld     (reg arg.(0));
+        I.fcomp   (reg arg.(1));
+        cmp
+  in
+  I.fnstsw ax;
+  match actual_cmp with
+  | Ceq ->
       if neg then begin
-      `	andb	$68, %ah\n`;
-      `	xorb	$64, %ah\n`;
-      `	jne	`
+        I.and_ (int 68) ah;
+        I.xor (int 64) ah;
+        I.jne lbl
       end else begin
-      `	andb	$69, %ah\n`;
-      `	cmpb	$64, %ah\n`;
-      `	je	`
+        I.and_ (int 69) ah;
+        I.cmp (int 64) ah;
+        I.je lbl
       end
   | Cne ->
       if neg then begin
-      `	andb	$69, %ah\n`;
-      `	cmpb	$64, %ah\n`;
-      `	je	`
+        I.and_ (int 69) ah;
+        I.cmp (int 64) ah;
+        I.je lbl
       end else begin
-      `	andb	$68, %ah\n`;
-      `	xorb	$64, %ah\n`;
-      `	jne	`
+        I.and_ (int 68) ah;
+        I.xor (int 64) ah;
+        I.jne lbl
       end
   | Cle ->
-      `	andb	$69, %ah\n`;
-      `	decb	%ah\n`;
-      `	cmpb	$64, %ah\n`;
+      I.and_ (int 69) ah;
+      I.dec ah;
+      I.cmp (int 64) ah;
       if neg
-      then `	jae	`
-      else `	jb	`
+      then I.jae lbl
+      else I.jb lbl
   | Cge ->
-      `	andb	$5, %ah\n`;
+      I.and_ (int 5) ah;
       if neg
-      then `	jne	`
-      else `	je	`
+      then I.jne lbl
+      else I.je lbl
   | Clt ->
-      `	andb	$69, %ah\n`;
-      `	cmpb	$1, %ah\n`;
+      I.and_ (int 69) ah;
+      I.cmp (int 1) ah;
       if neg
-      then `	jne	`
-      else `	je	`
+      then I.jne lbl
+      else I.je lbl
   | Cgt ->
-      `	andb	$69, %ah\n`;
+      I.and_ (int 69) ah;
       if neg
-      then `	jne	`
-      else `	je	`
-  end;
-  `{emit_label lbl}\n`
+      then I.jne lbl
+      else I.je lbl
 
 (* Emit a Ifloatspecial instruction *)
 
 let emit_floatspecial = function
-    "atan"  -> `	fld1; fpatan\n`
-  | "atan2" -> `	fpatan\n`
-  | "cos"   -> `	fcos\n`
-  | "log"   -> `	fldln2; fxch; fyl2x\n`
-  | "log10" -> `	fldlg2; fxch; fyl2x\n`
-  | "sin"   -> `	fsin\n`
-  | "sqrt"  -> `	fsqrt\n`
-  | "tan"   -> `	fptan; fstp %st(0)\n`
+  | "atan"  -> I.fld1 (); I.fpatan ()
+  | "atan2" -> I.fpatan ()
+  | "cos"   -> I.fcos ()
+  | "log"   -> I.fldln2 (); I.fxch st1; I.fyl2x ()
+  | "log10" -> I.fldlg2 (); I.fxch st1; I.fyl2x ()
+  | "sin"   -> I.fsin ()
+  | "sqrt"  -> I.fsqrt ()
+  | "tan"   -> I.fptan (); I.fstp st0
   | _ -> assert false
 
 (* Floating-point constants *)
@@ -415,18 +442,30 @@ let emit_floatspecial = function
 let float_constants = ref ([] : (int64 * int) list)
 
 let add_float_constant cst =
-  let repr = Int64.bits_of_float cst in
   try
-    List.assoc repr !float_constants
+    List.assoc cst !float_constants
   with
     Not_found ->
       let lbl = new_label() in
-      float_constants := (repr, lbl) :: !float_constants;
+      float_constants := (cst, lbl) :: !float_constants;
       lbl
 
-let emit_float_constant (cst, lbl) =
-  `{emit_label lbl}:`;
-  emit_float64_split_directive ".long" cst
+let emit_float64_split_directive x =
+  let lo = Int64.logand x 0xFFFF_FFFFL
+  and hi = Int64.shift_right_logical x 32 in
+  D.long (Const (if Arch.big_endian then hi else lo));
+  D.long (Const (if Arch.big_endian then lo else hi))
+
+let emit_float_constant cst lbl =
+  _label (emit_label lbl);
+  emit_float64_split_directive cst
+
+let emit_global_label s =
+  let lbl = Compilenv.make_symbol (Some s) in
+  add_def_symbol lbl;
+  let lbl = emit_symbol lbl in
+  D.global lbl;
+  _label lbl
 
 (* Output the assembly code for an instruction *)
 
@@ -434,406 +473,417 @@ let emit_float_constant (cst, lbl) =
 let function_name = ref ""
 (* Entry point for tail recursive calls *)
 let tailrec_entry_point = ref 0
-(* Label of trap for out-of-range accesses *)
-let range_check_trap = ref 0
 (* Record references to external C functions (for MacOSX) *)
 let external_symbols_direct = ref StringSet.empty
 let external_symbols_indirect = ref StringSet.empty
 
 let emit_instr fallthrough i =
-    emit_debug_info i.dbg;
-    match i.desc with
-      Lend -> ()
-    | Lop(Imove | Ispill | Ireload) ->
-        let src = i.arg.(0) and dst = i.res.(0) in
-        if src.loc <> dst.loc then begin
-          if src.typ = Float then
-            if is_tos src then
-              `	fstpl	{emit_reg dst}\n`
-            else if is_tos dst then
-              `	fldl	{emit_reg src}\n`
-            else begin
-              `	fldl	{emit_reg src}\n`;
-              `	fstpl	{emit_reg dst}\n`
-            end
-          else
-              `	movl	{emit_reg src}, {emit_reg dst}\n`
-        end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
-        if n = 0n then begin
-          match i.res.(0).loc with
-            Reg n -> `	xorl	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
-          | _     -> `	movl	$0, {emit_reg i.res.(0)}\n`
-        end else
-          `	movl	${emit_nativeint n}, {emit_reg i.res.(0)}\n`
-    | Lop(Iconst_float f) ->
-        begin match Int64.bits_of_float f with
-        | 0x0000_0000_0000_0000L ->       (* +0.0 *)
-          `	fldz\n`
-        | 0x8000_0000_0000_0000L ->       (* -0.0 *)
-          `	fldz\n	fchs\n`
-        | 0x3FF0_0000_0000_0000L ->       (*  1.0 *)
-          `	fld1\n`
-        | 0xBFF0_0000_0000_0000L ->       (* -1.0 *)
-          `	fld1\n	fchs\n`
-        | _ ->
+  emit_debug_info i.dbg;
+  match i.desc with
+  | Lend -> ()
+  | Lop(Imove | Ispill | Ireload) ->
+      let src = i.arg.(0) and dst = i.res.(0) in
+      if src.loc <> dst.loc then begin
+        if src.typ = Float then
+          if is_tos src then
+            I.fstp (reg dst)
+          else if is_tos dst then
+            I.fld (reg src)
+          else begin
+            I.fld (reg src);
+            I.fstp (reg dst)
+          end
+        else
+          I.mov (reg src) (reg dst)
+      end
+  | Lop(Iconst_int n | Iconst_blockheader n) ->
+      if n = 0n then begin
+        match i.res.(0).loc with
+        | Reg _ -> I.xor (reg i.res.(0)) (reg i.res.(0))
+        | _     -> I.mov (int 0) (reg i.res.(0))
+      end else
+        I.mov (nat n) (reg i.res.(0))
+  | Lop(Iconst_float f) ->
+      begin match f with
+      | 0x0000_0000_0000_0000L ->       (* +0.0 *)
+          I.fldz ()
+      | 0x8000_0000_0000_0000L ->       (* -0.0 *)
+          I.fldz (); I.fchs ()
+      | 0x3FF0_0000_0000_0000L ->       (*  1.0 *)
+          I.fld1 ()
+      | 0xBFF0_0000_0000_0000L ->       (* -1.0 *)
+          I.fld1 (); I.fchs ()
+      | _ ->
           let lbl = add_float_constant f in
-          `	fldl	{emit_label lbl}\n`
-        end
-    | Lop(Iconst_symbol s) ->
-        `	movl	${emit_symbol s}, {emit_reg i.res.(0)}\n`
-    | Lop(Icall_ind) ->
-        `	call	*{emit_reg i.arg.(0)}\n`;
-        record_frame i.live i.dbg
-    | Lop(Icall_imm s) ->
-        `	call	{emit_symbol s}\n`;
-        record_frame i.live i.dbg
-    | Lop(Itailcall_ind) ->
+          I.fld (mem_sym REAL8 (emit_label lbl))
+      end
+  | Lop(Iconst_symbol s) ->
+      add_used_symbol s;
+      I.mov (immsym s) (reg i.res.(0))
+  | Lop(Icall_ind) ->
+      I.call (reg i.arg.(0));
+      record_frame i.live i.dbg
+  | Lop(Icall_imm s) ->
+      add_used_symbol s;
+      emit_call s;
+      record_frame i.live i.dbg
+  | Lop(Itailcall_ind) ->
+      output_epilogue begin fun () ->
+        I.jmp (reg i.arg.(0))
+      end
+  | Lop(Itailcall_imm s) ->
+      if s = !function_name then
+        I.jmp (label !tailrec_entry_point)
+      else begin
         output_epilogue begin fun () ->
-        `	jmp	*{emit_reg i.arg.(0)}\n`
+          add_used_symbol s;
+          I.jmp (immsym s)
         end
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then
-          `	jmp	{emit_label !tailrec_entry_point}\n`
+      end
+  | Lop(Iextcall(s, alloc)) ->
+      add_used_symbol s;
+      if alloc then begin
+        if system <> S_macosx then
+          I.mov (immsym s) eax
         else begin
-          output_epilogue begin fun () ->
-          `	jmp	{emit_symbol s}\n`
-          end
+          external_symbols_indirect :=
+            StringSet.add s !external_symbols_indirect;
+          I.mov (mem_sym DWORD (Printf.sprintf "L%s$non_lazy_ptr"
+                              (emit_symbol s))) eax
+        end;
+        emit_call "caml_c_call";
+        record_frame i.live i.dbg
+      end else begin
+        if system <> S_macosx then
+          emit_call s
+        else begin
+          external_symbols_direct :=
+            StringSet.add s !external_symbols_direct;
+          I.call (sym (Printf.sprintf "L%s$stub" (emit_symbol s)))
         end
-    | Lop(Iextcall(s, alloc)) ->
-        if alloc then begin
-          if not macosx then
-            `	movl	${emit_symbol s}, %eax\n`
+      end
+  | Lop(Istackoffset n) ->
+      if n < 0
+      then I.add (int (-n)) esp
+      else I.sub (int n) esp;
+      cfi_adjust_cfa_offset n;
+      stack_offset := !stack_offset + n
+  | Lop(Iload(chunk, addr)) ->
+      let dest = i.res.(0) in
+      begin match chunk with
+      | Word_int | Word_val | Thirtytwo_signed | Thirtytwo_unsigned ->
+          I.mov (addressing addr DWORD i 0) (reg dest)
+      | Byte_unsigned ->
+          I.movzx (addressing addr BYTE i 0) (reg dest)
+      | Byte_signed ->
+          I.movsx (addressing addr BYTE i 0) (reg dest)
+      | Sixteen_unsigned ->
+          I.movzx (addressing addr WORD i 0) (reg dest)
+      | Sixteen_signed ->
+          I.movsx (addressing addr WORD i 0) (reg dest)
+      | Single ->
+          I.fld (addressing addr REAL4 i 0)
+      | Double | Double_u ->
+          I.fld (addressing addr REAL8 i 0)
+      end
+  | Lop(Istore(chunk, addr, _)) ->
+      begin match chunk with
+      | Word_int | Word_val | Thirtytwo_signed | Thirtytwo_unsigned ->
+          I.mov (reg i.arg.(0)) (addressing addr DWORD i 1)
+      | Byte_unsigned | Byte_signed ->
+          I.mov (reg8 i.arg.(0)) (addressing addr BYTE i 1)
+      | Sixteen_unsigned | Sixteen_signed ->
+          I.mov (reg16 i.arg.(0)) (addressing addr WORD i 1)
+      | Single ->
+          if is_tos i.arg.(0) then
+            I.fstp (addressing addr REAL4 i 1)
           else begin
-            external_symbols_indirect :=
-              StringSet.add s !external_symbols_indirect;
-            `	movl	L{emit_symbol s}$non_lazy_ptr, %eax\n`
-          end;
-          `	call	{emit_symbol "caml_c_call"}\n`;
-          record_frame i.live i.dbg
-        end else begin
-          if not macosx then
-            `	call	{emit_symbol s}\n`
+            I.fld (reg i.arg.(0));
+            I.fstp (addressing addr REAL4 i 1)
+          end
+      | Double | Double_u ->
+          if is_tos i.arg.(0) then
+            I.fstp (addressing addr REAL8 i 1)
           else begin
-            external_symbols_direct :=
-              StringSet.add s !external_symbols_direct;
-            `	call	L{emit_symbol s}$stub\n`
+            I.fld (reg i.arg.(0));
+            I.fstp (addressing addr REAL8 i 1)
           end
-        end
-    | Lop(Istackoffset n) ->
-        if n < 0
-        then `	addl	${emit_int(-n)}, %esp\n`
-        else `	subl	${emit_int(n)}, %esp\n`;
-        cfi_adjust_cfa_offset n;
-        stack_offset := !stack_offset + n
-    | Lop(Iload(chunk, addr)) ->
-        let dest = i.res.(0) in
-        begin match chunk with
-          | Word | Thirtytwo_signed | Thirtytwo_unsigned ->
-              `	movl	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Byte_unsigned ->
-              `	movzbl	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Byte_signed ->
-              `	movsbl	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Sixteen_unsigned ->
-              `	movzwl	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Sixteen_signed ->
-              `	movswl	{emit_addressing addr i.arg 0}, {emit_reg dest}\n`
-          | Single ->
-            `	flds	{emit_addressing addr i.arg 0}\n`
-          | Double | Double_u ->
-            `	fldl	{emit_addressing addr i.arg 0}\n`
-        end
-    | Lop(Istore(chunk, addr, _)) ->
-        begin match chunk with
-          | Word | Thirtytwo_signed | Thirtytwo_unsigned ->
-            `	movl	{emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Byte_unsigned | Byte_signed ->
-            `	movb	{emit_reg8 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Sixteen_unsigned | Sixteen_signed ->
-            `	movw	{emit_reg16 i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
-          | Single ->
-              if is_tos i.arg.(0) then
-                `	fstps	{emit_addressing addr i.arg 1}\n`
-              else begin
-                `	fldl	{emit_reg i.arg.(0)}\n`;
-                `	fstps	{emit_addressing addr i.arg 1}\n`
-              end
-          | Double | Double_u ->
-              if is_tos i.arg.(0) then
-                `	fstpl	{emit_addressing addr i.arg 1}\n`
-              else begin
-                `	fldl	{emit_reg i.arg.(0)}\n`;
-                `	fstpl	{emit_addressing addr i.arg 1}\n`
-              end
-        end
-    | Lop(Ialloc n) ->
-        if !fastcode_flag then begin
-          let lbl_redo = new_label() in
-          `{emit_label lbl_redo}:	movl	{emit_symbol "caml_young_ptr"}, %eax\n`;
-          `	subl	${emit_int n}, %eax\n`;
-          `	movl	%eax, {emit_symbol "caml_young_ptr"}\n`;
-          `	cmpl	{emit_symbol "caml_young_limit"}, %eax\n`;
-          let lbl_call_gc = new_label() in
-          let lbl_frame = record_frame_label i.live Debuginfo.none in
-          `	jb	{emit_label lbl_call_gc}\n`;
-          `	leal	4(%eax), {emit_reg i.res.(0)}\n`;
-          call_gc_sites :=
-            { gc_lbl = lbl_call_gc;
-              gc_return_lbl = lbl_redo;
-              gc_frame = lbl_frame } :: !call_gc_sites
-        end else begin
-          begin match n with
-            8  -> `	call	{emit_symbol "caml_alloc1"}\n`
-          | 12 -> `	call	{emit_symbol "caml_alloc2"}\n`
-          | 16 -> `	call	{emit_symbol "caml_alloc3"}\n`
-          | _  -> `	movl	${emit_int n}, %eax\n`;
-                  `	call	{emit_symbol "caml_allocN"}\n`
-          end;
-          `{record_frame i.live Debuginfo.none}	leal	4(%eax), {emit_reg i.res.(0)}\n`
-        end
-    | Lop(Iintop(Icomp cmp)) ->
-        `	cmpl	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}	%al\n`;
-        `	movzbl	%al, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Icomp cmp, n)) ->
-        `	cmpl	${emit_int n}, {emit_reg i.arg.(0)}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}	%al\n`;
-        `	movzbl	%al, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop Icheckbound) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmpl	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop_imm(Icheckbound, n)) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmpl	${emit_int n}, {emit_reg i.arg.(0)}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop(Idiv | Imod)) ->
-        `	cltd\n`;
-        `	idivl	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop(Ilsl | Ilsr | Iasr as op)) ->
-        (* We have i.arg.(0) = i.res.(0) and i.arg.(1) = %ecx *)
-        `	{emit_string(instr_for_intop op)}	%cl, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop Imulh) ->
-        `	imull	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop op) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.arg.(1)}, {emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, n)) when i.arg.(0).loc <> i.res.(0).loc ->
-        `	leal	{emit_int n}({emit_reg i.arg.(0)}), {emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
-        `	incl	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
-        `	decl	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(op, n)) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	${emit_int n}, {emit_reg i.res.(0)}\n`
-    | Lop(Inegf | Iabsf as floatop) ->
-        if not (is_tos i.arg.(0)) then
-          `	fldl	{emit_reg i.arg.(0)}\n`;
-        `	{emit_string(instr_for_floatop floatop)}\n`
-    | Lop(Iaddf | Isubf | Imulf | Idivf | Ispecific(Isubfrev | Idivfrev)
-          as floatop) ->
-        begin match (is_tos i.arg.(0), is_tos i.arg.(1)) with
-          (true, true) ->
+      end
+  | Lop(Ialloc n) ->
+      if !fastcode_flag then begin
+        let lbl_redo = new_label() in
+        def_label lbl_redo;
+        I.mov (sym32 "caml_young_ptr") eax;
+        I.sub (int n) eax;
+        I.mov eax (sym32 "caml_young_ptr");
+        I.cmp (sym32 "caml_young_limit") eax;
+        let lbl_call_gc = new_label() in
+        let lbl_frame = record_frame_label i.live Debuginfo.none in
+        I.jb (label lbl_call_gc);
+        I.lea (mem32 NONE 4 RAX) (reg i.res.(0));
+        call_gc_sites :=
+          { gc_lbl = lbl_call_gc;
+            gc_return_lbl = lbl_redo;
+            gc_frame = lbl_frame } :: !call_gc_sites
+      end else begin
+        begin match n with
+          8  -> emit_call "caml_alloc1"
+        | 12 -> emit_call "caml_alloc2"
+        | 16 -> emit_call "caml_alloc3"
+        | _  ->
+            I.mov (int n) eax;
+            emit_call "caml_allocN"
+        end;
+        record_frame i.live Debuginfo.none;
+        I.lea (mem32 NONE 4 RAX) (reg i.res.(0))
+      end
+  | Lop(Iintop(Icomp cmp)) ->
+      I.cmp (reg i.arg.(1)) (reg i.arg.(0));
+      I.set (cond cmp) al;
+      I.movzx al (reg i.res.(0));
+  | Lop(Iintop_imm(Icomp cmp, n)) ->
+      I.cmp (int n) (reg i.arg.(0));
+      I.set (cond cmp) al;
+      I.movzx al (reg i.res.(0))
+  | Lop(Iintop Icheckbound) ->
+      let lbl = bound_error_label i.dbg in
+      I.cmp (reg i.arg.(1)) (reg i.arg.(0));
+      I.jbe (label lbl)
+  | Lop(Iintop_imm(Icheckbound, n)) ->
+      let lbl = bound_error_label i.dbg in
+      I.cmp (int n) (reg i.arg.(0));
+      I.jbe (label lbl)
+  | Lop(Iintop(Idiv | Imod)) ->
+      I.cdq ();
+      I.idiv (reg i.arg.(1))
+  | Lop(Iintop(Ilsl | Ilsr | Iasr as op)) ->
+      (* We have i.arg.(0) = i.res.(0) and i.arg.(1) = %ecx *)
+      instr_for_intop op cl (reg i.res.(0))
+  | Lop(Iintop Imulh) ->
+      I.imul (reg i.arg.(1)) None
+  | Lop(Iintop op) ->
+      (* We have i.arg.(0) = i.res.(0) *)
+      instr_for_intop op (reg i.arg.(1)) (reg i.res.(0))
+  | Lop(Iintop_imm(Iadd, n)) when i.arg.(0).loc <> i.res.(0).loc ->
+      I.lea (mem32 NONE n (reg32 i.arg.(0))) (reg i.res.(0))
+  | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
+      I.inc (reg i.res.(0))
+  | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
+      I.dec (reg i.res.(0))
+  | Lop(Iintop_imm(op, n)) ->
+      (* We have i.arg.(0) = i.res.(0) *)
+      instr_for_intop op (int n) (reg i.res.(0))
+  | Lop(Inegf | Iabsf as floatop) ->
+      if not (is_tos i.arg.(0)) then
+        I.fld (reg i.arg.(0));
+      unary_instr_for_floatop floatop
+  | Lop(Iaddf | Isubf | Imulf | Idivf | Ispecific(Isubfrev | Idivfrev)
+        as floatop) ->
+      begin match (is_tos i.arg.(0), is_tos i.arg.(1)) with
+        (true, true) ->
           (* both operands on top of FP stack *)
-          `	{emit_string(instr_for_floatop_pop floatop)}	%st, %st(1)\n`
-        | (true, false) ->
+          instr_for_floatop_reversed_pop floatop st0 st1
+      | (true, false) ->
           (* first operand on stack *)
-          `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.arg.(1)}\n`
-        | (false, true) ->
+          instr_for_floatop floatop (reg i.arg.(1))
+      | (false, true) ->
           (* second operand on stack *)
-          `	{emit_string(instr_for_floatop_reversed floatop)}	{emit_reg i.arg.(0)}\n`
-        | (false, false) ->
+          instr_for_floatop_reversed floatop (reg i.arg.(0))
+      | (false, false) ->
           (* both operands in memory *)
-          `	fldl	{emit_reg i.arg.(0)}\n`;
-          `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.arg.(1)}\n`
-        end
-    | Lop(Ifloatofint) ->
-        begin match i.arg.(0).loc with
-          Stack s ->
-            `	fildl	{emit_reg i.arg.(0)}\n`
-        | _ ->
-            `	pushl	{emit_reg i.arg.(0)}\n`;
-            `	fildl	(%esp)\n`;
-            `	addl	$4, %esp\n`
-        end
-    | Lop(Iintoffloat) ->
-        if not (is_tos i.arg.(0)) then
-          `	fldl	{emit_reg i.arg.(0)}\n`;
-        stack_offset := !stack_offset - 8;
-        `	subl	$8, %esp\n`;
-        cfi_adjust_cfa_offset 8;
-        `	fnstcw	4(%esp)\n`;
-        `	movw	4(%esp), %ax\n`;
-        `	movb    $12, %ah\n`;
-        `	movw	%ax, 0(%esp)\n`;
-        `	fldcw	0(%esp)\n`;
-        begin match i.res.(0).loc with
-          Stack s ->
-            `	fistpl	{emit_reg i.res.(0)}\n`
+          I.fld (reg i.arg.(0));
+          instr_for_floatop floatop (reg i.arg.(1))
+      end
+  | Lop(Ifloatofint) ->
+      begin match i.arg.(0).loc with
+      | Stack _ ->
+          I.fild (reg i.arg.(0))
+      | _ ->
+          I.push (reg i.arg.(0));
+          I.fild (mem32 DWORD 0 RSP);
+          I.add (int 4) esp
+      end
+  | Lop(Iintoffloat) ->
+      if not (is_tos i.arg.(0)) then
+        I.fld (reg i.arg.(0));
+      stack_offset := !stack_offset - 8;
+      I.sub (int 8) esp;
+      cfi_adjust_cfa_offset 8;
+      I.fnstcw (mem32 NONE 4 RSP);
+      I.mov (mem32 WORD 4 RSP) ax;
+      I.mov (int 12) ah;
+      I.mov ax (mem32 WORD 0 RSP);
+      I.fldcw (mem32 NONE 0 RSP);
+      begin match i.res.(0).loc with
+      | Stack _ ->
+          I.fistp (reg i.res.(0))
+      | _ ->
+          I.fistp (mem32 DWORD 0 RSP);
+          I.mov (mem32 DWORD 0 RSP) (reg i.res.(0))
+      end;
+      I.fldcw (mem32 NONE 4 RSP);
+      I.add (int 8) esp;
+      cfi_adjust_cfa_offset (-8);
+      stack_offset := !stack_offset + 8
+  | Lop(Ispecific(Ilea addr)) ->
+      I.lea (addressing addr DWORD i 0) (reg i.res.(0))
+  | Lop(Ispecific(Istore_int(n, addr, _))) ->
+      I.mov (nat n) (addressing addr DWORD i 0)
+  | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
+      add_used_symbol s;
+      I.mov (immsym s) (addressing addr DWORD i 0)
+  | Lop(Ispecific(Ioffset_loc(n, addr))) ->
+      I.add (int n) (addressing addr DWORD i 0)
+  | Lop(Ispecific(Ipush)) ->
+      (* Push arguments in reverse order *)
+      for n = Array.length i.arg - 1 downto 0 do
+        let r = i.arg.(n) in
+        match r with
+          {loc = Reg _; typ = Float} ->
+            I.sub (int 8) esp;
+            cfi_adjust_cfa_offset 8;
+            I.fstp (mem32 REAL8 0 RSP);
+            stack_offset := !stack_offset + 8
+        | {loc = Stack sl; typ = Float} ->
+            let ofs = slot_offset sl 1 in
+            (* Use x87 stack to move from stack to stack,
+               instead of two 32-bit push instructions,
+               which could kill performance on modern CPUs (see #6979).
+            *)
+            I.fld (mem32 REAL8 ofs RSP);
+            I.sub (int 8) esp;
+            cfi_adjust_cfa_offset 8;
+            I.fstp (mem32 REAL8 0 RSP);
+            stack_offset := !stack_offset + 8
         | _ ->
-            `	fistpl	(%esp)\n`;
-            `	movl	(%esp), {emit_reg i.res.(0)}\n`
-        end;
-        `	fldcw	4(%esp)\n`;
-        `	addl	$8, %esp\n`;
-        cfi_adjust_cfa_offset (-8);
-        stack_offset := !stack_offset + 8
-    | Lop(Ispecific(Ilea addr)) ->
-        `	lea	{emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
-    | Lop(Ispecific(Istore_int(n, addr, _))) ->
-        `	movl	${emit_nativeint n}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
-        `	movl	${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Ioffset_loc(n, addr))) ->
-        `	addl	${emit_int n}, {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Ipush)) ->
-        (* Push arguments in reverse order *)
-        for n = Array.length i.arg - 1 downto 0 do
-          let r = i.arg.(n) in
-          match r with
-            {loc = Reg _; typ = Float} ->
-              `	subl	$8, %esp\n`;
-              cfi_adjust_cfa_offset 8;
-              `	fstpl	0(%esp)\n`;
-              stack_offset := !stack_offset + 8
-          | {loc = Stack sl; typ = Float} ->
-              let ofs = slot_offset sl 1 in
-              `	pushl	{emit_int(ofs + 4)}(%esp)\n`;
-              `	pushl	{emit_int(ofs + 4)}(%esp)\n`;
-              cfi_adjust_cfa_offset 8;
-              stack_offset := !stack_offset + 8
-          | _ ->
-              `	pushl	{emit_reg r}\n`;
-              cfi_adjust_cfa_offset 4;
-              stack_offset := !stack_offset + 4
-        done
-    | Lop(Ispecific(Ipush_int n)) ->
-        `	pushl	${emit_nativeint n}\n`;
-        cfi_adjust_cfa_offset 4;
-        stack_offset := !stack_offset + 4
-    | Lop(Ispecific(Ipush_symbol s)) ->
-        `	pushl	${emit_symbol s}\n`;
-        cfi_adjust_cfa_offset 4;
-        stack_offset := !stack_offset + 4
-    | Lop(Ispecific(Ipush_load addr)) ->
-        `	pushl	{emit_addressing addr i.arg 0}\n`;
-        cfi_adjust_cfa_offset 4;
-        stack_offset := !stack_offset + 4
-    | Lop(Ispecific(Ipush_load_float addr)) ->
-        `	pushl	{emit_addressing (offset_addressing addr 4) i.arg 0}\n`;
-        `	pushl	{emit_addressing addr i.arg 0}\n`;
-        cfi_adjust_cfa_offset 8;
-        stack_offset := !stack_offset + 8
-    | Lop(Ispecific(Ifloatarithmem(double, op, addr))) ->
-        if not (is_tos i.arg.(0)) then
-          `	fldl	{emit_reg i.arg.(0)}\n`;
-        `	{emit_string(instr_for_floatarithmem double op)}	{emit_addressing addr i.arg 1}\n`
-    | Lop(Ispecific(Ifloatspecial s)) ->
-        (* Push args on float stack if necessary *)
-        for k = 0 to Array.length i.arg - 1 do
-          if not (is_tos i.arg.(k)) then `	fldl	{emit_reg i.arg.(k)}\n`
-        done;
-        (* Fix-up for binary instrs whose args were swapped *)
-        if Array.length i.arg = 2 && is_tos i.arg.(1) then
-          `	fxch	%st(1)\n`;
-        emit_floatspecial s
-    | Lreloadretaddr ->
-        ()
-    | Lreturn ->
-        output_epilogue begin fun () ->
-        `	ret\n`
-        end
-    | Llabel lbl ->
-        `{emit_Llabel fallthrough lbl}:\n`
-    | Lbranch lbl ->
-        `	jmp	{emit_label lbl}\n`
-    | Lcondbranch(tst, lbl) ->
-        begin match tst with
-          Itruetest ->
-            output_test_zero i.arg.(0);
-            `	jne	{emit_label lbl}\n`
-        | Ifalsetest ->
-            output_test_zero i.arg.(0);
-            `	je	{emit_label lbl}\n`
-        | Iinttest cmp ->
-            `	cmpl	{emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm((Isigned Ceq | Isigned Cne |
-                        Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
-            output_test_zero i.arg.(0);
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm(cmp, n) ->
-            `	cmpl	${emit_int n}, {emit_reg i.arg.(0)}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Ifloattest(cmp, neg) ->
-            emit_float_test cmp neg i.arg lbl
-        | Ioddtest ->
-            `	testl	$1, {emit_reg i.arg.(0)}\n`;
-            `	jne	{emit_label lbl}\n`
-        | Ieventest ->
-            `	testl	$1, {emit_reg i.arg.(0)}\n`;
-            `	je	{emit_label lbl}\n`
-        end
-    | Lcondbranch3(lbl0, lbl1, lbl2) ->
-            `	cmpl	$1, {emit_reg i.arg.(0)}\n`;
-            begin match lbl0 with
-              None -> ()
-            | Some lbl -> `	jb	{emit_label lbl}\n`
-            end;
-            begin match lbl1 with
-              None -> ()
-            | Some lbl -> `	je	{emit_label lbl}\n`
-            end;
-            begin match lbl2 with
-              None -> ()
-            | Some lbl -> `	jg	{emit_label lbl}\n`
-            end
-    | Lswitch jumptbl ->
-        let lbl = new_label() in
-        `	jmp	*{emit_label lbl}(, {emit_reg i.arg.(0)}, 4)\n`;
-        `	.data\n`;
-        `{emit_label lbl}:`;
-        for i = 0 to Array.length jumptbl - 1 do
-          `	.long	{emit_label jumptbl.(i)}\n`
-        done;
-        `	.text\n`
-    | Lsetuptrap lbl ->
-        `	call	{emit_label lbl}\n`
-    | Lpushtrap ->
-        if trap_frame_size > 8 then
-          `	subl	${emit_int (trap_frame_size - 8)}, %esp\n`;
-        `	pushl	{emit_symbol "caml_exception_pointer"}\n`;
-        cfi_adjust_cfa_offset trap_frame_size;
-        `	movl	%esp, {emit_symbol "caml_exception_pointer"}\n`;
-        stack_offset := !stack_offset + trap_frame_size
-    | Lpoptrap ->
-        `	popl	{emit_symbol "caml_exception_pointer"}\n`;
-        `	addl	${emit_int (trap_frame_size - 4)}, %esp\n`;
-        cfi_adjust_cfa_offset (-trap_frame_size);
-        stack_offset := !stack_offset - trap_frame_size
-    | Lraise k  ->
-        begin match !Clflags.debug, k with
-        | true, Lambda.Raise_regular ->
-          `	call    {emit_symbol "caml_raise_exn"}\n`;
+            I.push (reg r);
+            cfi_adjust_cfa_offset 4;
+            stack_offset := !stack_offset + 4
+      done
+  | Lop(Ispecific(Ipush_int n)) ->
+      I.push (nat n);
+      cfi_adjust_cfa_offset 4;
+      stack_offset := !stack_offset + 4
+  | Lop(Ispecific(Ipush_symbol s)) ->
+      add_used_symbol s;
+      I.push (immsym s);
+      cfi_adjust_cfa_offset 4;
+      stack_offset := !stack_offset + 4
+  | Lop(Ispecific(Ipush_load addr)) ->
+      I.push (addressing addr DWORD i 0);
+      cfi_adjust_cfa_offset 4;
+      stack_offset := !stack_offset + 4
+  | Lop(Ispecific(Ipush_load_float addr)) ->
+      I.push (addressing (offset_addressing addr 4) DWORD i 0);
+      I.push (addressing addr DWORD i 0);
+      cfi_adjust_cfa_offset 8;
+      stack_offset := !stack_offset + 8
+  | Lop(Ispecific(Ifloatarithmem(double, op, addr))) ->
+      if not (is_tos i.arg.(0)) then
+        I.fld (reg i.arg.(0));
+      instr_for_floatarithmem op
+          (addressing addr
+             (if double then REAL8 else REAL4) i 1)
+  | Lop(Ispecific(Ifloatspecial s)) ->
+      (* Push args on float stack if necessary *)
+      for k = 0 to Array.length i.arg - 1 do
+        if not (is_tos i.arg.(k)) then I.fld (reg i.arg.(k))
+      done;
+      (* Fix-up for binary instrs whose args were swapped *)
+      if Array.length i.arg = 2 && is_tos i.arg.(1) then
+        I.fxch st1;
+      emit_floatspecial s
+  | Lreloadretaddr ->
+      ()
+  | Lreturn ->
+      output_epilogue begin fun () ->
+        I.ret ()
+      end
+  | Llabel lbl ->
+      emit_Llabel fallthrough lbl
+  | Lbranch lbl ->
+      I.jmp (label lbl)
+  | Lcondbranch(tst, lbl) ->
+      let lbl = label lbl in
+      begin match tst with
+      | Itruetest ->
+          output_test_zero i.arg.(0);
+          I.jne lbl;
+      | Ifalsetest ->
+          output_test_zero i.arg.(0);
+          I.je lbl
+      | Iinttest cmp ->
+          I.cmp (reg i.arg.(1)) (reg i.arg.(0));
+          I.j (cond cmp) lbl
+      | Iinttest_imm((Isigned Ceq | Isigned Cne |
+                      Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
+          output_test_zero i.arg.(0);
+          I.j (cond cmp) lbl
+      | Iinttest_imm(cmp, n) ->
+          I.cmp (int n) (reg i.arg.(0));
+          I.j (cond cmp) lbl
+      | Ifloattest(cmp, neg) ->
+          emit_float_test cmp neg i.arg lbl
+      | Ioddtest ->
+          I.test (int 1) (reg i.arg.(0));
+          I.jne lbl
+      | Ieventest ->
+          I.test (int 1) (reg i.arg.(0));
+          I.je lbl
+      end
+  | Lcondbranch3(lbl0, lbl1, lbl2) ->
+      I.cmp (int 1) (reg i.arg.(0));
+      begin match lbl0 with
+        None -> ()
+      | Some lbl -> I.jb (label lbl)
+      end;
+      begin match lbl1 with
+        None -> ()
+      | Some lbl -> I.je (label lbl)
+      end;
+      begin match lbl2 with
+        None -> ()
+      | Some lbl -> I.jg (label lbl)
+      end
+  | Lswitch jumptbl ->
+      let lbl = new_label() in
+      I.jmp (mem32 NONE 0 (reg32 i.arg.(0)) ~scale:4 ~sym:(emit_label lbl));
+      D.data ();
+      _label (emit_label lbl);
+      for i = 0 to Array.length jumptbl - 1 do
+        D.long (ConstLabel (emit_label jumptbl.(i)))
+      done;
+      D.text ()
+  | Lsetuptrap lbl ->
+      I.call (label lbl)
+  | Lpushtrap ->
+      if trap_frame_size > 8 then
+        I.sub (int (trap_frame_size - 8)) esp;
+      I.push (sym32 "caml_exception_pointer");
+      cfi_adjust_cfa_offset trap_frame_size;
+      I.mov esp (sym32 "caml_exception_pointer");
+      stack_offset := !stack_offset + trap_frame_size
+  | Lpoptrap ->
+      I.pop (sym32 "caml_exception_pointer");
+      I.add (int (trap_frame_size - 4)) esp;
+      cfi_adjust_cfa_offset (-trap_frame_size);
+      stack_offset := !stack_offset - trap_frame_size
+  | Lraise k  ->
+      begin match !Clflags.debug, k with
+      | true, Lambda.Raise_regular ->
+          emit_call "caml_raise_exn";
           record_frame Reg.Set.empty i.dbg
-        | true, Lambda.Raise_reraise ->
-          `	call    {emit_symbol "caml_reraise_exn"}\n`;
+      | true, Lambda.Raise_reraise ->
+          emit_call "caml_reraise_exn";
           record_frame Reg.Set.empty i.dbg
-        | false, _
-        | true, Lambda.Raise_notrace ->
-          `	movl	{emit_symbol "caml_exception_pointer"}, %esp\n`;
-          `	popl    {emit_symbol "caml_exception_pointer"}\n`;
+      | false, _
+      | true, Lambda.Raise_notrace ->
+          I.mov (sym32 "caml_exception_pointer") esp;
+          I.pop (sym32 "caml_exception_pointer");
           if trap_frame_size > 8 then
-            `	addl	${emit_int (trap_frame_size - 8)}, %esp\n`;
-          `	ret\n`
-        end
+            I.add (int (trap_frame_size - 8)) esp;
+          I.ret ()
+      end
 
 let rec emit_all fallthrough i =
   match i.desc with
@@ -841,65 +891,52 @@ let rec emit_all fallthrough i =
   | _ ->
       emit_instr fallthrough i;
       emit_all
-        (Linearize.has_fallthrough  i.desc)
+        (system = S_win32 || Linearize.has_fallthrough i.desc)
         i.next
 
 (* Emission of external symbol references (for MacOSX) *)
 
 let emit_external_symbol_direct s =
-  `L{emit_symbol s}$stub:\n`;
-  `	.indirect_symbol {emit_symbol s}\n`;
-  `	hlt ; hlt ; hlt ; hlt ; hlt\n`
+  _label (Printf.sprintf "L%s$stub" (emit_symbol s));
+  D.indirect_symbol (emit_symbol s);
+  I.hlt (); I.hlt (); I.hlt (); I.hlt () ; I.hlt ()
 
 let emit_external_symbol_indirect s =
-  `L{emit_symbol s}$non_lazy_ptr:\n`;
-  `	.indirect_symbol {emit_symbol s}\n`;
-  `	.long	0\n`
+  _label (Printf.sprintf "L%s$non_lazy_ptr" (emit_symbol s));
+  D.indirect_symbol (emit_symbol s);
+  D.long (const 0)
 
 let emit_external_symbols () =
-  `	.section __IMPORT,__pointers,non_lazy_symbol_pointers\n`;
+  D.section [ "__IMPORT"; "__pointers"] None ["non_lazy_symbol_pointers" ];
   StringSet.iter emit_external_symbol_indirect !external_symbols_indirect;
   external_symbols_indirect := StringSet.empty;
-  `	.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n`;
+  D.section [ "__IMPORT"; "__jump_table"] None
+    [ "symbol_stubs"; "self_modifying_code+pure_instructions"; "5" ];
   StringSet.iter emit_external_symbol_direct !external_symbols_direct;
   external_symbols_direct := StringSet.empty;
   if !Clflags.gprofile then begin
-    `Lmcount$stub:\n`;
-    `	.indirect_symbol mcount\n`;
-    `	hlt ; hlt ; hlt ; hlt ; hlt\n`
+    _label "Lmcount$stub";
+    D.indirect_symbol "mcount";
+    I.hlt (); I.hlt (); I.hlt () ; I.hlt () ; I.hlt ()
   end
 
 (* Emission of the profiling prelude *)
 
+let call_mcount mcount =
+  I.push eax;
+  I.mov esp ebp;
+  I.push ecx;
+  I.push edx;
+  I.call (sym mcount);
+  I.pop edx;
+  I.pop ecx;
+  I.pop eax
+
 let emit_profile () =
-  match Config.system with
-    "linux_elf" | "gnu" ->
-      `	pushl	%eax\n`;
-      `	movl	%esp, %ebp\n`;
-      `	pushl	%ecx\n`;
-      `	pushl	%edx\n`;
-      `	call	{emit_symbol "mcount"}\n`;
-      `	popl	%edx\n`;
-      `	popl	%ecx\n`;
-      `	popl	%eax\n`
-  | "bsd_elf" ->
-      `	pushl	%eax\n`;
-      `	movl	%esp, %ebp\n`;
-      `	pushl	%ecx\n`;
-      `	pushl	%edx\n`;
-      `	call	.mcount\n`;
-      `	popl	%edx\n`;
-      `	popl	%ecx\n`;
-      `	popl	%eax\n`
-  | "macosx" ->
-      `	pushl	%eax\n`;
-      `	movl	%esp, %ebp\n`;
-      `	pushl	%ecx\n`;
-      `	pushl	%edx\n`;
-      `	call	Lmcount$stub\n`;
-      `	popl	%edx\n`;
-      `	popl	%ecx\n`;
-      `	popl	%eax\n`
+  match system with
+  | S_linux_elf | S_gnu -> call_mcount "mcount"
+  | S_bsd_elf -> call_mcount ".mcount"
+  | S_macosx -> call_mcount "Lmcount$stub"
   | _ -> () (*unsupported yet*)
 
 (* Emission of a function declaration *)
@@ -912,123 +949,152 @@ let fundecl fundecl =
   call_gc_sites := [];
   bound_error_sites := [];
   bound_error_call := 0;
-  `	.text\n`;
-  emit_align 16;
-  if macosx
+  D.text ();
+  add_def_symbol fundecl.fun_name;
+  D.align (if system = S_win32 then 4 else 16);
+  if system = S_macosx
   && not !Clflags.output_c_object
   && is_generic_function fundecl.fun_name
   then (* PR#4690 *)
-    `	.private_extern	{emit_symbol fundecl.fun_name}\n`
+    D.private_extern (emit_symbol fundecl.fun_name)
   else
-    `	.globl	{emit_symbol fundecl.fun_name}\n`;
-  `{emit_symbol fundecl.fun_name}:\n`;
+    D.global (emit_symbol fundecl.fun_name);
+  D.label (emit_symbol fundecl.fun_name);
   emit_debug_info fundecl.fun_dbg;
   cfi_startproc ();
   if !Clflags.gprofile then emit_profile();
   let n = frame_size() - 4 in
-  if n > 0 then
-  begin
-    `	subl	${emit_int n}, %esp\n`;
+  if n > 0 then  begin
+    I.sub (int n) esp;
     cfi_adjust_cfa_offset n;
   end;
-  `{emit_label !tailrec_entry_point}:\n`;
+  def_label !tailrec_entry_point;
   emit_all true fundecl.fun_body;
   List.iter emit_call_gc !call_gc_sites;
   emit_call_bound_errors ();
   cfi_endproc ();
-  begin match Config.system with
-    "linux_elf" | "bsd_elf" | "gnu" ->
-      `	.type	{emit_symbol fundecl.fun_name},@function\n`;
-      `	.size	{emit_symbol fundecl.fun_name},.-{emit_symbol fundecl.fun_name}\n`
-  | _ -> () end
+  begin match system with
+  | S_linux_elf | S_bsd_elf | S_gnu ->
+      D.type_ (emit_symbol fundecl.fun_name) "@function";
+      D.size (emit_symbol fundecl.fun_name)
+        (ConstSub (
+            ConstThis,
+            ConstLabel (emit_symbol fundecl.fun_name)))
+  | _ -> ()
+  end
 
 
 (* Emission of data *)
 
 let emit_item = function
-    Cglobal_symbol s ->
-      `	.globl	{emit_symbol s}\n`;
-  | Cdefine_symbol s ->
-      `{emit_symbol s}:\n`
-  | Cdefine_label lbl ->
-      `{emit_data_label lbl}:\n`
-  | Cint8 n ->
-      `	.byte	{emit_int n}\n`
-  | Cint16 n ->
-      `	{emit_string word_dir}	{emit_int n}\n`
-  | Cint32 n ->
-      `	.long	{emit_nativeint n}\n`
-  | Cint n ->
-      `	.long	{emit_nativeint n}\n`
-  | Csingle f ->
-      emit_float32_directive ".long" (Int32.bits_of_float f)
-  | Cdouble f ->
-      emit_float64_split_directive ".long" (Int64.bits_of_float f)
-  | Csymbol_address s ->
-      `	.long	{emit_symbol s}\n`
-  | Clabel_address lbl ->
-      `	.long	{emit_data_label lbl}\n`
-  | Cstring s ->
-      if use_ascii_dir
-      then emit_string_directive "	.ascii	" s
-      else emit_bytes_directive  "	.byte	" s
-  | Cskip n ->
-      if n > 0 then `	{emit_string skip_dir}	{emit_int n}\n`
-  | Calign n ->
-      emit_align n
+  | Cglobal_symbol s -> D.global (emit_symbol s)
+  | Cdefine_symbol s -> add_def_symbol s; _label (emit_symbol s)
+  | Cdefine_label lbl -> _label (emit_data_label lbl)
+  | Cint8 n -> D.byte (const n)
+  | Cint16 n -> D.word (const n)
+  | Cint32 n -> D.long (const_nat n)
+  | Cint n -> D.long (const_nat n)
+  | Csingle f -> D.long (Const (Int64.of_int32 (Int32.bits_of_float f)))
+  | Cdouble f -> emit_float64_split_directive (Int64.bits_of_float f)
+  | Csymbol_address s -> add_used_symbol s; D.long (ConstLabel (emit_symbol s))
+  | Clabel_address lbl -> D.long (ConstLabel (emit_data_label lbl))
+  | Cstring s -> D.bytes s
+  | Cskip n -> if n > 0 then D.space n
+  | Calign n -> D.align n
 
 let data l =
-  `	.data\n`;
+  D.data ();
   List.iter emit_item l
 
 (* Beginning / end of an assembly file *)
 
 let begin_assembly() =
+  X86_proc.reset_asm_code ();
   reset_debug_info();                   (* PR#5603 *)
   float_constants := [];
-  let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
-  `	.data\n`;
-  `	.globl	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin}:\n`;
-  let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
-  `	.text\n`;
-  `	.globl	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin}:\n`;
-  if macosx then `	nop\n` (* PR#4690 *)
+  if system = S_win32 then begin
+    D.mode386 ();
+    D.model "FLAT";
+    D.extrn "_caml_young_ptr" DWORD;
+    D.extrn "_caml_young_limit" DWORD;
+    D.extrn "_caml_exception_pointer" DWORD;
+    D.extrn "_caml_extra_params" DWORD;
+    D.extrn "_caml_call_gc" PROC;
+    D.extrn "_caml_c_call" PROC;
+    D.extrn "_caml_allocN" PROC;
+    D.extrn "_caml_alloc1" PROC;
+    D.extrn "_caml_alloc2" PROC;
+    D.extrn "_caml_alloc3" PROC;
+    D.extrn "_caml_ml_array_bound_error" PROC;
+    D.extrn "_caml_raise_exn" PROC;
+    D.extrn "_caml_reraise_exn" PROC;
+  end;
+
+  D.data ();
+  emit_global_label "data_begin";
+
+  D.text ();
+  emit_global_label "code_begin";
+  if system = S_macosx then I.nop (); (* PR#4690 *)
+  ()
 
 let end_assembly() =
   if !float_constants <> [] then begin
-    `	.data\n`;
-    List.iter emit_float_constant !float_constants
+    D.data ();
+    List.iter (fun (cst,lbl) -> emit_float_constant cst lbl) !float_constants
   end;
-  let lbl_end = Compilenv.make_symbol (Some "code_end") in
-  `	.text\n`;
-  if macosx then `	nop\n`; (* suppress "ld warning: atom sorting error" *)
-  `	.globl	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end}:\n`;
-  `	.data\n`;
-  let lbl_end = Compilenv.make_symbol (Some "data_end") in
-  `	.globl	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end}:\n`;
-  `	.long	0\n`;
-  let lbl = Compilenv.make_symbol (Some "frametable") in
-  `	.globl	{emit_symbol lbl}\n`;
-  `{emit_symbol lbl}:\n`;
+
+  D.text ();
+  if system = S_macosx then I.nop ();
+  (* suppress "ld warning: atom sorting error" *)
+
+  emit_global_label "code_end";
+
+  D.data ();
+  emit_global_label "data_end";
+  D.long (const 0);
+
+  emit_global_label "frametable";
+
   emit_frames
-    { efa_label = (fun l -> `	.long	{emit_label l}\n`);
-      efa_16 = (fun n -> `	{emit_string word_dir}	{emit_int n}\n`);
-      efa_32 = (fun n -> `	.long	{emit_int32 n}\n`);
-      efa_word = (fun n -> `	.long	{emit_int n}\n`);
-      efa_align = emit_align;
+    { efa_label = (fun l -> D.long (ConstLabel (emit_label l)));
+      efa_16 = (fun n -> D.word (const n));
+      efa_32 = (fun n -> D.long (const_32 n));
+      efa_word = (fun n -> D.long (const n));
+      efa_align = D.align;
       efa_label_rel = (fun lbl ofs ->
-                           `	.long	{emit_label lbl} - . + {emit_int32 ofs}\n`);
-      efa_def_label = (fun l -> `{emit_label l}:\n`);
-      efa_string = (fun s ->
-        let s = s ^ "\000" in
-        if use_ascii_dir
-        then emit_string_directive "	.ascii	" s
-        else emit_bytes_directive  "	.byte	" s) };
-  if macosx then emit_external_symbols ();
-  if Config.system = "linux_elf" then
+          D.long (ConstAdd (
+              ConstSub(ConstLabel(emit_label lbl),
+                       ConstThis),
+              const_32 ofs)));
+      efa_def_label = (fun l -> _label (emit_label l));
+      efa_string = (fun s -> D.bytes (s ^ "\000"))
+    };
+
+  if system = S_macosx then emit_external_symbols ();
+  if system = S_linux_elf then
     (* Mark stack as non-executable, PR#4564 *)
-    `\n	.section .note.GNU-stack,\"\",%progbits\n`
+    D.section [".note.GNU-stack"] (Some "") ["%progbits"];
+
+  if system = S_win32 then begin
+    D.comment "External functions";
+    StringSet.iter
+      (fun s ->
+         if not (StringSet.mem s !symbols_defined) then
+           D.extrn (emit_symbol s) PROC)
+      !symbols_used;
+    symbols_used := StringSet.empty;
+    symbols_defined := StringSet.empty;
+  end;
+
+  let asm =
+    if !Emitaux.create_asm_file then
+      Some
+        (
+         (if X86_proc.masm then X86_masm.generate_asm
+          else X86_gas.generate_asm) !Emitaux.output_channel
+        )
+    else
+      None
+  in
+  X86_proc.generate_code asm
diff --git a/asmcomp/i386/emit_nt.mlp b/asmcomp/i386/emit_nt.mlp
deleted file mode 100644
index ef5205ef..00000000
--- a/asmcomp/i386/emit_nt.mlp
+++ /dev/null
@@ -1,893 +0,0 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
-
-(* Emission of Intel 386 assembly code, MASM syntax. *)
-
-module StringSet =
-  Set.Make(struct type t = string let compare (x:t) y = compare x y end)
-
-open Misc
-open Cmm
-open Arch
-open Proc
-open Reg
-open Mach
-open Linearize
-open Emitaux
-
-(* Tradeoff between code size and code speed *)
-
-let fastcode_flag = ref true
-
-(* Layout of the stack frame *)
-
-let stack_offset = ref 0
-
-let frame_size () =                     (* includes return address *)
-  !stack_offset + 4 * num_stack_slots.(0) + 8 * num_stack_slots.(1) + 4
-
-let slot_offset loc cl =
-  match loc with
-    Incoming n ->
-      assert (n >= 0);
-      frame_size() + n
-  | Local n ->
-      if cl = 0
-      then !stack_offset + n * 4
-      else !stack_offset + num_stack_slots.(0) * 4 + n * 8
-  | Outgoing n ->
-      assert (n >= 0);
-      n
-(* Record symbols used and defined - at the end generate extern for those
-   used but not defined *)
-
-let symbols_defined = ref StringSet.empty
-let symbols_used = ref StringSet.empty
-
-let add_def_symbol s =
-  symbols_defined := StringSet.add s !symbols_defined
-
-let add_used_symbol s =
-  symbols_used := StringSet.add s !symbols_used
-
-let emit_symbol s =
-  emit_string "_"; Emitaux.emit_symbol '$' s
-
-(* Output a 32 or 64 bit integer in hex *)
-
-let emit_int32 n = emit_printf "0%lxh" n
-let emit_int64 n = emit_printf "0%Lxh" n
-
-(* Output a label *)
-
-let emit_label lbl =
-  emit_string "L"; emit_int lbl
-
-let emit_data_label lbl =
-  emit_string "Ld"; emit_int lbl
-
-(* Output an align directive. *)
-
-let emit_align n = `	ALIGN	{emit_int n}\n`
-
-(* Output a pseudo-register *)
-
-let emit_reg = function
-    { loc = Reg r } ->
-      emit_string (register_name r)
-  | { loc = Stack(Incoming n | Outgoing n) } when n < 0 ->
-      `{emit_symbol "caml_extra_params"} + {emit_int (n + 64)}`
-  | { loc = Stack s; typ = Float } as r ->
-      let ofs = slot_offset s (register_class r) in
-      `REAL8 PTR {emit_int ofs}[esp]`
-  | { loc = Stack s } as r ->
-      let ofs = slot_offset s (register_class r) in
-      `DWORD PTR {emit_int ofs}[esp]`
-  | { loc = Unknown } ->
-      fatal_error "Emit.emit_reg"
-
-(* Output a reference to the lower 8 bits or lower 16 bits of a register *)
-
-let reg_low_byte_name = [| "al"; "bl"; "cl"; "dl" |]
-let reg_low_half_name = [| "ax"; "bx"; "cx"; "dx"; "si"; "di"; "bp" |]
-
-let emit_reg8 r =
-  match r.loc with
-    Reg r when r < 4 -> emit_string (reg_low_byte_name.(r))
-  | _ -> fatal_error "Emit.emit_reg8"
-
-let emit_reg16 r =
-  match r.loc with
-    Reg r when r < 7 -> emit_string (reg_low_half_name.(r))
-  | _ -> fatal_error "Emit.emit_reg16"
-
-(* Check if the given register overlaps (same location) with the given
-   array of registers *)
-
-let register_overlap reg arr =
-  try
-    for i = 0 to Array.length arr - 1 do
-      if reg.loc = arr.(i).loc then raise Exit
-    done;
-    false
-  with Exit ->
-    true
-
-(* Output an addressing mode *)
-
-let emit_signed_int d =
-  if d > 0 then emit_char '+';
-  if d <> 0 then emit_int d
-
-let emit_addressing addr r n =
-  match addr with
-    Ibased(s, d) ->
-      add_used_symbol s;
-      `{emit_symbol s}{emit_signed_int d}`
-  | Iindexed d ->
-      `[{emit_reg r.(n)}{emit_signed_int d}]`
-  | Iindexed2 d ->
-      `[{emit_reg r.(n)}+{emit_reg r.(n+1)}{emit_signed_int d}]`
-  | Iscaled(2, d) ->
-      `[{emit_reg r.(n)}+{emit_reg r.(n)}{emit_signed_int d}]`
-  | Iscaled(scale, d) ->
-      `[{emit_reg r.(n)}*{emit_int scale}{emit_signed_int d}]`
-  | Iindexed2scaled(scale, d) ->
-      `[{emit_reg r.(n)}+{emit_reg r.(n+1)}*{emit_int scale}{emit_signed_int d}]`
-
-(* Record live pointers at call points *)
-
-let record_frame_label live dbg =
-  let lbl = new_label() in
-  let live_offset = ref [] in
-  Reg.Set.iter
-    (function
-        {typ = Addr; loc = Reg r} ->
-          live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
-          live_offset := slot_offset s (register_class reg) :: !live_offset
-      | _ -> ())
-    live;
-  frame_descriptors :=
-    { fd_lbl = lbl;
-      fd_frame_size = frame_size();
-      fd_live_offset = !live_offset;
-      fd_debuginfo = dbg } :: !frame_descriptors;
-  lbl
-
-let record_frame live dbg =
-  let lbl = record_frame_label live dbg in `{emit_label lbl}:\n`
-
-(* Record calls to the GC -- we've moved them out of the way *)
-
-type gc_call =
-  { gc_lbl: label;                      (* Entry label *)
-    gc_return_lbl: label;               (* Where to branch after GC *)
-    gc_frame: label }                   (* Label of frame descriptor *)
-
-let call_gc_sites = ref ([] : gc_call list)
-
-let emit_call_gc gc =
-  `{emit_label gc.gc_lbl}:	call	_caml_call_gc\n`;
-  `{emit_label gc.gc_frame}:	jmp	{emit_label gc.gc_return_lbl}\n`
-
-(* Record calls to caml_ml_array_bound_error.
-   In -g mode, we maintain one call to caml_ml_array_bound_error
-   per bound check site.  Without -g, we can share a single call. *)
-
-type bound_error_call =
-  { bd_lbl: label;                      (* Entry label *)
-    bd_frame: label }                   (* Label of frame descriptor *)
-
-let bound_error_sites = ref ([] : bound_error_call list)
-let bound_error_call = ref 0
-
-let bound_error_label dbg =
-  if !Clflags.debug then begin
-    let lbl_bound_error = new_label() in
-    let lbl_frame = record_frame_label Reg.Set.empty dbg in
-    bound_error_sites :=
-     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
-   lbl_bound_error
- end else begin
-   if !bound_error_call = 0 then bound_error_call := new_label();
-   !bound_error_call
- end
-
-let emit_call_bound_error bd =
-  `{emit_label bd.bd_lbl}:	call	_caml_ml_array_bound_error\n`;
-  `{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}:	call	_caml_ml_array_bound_error\n`
-
-(* Names for instructions *)
-
-let instr_for_intop = function
-    Iadd -> "add"
-  | Isub -> "sub"
-  | Imul -> "imul"
-  | Iand -> "and"
-  | Ior -> "or"
-  | Ixor -> "xor"
-  | Ilsl -> "sal"
-  | Ilsr -> "shr"
-  | Iasr -> "sar"
-  | _ -> fatal_error "Emit: instr_for_intop"
-
-let instr_for_floatop = function
-    Inegf -> "fchs"
-  | Iabsf -> "fabs"
-  | Iaddf -> "fadd"
-  | Isubf -> "fsub"
-  | Imulf -> "fmul"
-  | Idivf -> "fdiv"
-  | Ispecific Isubfrev -> "fsubr"
-  | Ispecific Idivfrev -> "fdivr"
-  | _ -> fatal_error "Emit: instr_for_floatop"
-
-let instr_for_floatop_reversed = function
-    Iaddf -> "fadd"
-  | Isubf -> "fsubr"
-  | Imulf -> "fmul"
-  | Idivf -> "fdivr"
-  | Ispecific Isubfrev -> "fsub"
-  | Ispecific Idivfrev -> "fdiv"
-  | _ -> fatal_error "Emit: instr_for_floatop_reversed"
-
-let instr_for_floatarithmem = function
-    Ifloatadd -> "fadd"
-  | Ifloatsub -> "fsub"
-  | Ifloatsubrev -> "fsubr"
-  | Ifloatmul -> "fmul"
-  | Ifloatdiv -> "fdiv"
-  | Ifloatdivrev -> "fdivr"
-
-let name_for_cond_branch = function
-    Isigned Ceq -> "e"     | Isigned Cne -> "ne"
-  | Isigned Cle -> "le"    | Isigned Cgt -> "g"
-  | Isigned Clt -> "l"     | Isigned Cge -> "ge"
-  | Iunsigned Ceq -> "e"   | Iunsigned Cne -> "ne"
-  | Iunsigned Cle -> "be"  | Iunsigned Cgt -> "a"
-  | Iunsigned Clt -> "b"   | Iunsigned Cge -> "ae"
-
-(* Output an = 0 or <> 0 test. *)
-
-let output_test_zero arg =
-  match arg.loc with
-    Reg r -> `	test   {emit_reg arg}, {emit_reg arg}\n`
-  | _     -> `	cmp    {emit_reg arg}, 0\n`
-
-(* Deallocate the stack frame before a return or tail call *)
-
-let output_epilogue () =
-  let n = frame_size() - 4 in
-  if n > 0 then `	add    esp, {emit_int n}\n`
-
-(* Determine if the given register is the top of the floating-point stack *)
-
-let is_tos = function { loc = Reg _; typ = Float } -> true | _ -> false
-
-(* Emit the code for a floating-point comparison *)
-
-let emit_float_test cmp neg arg lbl =
-  let actual_cmp =
-    match (is_tos arg.(0), is_tos arg.(1)) with
-      (true, true) ->
-      (* both args on top of FP stack *)
-      `	fcompp\n`;
-      cmp
-    | (true, false) ->
-      (* first arg on top of FP stack *)
-      `	fcomp	{emit_reg arg.(1)}\n`;
-      cmp
-    | (false, true) ->
-      (* second arg on top of FP stack *)
-      `	fcomp	{emit_reg arg.(0)}\n`;
-      Cmm.swap_comparison cmp
-    | (false, false) ->
-      `	fld	{emit_reg arg.(0)}\n`;
-      `	fcomp	{emit_reg arg.(1)}\n`;
-      cmp
-    in
-  `	fnstsw	ax\n`;
-  begin match actual_cmp with
-    Ceq ->
-      if neg then begin
-      `	and	ah, 68\n`;
-      `	xor	ah, 64\n`;
-      `	jne	`
-      end else begin
-      `	and	ah, 69\n`;
-      `	cmp	ah, 64\n`;
-      `	je	`
-      end
-  | Cne ->
-      if neg then begin
-      `	and	ah, 69\n`;
-      `	cmp	ah, 64\n`;
-      `	je	`
-      end else begin
-      `	and	ah, 68\n`;
-      `	xor	ah, 64\n`;
-      `	jne	`
-      end
-  | Cle ->
-      `	and	ah, 69\n`;
-      `	dec	ah\n`;
-      `	cmp	ah, 64\n`;
-      if neg
-      then `	jae	`
-      else `	jb	`
-  | Cge ->
-      `	and	ah, 5\n`;
-      if neg
-      then `	jne	`
-      else `	je	`
-  | Clt ->
-      `	and	ah, 69\n`;
-      `	cmp	ah, 1\n`;
-      if neg
-      then `	jne	`
-      else `	je	`
-  | Cgt ->
-      `	and	ah, 69\n`;
-      if neg
-      then `	jne	`
-      else `	je	`
-  end;
-  `{emit_label lbl}\n`
-
-(* Emit a Ifloatspecial instruction *)
-
-let emit_floatspecial = function
-    "atan"  -> `	fld1\n\tfpatan\n`
-  | "atan2" -> `	fpatan\n`
-  | "cos"   -> `	fcos\n`
-  | "log"   -> `	fldln2\n\tfxch\n\tfyl2x\n`
-  | "log10" -> `	fldlg2\n\tfxch\n\tfyl2x\n`
-  | "sin"   -> `	fsin\n`
-  | "sqrt"  -> `	fsqrt\n`
-  | "tan"   -> `	fptan\n\tfstp st(0)\n`
-  | _ -> assert false
-
-(* Floating-point constants *)
-
-let float_constants = ref ([] : (int64 * int) list)
-
-let add_float_constant cst =
-  let repr = Int64.bits_of_float cst in
-  try
-    List.assoc repr !float_constants
-  with
-    Not_found ->
-      let lbl = new_label() in
-      float_constants := (repr, lbl) :: !float_constants;
-      lbl
-
-let emit_float_constant (cst, lbl) =
-  `{emit_label lbl}	QWORD	{emit_int64 cst}\n`
-
-(* Output the assembly code for an instruction *)
-
-(* Name of current function *)
-let function_name = ref ""
-(* Entry point for tail recursive calls *)
-let tailrec_entry_point = ref 0
-(* Label of trap for out-of-range accesses *)
-let range_check_trap = ref 0
-
-let emit_instr i =
-    match i.desc with
-      Lend -> ()
-    | Lop(Imove | Ispill | Ireload) ->
-        let src = i.arg.(0) and dst = i.res.(0) in
-        if src.loc <> dst.loc then begin
-          if src.typ = Float then
-            if is_tos src then
-              `	fstp	{emit_reg dst}\n`
-            else if is_tos dst then
-              `	fld	{emit_reg src}\n`
-            else begin
-              `	fld	{emit_reg src}\n`;
-              `	fstp	{emit_reg dst}\n`
-            end
-          else
-            `	mov	{emit_reg dst}, {emit_reg src}\n`
-        end
-    | Lop(Iconst_int n | Iconst_blockheader n) ->
-        if n = 0n then begin
-          match i.res.(0).loc with
-            Reg n -> `	xor	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
-          | _     -> `	mov	{emit_reg i.res.(0)}, 0\n`
-        end else
-          `	mov	{emit_reg i.res.(0)}, {emit_nativeint n}\n`
-    | Lop(Iconst_float f) ->
-        begin match Int64.bits_of_float f with
-        | 0x0000_0000_0000_0000L ->       (* +0.0 *)
-          `	fldz\n`
-        | 0x8000_0000_0000_0000L ->       (* -0.0 *)
-          `	fldz\n	fchs\n`
-        | 0x3FF0_0000_0000_0000L ->       (*  1.0 *)
-          `	fld1\n`
-        | 0xBFF0_0000_0000_0000L ->       (* -1.0 *)
-          `	fld1\n	fchs\n`
-        | _ ->
-          let lbl = add_float_constant f in
-          `	fld	{emit_label lbl}\n`
-        end
-    | Lop(Iconst_symbol s) ->
-        add_used_symbol s;
-        `	mov	{emit_reg i.res.(0)}, OFFSET {emit_symbol s}\n`
-    | Lop(Icall_ind) ->
-        `	call	{emit_reg i.arg.(0)}\n`;
-        record_frame i.live i.dbg
-    | Lop(Icall_imm s) ->
-        add_used_symbol s;
-        `	call	{emit_symbol s}\n`;
-        record_frame i.live i.dbg
-    | Lop(Itailcall_ind) ->
-        output_epilogue();
-        `	jmp	{emit_reg i.arg.(0)}\n`
-    | Lop(Itailcall_imm s) ->
-        if s = !function_name then
-          `	jmp	{emit_label !tailrec_entry_point}\n`
-        else begin
-          output_epilogue();
-          add_used_symbol s;
-          `	jmp	{emit_symbol s}\n`
-        end
-    | Lop(Iextcall(s, alloc)) ->
-        add_used_symbol s ;
-        if alloc then begin
-          `	mov	eax, OFFSET {emit_symbol s}\n`;
-          `	call	_caml_c_call\n`;
-          record_frame i.live i.dbg
-        end else begin
-          `	call	{emit_symbol s}\n`
-        end
-    | Lop(Istackoffset n) ->
-        if n >= 0
-        then `	sub	esp, {emit_int n}\n`
-        else `	add	esp, {emit_int(-n)}\n`;
-        stack_offset := !stack_offset + n
-    | Lop(Iload(chunk, addr)) ->
-        let dest = i.res.(0) in
-        begin match chunk with
-          | Word | Thirtytwo_signed | Thirtytwo_unsigned ->
-            `	mov	{emit_reg dest}, DWORD PTR {emit_addressing addr i.arg 0}\n`
-          | Byte_unsigned ->
-              `	movzx	{emit_reg dest}, BYTE PTR {emit_addressing addr i.arg 0}\n`
-          | Byte_signed ->
-              `	movsx	{emit_reg dest}, BYTE PTR {emit_addressing addr i.arg 0}\n`
-          | Sixteen_unsigned ->
-              `	movzx	{emit_reg dest}, WORD PTR {emit_addressing addr i.arg 0}\n`
-          | Sixteen_signed ->
-              `	movsx	{emit_reg dest}, WORD PTR {emit_addressing addr i.arg 0}\n`
-          | Single ->
-            `	fld	REAL4 PTR {emit_addressing addr i.arg 0}\n`
-          | Double | Double_u ->
-            `	fld	REAL8 PTR {emit_addressing addr i.arg 0}\n`
-        end
-    | Lop(Istore(chunk, addr, _)) ->
-        begin match chunk with
-          | Word | Thirtytwo_signed | Thirtytwo_unsigned ->
-            `	mov	DWORD PTR {emit_addressing addr i.arg 1}, {emit_reg i.arg.(0)}\n`
-          | Byte_unsigned | Byte_signed ->
-            `	mov	BYTE PTR {emit_addressing addr i.arg 1}, {emit_reg8 i.arg.(0)}\n`
-          | Sixteen_unsigned | Sixteen_signed ->
-            `	mov	WORD PTR {emit_addressing addr i.arg 1}, {emit_reg16 i.arg.(0)}\n`
-          | Single ->
-              if is_tos i.arg.(0) then
-                `	fstp	REAL4 PTR {emit_addressing addr i.arg 1}\n`
-              else begin
-                `	fld	{emit_reg i.arg.(0)}\n`;
-                `	fstp	REAL4 PTR {emit_addressing addr i.arg 1}\n`
-              end
-          | Double | Double_u ->
-              if is_tos i.arg.(0) then
-                `	fstp	REAL8 PTR {emit_addressing addr i.arg 1}\n`
-              else begin
-                `	fld	{emit_reg i.arg.(0)}\n`;
-                `	fstp	REAL8 PTR {emit_addressing addr i.arg 1}\n`
-              end
-        end
-    | Lop(Ialloc n) ->
-        if !fastcode_flag then begin
-          let lbl_redo = new_label() in
-          `{emit_label lbl_redo}:	mov	eax, _caml_young_ptr\n`;
-          `	sub	eax, {emit_int n}\n`;
-          `	mov	_caml_young_ptr, eax\n`;
-          `	cmp	eax, _caml_young_limit\n`;
-          let lbl_call_gc = new_label() in
-          let lbl_frame = record_frame_label i.live Debuginfo.none in
-          `	jb	{emit_label lbl_call_gc}\n`;
-          `	lea	{emit_reg i.res.(0)}, [eax+4]\n`;
-          call_gc_sites :=
-            { gc_lbl = lbl_call_gc;
-              gc_return_lbl = lbl_redo;
-              gc_frame = lbl_frame } :: !call_gc_sites
-        end else begin
-          begin match n with
-            8  -> `	call	_caml_alloc1\n`
-          | 12 -> `	call	_caml_alloc2\n`
-          | 16 -> `	call	_caml_alloc3\n`
-          | _  -> `	mov	eax, {emit_int n}\n`;
-                  `	call	_caml_allocN\n`
-          end;
-          `{record_frame i.live Debuginfo.none}        lea     {emit_reg i.res.(0)}, [eax+4]\n`
-        end
-    | Lop(Iintop(Icomp cmp)) ->
-        `	cmp	{emit_reg i.arg.(0)},{emit_reg i.arg.(1)}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}      al\n`;
-        `	movzx	{emit_reg i.res.(0)}, al\n`
-    | Lop(Iintop_imm(Icomp cmp, n)) ->
-        `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-        let b = name_for_cond_branch cmp in
-        `	set{emit_string b}      al\n`;
-        `	movzx	{emit_reg i.res.(0)}, al\n`
-    | Lop(Iintop Icheckbound) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmp	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop_imm(Icheckbound, n)) ->
-        let lbl = bound_error_label i.dbg in
-        `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-        `	jbe	{emit_label lbl}\n`
-    | Lop(Iintop(Idiv | Imod)) ->
-        `	cdq\n`;
-        `	idiv	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop(Ilsl | Ilsr | Iasr as op)) ->
-        (* We have i.arg.(0) = i.res.(0) and i.arg.(1) = %ecx *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.res.(0)}, cl\n`
-    | Lop(Iintop Imulh) ->
-        `	imul	{emit_reg i.arg.(1)}\n`
-    | Lop(Iintop op) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.res.(0)}, {emit_reg i.arg.(1)}\n`
-    | Lop(Iintop_imm(Iadd, n)) when i.arg.(0).loc <> i.res.(0).loc ->
-        `	lea	{emit_reg i.res.(0)}, [{emit_reg i.arg.(0)}+{emit_int n}]\n`
-    | Lop(Iintop_imm(Iadd, 1) | Iintop_imm(Isub, -1)) ->
-        `	inc	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(Iadd, -1) | Iintop_imm(Isub, 1)) ->
-        `	dec	{emit_reg i.res.(0)}\n`
-    | Lop(Iintop_imm(op, n)) ->
-        (* We have i.arg.(0) = i.res.(0) *)
-        `	{emit_string(instr_for_intop op)}	{emit_reg i.res.(0)}, {emit_int n}\n`
-    | Lop(Inegf | Iabsf as floatop) ->
-        if not (is_tos i.arg.(0)) then
-          `	fld	{emit_reg i.arg.(0)}\n`;
-        `	{emit_string(instr_for_floatop floatop)}\n`
-    | Lop(Iaddf | Isubf | Imulf | Idivf | Ispecific(Isubfrev | Idivfrev)
-          as floatop) ->
-        begin match (is_tos i.arg.(0), is_tos i.arg.(1)) with
-          (true, true) ->
-          (* both operands on top of FP stack *)
-          `	{emit_string(instr_for_floatop_reversed floatop)}\n`
-        | (true, false) ->
-          (* first operand on stack *)
-          `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.arg.(1)}\n`
-        | (false, true) ->
-          (* second operand on stack *)
-          `	{emit_string(instr_for_floatop_reversed floatop)}	{emit_reg i.arg.(0)}\n`
-        | (false, false) ->
-          (* both operands in memory *)
-          `	fld	{emit_reg i.arg.(0)}\n`;
-          `	{emit_string(instr_for_floatop floatop)}	{emit_reg i.arg.(1)}\n`
-        end
-    | Lop(Ifloatofint) ->
-        begin match i.arg.(0).loc with
-          Stack s ->
-            `	fild	{emit_reg i.arg.(0)}\n`
-        | _ ->
-            `	push	{emit_reg i.arg.(0)}\n`;
-            `	fild	DWORD PTR [esp]\n`;
-            `	add	esp, 4\n`
-        end
-    | Lop(Iintoffloat) ->
-        if not (is_tos i.arg.(0)) then
-          `	fld	{emit_reg i.arg.(0)}\n`;
-        stack_offset := !stack_offset - 8;
-        `	sub	esp, 8\n`;
-        `	fnstcw	[esp+4]\n`;
-        `	mov	ax, [esp+4]\n`;
-        `	mov	ah, 12\n`;
-        `	mov	[esp], ax\n`;
-        `	fldcw	[esp]\n`;
-        begin match i.res.(0).loc with
-          Stack s ->
-            `	fistp	{emit_reg i.res.(0)}\n`
-        | _ ->
-            `	fistp	DWORD PTR [esp]\n`;
-            `	mov	{emit_reg i.res.(0)}, [esp]\n`
-        end;
-        `	fldcw	[esp+4]\n`;
-        `	add	esp, 8\n`;
-        stack_offset := !stack_offset + 8
-    | Lop(Ispecific(Ilea addr)) ->
-        `	lea	{emit_reg i.res.(0)}, DWORD PTR {emit_addressing addr i.arg 0}\n`
-    | Lop(Ispecific(Istore_int(n, addr, _))) ->
-        `	mov	DWORD PTR {emit_addressing addr i.arg 0},{emit_nativeint n}\n`
-    | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
-        add_used_symbol s ;
-        `	mov	DWORD PTR {emit_addressing addr i.arg 0},OFFSET {emit_symbol s}\n`
-    | Lop(Ispecific(Ioffset_loc(n, addr))) ->
-        `	add	DWORD PTR {emit_addressing addr i.arg 0},{emit_int n}\n`
-    | Lop(Ispecific(Ipush)) ->
-        (* Push arguments in reverse order *)
-        for n = Array.length i.arg - 1 downto 0 do
-          let r = i.arg.(n) in
-          match r with
-            {loc = Reg rn; typ = Float} ->
-              `	sub	esp, 8\n`;
-              `	fstp	REAL8 PTR 0[esp]\n`;
-              stack_offset := !stack_offset + 8
-          | {loc = Stack sl; typ = Float} ->
-              let ofs = slot_offset sl 1 in
-              `	push	DWORD PTR {emit_int (ofs + 4)}[esp]\n`;
-              `	push	DWORD PTR {emit_int (ofs + 4)}[esp]\n`;
-              stack_offset := !stack_offset + 8
-          | _ ->
-              `	push	{emit_reg r}\n`;
-              stack_offset := !stack_offset + 4
-        done
-    | Lop(Ispecific(Ipush_int n)) ->
-        `	push	{emit_nativeint n}\n`;
-        stack_offset := !stack_offset + 4
-    | Lop(Ispecific(Ipush_symbol s)) ->
-        add_used_symbol s;
-        `	push	OFFSET {emit_symbol s}\n`;
-        stack_offset := !stack_offset + 4
-    | Lop(Ispecific(Ipush_load addr)) ->
-        `	push	DWORD PTR {emit_addressing addr i.arg 0}\n`;
-        stack_offset := !stack_offset + 4
-    | Lop(Ispecific(Ipush_load_float addr)) ->
-        `	push	DWORD PTR {emit_addressing (offset_addressing addr 4) i.arg 0}\n`;
-        `	push	DWORD PTR {emit_addressing addr i.arg 0}\n`;
-        stack_offset := !stack_offset + 8
-    | Lop(Ispecific(Ifloatarithmem(double, op, addr))) ->
-        if not (is_tos i.arg.(0)) then
-          `	fld	{emit_reg i.arg.(0)}\n`;
-        let size = if double then "REAL8" else "REAL4" in
-        `	{emit_string(instr_for_floatarithmem op)}	{emit_string size} PTR {emit_addressing addr i.arg 1}\n`
-    | Lop(Ispecific(Ifloatspecial s)) ->
-        (* Push args on float stack if necessary *)
-        for k = 0 to Array.length i.arg - 1 do
-          if not (is_tos i.arg.(k)) then `	fld	{emit_reg i.arg.(k)}\n`
-        done;
-        (* Fix-up for binary instrs whose args were swapped *)
-        if Array.length i.arg = 2 && is_tos i.arg.(1) then
-          `	fxch	st(1)\n`;
-        emit_floatspecial s
-    | Lreloadretaddr ->
-        ()
-    | Lreturn ->
-        output_epilogue();
-        `	ret\n`
-    | Llabel lbl ->
-        `{emit_label lbl}:\n`
-    | Lbranch lbl ->
-        `	jmp	{emit_label lbl}\n`
-    | Lcondbranch(tst, lbl) ->
-        begin match tst with
-          Itruetest ->
-            output_test_zero i.arg.(0);
-            `	jne	{emit_label lbl}\n`
-        | Ifalsetest ->
-            output_test_zero i.arg.(0);
-            `	je	{emit_label lbl}\n`
-        | Iinttest cmp ->
-            `	cmp	{emit_reg i.arg.(0)},{emit_reg i.arg.(1)}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}        {emit_label lbl}\n`
-        | Iinttest_imm((Isigned Ceq | Isigned Cne |
-                        Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
-            output_test_zero i.arg.(0);
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Iinttest_imm(cmp, n) ->
-            `	cmp	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-            let b = name_for_cond_branch cmp in
-            `	j{emit_string b}	{emit_label lbl}\n`
-        | Ifloattest(cmp, neg) ->
-            emit_float_test cmp neg i.arg lbl
-        | Ioddtest ->
-            `	test	{emit_reg i.arg.(0)}, 1\n`;
-            `	jne	{emit_label lbl}\n`
-        | Ieventest ->
-            `	test	{emit_reg i.arg.(0)}, 1\n`;
-            `	je	{emit_label lbl}\n`
-        end
-    | Lcondbranch3(lbl0, lbl1, lbl2) ->
-            `	cmp	{emit_reg i.arg.(0)}, 1\n`;
-            begin match lbl0 with
-              None -> ()
-            | Some lbl -> `	jb	{emit_label lbl}\n`
-            end;
-            begin match lbl1 with
-              None -> ()
-            | Some lbl -> `	je	{emit_label lbl}\n`
-            end;
-            begin match lbl2 with
-              None -> ()
-            | Some lbl -> `	jg	{emit_label lbl}\n`
-            end
-    | Lswitch jumptbl ->
-        let lbl = new_label() in
-        `	jmp	[{emit_reg i.arg.(0)} * 4 + {emit_label lbl}]\n`;
-        `	.DATA\n`;
-        `{emit_label lbl}`;
-        for i = 0 to Array.length jumptbl - 1 do
-          `	DWORD	{emit_label jumptbl.(i)}\n`
-        done;
-        `	.CODE\n`
-    | Lsetuptrap lbl ->
-        `	call	{emit_label lbl}\n`
-    | Lpushtrap ->
-        `	push	_caml_exception_pointer\n`;
-        `	mov	_caml_exception_pointer, esp\n`;
-        stack_offset := !stack_offset + 8
-    | Lpoptrap ->
-        `	pop	_caml_exception_pointer\n`;
-        `	add	esp, 4\n`;
-        stack_offset := !stack_offset - 8
-    | Lraise k ->
-        begin match !Clflags.debug, k with
-        | true, Lambda.Raise_regular ->
-          `	call	_caml_raise_exn\n`;
-          record_frame Reg.Set.empty i.dbg
-        | true, Lambda.Raise_reraise ->
-          `	call	_caml_reraise_exn\n`;
-          record_frame Reg.Set.empty i.dbg
-        | false, _
-        | true, Lambda.Raise_notrace ->
-          `	mov	esp, _caml_exception_pointer\n`;
-          `	pop	_caml_exception_pointer\n`;
-          `	ret\n`
-        end
-
-let rec emit_all i =
-  match i.desc with Lend -> () | _ -> emit_instr i; emit_all i.next
-
-(* Emission of a function declaration *)
-
-let fundecl fundecl =
-  function_name := fundecl.fun_name;
-  fastcode_flag := fundecl.fun_fast;
-  tailrec_entry_point := new_label();
-  stack_offset := 0;
-  call_gc_sites := [];
-  bound_error_sites := [];
-  bound_error_call := 0;
-  `	.CODE\n`;
-  add_def_symbol fundecl.fun_name;
-  emit_align 4;
-  `	PUBLIC	{emit_symbol fundecl.fun_name}\n`;
-  `{emit_symbol fundecl.fun_name}:\n`;
-  let n = frame_size() - 4 in
-  if n > 0 then
-    `	sub	esp, {emit_int n}\n`;
-  `{emit_label !tailrec_entry_point}:\n`;
-  emit_all fundecl.fun_body;
-  List.iter emit_call_gc !call_gc_sites;
-  emit_call_bound_errors ()
-
-(* Emission of data *)
-
-let emit_item = function
-    Cglobal_symbol s ->
-      `	PUBLIC	{emit_symbol s}\n`;
-  | Cdefine_symbol s ->
-      add_def_symbol s ;
-      `{emit_symbol s} LABEL DWORD\n`
-  | Cdefine_label lbl ->
-      `{emit_data_label lbl}	LABEL DWORD\n`
-  | Cint8 n ->
-      `	BYTE	{emit_int n}\n`
-  | Cint16 n ->
-      `	WORD	{emit_int n}\n`
-  | Cint n ->
-      `	DWORD	{emit_nativeint n}\n`
-  | Cint32 n ->
-      `	DWORD	{emit_nativeint n}\n`
-  | Csingle f ->
-      `	DWORD	{emit_int32 (Int32.bits_of_float f)}\n`
-  | Cdouble f ->
-      `	QWORD	{emit_int64 (Int64.bits_of_float f)}\n`
-  | Csymbol_address s ->
-      add_used_symbol s ;
-      `	DWORD	{emit_symbol s}\n`
-  | Clabel_address lbl ->
-      `	DWORD	{emit_data_label lbl}\n`
-  | Cstring s ->
-      emit_bytes_directive "	BYTE	" s
-  | Cskip n ->
-      if n > 0 then `	BYTE	{emit_int n} DUP (?)\n`
-  | Calign n ->
-      emit_align n
-
-let data l =
-  `	.DATA\n`;
-  List.iter emit_item l
-
-(* Beginning / end of an assembly file *)
-
-let begin_assembly() =
-  float_constants := [];
-  `.386\n`;
-  `	.MODEL	FLAT\n\n`;
-  `	EXTERN _caml_young_ptr: DWORD\n`;
-  `	EXTERN _caml_young_limit: DWORD\n`;
-  `	EXTERN _caml_exception_pointer: DWORD\n`;
-  `	EXTERN _caml_extra_params: DWORD\n`;
-  `	EXTERN _caml_call_gc: PROC\n`;
-  `	EXTERN _caml_c_call: PROC\n`;
-  `	EXTERN _caml_allocN: PROC\n`;
-  `	EXTERN _caml_alloc1: PROC\n`;
-  `	EXTERN _caml_alloc2: PROC\n`;
-  `	EXTERN _caml_alloc3: PROC\n`;
-  `	EXTERN _caml_ml_array_bound_error: PROC\n`;
-  `	EXTERN _caml_raise_exn: PROC\n`;
-  `	EXTERN _caml_reraise_exn: PROC\n`;
-  `	.DATA\n`;
-  let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
-  add_def_symbol lbl_begin;
-  `	PUBLIC	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin}	LABEL	DWORD\n`;
-  `	.CODE\n`;
-  let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
-  add_def_symbol lbl_begin;
-  `	PUBLIC	{emit_symbol lbl_begin}\n`;
-  `{emit_symbol lbl_begin}	LABEL	DWORD\n`
-
-let end_assembly() =
-  if !float_constants <> [] then begin
-    `	.DATA\n`;
-    List.iter emit_float_constant !float_constants;
-  end;
-  `	.CODE\n`;
-  let lbl_end = Compilenv.make_symbol (Some "code_end") in
-  add_def_symbol lbl_end;
-  `	PUBLIC	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end}	LABEL	DWORD\n`;
-  `	.DATA\n`;
-  let lbl_end = Compilenv.make_symbol (Some "data_end") in
-  add_def_symbol lbl_end;
-  `	PUBLIC	{emit_symbol lbl_end}\n`;
-  `{emit_symbol lbl_end}	LABEL	DWORD\n`;
-  `	DWORD	0\n`;
-  let lbl = Compilenv.make_symbol (Some "frametable") in
-  add_def_symbol lbl;
-  `	PUBLIC	{emit_symbol lbl}\n`;
-  `{emit_symbol lbl}`;
-  emit_frames
-    { efa_label = (fun l -> `	DWORD	{emit_label l}\n`);
-      efa_16 = (fun n -> `	WORD	{emit_int n}\n`);
-      efa_32 = (fun n -> `	DWORD	{emit_int32 n}\n`);
-      efa_word = (fun n -> `	DWORD	{emit_int n}\n`);
-      efa_align = emit_align;
-      efa_label_rel = (fun lbl ofs ->
-                           `	DWORD	{emit_label lbl} - THIS BYTE + {emit_int32 ofs}\n`);
-      efa_def_label = (fun l -> `{emit_label l}	LABEL	DWORD\n`);
-      efa_string = (fun s -> emit_bytes_directive  "	BYTE	" (s ^ "\000")) };
-  `\n;External functions\n\n`;
-  StringSet.iter
-    (fun s ->
-      if not (StringSet.mem s !symbols_defined) then
-        `	EXTERN	{emit_symbol s}: PROC\n`)
-    !symbols_used;
-  symbols_used := StringSet.empty;
-  symbols_defined := StringSet.empty;
-  `END\n`
diff --git a/asmcomp/i386/proc.ml b/asmcomp/i386/proc.ml
index 0b010d24..b7e17843 100644
--- a/asmcomp/i386/proc.ml
+++ b/asmcomp/i386/proc.ml
@@ -1,14 +1,18 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+# 2 "asmcomp/i386/proc.ml"
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the Intel 386 processor *)
 
@@ -53,8 +57,7 @@ let num_register_classes = 2
 
 let register_class r =
   match r.typ with
-    Int -> 0
-  | Addr -> 0
+  | Val | Int | Addr -> 0
   | Float -> 1
 
 let num_available_registers = [| 7; 0 |]
@@ -87,7 +90,6 @@ let phys_reg n =
 let eax = phys_reg 0
 let ecx = phys_reg 2
 let edx = phys_reg 3
-let tos = phys_reg 100
 
 let stack_slot slot ty =
   Reg.at_location ty (Stack slot)
@@ -117,7 +119,7 @@ let calling_conventions first_int last_int first_float last_float make_stack
   let ofs = ref (-64) in
   for i = 0 to Array.length arg - 1 do
     match arg.(i).typ with
-      Int | Addr as ty ->
+      Val | Int | Addr as ty ->
         if !int <= last_int then begin
           loc.(i) <- phys_reg !int;
           incr int
@@ -140,17 +142,22 @@ let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
 let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
 
+(* Six arguments in integer registers plus eight in global memory. *)
+let max_arguments_for_tailcalls = 14
+
 let loc_arguments arg =
   calling_conventions 0 5 100 99 outgoing arg
 let loc_parameters arg =
   let (loc, ofs) = calling_conventions 0 5 100 99 incoming arg in loc
 let loc_results res =
   let (loc, ofs) = calling_conventions 0 5 100 100 not_supported res in loc
-let extcall_use_push = true
 let loc_external_arguments arg =
   fatal_error "Proc.loc_external_arguments"
 let loc_external_results res =
-  let (loc, ofs) = calling_conventions 0 0 100 100 not_supported res in loc
+  match res with
+  | [|{typ=Int};{typ=Int}|] -> [|eax; edx|]
+  | _ ->
+      let (loc, ofs) = calling_conventions 0 0 100 100 not_supported res in loc
 
 let loc_exn_bucket = eax
 
@@ -216,12 +223,6 @@ let contains_calls = ref false
 (* Calling the assembler *)
 
 let assemble_file infile outfile =
-  if masm then
-    Ccomp.command (Config.asm ^
-                   Filename.quote outfile ^ " " ^ Filename.quote infile ^
-                   (if !Clflags.verbose then "" else ">NUL"))
-  else
-    Ccomp.command (Config.asm ^ " -o " ^
-                   Filename.quote outfile ^ " " ^ Filename.quote infile)
+  X86_proc.assemble_file infile outfile
 
 let init () = ()
diff --git a/asmcomp/i386/reload.ml b/asmcomp/i386/reload.ml
index bc1b08f5..67f3e571 100644
--- a/asmcomp/i386/reload.ml
+++ b/asmcomp/i386/reload.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Cmm
 open Arch
diff --git a/asmcomp/i386/scheduling.ml b/asmcomp/i386/scheduling.ml
index b166a05a..05627b04 100644
--- a/asmcomp/i386/scheduling.ml
+++ b/asmcomp/i386/scheduling.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 let () = let module M = Schedgen in () (* to create a dependency *)
 
diff --git a/asmcomp/i386/selection.ml b/asmcomp/i386/selection.ml
index 10d2d40e..f37781d2 100644
--- a/asmcomp/i386/selection.ml
+++ b/asmcomp/i386/selection.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1997 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1997 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction selection for the Intel x86 *)
 
@@ -31,11 +34,11 @@ let rec select_addr exp =
   match exp with
     Cconst_symbol s ->
       (Asymbol s, 0)
-  | Cop((Caddi | 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 | Csuba), [arg; Cconst_int m]) ->
+  | Cop(Csubi, [arg; Cconst_int m]) ->
       let (a, n) = select_addr arg in (a, n - m)
-  | Cop((Caddi | 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)]) ->
       begin match select_addr arg with
@@ -52,7 +55,7 @@ let rec select_addr exp =
         (Alinear e, n) -> (Ascale(e, mult), n * mult)
       | _ -> (Alinear exp, 0)
       end
-  | Cop((Caddi | Cadda), [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)
@@ -196,8 +199,8 @@ method! select_store is_assign addr exp =
 method! select_operation op args =
   match op with
   (* Recognize the LEA instruction *)
-    Caddi | Cadda | Csubi | Csuba ->
-      begin match self#select_addressing Word (Cop(op, args)) with
+    Caddi | Caddv | Cadda | Csubi ->
+      begin match self#select_addressing Word_int (Cop(op, args)) with
         (Iindexed d, _) -> super#select_operation op args
       | (Iindexed2 0, _) -> super#select_operation op args
       | (addr, arg) -> (Ispecific(Ilea addr), [arg])
@@ -215,11 +218,11 @@ method! select_operation op args =
       self#select_floatarith Idivf (Ispecific Idivfrev) Ifloatdiv Ifloatdivrev
                              args
   (* Recognize store instructions *)
-  | Cstore Word ->
+  | Cstore ((Word_int | Word_val) as chunk, _) ->
       begin match args with
         [loc; Cop(Caddi, [Cop(Cload _, [loc']); Cconst_int n])]
         when loc = loc' ->
-          let (addr, arg) = self#select_addressing Word loc in
+          let (addr, arg) = self#select_addressing chunk loc in
           (Ispecific(Ioffset_loc(n, addr)), [arg])
       | _ ->
           super#select_operation op args
@@ -280,8 +283,8 @@ 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, [loc]) ->
-      let (addr, arg) = self#select_addressing Word loc in
+  | 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]) ->
       let (addr, arg) = self#select_addressing Double_u loc in
diff --git a/asmcomp/import_approx.ml b/asmcomp/import_approx.ml
new file mode 100644
index 00000000..34a0b85f
--- /dev/null
+++ b/asmcomp/import_approx.ml
@@ -0,0 +1,175 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+module A = Simple_value_approx
+
+let import_set_of_closures =
+  let import_function_declarations (clos : Flambda.function_declarations)
+        : Flambda.function_declarations =
+    (* CR-soon mshinwell for pchambart: Do we still need to do this
+       rewriting?  I'm wondering if maybe we don't have to any more. *)
+    let sym_to_fun_var_map (clos : Flambda.function_declarations) =
+      Variable.Map.fold (fun fun_var _ acc ->
+           let closure_id = Closure_id.wrap fun_var in
+           let sym = Compilenv.closure_symbol closure_id in
+           Symbol.Map.add sym fun_var acc)
+        clos.funs Symbol.Map.empty
+    in
+    let sym_map = sym_to_fun_var_map clos in
+    let f_named (named : Flambda.named) =
+      match named with
+      | Symbol sym ->
+        begin try Flambda.Expr (Var (Symbol.Map.find sym sym_map)) with
+        | Not_found -> named
+        end
+      | named -> named
+    in
+    let funs =
+      Variable.Map.map (fun (function_decl : Flambda.function_declaration) ->
+          let body =
+            Flambda_iterators.map_toplevel_named f_named function_decl.body
+          in
+          Flambda.create_function_declaration ~params:function_decl.params
+            ~body ~stub:function_decl.stub ~dbg:function_decl.dbg
+            ~inline:function_decl.inline
+            ~specialise:function_decl.specialise
+            ~is_a_functor:function_decl.is_a_functor)
+        clos.funs
+    in
+    Flambda.update_function_declarations clos ~funs
+  in
+  let aux 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
+      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
+    in
+    import_function_declarations function_declarations
+  in
+  Set_of_closures_id.Tbl.memoize Compilenv.imported_sets_of_closures_table aux
+
+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 =
+    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
+    with
+    | exception Not_found ->
+      Misc.fatal_errorf "Set of closures ID %a not found in invariant_params \
+          (when importing [%a: %s])"
+        Set_of_closures_id.print set_of_closures_id
+        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
+  in
+  match Export_info.find_description ex_info ex with
+  | exception Not_found -> A.value_unknown Other
+  | Value_int i -> A.value_int i
+  | Value_char c -> A.value_char c
+  | Value_constptr i -> A.value_constptr i
+  | Value_float f -> A.value_float f
+  | Value_float_array float_array ->
+    begin match float_array.contents with
+    | Unknown_or_mutable ->
+      A.value_mutable_float_array ~size:float_array.size
+    | Contents contents ->
+      A.value_immutable_float_array contents
+    end
+  | Export_info.Value_boxed_int (t, i) -> A.value_boxed_int t i
+  | Value_string { size; contents } ->
+    let contents =
+      match contents with
+      | Unknown_or_mutable -> None
+      | Contents contents -> Some contents
+    in
+    A.value_string size contents
+  | Value_mutable_block _ -> A.value_unknown Other
+  | Value_block (tag, fields) ->
+    A.value_block tag (Array.map import_approx fields)
+  | Value_closure { closure_id;
+        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:(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
+  | 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
+
+and import_approx (ap : Export_info.approx) =
+  match ap with
+  | Value_unknown -> A.value_unknown Other
+  | Value_id ex -> A.value_extern ex
+  | Value_symbol sym -> A.value_symbol sym
+
+let import_symbol sym =
+  if Compilenv.is_predefined_exception sym then
+    A.value_unknown Other
+  else
+    let symbol_id_map =
+      let global = Symbol.compilation_unit sym in
+      (Compilenv.approx_for_global global).symbol_id
+    in
+    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
+
+(* Note for code reviewers: Observe that [really_import] iterates until
+   the approximation description is fully resolved (or a necessary .cmx
+   file is missing). *)
+
+let rec really_import (approx : A.descr) =
+  match approx with
+  | Value_extern ex -> really_import_ex ex
+  | Value_symbol sym -> really_import_symbol sym
+  | r -> r
+
+and really_import_ex ex =
+  really_import (import_ex ex).descr
+
+and really_import_symbol sym =
+  really_import (import_symbol sym).descr
+
+let really_import_approx (approx : Simple_value_approx.t) =
+  A.replace_description approx (really_import approx.descr)
diff --git a/asmcomp/import_approx.mli b/asmcomp/import_approx.mli
new file mode 100644
index 00000000..23d9d294
--- /dev/null
+++ b/asmcomp/import_approx.mli
@@ -0,0 +1,34 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-9-30-40-41-42"]
+
+(** Create simple value approximations from the export information in
+    .cmx files. *)
+
+(** Given an approximation description, load .cmx files (possibly more
+    than one) until the description is fully resolved.  If a necessary .cmx
+    file cannot be found, "unresolved" will be returned. *)
+val really_import : Simple_value_approx.descr -> Simple_value_approx.descr
+
+(** Maps the description of the given approximation through [really_import]. *)
+val really_import_approx : Simple_value_approx.t -> Simple_value_approx.t
+
+(** Read and convert the approximation of a given symbol from the
+    relevant .cmx file.  Unlike the "really_" functions, this does not
+    continue to load .cmx files until the approximation is fully
+    resolved. *)
+val import_symbol : Symbol.t -> Simple_value_approx.t
diff --git a/asmcomp/interf.ml b/asmcomp/interf.ml
index 2d541eee..2376aa21 100644
--- a/asmcomp/interf.ml
+++ b/asmcomp/interf.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Construction of the interference graph.
    Annotate pseudoregs with interference lists and preference lists. *)
diff --git a/asmcomp/interf.mli b/asmcomp/interf.mli
index a9b0b630..13549a1d 100644
--- a/asmcomp/interf.mli
+++ b/asmcomp/interf.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Construction of the interference graph.
    Annotate pseudoregs with interference lists and preference lists. *)
diff --git a/asmcomp/linearize.ml b/asmcomp/linearize.ml
index 64678c1d..7cf99fe1 100644
--- a/asmcomp/linearize.ml
+++ b/asmcomp/linearize.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Transformation of Mach code into a list of pseudo-instructions. *)
 
diff --git a/asmcomp/linearize.mli b/asmcomp/linearize.mli
index 2996a29b..6d6d01cb 100644
--- a/asmcomp/linearize.mli
+++ b/asmcomp/linearize.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Transformation of Mach code into a list of pseudo-instructions. *)
 
diff --git a/asmcomp/liveness.ml b/asmcomp/liveness.ml
index 2ef322ef..1ce943ab 100644
--- a/asmcomp/liveness.ml
+++ b/asmcomp/liveness.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Liveness analysis.
    Annotate mach code with the set of regs live at each point. *)
diff --git a/asmcomp/liveness.mli b/asmcomp/liveness.mli
index ed2f1a8a..7a8fae62 100644
--- a/asmcomp/liveness.mli
+++ b/asmcomp/liveness.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Liveness analysis.
    Annotate mach code with the set of regs live at each point. *)
diff --git a/asmcomp/mach.ml b/asmcomp/mach.ml
index 3a717476..0770b988 100644
--- a/asmcomp/mach.ml
+++ b/asmcomp/mach.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Representation of machine code by sequences of pseudoinstructions *)
 
@@ -36,7 +39,7 @@ type operation =
   | Ispill
   | Ireload
   | Iconst_int of nativeint
-  | Iconst_float of float
+  | Iconst_float of int64
   | Iconst_symbol of string
   | Iconst_blockheader of nativeint
   | Icall_ind
diff --git a/asmcomp/mach.mli b/asmcomp/mach.mli
index 618e5e4c..d3d912d2 100644
--- a/asmcomp/mach.mli
+++ b/asmcomp/mach.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Representation of machine code by sequences of pseudoinstructions *)
 
@@ -36,7 +39,7 @@ type operation =
   | Ispill
   | Ireload
   | Iconst_int of nativeint
-  | Iconst_float of float
+  | Iconst_float of int64
   | Iconst_symbol of string
   | Iconst_blockheader of nativeint
   | Icall_ind
diff --git a/asmcomp/power/CSE.ml b/asmcomp/power/CSE.ml
index ec10d2df..3106bdd8 100644
--- a/asmcomp/power/CSE.ml
+++ b/asmcomp/power/CSE.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* CSE for the PowerPC *)
 
diff --git a/asmcomp/power/NOTES.md b/asmcomp/power/NOTES.md
new file mode 100644
index 00000000..d54c0869
--- /dev/null
+++ b/asmcomp/power/NOTES.md
@@ -0,0 +1,26 @@
+# Supported platforms
+
+IBM POWER and Freescale (nee Motorola) PowerPC processors, in three flavors:
+* 32 bits, ELF ABI: Debian's `powerpc`
+* 64 bits big-endian, ELF ABI v1: Debian's `powerpc`
+* 64 bits little-endian, ELF ABI v2: Debian's `ppc64el`
+
+No longer supported: AIX and MacOS X.
+
+# Reference documents
+
+* Instruction set architecture:
+  _PowerPC User Instruction Set Architecture_,
+  book 1 of _PowerPC Architecture Book_
+  (http://www.ibm.com/developerworks/systems/library/es-archguide-v2.html).
+* ELF ABI 32 bits:
+  _System V Application Binary Interface, PowerPC Processor Supplement_
+* ELF ABI 64 bits version 1:
+  _64-bit PowerPC ELF Application Binary Interface Supplement_
+  (http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html)
+* ELF ABI 64 bits version 2:
+   _Power Architecture 64-bit ELF V2 ABI Specification,
+    OpenPOWER ABI for Linux Supplement_
+  (http://openpowerfoundation.org/technical/technical-resources/technical-specifications/)
+* _The PowerPC Compiler Writer's Guide_, Warthman Associates, 1996.
+  (PDF available from various sources on the Web.)
diff --git a/asmcomp/power/arch.ml b/asmcomp/power/arch.ml
index cbeba916..2e7d19ca 100644
--- a/asmcomp/power/arch.ml
+++ b/asmcomp/power/arch.ml
@@ -1,22 +1,45 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Specific operations for the PowerPC processor *)
 
 open Format
 
+let ppc64 =
+  match Config.model with
+  | "ppc" -> false
+  | "ppc64" | "ppc64le" -> true
+  | _ -> assert false
+
+type abi = ELF32 | ELF64v1 | ELF64v2
+
+let abi =
+  match Config.model with
+  | "ppc" -> ELF32
+  | "ppc64" -> ELF64v1
+  | "ppc64le" -> ELF64v2
+  | _ -> assert false
+
 (* Machine-specific command-line options *)
 
-let command_line_options = []
+let big_toc = ref false
+
+let command_line_options = [
+  "-flarge-toc", Arg.Set big_toc,
+     " Support TOC (table of contents) greater than 64 kbytes"
+]
 
 (* Specific operations *)
 
@@ -34,16 +57,18 @@ type addressing_mode =
 
 (* Sizes, endianness *)
 
-let big_endian = true
-
-let ppc64 =
-  match Config.model with "ppc64" -> true | _ -> false
+let big_endian =
+  match Config.model with
+  | "ppc" -> true
+  | "ppc64" -> true
+  | "ppc64le" -> false
+  | _ -> assert false
 
 let size_addr = if ppc64 then 8 else 4
 let size_int = size_addr
 let size_float = 8
 
-let allow_unaligned_access = false
+let allow_unaligned_access = true
 
 (* Behavior of division *)
 
diff --git a/asmcomp/power/emit.mlp b/asmcomp/power/emit.mlp
index 43440852..c9b26e85 100644
--- a/asmcomp/power/emit.mlp
+++ b/asmcomp/power/emit.mlp
@@ -1,20 +1,20 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Emission of PowerPC assembly code *)
 
-module StringSet =
-  Set.Make(struct type t = string let compare (x:t) y = compare x y end)
-
 open Misc
 open Cmm
 open Arch
@@ -24,42 +24,60 @@ open Mach
 open Linearize
 open Emitaux
 
+(* Reserved space at bottom of stack *)
+
+let reserved_stack_space =
+  match abi with
+  | ELF32 -> 0
+  | ELF64v1 -> 48
+  | ELF64v2 -> 32
+
 (* Layout of the stack.  The stack is kept 16-aligned. *)
 
 let stack_offset = ref 0
 
 let frame_size () =
   let size =
+    reserved_stack_space +
     !stack_offset +                     (* Trap frame, outgoing parameters *)
     size_int * num_stack_slots.(0) +    (* Local int variables *)
     size_float * num_stack_slots.(1) +  (* Local float variables *)
-    (if !contains_calls then size_int else 0) in (* The return address *)
+    (if !contains_calls && abi = ELF32 then size_int else 0) in
+                                        (* The return address *)
   Misc.align size 16
 
 let slot_offset loc cls =
   match loc with
     Local n ->
-      if cls = 0
-      then !stack_offset + num_stack_slots.(1) * size_float + n * size_int
-      else !stack_offset + n * size_float
-  | Incoming n -> frame_size() + n
-  | Outgoing n -> n
+      reserved_stack_space + !stack_offset +
+      (if cls = 0 then num_stack_slots.(1) * size_float + n * size_int
+                  else n * size_float)
+  | Incoming n -> frame_size() + reserved_stack_space + n
+  | Outgoing n -> reserved_stack_space + n
+
+let retaddr_offset () =
+  match abi with
+  | ELF32 -> frame_size() - size_addr
+  | ELF64v1 | ELF64v2 -> frame_size() + 16
+
+let toc_save_offset () =
+  match abi with
+  | ELF32 -> assert false
+  | ELF64v1 | ELF64v2 -> frame_size() + 8
+
+let (trap_size, trap_handler_offset, trap_previous_offset) =
+  match abi with
+  | ELF32 -> (16, 0, 4)
+  | ELF64v1 -> (32, 56, 64)
+  | ELF64v2 -> (32, 40, 48)
 
 (* Output a symbol *)
 
-let emit_symbol =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" -> (fun s -> Emitaux.emit_symbol '.' s)
-  | "rhapsody"    -> (fun s -> emit_char '_'; Emitaux.emit_symbol '$' s)
-  | _ -> assert false
+let emit_symbol s = Emitaux.emit_symbol '.' s
 
 (* Output a label *)
 
-let label_prefix =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" -> ".L"
-  | "rhapsody" -> "L"
-  | _ -> assert false
+let label_prefix = ".L"
 
 let emit_label lbl =
   emit_string label_prefix; emit_int lbl
@@ -69,23 +87,23 @@ let emit_data_label lbl =
 
 (* Section switching *)
 
-let data_space =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" -> "	.section \".data\"\n"
-  | "rhapsody"    -> "	.data\n"
-  | _ -> assert false
-
 let code_space =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" -> "	.section \".text\"\n"
-  | "rhapsody"    -> "	.text\n"
-  | _ -> assert false
+  "	.section \".text\"\n"
+
+let function_descr_space =
+  match abi with
+  | ELF32 -> code_space
+  | ELF64v1 -> "	.section \".opd\",\"aw\"\n"
+  | ELF64v2 -> code_space
+
+let data_space =
+  "	.section \".data\"\n"
 
 let rodata_space =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" -> "	.section \".rodata\"\n"
-  | "rhapsody"    -> "	.const\n"
-  | _ -> assert false
+  "	.section \".rodata\"\n"
+
+let toc_space =
+  " .section \".toc\",\"aw\"\n"
 
 (* Names of instructions that differ in 32 and 64-bit modes *)
 
@@ -95,51 +113,57 @@ let lwa = if ppc64 then "lwa" else "lwz"
 let cmpg = if ppc64 then "cmpd" else "cmpw"
 let cmplg = if ppc64 then "cmpld" else "cmplw"
 let datag = if ppc64 then ".quad" else ".long"
-let aligng = if ppc64 then 3 else 2
 let mullg = if ppc64 then "mulld" else "mullw"
 let divg = if ppc64 then "divd" else "divw"
 let tglle = if ppc64 then "tdlle" else "twlle"
-let sragi = if ppc64 then "sradi" else "srawi"
 let slgi = if ppc64 then "sldi" else "slwi"
-let fctigz = if ppc64 then "fctidz" else "fctiwz"
+
+(* Output a processor register *)
+
+let emit_gpr = emit_int
 
 (* Output a pseudo-register *)
 
 let emit_reg r =
   match r.loc with
-    Reg r -> emit_string (register_name r)
+  | Reg r -> emit_string (register_name r)
   | _ -> fatal_error "Emit.emit_reg"
 
-let use_full_regnames =
-  Config.system = "rhapsody"
-
-let emit_gpr r =
-  if use_full_regnames then emit_char 'r';
-  emit_int r
-
-let emit_fpr r =
-  if use_full_regnames then emit_char 'f';
-  emit_int r
-
-let emit_ccr r =
-  if use_full_regnames then emit_string "cr";
-  emit_int r
-
 (* Output a stack reference *)
 
 let emit_stack r =
   match r.loc with
-    Stack s ->
-      let ofs = slot_offset s (register_class r) in `{emit_int ofs}({emit_gpr 1})`
+  | Stack s ->
+      let ofs = slot_offset s (register_class r) in `{emit_int ofs}(1)`
   | _ -> fatal_error "Emit.emit_stack"
 
+(* Output the name of a symbol plus an optional offset *)
+
+let emit_symbol_offset (s, d) =
+  emit_symbol s;
+  if d > 0 then `+`;
+  if d <> 0 then emit_int d
+
 (* Split a 32-bit integer constants in two 16-bit halves *)
 
-let low n = n land 0xFFFF
-let high n = n asr 16
+let low_high_u n = (n land 0xFFFF, n asr 16)
+  (* unsigned low half, for use with "ori" *)
 
-let nativelow n = Nativeint.to_int n land 0xFFFF
-let nativehigh n = Nativeint.to_int (Nativeint.shift_right n 16)
+let native_low_high_u n =
+  (Nativeint.(to_int (logand n 0xFFFFn)),
+   Nativeint.(to_int (shift_right n 16)))
+  (* unsigned low half, for use with "ori" *)
+
+let low_high_s n =
+  let lo = ((n + 0x8000) land 0xFFFF) - 0x8000 in
+  (lo, (n - lo) asr 16)
+  (* signed low half, for use with "addi" *)
+
+let native_low_high_s n =
+  let lo = Nativeint.(sub (logand (add n 0x8000n) 0xFFFFn) 0x8000n) in
+  (Nativeint.to_int lo,
+   Nativeint.(to_int (shift_right (sub n lo) 16)))
+  (* signed low half, for use with "addi" *)
 
 let is_immediate n =
   n <= 32767 && n >= -32768
@@ -147,47 +171,83 @@ let is_immediate n =
 let is_native_immediate n =
   n <= 32767n && n >= -32768n
 
+(* Record TOC entries *)
+
+type tocentry =
+  | TocSym of string
+  | TocLabel of int
+  | TocInt of nativeint
+  | TocFloat of int64
+
+let tocref_entries : (tocentry, label) Hashtbl.t = Hashtbl.create 64
+
+let emit_tocentry = function
+  | TocSym s -> emit_symbol s
+  | TocInt i -> emit_nativeint i
+  | TocFloat f -> emit_printf "0x%Lx # %.12g" f (Int64.float_of_bits f)
+  | TocLabel lbl -> emit_label lbl
+
+let label_for_tocref entry =
+  try
+    Hashtbl.find tocref_entries entry
+  with Not_found ->
+    let lbl = new_label() in
+    Hashtbl.add tocref_entries entry lbl;
+    lbl
+
+let emit_toctable () =
+  Hashtbl.iter
+    (fun entry lbl ->
+      `{emit_label lbl}:	.quad	{emit_tocentry entry}\n`)
+    tocref_entries
+
+(* Emit a load from a TOC entry *)
+
+let emit_tocload emit_dest dest entry =
+  let lbl = label_for_tocref entry in
+  if !big_toc || !Clflags.for_package <> None then begin
+    `	addis	{emit_dest dest}, 2, {emit_label lbl}@toc@ha\n`;
+    `	ld	{emit_dest dest}, {emit_label lbl}@toc@l({emit_dest dest}) # {emit_tocentry entry}\n`
+  end else begin
+    `	ld	{emit_dest dest}, {emit_label lbl}@toc(2) # {emit_tocentry entry}\n`
+  end
+
 (* Output a "upper 16 bits" or "lower 16 bits" operator. *)
 
 let emit_upper emit_fun arg =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" ->
-      emit_fun arg; emit_string "@ha"
-  | "rhapsody" ->
-      emit_string "ha16("; emit_fun arg; emit_string ")"
-  | _ -> assert false
+  emit_fun arg; emit_string "@ha"
 
 let emit_lower emit_fun arg =
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" ->
-      emit_fun arg; emit_string "@l"
-  | "rhapsody" ->
-      emit_string "lo16("; emit_fun arg; emit_string ")"
-  | _ -> assert false
+  emit_fun arg; emit_string "@l"
 
 (* Output a load or store operation *)
 
-let emit_symbol_offset (s, d) =
-  emit_symbol s;
-  if d > 0 then `+`;
-  if d <> 0 then emit_int d
-
 let valid_offset instr ofs =
-  ofs land 3 = 0 || (instr <> "ld" && instr <> "std")
+  ofs land 3 = 0 || (instr <> "ld" && instr <> "std" && instr <> "lwa")
 
 let emit_load_store instr addressing_mode addr n arg =
   match addressing_mode with
-    Ibased(s, d) ->
-      `	addis	{emit_gpr 11}, 0, {emit_upper emit_symbol_offset (s,d)}\n`;
-      `	{emit_string instr}	{emit_reg arg}, {emit_lower emit_symbol_offset (s,d)}({emit_gpr 11})\n`
+  | Ibased(s, d) ->
+      begin match abi with
+      | ELF32 ->
+        `	addis	11, 0, {emit_upper emit_symbol_offset (s,d)}\n`;
+        `	{emit_string instr}	{emit_reg arg}, {emit_lower emit_symbol_offset (s,d)}(11)\n`
+      | ELF64v1 | ELF64v2 ->
+        emit_tocload emit_gpr 11 (TocSym s);
+        let (lo, hi) = low_high_s d in
+        if hi <> 0 then
+          `	addis	11, 11, {emit_int hi}\n`;
+        `	{emit_string instr}	{emit_reg arg}, {emit_int lo}(11)\n`
+      end
   | Iindexed ofs ->
       if is_immediate ofs && valid_offset instr ofs then
         `	{emit_string instr}	{emit_reg arg}, {emit_int ofs}({emit_reg addr.(n)})\n`
       else begin
-        `	lis	{emit_gpr 0}, {emit_int(high ofs)}\n`;
-        if low ofs <> 0 then
-          `	ori	{emit_gpr 0}, {emit_gpr 0}, {emit_int(low ofs)}\n`;
-        `	{emit_string instr}x	{emit_reg arg}, {emit_reg addr.(n)}, {emit_gpr 0}\n`
+        let (lo, hi) = low_high_u ofs in
+        `	addis	0, 0, {emit_int hi}\n`;
+        if lo <> 0 then
+          `	ori	0, 0, {emit_int lo}\n`;
+        `	{emit_string instr}x	{emit_reg arg}, {emit_reg addr.(n)}, 0\n`
       end
   | Iindexed2 ->
       `	{emit_string instr}x	{emit_reg arg}, {emit_reg addr.(n)}, {emit_reg addr.(n+1)}\n`
@@ -195,18 +255,52 @@ let emit_load_store instr addressing_mode addr n arg =
 (* After a comparison, extract the result as 0 or 1 *)
 
 let emit_set_comp cmp res =
-  `	mfcr	{emit_gpr 0}\n`;
+  `	mfcr	0\n`;
   let bitnum =
     match cmp with
       Ceq | Cne -> 2
     | Cgt | Cle -> 1
     | Clt | Cge -> 0 in
-`	rlwinm	{emit_reg res}, {emit_gpr 0}, {emit_int(bitnum+1)}, 31, 31\n`;
+`	rlwinm	{emit_reg res}, 0, {emit_int(bitnum+1)}, 31, 31\n`;
   begin match cmp with
     Cne | Cle | Cge -> `	xori	{emit_reg res}, {emit_reg res}, 1\n`
   | _ -> ()
   end
 
+(* Free the stack frame *)
+
+let emit_free_frame () =
+  let n = frame_size() in
+  if n > 0 then
+    `	addi	1, 1, {emit_int n}\n`
+
+(* Emit a "bl" instruction to a given symbol *)
+
+let emit_call s =
+  match abi with
+  | ELF32 when !Clflags.dlcode || !Clflags.pic_code ->
+    `	bl	{emit_symbol s}@plt\n`
+  | _ ->
+    `	bl	{emit_symbol s}\n`
+
+(* Add a nop after a "bl" call for ELF64 *)
+
+let emit_call_nop () =
+  match abi with
+  | ELF32 -> ()
+  | ELF64v1 | ELF64v2 -> `	nop	\n`
+
+(* Reload the TOC register r2 from the value saved on the stack *)
+
+let emit_reload_toc () =
+  `	ld	2, {emit_int (toc_save_offset())}(1)\n`
+
+(* Adjust stack_offset and emit corresponding CFI directive *)
+
+let adjust_stack_offset delta =
+  stack_offset := !stack_offset + delta;
+  cfi_adjust_cfa_offset delta
+
 (* Record live pointers at call points *)
 
 let record_frame live dbg =
@@ -214,10 +308,12 @@ let record_frame live dbg =
   let live_offset = ref [] in
   Reg.Set.iter
     (function
-        {typ = Addr; loc = Reg r} ->
-          live_offset := (r lsl 1) + 1 :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
+      | {typ = Val; loc = Reg r} ->
+          live_offset := ((r lsl 1) + 1) :: !live_offset
+      | {typ = Val; loc = Stack s} as reg ->
           live_offset := slot_offset s (register_class reg) :: !live_offset
+      | {typ = Addr} as r ->
+          Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
   frame_descriptors :=
@@ -227,23 +323,16 @@ let record_frame live dbg =
       fd_debuginfo = dbg } :: !frame_descriptors;
   `{emit_label lbl}:\n`
 
-(* Record floating-point and large integer literals *)
+(* Record floating-point literals (for PPC32) *)
 
 let float_literals = ref ([] : (int64 * int) list)
-let int_literals = ref ([] : (nativeint * int) list)
-
-(* Record external C functions to be called in a position-independent way
-   (for MacOSX) *)
 
-let pic_externals = (Config.system = "rhapsody")
+(* Record jump tables (for PPC64).  In order to reduce the size of the TOC,
+   we concatenate all jumptables and emit them at the end of the compilation
+   unit. *)
 
-let external_functions = ref StringSet.empty
-
-let emit_external s =
-  `	.non_lazy_symbol_pointer\n`;
-  `L{emit_symbol s}$non_lazy_ptr:\n`;
-  `	.indirect_symbol {emit_symbol s}\n`;
-  `	{emit_string datag}	0\n`
+let jumptables = ref ([] : label list)  (* in reverse order *)
+let jumptables_lbl = ref (-1)
 
 (* Names for conditional branches after comparisons *)
 
@@ -303,11 +392,11 @@ let name_for_specific = function
 let function_name = ref ""
 (* Entry point for tail recursive calls *)
 let tailrec_entry_point = ref 0
-(* Names of functions defined in the current file *)
-let defined_functions = ref StringSet.empty
 (* Label of glue code for calling the GC *)
 let call_gc_label = ref 0
 
+(* Relaxation of branches that exceed the span of a relative branch. *)
+
 module BR = Branch_relaxation.Make (struct
   type distance = int
 
@@ -331,8 +420,21 @@ module BR = Branch_relaxation.Make (struct
 
   let offset_pc_at_branch = 1
 
+  let size =
+    match abi with
+    | ELF32 -> (fun a b c -> a)
+    | ELF64v1 -> (fun a b c -> b)
+    | ELF64v2 -> (fun a b c -> c)
+
+  let tocload_size() =
+    if !big_toc || !Clflags.for_package <> None then 2 else 1
+
   let load_store_size = function
-    | Ibased(s, d) -> 2
+    | Ibased(s, d) ->
+        if abi = ELF32 then 2 else begin
+          let (lo, hi) = low_high_s d in
+          tocload_size() + (if hi = 0 then 1 else 2)
+        end
     | Iindexed ofs -> if is_immediate ofs then 1 else 3
     | Iindexed2 -> 1
 
@@ -340,15 +442,23 @@ module BR = Branch_relaxation.Make (struct
     | Lend -> 0
     | Lop(Imove | Ispill | Ireload) -> 1
     | Lop(Iconst_int n | Iconst_blockheader n) ->
-      if is_native_immediate n then 1 else 2
-    | Lop(Iconst_float s) -> 2
-    | Lop(Iconst_symbol s) -> 2
-    | Lop(Icall_ind) -> 2
-    | Lop(Icall_imm s) -> 1
-    | Lop(Itailcall_ind) -> 5
-    | Lop(Itailcall_imm s) -> if s = !function_name then 1 else 4
-    | Lop(Iextcall(s, true)) -> 3
-    | Lop(Iextcall(s, false)) -> if pic_externals then 4 else 1
+      if is_native_immediate n then 1
+      else if (let (lo, hi) = native_low_high_s n in
+               hi >= -0x8000 && hi <= 0x7FFF) then 2
+      else if (let (lo, hi) = native_low_high_u n in
+               hi >= -0x8000 && hi <= 0x7FFF) then 2
+      else tocload_size()
+    | Lop(Iconst_float s) -> if abi = ELF32 then 2 else tocload_size()
+    | Lop(Iconst_symbol s) -> if abi = ELF32 then 2 else tocload_size()
+    | Lop(Icall_ind) -> size 2 5 4
+    | Lop(Icall_imm s) -> size 1 3 3
+    | Lop(Itailcall_ind) -> size 5 7 6
+    | Lop(Itailcall_imm s) ->
+        if s = !function_name
+        then 1
+        else size 4 (7 + tocload_size()) (6 + tocload_size())
+    | Lop(Iextcall(s, true)) -> size 3 (2 + tocload_size()) (2 + tocload_size())
+    | Lop(Iextcall(s, false)) -> size 1 2 2
     | Lop(Istackoffset n) -> 1
     | Lop(Iload(chunk, addr)) ->
       if chunk = Byte_signed
@@ -375,9 +485,9 @@ module BR = Branch_relaxation.Make (struct
       1 + (if lbl0 = None then 0 else 1)
         + (if lbl1 = None then 0 else 1)
         + (if lbl2 = None then 0 else 1)
-    | Lswitch jumptbl -> 8
-    | Lsetuptrap lbl -> 1
-    | Lpushtrap -> 4
+    | Lswitch jumptbl -> size 7 (5 + tocload_size()) (5 + tocload_size())
+    | Lsetuptrap lbl -> size 1 2 2
+    | Lpushtrap -> size 4 5 5
     | Lpoptrap -> 2
     | Lraise _ -> 6
 
@@ -392,22 +502,23 @@ end)
 
 (* Output the assembly code for an instruction *)
 
-let rec emit_instr i dslot =
+let emit_instr i =
+    emit_debug_info i.dbg;
     match i.desc with
-      Lend -> ()
+    | Lend -> ()
     | Lop(Imove | Ispill | Ireload) ->
         let src = i.arg.(0) and dst = i.res.(0) in
         if src.loc <> dst.loc then begin
            match (src, dst) with
-              {loc = Reg rs; typ = (Int | Addr)}, {loc = Reg rd} ->
+           |  {loc = Reg rs; typ = (Val | Int | Addr)}, {loc = Reg rd} ->
                 `	mr	{emit_reg dst}, {emit_reg src}\n`
             | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = Float} ->
                 `	fmr	{emit_reg dst}, {emit_reg src}\n`
-            | {loc = Reg rs; typ = (Int | Addr)}, {loc = Stack sd} ->
+            | {loc = Reg rs; typ = (Val | Int | Addr)}, {loc = Stack sd} ->
                 `	{emit_string stg}	{emit_reg src}, {emit_stack dst}\n`
             | {loc = Reg rs; typ = Float}, {loc = Stack sd} ->
                 `	stfd	{emit_reg src}, {emit_stack dst}\n`
-            | {loc = Stack ss; typ = (Int | Addr)}, {loc = Reg rd} ->
+            | {loc = Stack ss; typ = (Val | Int | Addr)}, {loc = Reg rd} ->
                 `	{emit_string lg}	{emit_reg dst}, {emit_stack src}\n`
             | {loc = Stack ss; typ = Float}, {loc = Reg rd} ->
                 `	lfd	{emit_reg dst}, {emit_stack src}\n`
@@ -417,93 +528,176 @@ let rec emit_instr i dslot =
     | Lop(Iconst_int n | Iconst_blockheader n) ->
         if is_native_immediate n then
           `	li	{emit_reg i.res.(0)}, {emit_nativeint n}\n`
-        else if n >= -0x8000_0000n && n <= 0x7FFF_FFFFn then begin
-          `	lis	{emit_reg i.res.(0)}, {emit_int(nativehigh n)}\n`;
-          if nativelow n <> 0 then
-            `	ori	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, {emit_int(nativelow n)}\n`
+        else begin
+        (* Try a signed decomposition first, because the sequence
+           addis/addi is eligible for instruction fusion. *)
+        let (lo, hi) = native_low_high_s n in
+        if hi >= -0x8000 && hi <= 0x7FFF then begin
+          `	addis	{emit_reg i.res.(0)}, 0, {emit_int hi}\n`;
+          if lo <> 0 then
+          `	addi	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, {emit_int lo}\n`
+        end else begin
+        (* Now try an unsigned decomposition *)
+        let (lo, hi) = native_low_high_u n in
+        if hi >= -0x8000 && hi <= 0x7FFF then begin
+          `	addis	{emit_reg i.res.(0)}, 0, {emit_int hi}\n`;
+          if lo <> 0 then
+          `	ori	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, {emit_int lo}\n`
         end else begin
+          match abi with
+          | ELF32 -> assert false
+          | ELF64v1 | ELF64v2 ->
+              emit_tocload emit_reg i.res.(0) (TocInt n)
+        end end end
+    | Lop(Iconst_float f) ->
+        begin match abi with
+        | ELF32 ->
           let lbl = new_label() in
-          int_literals := (n, lbl) :: !int_literals;
-          `	addis	{emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
-          `	{emit_string lg}	{emit_reg i.res.(0)}, {emit_lower emit_label lbl}({emit_gpr 11})\n`
+          float_literals := (f, lbl) :: !float_literals;
+          `	addis	11, 0, {emit_upper emit_label lbl}\n`;
+          `	lfd	{emit_reg i.res.(0)}, {emit_lower emit_label lbl}(11)\n`
+        | ELF64v1 | ELF64v2 ->
+          let entry = TocFloat f in
+          let lbl = label_for_tocref entry in
+          if !big_toc || !Clflags.for_package <> None then begin
+            `	addis	11, 2, {emit_label lbl}@toc@ha\n`;
+            `	lfd	{emit_reg i.res.(0)}, {emit_label lbl}@toc@l(11) # {emit_tocentry entry}\n`
+          end else begin
+            `	lfd	{emit_reg i.res.(0)}, {emit_label lbl}@toc(2) # {emit_tocentry entry}\n`
+          end
         end
-    | Lop(Iconst_float f) ->
-        let lbl = new_label() in
-        float_literals := (Int64.bits_of_float f, lbl) :: !float_literals;
-        `	addis	{emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
-        `	lfd	{emit_reg i.res.(0)}, {emit_lower emit_label lbl}({emit_gpr 11})\n`
     | Lop(Iconst_symbol s) ->
-        `	addis	{emit_reg i.res.(0)}, 0, {emit_upper emit_symbol s}\n`;
-        `	addi	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, {emit_lower emit_symbol s}\n`
+        begin match abi with
+        | ELF32 ->
+          `	addis	{emit_reg i.res.(0)}, 0, {emit_upper emit_symbol s}\n`;
+          `	addi	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, {emit_lower emit_symbol s}\n`
+        | ELF64v1 | ELF64v2 ->
+          emit_tocload emit_reg i.res.(0) (TocSym s)
+        end
     | Lop(Icall_ind) ->
-        `	mtctr	{emit_reg i.arg.(0)}\n`;
-        `	bctrl\n`;
-        record_frame i.live i.dbg
+        begin match abi with
+        | ELF32 ->
+          `	mtctr	{emit_reg i.arg.(0)}\n`;
+          `	bctrl\n`;
+          record_frame i.live i.dbg
+        | ELF64v1 ->
+          `	ld	0, 0({emit_reg i.arg.(0)})\n`;  (* code pointer *)
+          `	mtctr	0\n`;
+          `	ld	2, 8({emit_reg i.arg.(0)})\n`;  (* TOC for callee *)
+          `	bctrl\n`;
+          record_frame i.live i.dbg;
+          emit_reload_toc()
+        | ELF64v2 ->
+          `	mtctr	{emit_reg i.arg.(0)}\n`;
+          `	mr	12, {emit_reg i.arg.(0)}\n`;  (* addr of fn in r12 *)
+          `	bctrl\n`;
+          record_frame i.live i.dbg;
+          emit_reload_toc()
+        end
     | Lop(Icall_imm s) ->
-        `	bl	{emit_symbol s}\n`;
-        record_frame i.live i.dbg
+        begin match abi with
+        | ELF32 ->
+            emit_call s;
+            record_frame i.live i.dbg
+        | ELF64v1 | ELF64v2 ->
+        (* For PPC64, we cannot just emit a "bl s; nop" sequence, because
+           of the following scenario:
+              - current function f1 calls f2 that has the same TOC
+              - f2 tailcalls f3 that has a different TOC
+           Because f1 and f2 have the same TOC, the linker inserted no
+           code in f1 to save and restore r2 around the call to f2.
+           Because f2 tailcalls f3, r2 will not be restored to f2's TOC
+           when f3 returns.  So, we're back into f1, with the wrong TOC in r2.
+           We have two options:
+             1- Turn the call into an indirect call, like we do for
+                Itailcall_imm.  Cost: 6 instructions.
+             2- Follow the "bl" with an instruction to restore r2
+                explicitly.  If the called function has a different TOC,
+                this instruction is redundant with those inserted
+                by the linker, but this is harmless.
+                Cost: 3 instructions if same TOC, 7 if different TOC.
+           Let's try option 2. *)
+            emit_call s;
+            record_frame i.live i.dbg;
+            `	nop\n`;
+            emit_reload_toc()
+        end
     | Lop(Itailcall_ind) ->
-        let n = frame_size() in
-        `	mtctr	{emit_reg i.arg.(0)}\n`;
+        begin match abi with
+        | ELF32 ->
+          `	mtctr	{emit_reg i.arg.(0)}\n`
+        | ELF64v1 ->
+          `	ld	0, 0({emit_reg i.arg.(0)})\n`;  (* code pointer *)
+          `	mtctr	0\n`;
+          `	ld	2, 8({emit_reg i.arg.(0)})\n`   (* TOC for callee *)
+        | ELF64v2 ->
+          `	mtctr	{emit_reg i.arg.(0)}\n`;
+          `	mr	12, {emit_reg i.arg.(0)}\n`   (* addr of fn in r12 *)
+        end;
         if !contains_calls then begin
-          `	{emit_string lg}	{emit_gpr 11}, {emit_int(n - size_addr)}({emit_gpr 1})\n`;
-          `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int n}\n`;
-          `	mtlr	{emit_gpr 11}\n`
-        end else begin
-          if n > 0 then
-            `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int n}\n`
+          `	{emit_string lg}	11, {emit_int(retaddr_offset())}(1)\n`;
+          `	mtlr	11\n`
         end;
+        emit_free_frame();
         `	bctr\n`
     | Lop(Itailcall_imm s) ->
         if s = !function_name then
           `	b	{emit_label !tailrec_entry_point}\n`
         else begin
-          let n = frame_size() in
+          begin match abi with
+          | ELF32 ->
+            ()
+          | ELF64v1 ->
+            emit_tocload emit_gpr 11 (TocSym s);
+            `	ld	0, 0(11)\n`;  (* code pointer *)
+            `	mtctr	0\n`;
+            `	ld	2, 8(11)\n`   (* TOC for callee *)
+          | ELF64v2 ->
+            emit_tocload emit_gpr 12 (TocSym s); (* addr of fn must be in r12 *)
+            `	mtctr	12\n`
+          end;
           if !contains_calls then begin
-            `	{emit_string lg}	{emit_gpr 11}, {emit_int(n - size_addr)}({emit_gpr 1})\n`;
-            `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int n}\n`;
-            `	mtlr	{emit_gpr 11}\n`
-          end else begin
-            if n > 0 then
-              `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int n}\n`
+            `	{emit_string lg}	11, {emit_int(retaddr_offset())}(1)\n`;
+            `	mtlr	11\n`
           end;
-          `	b	{emit_symbol s}\n`
+          emit_free_frame();
+          begin match abi with
+          | ELF32 ->
+            `	b	{emit_symbol s}\n`
+          | ELF64v1 | ELF64v2 ->
+            `	bctr\n`
+          end
         end
     | Lop(Iextcall(s, alloc)) ->
-        if alloc then begin
-          if pic_externals then begin
-            external_functions := StringSet.add s !external_functions;
-            `	addis	{emit_gpr 11}, 0, ha16(L{emit_symbol s}$non_lazy_ptr)\n`;
-            `	{emit_string lg}	{emit_gpr 11}, lo16(L{emit_symbol s}$non_lazy_ptr)({emit_gpr 11})\n`
-          end else begin
-            `	addis	{emit_gpr 11}, 0, {emit_upper emit_symbol s}\n`;
-            `	addi	{emit_gpr 11}, {emit_gpr 11}, {emit_lower emit_symbol s}\n`
-          end;
-          `	bl	{emit_symbol "caml_c_call"}\n`;
-          record_frame i.live i.dbg
+        if not alloc then begin
+          emit_call s;
+          emit_call_nop()
         end else begin
-          if pic_externals then begin
-            external_functions := StringSet.add s !external_functions;
-            `	addis	{emit_gpr 11}, 0, ha16(L{emit_symbol s}$non_lazy_ptr)\n`;
-            `	{emit_string lg}	{emit_gpr 11}, lo16(L{emit_symbol s}$non_lazy_ptr)({emit_gpr 11})\n`;
-            `	mtctr	{emit_gpr 11}\n`;
-            `	bctrl\n`
-          end else
-          `	bl	{emit_symbol s}\n`
+          match abi with
+          | ELF32 ->
+            `	addis	28, 0, {emit_upper emit_symbol s}\n`;
+            `	addi	28, 28, {emit_lower emit_symbol s}\n`;
+            emit_call "caml_c_call";
+            record_frame i.live i.dbg
+          | ELF64v1 | ELF64v2 ->
+            emit_tocload emit_gpr 28 (TocSym s);
+            emit_call "caml_c_call";
+            record_frame i.live i.dbg;
+            `	nop\n`
         end
     | Lop(Istackoffset n) ->
-        `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int (-n)}\n`;
-        stack_offset := !stack_offset + n
+        `	addi	1, 1, {emit_int (-n)}\n`;
+        adjust_stack_offset n
     | Lop(Iload(chunk, addr)) ->
         let loadinstr =
           match chunk with
-            Byte_unsigned -> "lbz"
+          | Byte_unsigned -> "lbz"
           | Byte_signed -> "lbz"
           | Sixteen_unsigned -> "lhz"
           | Sixteen_signed -> "lha"
           | Thirtytwo_unsigned -> "lwz"
           | Thirtytwo_signed -> if ppc64 then "lwa" else "lwz"
-	  | Word -> lg
+	  | Word_int | Word_val -> lg
           | Single -> "lfs"
           | Double | Double_u -> "lfd" in
         emit_load_store loadinstr addr i.arg 0 i.res.(0);
@@ -512,35 +706,37 @@ let rec emit_instr i dslot =
     | Lop(Istore(chunk, addr, _)) ->
         let storeinstr =
           match chunk with
-            Byte_unsigned | Byte_signed -> "stb"
+          | Byte_unsigned | Byte_signed -> "stb"
           | Sixteen_unsigned | Sixteen_signed -> "sth"
 	  | Thirtytwo_unsigned | Thirtytwo_signed -> "stw"
-	  | Word -> stg
+	  | Word_int | Word_val -> stg
           | Single -> "stfs"
           | Double | Double_u -> "stfd" in
         emit_load_store storeinstr addr i.arg 1 i.arg.(0)
     | Lop(Ialloc n) ->
         if !call_gc_label = 0 then call_gc_label := new_label();
-        `	addi    {emit_gpr 31}, {emit_gpr 31}, {emit_int(-n)}\n`;
-        `	{emit_string cmplg}	{emit_gpr 31}, {emit_gpr 30}\n`;
-        `	addi	{emit_reg i.res.(0)}, {emit_gpr 31}, {emit_int size_addr}\n`;
+        `	addi    31, 31, {emit_int(-n)}\n`;
+        `	{emit_string cmplg}	31, 30\n`;
+        `	addi	{emit_reg i.res.(0)}, 31, {emit_int size_addr}\n`;
         `	bltl	{emit_label !call_gc_label}\n`;
+        (* Exactly 4 instructions after the beginning of the alloc sequence *)
         record_frame i.live Debuginfo.none
     | Lop(Ispecific(Ialloc_far n)) ->
         if !call_gc_label = 0 then call_gc_label := new_label();
         let lbl = new_label() in
-        `	addi    {emit_gpr 31}, {emit_gpr 31}, {emit_int(-n)}\n`;
-        `	{emit_string cmplg}	{emit_gpr 31}, {emit_gpr 30}\n`;
+        `	addi    31, 31, {emit_int(-n)}\n`;
+        `	{emit_string cmplg}	31, 30\n`;
         `	bge	{emit_label lbl}\n`;
         `	bl	{emit_label !call_gc_label}\n`;
+        (* Exactly 4 instructions after the beginning of the alloc sequence *)
         record_frame i.live Debuginfo.none;
-        `{emit_label lbl}:	addi	{emit_reg i.res.(0)}, {emit_gpr 31}, {emit_int size_addr}\n`
+        `{emit_label lbl}:	addi	{emit_reg i.res.(0)}, 31, {emit_int size_addr}\n`
     | Lop(Iintop Isub) ->               (* subfc has swapped arguments *)
         `	subfc	{emit_reg i.res.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`
     | Lop(Iintop Imod) ->
-        `	{emit_string divg}	{emit_gpr 0}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
-        `	{emit_string mullg}	{emit_gpr 0}, {emit_gpr 0}, {emit_reg i.arg.(1)}\n`;
-        `	subfc	{emit_reg i.res.(0)}, {emit_gpr 0}, {emit_reg i.arg.(0)}\n`
+        `	{emit_string divg}	0, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
+        `	{emit_string mullg}	0, 0, {emit_reg i.arg.(1)}\n`;
+        `	subfc	{emit_reg i.res.(0)}, 0, {emit_reg i.arg.(0)}\n`
     | Lop(Iintop(Icomp cmp)) ->
         begin match cmp with
           Isigned c ->
@@ -583,40 +779,43 @@ let rec emit_instr i dslot =
         `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`
     | Lop(Ifloatofint) ->
 	if ppc64 then begin
-	  `	stdu	{emit_reg i.arg.(0)}, -16({emit_gpr 1})\n`;
-          `	lfd	{emit_reg i.res.(0)}, 0({emit_gpr 1})\n`;
-          `	addi	{emit_gpr 1}, {emit_gpr 1}, 16\n`;
+          (* Can use protected zone (288 bytes below r1 *)
+	  `	std	{emit_reg i.arg.(0)}, -16(1)\n`;
+          `	lfd	{emit_reg i.res.(0)}, -16(1)\n`;
           `	fcfid	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
 	end else begin
           let lbl = new_label() in
           float_literals := (0x4330000080000000L, lbl) :: !float_literals;
-          `	addis	{emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
-          `	lfd	{emit_fpr 0}, {emit_lower emit_label lbl}({emit_gpr 11})\n`;
-          `	lis	{emit_gpr 0}, 0x4330\n`;
-          `	stwu	{emit_gpr 0}, -16({emit_gpr 1})\n`;
-          `	xoris	{emit_gpr 0}, {emit_reg i.arg.(0)}, 0x8000\n`;
-          `	stw	{emit_gpr 0}, 4({emit_gpr 1})\n`;
-          `	lfd	{emit_reg i.res.(0)}, 0({emit_gpr 1})\n`;
-          `	addi	{emit_gpr 1}, {emit_gpr 1}, 16\n`;
-          `	fsub	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, {emit_fpr 0}\n`
+          `	addis	11, 0, {emit_upper emit_label lbl}\n`;
+          `	lfd	0, {emit_lower emit_label lbl}(11)\n`;
+          `	lis	0, 0x4330\n`;
+          `	stwu	0, -16(1)\n`;
+          `	xoris	0, {emit_reg i.arg.(0)}, 0x8000\n`;
+          `	stw	0, 4(1)\n`;
+          `	lfd	{emit_reg i.res.(0)}, 0(1)\n`;
+          `	addi	1, 1, 16\n`;
+          `	fsub	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}, 0\n`
 	end
     | Lop(Iintoffloat) ->
-        let ofs = if ppc64 then 0 else 4 in
-        `	{emit_string fctigz}	{emit_fpr 0}, {emit_reg i.arg.(0)}\n`;
-        `	stfdu	{emit_fpr 0}, -16({emit_gpr 1})\n`;
-        `	{emit_string lg}	{emit_reg i.res.(0)}, {emit_int ofs}({emit_gpr 1})\n`;
-        `	addi	{emit_gpr 1}, {emit_gpr 1}, 16\n`
+        if ppc64 then begin
+          (* Can use protected zone (288 bytes below r1 *)
+          `	fctidz	0, {emit_reg i.arg.(0)}\n`;
+          `	stfd	0, -16(1)\n`;
+          `	ld	{emit_reg i.res.(0)}, -16(1)\n`
+        end else begin
+          `	fctiwz	0, {emit_reg i.arg.(0)}\n`;
+          `	stfdu	0, -16(1)\n`;
+          `	lwz	{emit_reg i.res.(0)}, 4(1)\n`;
+          `	addi	1, 1, 16\n`
+        end
     | Lop(Ispecific sop) ->
         let instr = name_for_specific sop in
         `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}, {emit_reg i.arg.(2)}\n`
     | Lreloadretaddr ->
-        let n = frame_size() in
-        `	{emit_string lg}	{emit_gpr 11}, {emit_int(n - size_addr)}({emit_gpr 1})\n`;
-        `	mtlr	{emit_gpr 11}\n`
+        `	{emit_string lg}	11, {emit_int(retaddr_offset())}(1)\n`;
+        `	mtlr	11\n`
     | Lreturn ->
-        let n = frame_size() in
-        if n > 0 then
-          `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int n}\n`;
+        emit_free_frame();
         `	blr\n`
     | Llabel lbl ->
         `{emit_label lbl}:\n`
@@ -626,24 +825,20 @@ let rec emit_instr i dslot =
         begin match tst with
           Itruetest ->
             `	{emit_string cmpg}i	{emit_reg i.arg.(0)}, 0\n`;
-            emit_delay dslot;
             `	bne	{emit_label lbl}\n`
         | Ifalsetest ->
             `	{emit_string cmpg}i	{emit_reg i.arg.(0)}, 0\n`;
-            emit_delay dslot;
             `	beq	{emit_label lbl}\n`
         | Iinttest cmp ->
             let (comp, branch) = name_for_int_comparison cmp in
             `	{emit_string comp}	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
-            emit_delay dslot;
             `	{emit_string branch}	{emit_label lbl}\n`
         | Iinttest_imm(cmp, n) ->
             let (comp, branch) = name_for_int_comparison cmp in
             `	{emit_string comp}i	{emit_reg i.arg.(0)}, {emit_int n}\n`;
-            emit_delay dslot;
             `	{emit_string branch}	{emit_label lbl}\n`
         | Ifloattest(cmp, neg) ->
-            `	fcmpu	{emit_ccr 0}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
+            `	fcmpu	0, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
             (* bit 0 = lt, bit 1 = gt, bit 2 = eq *)
             let (bitnum, negtst) =
               match cmp with
@@ -655,22 +850,18 @@ let rec emit_instr i dslot =
               | Cge -> `	cror	3, 1, 2\n`; (* gt or eq *)
                        (3, neg)
               | Clt -> (0, neg) in
-            emit_delay dslot;
             if negtst
             then `	bf	{emit_int bitnum}, {emit_label lbl}\n`
             else `	bt	{emit_int bitnum}, {emit_label lbl}\n`
         | Ioddtest ->
-            `	andi.	{emit_gpr 0}, {emit_reg i.arg.(0)}, 1\n`;
-            emit_delay dslot;
+            `	andi.	0, {emit_reg i.arg.(0)}, 1\n`;
             `	bne	{emit_label lbl}\n`
         | Ieventest ->
-            `	andi.	{emit_gpr 0}, {emit_reg i.arg.(0)}, 1\n`;
-            emit_delay dslot;
+            `	andi.	0, {emit_reg i.arg.(0)}, 1\n`;
             `	beq	{emit_label lbl}\n`
         end
     | Lcondbranch3(lbl0, lbl1, lbl2) ->
         `	{emit_string cmpg}i	{emit_reg i.arg.(0)}, 1\n`;
-        emit_delay dslot;
         begin match lbl0 with
           None -> ()
         | Some lbl -> `	blt	{emit_label lbl}\n`
@@ -685,128 +876,162 @@ let rec emit_instr i dslot =
         end
     | Lswitch jumptbl ->
         let lbl = new_label() in
-        `	addis	{emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
-        `	addi	{emit_gpr 11}, {emit_gpr 11}, {emit_lower emit_label lbl}\n`;
-        `	{emit_string slgi}	{emit_gpr 0}, {emit_reg i.arg.(0)}, 2\n`;
-        `	{emit_string lwa}x	{emit_gpr 0}, {emit_gpr 11}, {emit_gpr 0}\n`;
-        `	add	{emit_gpr 0}, {emit_gpr 11}, {emit_gpr 0}\n`;
-        `	mtctr	{emit_gpr 0}\n`;
+        if ppc64 then begin
+          if !jumptables_lbl < 0 then jumptables_lbl := lbl;
+          let start = List.length !jumptables in
+          let (start_lo, start_hi) = low_high_s start in
+          emit_tocload emit_gpr 11 (TocLabel !jumptables_lbl);
+          `	addi	12, {emit_reg i.arg.(0)}, {emit_int start_lo}\n`;
+          if start_hi <> 0 then
+            `	addis	12, 12, {emit_int start_hi}\n`;
+          `	sldi	12, 12, 2\n`
+        end else begin
+          `	addis	11, 0, {emit_upper emit_label lbl}\n`;
+          `	addi	11, 11, {emit_lower emit_label lbl}\n`;
+          `	slwi	12, {emit_reg i.arg.(0)}, 2\n`
+        end;
+        `	{emit_string lwa}x	0, 11, 12\n`;
+        `	add	0, 11, 0\n`;
+        `	mtctr	0\n`;
         `	bctr\n`;
-        emit_string rodata_space;
-        `{emit_label lbl}:`;
-        for i = 0 to Array.length jumptbl - 1 do
-          `	.long	{emit_label jumptbl.(i)} - {emit_label lbl}\n`
-        done;
-        emit_string code_space
+        if ppc64 then begin
+          jumptables := List.rev_append (Array.to_list jumptbl) !jumptables
+        end else begin
+          emit_string rodata_space;
+          `{emit_label lbl}:`;
+          for i = 0 to Array.length jumptbl - 1 do
+            `	.long	{emit_label jumptbl.(i)} - {emit_label lbl}\n`
+          done;
+          emit_string code_space
+        end
     | Lsetuptrap lbl ->
-        `	bl	{emit_label lbl}\n`
+        `	bl	{emit_label lbl}\n`;
+        begin match abi with
+        | ELF32 -> ()
+        | ELF64v1 | ELF64v2 -> emit_reload_toc()
+        end
     | Lpushtrap ->
-        stack_offset := !stack_offset + 16;
-        `	mflr	{emit_gpr 0}\n`;
-        `	{emit_string stg}u	{emit_gpr 0}, -16({emit_gpr 1})\n`;
-        `	{emit_string stg}	{emit_gpr 29}, {emit_int size_addr}({emit_gpr 1})\n`;
-        `	mr	{emit_gpr 29}, {emit_gpr 1}\n`
+        begin match abi with
+        | ELF32 ->
+          `	mflr	0\n`;
+          `	stwu    0, -16(1)\n`;
+          adjust_stack_offset 16;
+          `	stw	29, 4(1)\n`;
+          `	mr	29, 1\n`
+        | ELF64v1 | ELF64v2 ->
+          `	mflr	0\n`;
+          `	addi	1, 1, -32\n`;
+          adjust_stack_offset 32;
+          `	std     0, {emit_int trap_handler_offset}(1)\n`;
+          `	std	29, {emit_int trap_previous_offset}(1)\n`;
+          `	mr	29, 1\n`
+          end
     | Lpoptrap ->
-        `	{emit_string lg}	{emit_gpr 29}, {emit_int size_addr}({emit_gpr 1})\n`;
-        `	addi	{emit_gpr 1}, {emit_gpr 1}, 16\n`;
-        stack_offset := !stack_offset - 16
+        `	{emit_string lg}	29, {emit_int trap_previous_offset}(1)\n`;
+        `	addi	1, 1, {emit_int trap_size}\n`;
+        adjust_stack_offset (-trap_size)
     | Lraise k ->
         begin match !Clflags.debug, k with
         | true, Lambda.Raise_regular ->
-          `	bl	{emit_symbol "caml_raise_exn"}\n`;
-          record_frame Reg.Set.empty i.dbg
+            emit_call "caml_raise_exn";
+            record_frame Reg.Set.empty i.dbg;
+            emit_call_nop()
         | true, Lambda.Raise_reraise ->
-          `	bl	{emit_symbol "caml_reraise_exn"}\n`;
-          record_frame Reg.Set.empty i.dbg
+            emit_call "caml_reraise_exn";
+            record_frame Reg.Set.empty i.dbg;
+            emit_call_nop()
         | false, _
         | true, Lambda.Raise_notrace ->
-          `	{emit_string lg}	{emit_gpr 0}, 0({emit_gpr 29})\n`;
-          `	mr	{emit_gpr 1}, {emit_gpr 29}\n`;
-          `	mtctr	{emit_gpr 0}\n`;
-          `	{emit_string lg}	{emit_gpr 29}, {emit_int size_addr}({emit_gpr 1})\n`;
-          `	addi	{emit_gpr 1}, {emit_gpr 1}, 16\n`;
-          `	bctr\n`
+            `	{emit_string lg}	0, {emit_int trap_handler_offset}(29)\n`;
+            `	mr	1, 29\n`;
+            `	mtctr   0\n`;
+            `	{emit_string lg}	29, {emit_int trap_previous_offset}(1)\n`;
+            `	addi	1, 1, {emit_int trap_size}\n`;
+            `	bctr\n`
         end
 
-and emit_delay = function
-    None -> ()
-  | Some i -> emit_instr i None
-
-(* Checks if a pseudo-instruction expands to instructions
-   that do not branch and do not affect CR0 nor R12. *)
-
-let is_simple_instr i =
-  match i.desc with
-    Lop op ->
-      begin match op with
-        Icall_imm _ | Icall_ind | Itailcall_imm _ | Itailcall_ind |
-        Iextcall(_, _) -> false
-      | Ialloc(_) -> false
-      | Iintop(Icomp _) -> false
-      | Iintop_imm(Iand, _) -> false
-      | Iintop_imm(Icomp _, _) -> false
-      | _ -> true
-      end
-  | Lreloadretaddr -> true
-  | _ -> false
-
-let no_interference res arg =
-  try
-    for i = 0 to Array.length arg - 1 do
-      for j = 0 to Array.length res - 1 do
-        if arg.(i).loc = res.(j).loc then raise Exit
-      done
-    done;
-    true
-  with Exit ->
-    false
-
-(* Emit a sequence of instructions, trying to fill delay slots for branches *)
+(* Emit a sequence of instructions *)
 
 let rec emit_all i =
-  match i with
-    {desc = Lend} -> ()
-  | {next = {desc = (Lcondbranch(_, _) | Lcondbranch3(_, _, _))}}
-    when is_simple_instr i && no_interference i.res i.next.arg ->
-      emit_instr i.next (Some i);
-      emit_all i.next.next
-  | _ ->
-      emit_instr i None;
-      emit_all i.next
+  match i.desc with
+  | Lend -> ()
+  |  _   -> emit_instr i; emit_all i.next
+
+(* Emission of the profiling prelude *)
+
+let emit_profile () =
+  match abi with
+  | ELF32 ->
+      `	mflr    0\n`;
+      `	addi	1, 1, -16\n`;
+      `	stw	0, 4(1)\n`;
+      (* _mcount preserves the registers used for parameter passing *)
+      (* when it returns, lr contains the original return address *)
+      `	bl	{emit_symbol "_mcount"}\n`;
+      `	addi	1, 1, 16\n`
+  | ELF64v1 | ELF64v2 ->
+      `	mflr	0\n`;
+      (* save the registers used for parameter passing *)
+      `	bl	{emit_symbol "caml_before_mcount"}\n`;
+      `	bl	{emit_symbol "_mcount"}\n`;
+      `	nop\n`;
+      (* restore the registers used for parameter passing *)
+      `	bl	{emit_symbol "caml_after_mcount"}\n`;
+      `	mtlr	0\n`
 
 (* Emission of a function declaration *)
 
 let fundecl fundecl =
   function_name := fundecl.fun_name;
-  defined_functions := StringSet.add fundecl.fun_name !defined_functions;
   tailrec_entry_point := new_label();
   stack_offset := 0;
   call_gc_label := 0;
   float_literals := [];
-  int_literals := [];
-  if Config.system = "rhapsody"
-  && not !Clflags.output_c_object
-  && is_generic_function fundecl.fun_name
-  then (* PR#4690 *)
-    `	.private_extern	{emit_symbol fundecl.fun_name}\n`
-  else
-  `	.globl	{emit_symbol fundecl.fun_name}\n`;
-  begin match Config.system with
-  | "elf" | "bsd" | "bsd_elf" ->
-      `	.type	{emit_symbol fundecl.fun_name}, @function\n`
-  | _ -> ()
+  jumptables := []; jumptables_lbl := -1;
+  begin match abi with
+  | ELF32 ->
+    emit_string code_space;
+    `	.globl	{emit_symbol fundecl.fun_name}\n`;
+    `	.type	{emit_symbol fundecl.fun_name}, @function\n`;
+    `	.align	2\n`;
+    `{emit_symbol fundecl.fun_name}:\n`
+  | ELF64v1 ->
+    emit_string function_descr_space;
+    `	.align 3\n`;
+    `	.globl	{emit_symbol fundecl.fun_name}\n`;
+    `	.type   {emit_symbol fundecl.fun_name}, @function\n`;
+    `{emit_symbol fundecl.fun_name}:\n`;
+    `	.quad .L.{emit_symbol fundecl.fun_name}, .TOC.@tocbase\n`;
+    emit_string code_space;
+    `	.align  2\n`;
+    `.L.{emit_symbol fundecl.fun_name}:\n`
+  | ELF64v2 ->
+    emit_string code_space;
+    `	.globl	{emit_symbol fundecl.fun_name}\n`;
+    `	.type	{emit_symbol fundecl.fun_name}, @function\n`;
+    `	.align	2\n`;
+    `{emit_symbol fundecl.fun_name}:\n`;
+    `0:	addis	2, 12, (.TOC. - 0b)@ha\n`;
+    `	addi	2, 2, (.TOC. - 0b)@l\n`;
+    `	.localentry {emit_symbol fundecl.fun_name}, . - 0b\n`
   end;
-  emit_string code_space;
-  `	.align	2\n`;
-  `{emit_symbol fundecl.fun_name}:\n`;
+  emit_debug_info fundecl.fun_dbg;
+  cfi_startproc();
+  if !Clflags.gprofile then emit_profile();
   let n = frame_size() in
+  if n > 0 then begin
+    `	addi	1, 1, {emit_int(-n)}\n`;
+    cfi_adjust_cfa_offset n
+  end;
   if !contains_calls then begin
-    `	mflr	{emit_gpr 0}\n`;
-    `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int(-n)}\n`;
-    `	{emit_string stg}	{emit_gpr 0}, {emit_int(n - size_addr)}({emit_gpr 1})\n`
-  end else begin
-    if n > 0 then
-      `	addi	{emit_gpr 1}, {emit_gpr 1}, {emit_int(-n)}\n`
+    let ra = retaddr_offset() in
+    `	mflr	0\n`;
+    `	{emit_string stg}	0, {emit_int ra}(1)\n`;
+    cfi_offset ~reg: 65 (* LR *) ~offset: (ra - n);
+    match abi with
+    | ELF32 -> ()
+    | ELF64v1 | ELF64v2 ->
+      `	std	2, {emit_int(toc_save_offset())}(1)\n`
   end;
   `{emit_label !tailrec_entry_point}:\n`;
   (* On this target, there is at most one "out of line" code block per
@@ -817,34 +1042,57 @@ let fundecl fundecl =
   (* Emit the glue code to call the GC *)
   if !call_gc_label > 0 then begin
     `{emit_label !call_gc_label}:\n`;
-    `	b	{emit_symbol "caml_call_gc"}\n`
+    match abi with
+    | ELF32 ->
+      `	b	{emit_symbol "caml_call_gc"}\n`
+    | ELF64v1 ->
+      `	std	2, 40(1)\n`;
+             (* save our TOC, will be restored by caml_call_gc *)
+      emit_tocload emit_gpr 11 (TocSym "caml_call_gc");
+      `	ld	0, 0(11)\n`;
+      `	mtctr	0\n`;
+      `	ld	2, 8(11)\n`;
+      `	bctr\n`
+    | ELF64v2 ->
+      `	std	2, 24(1)\n`;
+             (* save our TOC, will be restored by caml_call_gc *)
+      emit_tocload emit_gpr 12 (TocSym "caml_call_gc");
+      `	mtctr	12\n`;
+      `	bctr\n`
+  end;
+  cfi_endproc();
+  begin match abi with
+  | ELF32 | ELF64v2 ->
+    `	.size	{emit_symbol fundecl.fun_name}, . - {emit_symbol fundecl.fun_name}\n`
+  | ELF64v1 ->
+    `	.size	{emit_symbol fundecl.fun_name}, . - .L.{emit_symbol fundecl.fun_name}\n`
   end;
   (* Emit the numeric literals *)
-  if !float_literals <> [] || !int_literals <> [] then begin
+  if !float_literals <> [] then begin
     emit_string rodata_space;
     `	.align	3\n`;
     List.iter
       (fun (f, lbl) ->
         `{emit_label lbl}:`;
-        if ppc64
-        then emit_float64_directive ".quad" f
-        else emit_float64_split_directive ".long" f)
-      !float_literals;
+        emit_float64_split_directive ".long" f)
+      !float_literals
+  end;
+  (* Emit the jump tables *)
+  if !jumptables <> [] then begin
+    emit_string rodata_space;
+    `	.align	2\n`;
+    `{emit_label !jumptables_lbl}:`;
     List.iter
-      (fun (n, lbl) ->
-        `{emit_label lbl}:	{emit_string datag}	{emit_nativeint n}\n`)
-      !int_literals
+      (fun  lbl ->
+          `	.long	{emit_label lbl} - {emit_label !jumptables_lbl}\n`)
+      (List.rev !jumptables)
   end
 
 (* Emission of data *)
 
 let declare_global_data s =
   `	.globl	{emit_symbol s}\n`;
-  match Config.system with
-  | "elf" | "bsd" | "bsd_elf" ->
-    `	.type	{emit_symbol s}, @object\n`
-  | "rhapsody" -> ()
-  | _ -> assert false
+  `	.type	{emit_symbol s}, @object\n`
 
 let emit_item = function
     Cglobal_symbol s ->
@@ -880,33 +1128,69 @@ let emit_item = function
 
 let data l =
   emit_string data_space;
+  `	.align  {emit_int (if ppc64 then 3 else 2)}\n`;
   List.iter emit_item l
 
 (* Beginning / end of an assembly file *)
 
 let begin_assembly() =
-  defined_functions := StringSet.empty;
-  external_functions := StringSet.empty;
+  reset_debug_info();
+  `	.file	\"\"\n`;  (* PR#7037 *)
+  begin match abi with
+  | ELF64v2 -> `	.abiversion 2\n`
+  | _ -> ()
+  end;
+  Hashtbl.clear tocref_entries;
   (* Emit the beginning of the segments *)
   let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
   emit_string data_space;
   declare_global_data lbl_begin;
   `{emit_symbol lbl_begin}:\n`;
   let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
-  emit_string code_space;
+  emit_string function_descr_space;
+  (* For the ELF64v1 ABI, we must make sure that the .opd and .data
+     sections are in different pages.  .opd comes after .data,
+     so aligning .opd is enough.  To save space, we do it only
+     for the startup file, not for every OCaml compilation unit. *)
+  let c = Compilenv.current_unit_name() in
+  if abi = ELF64v1 && (c = "_startup" || c = "_shared_startup") then begin
+    `	.p2align	12\n`
+  end;
   declare_global_data lbl_begin;
   `{emit_symbol lbl_begin}:\n`
 
 let end_assembly() =
-  if pic_externals then
-    (* Emit the pointers to external functions *)
-    StringSet.iter emit_external !external_functions;
+  (* In profiling mode, for ELF64, emit the helper functions
+     for register saving and restoring.  We put one copy of these
+     functions in every generated file, instead of defining
+     them once in asmrun/power.S, so that we can call them
+     without risking to save r2 in the wrong place. *)
+  if ppc64 && !Clflags.gprofile then begin
+    let save_area = reserved_stack_space + (if abi = ELF64v1 then 8*8 else 0) in
+    let stacksize = save_area + 8*8 in
+    emit_string code_space;
+    `	.align	2\n`;
+    `{emit_symbol "caml_before_mcount"}:\n`;
+    `	stdu	1, {emit_int (-stacksize)}(1)\n`;
+    `	std	0, {emit_int (16 + stacksize)}(1)\n`;
+    for i = 3 to 10 do
+    `	std	{emit_gpr i}, {emit_int (save_area + (i - 3) * 8)}(1)\n`
+    done;
+    `	blr\n`;
+    `{emit_symbol "caml_after_mcount"}:\n`;
+    `	ld	0, {emit_int (16 + stacksize)}(1)\n`;
+    for i = 3 to 10 do
+    `	ld	{emit_gpr i}, {emit_int (save_area + (i - 3) * 8)}(1)\n`
+    done;
+    `	addi	1, 1, {emit_int stacksize}\n`;
+    `	blr\n`
+  end;
   (* Emit the end of the segments *)
-  emit_string code_space;
+  emit_string function_descr_space;
   let lbl_end = Compilenv.make_symbol (Some "code_end") in
   declare_global_data lbl_end;
   `{emit_symbol lbl_end}:\n`;
-  `	.long	0\n`;
+  if abi <> ELF64v1 then `	.long	0\n`;
   emit_string data_space;
   let lbl_end = Compilenv.make_symbol (Some "data_end") in
   declare_global_data lbl_end;
@@ -922,9 +1206,18 @@ let end_assembly() =
       efa_16 = (fun n -> `	.short	{emit_int n}\n`);
       efa_32 = (fun n -> `	.long	{emit_int32 n}\n`);
       efa_word = (fun n -> `	{emit_string datag}	{emit_int n}\n`);
-      efa_align = (fun n -> `	.align	{emit_int (Misc.log2 n)}\n`);
+      efa_align = (fun n -> `	.balign	{emit_int n}\n`);
       efa_label_rel = (fun lbl ofs ->
                            `	.long	({emit_label lbl} - .) + {emit_int32 ofs}\n`);
       efa_def_label = (fun l -> `{emit_label l}:\n`);
       efa_string = (fun s -> emit_bytes_directive "	.byte	" (s ^ "\000"))
-     }
+     };
+  (* Emit the TOC entries *)
+  begin match abi with
+  | ELF32 -> ()
+  | ELF64v1 | ELF64v2 ->
+      emit_string toc_space;
+      emit_toctable();
+      Hashtbl.clear tocref_entries
+  end;
+  `	.section .note.GNU-stack,\"\",%progbits\n`
diff --git a/asmcomp/power/proc.ml b/asmcomp/power/proc.ml
index 934d2cbf..feb66a26 100644
--- a/asmcomp/power/proc.ml
+++ b/asmcomp/power/proc.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the Power PC *)
 
@@ -42,33 +45,21 @@ let word_addressed = false
 *)
 
 let int_reg_name =
-  if Config.system = "rhapsody" then
-    [| "r3"; "r4"; "r5"; "r6"; "r7"; "r8"; "r9"; "r10";
-       "r14"; "r15"; "r16"; "r17"; "r18"; "r19"; "r20"; "r21";
-       "r22"; "r23"; "r24"; "r25"; "r26"; "r27"; "r28" |]
-  else
-    [| "3"; "4"; "5"; "6"; "7"; "8"; "9"; "10";
-       "14"; "15"; "16"; "17"; "18"; "19"; "20"; "21";
-       "22"; "23"; "24"; "25"; "26"; "27"; "28" |]
+  [| "3"; "4"; "5"; "6"; "7"; "8"; "9"; "10";
+     "14"; "15"; "16"; "17"; "18"; "19"; "20"; "21";
+     "22"; "23"; "24"; "25"; "26"; "27"; "28" |]
 
 let float_reg_name =
-  if Config.system = "rhapsody" then
-    [| "f1"; "f2"; "f3"; "f4"; "f5"; "f6"; "f7"; "f8";
-       "f9"; "f10"; "f11"; "f12"; "f13"; "f14"; "f15"; "f16";
-       "f17"; "f18"; "f19"; "f20"; "f21"; "f22"; "f23"; "f24";
-       "f25"; "f26"; "f27"; "f28"; "f29"; "f30"; "f31" |]
-  else
-    [| "1"; "2"; "3"; "4"; "5"; "6"; "7"; "8";
-       "9"; "10"; "11"; "12"; "13"; "14"; "15"; "16";
-       "17"; "18"; "19"; "20"; "21"; "22"; "23"; "24";
-       "25"; "26"; "27"; "28"; "29"; "30"; "31" |]
+  [| "1"; "2"; "3"; "4"; "5"; "6"; "7"; "8";
+     "9"; "10"; "11"; "12"; "13"; "14"; "15"; "16";
+     "17"; "18"; "19"; "20"; "21"; "22"; "23"; "24";
+     "25"; "26"; "27"; "28"; "29"; "30"; "31" |]
 
 let num_register_classes = 2
 
 let register_class r =
   match r.typ with
-    Int -> 0
-  | Addr -> 0
+  | Val | Int | Addr -> 0
   | Float -> 1
 
 let num_available_registers = [| 23; 31 |]
@@ -102,29 +93,74 @@ let stack_slot slot ty =
 (* Calling conventions *)
 
 let calling_conventions
-    first_int last_int first_float last_float make_stack stack_ofs arg =
-  let loc = Array.make (Array.length arg) Reg.dummy in
+    first_int last_int first_float last_float
+    make_stack stack_ofs reg_use_stack arg =
+  let loc = Array.make (Array.length arg) [| Reg.dummy |] in
   let int = ref first_int in
   let float = ref first_float in
   let ofs = ref stack_ofs in
   for i = 0 to Array.length arg - 1 do
-    match arg.(i).typ with
-      Int | Addr as ty ->
-        if !int <= last_int then begin
-          loc.(i) <- phys_reg !int;
-          incr int
-        end else begin
-          loc.(i) <- stack_slot (make_stack !ofs) ty;
-          ofs := !ofs + size_int
-        end
-    | Float ->
-        if !float <= last_float then begin
-          loc.(i) <- phys_reg !float;
-          incr float
-        end else begin
-          loc.(i) <- stack_slot (make_stack !ofs) Float;
-          ofs := !ofs + size_float
-        end
+    match arg.(i) with
+    | [| arg |] ->
+      begin match arg.typ with
+      | Val | Int | Addr as ty ->
+          if !int <= last_int then begin
+            loc.(i) <- [| phys_reg !int |];
+            incr int;
+            if reg_use_stack then ofs := !ofs + size_int
+          end else begin
+            loc.(i) <- [| stack_slot (make_stack !ofs) ty |];
+            ofs := !ofs + size_int
+          end
+      | Float ->
+          if !float <= last_float then begin
+            loc.(i) <- [| phys_reg !float |];
+            incr float;
+            (* On 64-bit platforms, passing a float in a float register
+               reserves a normal register as well *)
+            if size_int = 8 then incr int;
+            if reg_use_stack then ofs := !ofs + size_float
+          end else begin
+            ofs := Misc.align !ofs size_float;
+            loc.(i) <- [| stack_slot (make_stack !ofs) Float |];
+            ofs := !ofs + size_float
+          end
+      end
+    | [| arg1; arg2 |] ->
+      (* Passing of 64-bit quantities to external functions
+         on 32-bit platform. *)
+      assert (size_int = 4);
+      begin match arg1.typ, arg2.typ with
+      | Int, Int ->
+          (* 64-bit quantities split across two registers must either be in a
+             consecutive pair of registers where the lowest numbered is an
+             even-numbered register; or in a stack slot that is 8-byte
+             aligned. *)
+          int := Misc.align !int 2;
+          if !int <= last_int - 1 then begin
+            let reg_lower = phys_reg !int in
+            let reg_upper = phys_reg (!int + 1) in
+            loc.(i) <- [| reg_lower; reg_upper |];
+            int := !int + 2
+          end else begin
+            let size_int64 = 8 in
+            ofs := Misc.align !ofs size_int64;
+            let ofs_lower = !ofs in
+            let ofs_upper = !ofs + size_int in
+            let stack_lower = stack_slot (make_stack ofs_lower) Int in
+            let stack_upper = stack_slot (make_stack ofs_upper) Int in
+            loc.(i) <- [| stack_lower; stack_upper |];
+            ofs := !ofs + size_int64
+          end
+      | _, _ ->
+        let f = function Int -> "I" | Addr -> "A" | Val -> "V" | Float -> "F" in
+        fatal_error (Printf.sprintf "Proc.calling_conventions: bad register \
+            type(s) for multi-register argument: %s, %s"
+          (f arg1.typ) (f arg2.typ))
+      end
+    | _ ->
+      fatal_error "Proc.calling_conventions: bad number of registers for \
+                   multi-register argument"
   done;
   (loc, Misc.align !ofs 16)
   (* Keep stack 16-aligned. *)
@@ -133,68 +169,89 @@ let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
 let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
 
+let single_regs arg = Array.map (fun arg -> [| arg |]) arg
+let ensure_single_regs res =
+  Array.map (function
+      | [| res |] -> res
+      | _ -> failwith "Proc.ensure_single_regs")
+    res
+
+let max_arguments_for_tailcalls = 8
+
 let loc_arguments arg =
-  calling_conventions 0 7 100 112 outgoing 0 arg
+  let (loc, ofs) =
+    calling_conventions 0 7 100 112 outgoing 0 false (single_regs arg)
+  in
+  (ensure_single_regs loc, ofs)
 let loc_parameters arg =
-  let (loc, ofs) = calling_conventions 0 7 100 112 incoming 0 arg in loc
+  let (loc, ofs) =
+    calling_conventions 0 7 100 112 incoming 0 false (single_regs arg)
+  in
+  ensure_single_regs loc
 let loc_results res =
-  let (loc, ofs) = calling_conventions 0 7 100 112 not_supported 0 res in loc
-
-(* C calling conventions under PowerOpen:
-     use GPR 3-10 and FPR 1-13 just like ML calling
-     conventions, but always reserve stack space for all arguments.
-     Also, using a float register automatically reserves two int registers
-     (in 32-bit mode) or one int register (in 64-bit mode).
-     (If we were to call a non-prototyped C function, each float argument
-      would have to go both in a float reg and in the matching pair
-      of integer regs.)
-
-   C calling conventions under SVR4:
+  let (loc, ofs) =
+    calling_conventions 0 7 100 112 not_supported 0 false (single_regs res)
+  in
+  ensure_single_regs loc
+
+(* C calling conventions for ELF32:
      use GPR 3-10 and FPR 1-8 just like ML calling conventions.
      Using a float register does not affect the int registers.
      Always reserve 8 bytes at bottom of stack, plus whatever is needed
-     to hold the overflow arguments. *)
-
-let poweropen_external_conventions first_int last_int
-                                   first_float last_float arg =
-  let loc = Array.make (Array.length arg) Reg.dummy in
-  let int = ref first_int in
-  let float = ref first_float in
-  let ofs = ref (14 * size_addr) in
-  for i = 0 to Array.length arg - 1 do
-    match arg.(i).typ with
-      Int | Addr as ty ->
-        if !int <= last_int then begin
-          loc.(i) <- phys_reg !int;
-          incr int
-        end else begin
-          loc.(i) <- stack_slot (Outgoing !ofs) ty;
-          ofs := !ofs + size_int
-        end
-    | Float ->
-        if !float <= last_float then begin
-          loc.(i) <- phys_reg !float;
-          incr float
-        end else begin
-          loc.(i) <- stack_slot (Outgoing !ofs) Float;
-          ofs := !ofs + size_float
-        end;
-        int := !int + (if ppc64 then 1 else 2)
-  done;
-  (loc, Misc.align !ofs 16) (* Keep stack 16-aligned *)
+     to hold the overflow arguments.
+   C calling conventions for ELF64v1:
+     Use GPR 3-10 for the first integer arguments.
+     Use FPR 1-13 for the first float arguments.
+     Always reserve stack space for all arguments, even when passed in
+     registers.
+     Always reserve at least 8 words (64 bytes) for the arguments.
+     Always reserve 48 bytes at bottom of stack, plus whatever is needed
+     to hold the arguments.
+     The reserved 48 bytes are automatically added in emit.mlp
+     and need not appear here.
+   C calling conventions for ELF64v2:
+     Use GPR 3-10 for the first integer arguments.
+     Use FPR 1-13 for the first float arguments.
+     If all arguments fit in registers, don't reserve stack space.
+     Otherwise, reserve stack space for all arguments.
+     Always reserve 32 bytes at bottom of stack, plus whatever is needed
+     to hold the arguments.
+     The reserved 32 bytes are automatically added in emit.mlp
+     and need not appear here.
+*)
 
 let loc_external_arguments =
-  match Config.system with
-  | "rhapsody" -> poweropen_external_conventions 0 7 100 112
-  | "elf" | "bsd" | "bsd_elf" -> calling_conventions 0 7 100 107 outgoing 8
-  | _ -> assert false
+  match abi with
+  | ELF32 ->
+      calling_conventions 0 7 100 107 outgoing 8 false
+  | ELF64v1 ->
+      fun args ->
+      let (loc, ofs) =
+        calling_conventions 0 7 100 112 outgoing 0 true args in
+      (loc, max ofs 64)
+  | ELF64v2 ->
+      fun args ->
+      let (loc, ofs) =
+        calling_conventions 0 7 100 112 outgoing 0 true args in
+      if Array.fold_left
+           (fun stk r ->
+              assert (Array.length r = 1);
+              match r.(0).loc with
+              | Stack _ -> true
+              | _ -> stk)
+           false loc
+      then (loc, ofs)
+      else (loc, 0)
 
 let extcall_use_push = false
 
 (* Results are in GPR 3 and FPR 1 *)
 
 let loc_external_results res =
-  let (loc, ofs) = calling_conventions 0 0 100 100 not_supported 0 res in loc
+  let (loc, ofs) =
+    calling_conventions 0 1 100 100 not_supported 0 false (single_regs res)
+  in
+  ensure_single_regs loc
 
 (* Exceptions are in GPR 3 *)
 
diff --git a/asmcomp/power/reload.ml b/asmcomp/power/reload.ml
index 98f747a8..040c7939 100644
--- a/asmcomp/power/reload.ml
+++ b/asmcomp/power/reload.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Reloading for the PowerPC *)
 
diff --git a/asmcomp/power/scheduling.ml b/asmcomp/power/scheduling.ml
index 7adaa2ee..14f2ed81 100644
--- a/asmcomp/power/scheduling.ml
+++ b/asmcomp/power/scheduling.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction scheduling for the Power PC *)
 
diff --git a/asmcomp/power/selection.ml b/asmcomp/power/selection.ml
index 86aea05f..c7ef00c5 100644
--- a/asmcomp/power/selection.ml
+++ b/asmcomp/power/selection.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1997 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1997 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction selection for the Power PC processor *)
 
@@ -26,11 +29,11 @@ type addressing_expr =
 let rec select_addr = function
     Cconst_symbol s ->
       (Asymbol s, 0)
-  | Cop((Caddi | Cadda), [arg; Cconst_int m]) ->
+  | Cop((Caddi | Caddv | Cadda), [arg; Cconst_int m]) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop((Caddi | Cadda), [Cconst_int m; arg]) ->
+  | Cop((Caddi | Caddv | Cadda), [Cconst_int m; arg]) ->
       let (a, n) = select_addr arg in (a, n + m)
-  | Cop((Caddi | 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)
diff --git a/asmcomp/printclambda.ml b/asmcomp/printclambda.ml
index b28d749e..ba0c6462 100644
--- a/asmcomp/printclambda.ml
+++ b/asmcomp/printclambda.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 
 open Format
@@ -31,14 +34,27 @@ let rec structured_constant ppf = function
       List.iter (fun f -> fprintf ppf ",%F" f) fl;
       fprintf ppf ")"
   | Uconst_string s -> fprintf ppf "%S" s
+  | Uconst_closure(clos, sym, fv) ->
+      let idents ppf =
+        List.iter (fprintf ppf "@ %a" Ident.print)in
+      let one_fun ppf f =
+        fprintf ppf "(fun@ %s@ %d@ @[<2>%a@]@ @[<2>%a@])"
+          f.label f.arity idents f.params lam f.body in
+      let funs ppf =
+        List.iter (fprintf ppf "@ %a" one_fun) in
+      let sconsts ppf scl =
+        List.iter (fun sc -> fprintf ppf "@ %a" uconstant sc) scl in
+      fprintf ppf "@[<2>(const_closure%a %s@ %a)@]" funs clos sym sconsts fv
+
 
 and uconstant ppf = function
-  | Uconst_ref (s, c) ->
+  | Uconst_ref (s, Some c) ->
       fprintf ppf "%S=%a" s structured_constant c
+  | Uconst_ref (s, None) -> fprintf ppf "%S"s
   | Uconst_int i -> fprintf ppf "%i" i
   | Uconst_ptr i -> fprintf ppf "%ia" i
 
-let rec lam ppf = function
+and lam ppf = function
   | Uvar id ->
       Ident.print ppf id
   | Uconst c -> uconstant ppf c
@@ -157,6 +173,8 @@ let rec lam ppf = function
         else if k = Lambda.Cached then "cache"
         else "" in
       fprintf ppf "@[<2>(send%s@ %a@ %a%a)@]" kind lam obj lam met args largs
+  | Uunreachable ->
+      fprintf ppf "unreachable"
 
 and sequence ppf ulam = match ulam with
   | Usequence(l1, l2) ->
diff --git a/asmcomp/printclambda.mli b/asmcomp/printclambda.mli
index d138b958..3b1ff58f 100644
--- a/asmcomp/printclambda.mli
+++ b/asmcomp/printclambda.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Clambda
 open Format
diff --git a/asmcomp/printcmm.ml b/asmcomp/printcmm.ml
index 89c8582a..b97f5370 100644
--- a/asmcomp/printcmm.ml
+++ b/asmcomp/printcmm.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pretty-printing of C-- code *)
 
@@ -16,6 +19,7 @@ open Format
 open Cmm
 
 let machtype_component ppf = function
+  | Val -> fprintf ppf "val"
   | Addr -> fprintf ppf "addr"
   | Int -> fprintf ppf "int"
   | Float -> fprintf ppf "float"
@@ -43,7 +47,8 @@ let chunk = function
   | Sixteen_signed -> "signed int16"
   | Thirtytwo_unsigned -> "unsigned int32"
   | Thirtytwo_signed -> "signed int32"
-  | Word -> ""
+  | Word_int -> "int"
+  | Word_val -> "val"
   | Single -> "float32"
   | Double -> "float64"
   | Double_u -> "float64u"
@@ -52,11 +57,15 @@ let operation = function
   | Capply(ty, d) -> "app" ^ Debuginfo.to_string d
   | Cextcall(lbl, ty, alloc, d) ->
       Printf.sprintf "extcall \"%s\"%s" lbl (Debuginfo.to_string d)
-  | Cload Word -> "load"
   | Cload c -> Printf.sprintf "load %s" (chunk c)
   | Calloc -> "alloc"
-  | Cstore Word -> "store"
-  | Cstore c -> Printf.sprintf "store %s" (chunk c)
+  | Cstore (c, init) ->
+    let init =
+      match init with
+      | Lambda.Initialization -> "(init)"
+      | Lambda.Assignment -> ""
+    in
+    Printf.sprintf "store %s%s" (chunk c) init
   | Caddi -> "+"
   | Csubi -> "-"
   | Cmuli -> "*"
@@ -70,8 +79,8 @@ let operation = function
   | Clsr -> ">>u"
   | Casr -> ">>s"
   | Ccmpi c -> comparison c
+  | Caddv -> "+v"
   | Cadda -> "+a"
-  | Csuba -> "-a"
   | Ccmpa c -> Printf.sprintf "%sa" (comparison c)
   | Cnegf -> "~f"
   | Cabsf -> "absf"
diff --git a/asmcomp/printcmm.mli b/asmcomp/printcmm.mli
index 1c97c4a0..31145e65 100644
--- a/asmcomp/printcmm.mli
+++ b/asmcomp/printcmm.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pretty-printing of C-- code *)
 
diff --git a/asmcomp/printlinear.ml b/asmcomp/printlinear.ml
index df58c5cc..fb3d397b 100644
--- a/asmcomp/printlinear.ml
+++ b/asmcomp/printlinear.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pretty-printing of linearized machine code *)
 
diff --git a/asmcomp/printlinear.mli b/asmcomp/printlinear.mli
index 68eda9c1..b598868e 100644
--- a/asmcomp/printlinear.mli
+++ b/asmcomp/printlinear.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pretty-printing of linearized machine code *)
 
diff --git a/asmcomp/printmach.ml b/asmcomp/printmach.ml
index a39160d2..82b95a8b 100644
--- a/asmcomp/printmach.ml
+++ b/asmcomp/printmach.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pretty-printing of pseudo machine code *)
 
@@ -21,7 +24,8 @@ let reg ppf r =
   if not (Reg.anonymous r) then
     fprintf ppf "%s" (Reg.name r)
   else
-    fprintf ppf "%s" (match r.typ with Addr -> "A" | Int -> "I" | Float -> "F");
+    fprintf ppf "%s"
+      (match r.typ with Val -> "V" | Addr -> "A" | Int -> "I" | Float -> "F");
   fprintf ppf "/%i" r.stamp;
   begin match r.loc with
   | Unknown -> ()
@@ -56,7 +60,10 @@ let regsetaddr ppf s =
     (fun r ->
       if !first then begin first := false; fprintf ppf "%a" reg r end
       else fprintf ppf "@ %a" reg r;
-      match r.typ with Addr -> fprintf ppf "*" | _ -> ())
+      match r.typ with
+      | Val -> fprintf ppf "*"
+      | Addr -> fprintf ppf "!"
+      | _ -> ())
     s
 
 let intcomp = function
@@ -105,7 +112,7 @@ let operation op arg ppf res =
   | Ireload -> fprintf ppf "%a (reload)" regs arg
   | Iconst_int n
   | Iconst_blockheader n -> fprintf ppf "%s" (Nativeint.to_string n)
-  | Iconst_float f -> fprintf ppf "%F" f
+  | Iconst_float f -> fprintf ppf "%F" (Int64.float_of_bits f)
   | Iconst_symbol s -> fprintf ppf "\"%s\"" s
   | Icall_ind -> fprintf ppf "call %a" regs arg
   | Icall_imm lbl -> fprintf ppf "call \"%s\" %a" lbl regs arg
diff --git a/asmcomp/printmach.mli b/asmcomp/printmach.mli
index bfb0dbef..fb7411a6 100644
--- a/asmcomp/printmach.mli
+++ b/asmcomp/printmach.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pretty-printing of pseudo machine code *)
 
diff --git a/asmcomp/proc.mli b/asmcomp/proc.mli
index cabac4db..06009998 100644
--- a/asmcomp/proc.mli
+++ b/asmcomp/proc.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Processor descriptions *)
 
@@ -28,10 +31,23 @@ val rotate_registers: bool
 val loc_arguments: Reg.t array -> Reg.t array * int
 val loc_results: Reg.t array -> Reg.t array
 val loc_parameters: Reg.t array -> Reg.t array
-val loc_external_arguments: Reg.t array -> Reg.t array * int
+(* For argument number [n] split across multiple registers, the target-specific
+   implementation of [loc_external_arguments] must return [regs] such that
+   [regs.(n).(0)] is to hold the part of the value at the lowest address.
+   (All that matters for the input to [loc_external_arguments] is the pattern
+   of lengths and register types of the various supplied arrays.) *)
+val loc_external_arguments: Reg.t array array -> Reg.t array array * int
 val loc_external_results: Reg.t array -> Reg.t array
 val loc_exn_bucket: Reg.t
 
+(* The maximum number of arguments of an OCaml to OCaml function call for
+   which it is guaranteed there will be no arguments passed on the stack.
+   (Above this limit, tail call optimization may be disabled.)
+   N.B. The values for this parameter in the backends currently assume
+   that no unboxed floats are passed using the OCaml calling conventions.
+*)
+val max_arguments_for_tailcalls : int
+
 (* Maximal register pressures for pre-spilling *)
 val safe_register_pressure: Mach.operation -> int
 val max_register_pressure: Mach.operation -> int array
diff --git a/asmcomp/reg.ml b/asmcomp/reg.ml
index 8f0298a9..441a6d38 100644
--- a/asmcomp/reg.ml
+++ b/asmcomp/reg.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Cmm
 
@@ -32,7 +35,7 @@ end
 type t =
   { mutable raw_name: Raw_name.t;
     stamp: int;
-    typ: Cmm.machtype_component;
+    mutable typ: Cmm.machtype_component;
     mutable loc: location;
     mutable spill: bool;
     mutable part: int option;
diff --git a/asmcomp/reg.mli b/asmcomp/reg.mli
index e3cb2d95..d918f07e 100644
--- a/asmcomp/reg.mli
+++ b/asmcomp/reg.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Pseudo-registers *)
 
@@ -20,7 +23,7 @@ end
 type t =
   { mutable raw_name: Raw_name.t;       (* Name *)
     stamp: int;                         (* Unique stamp *)
-    typ: Cmm.machtype_component;        (* Type of contents *)
+    mutable typ: Cmm.machtype_component;(* Type of contents *)
     mutable loc: location;              (* Actual location *)
     mutable spill: bool;                (* "true" to force stack allocation  *)
     mutable part: int option;           (* Zero-based index of part of value *)
diff --git a/asmcomp/reload.mli b/asmcomp/reload.mli
index cecacbd4..f636877b 100644
--- a/asmcomp/reload.mli
+++ b/asmcomp/reload.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Insert load/stores for pseudoregs that got assigned to stack locations. *)
 
diff --git a/asmcomp/reloadgen.ml b/asmcomp/reloadgen.ml
index 30f23a82..09c68b7e 100644
--- a/asmcomp/reloadgen.ml
+++ b/asmcomp/reloadgen.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Insert load/stores for pseudoregs that got assigned to stack locations. *)
 
@@ -16,15 +19,6 @@ open Misc
 open Reg
 open Mach
 
-let access_stack r =
-  try
-    for i = 0 to Array.length r - 1 do
-      match r.(i).loc with Stack _ -> raise Exit | _ -> ()
-    done;
-    false
-  with Exit ->
-    true
-
 let insert_move src dst next =
   if src.loc = dst.loc
   then next
diff --git a/asmcomp/reloadgen.mli b/asmcomp/reloadgen.mli
index 45c68d1c..75e870fb 100644
--- a/asmcomp/reloadgen.mli
+++ b/asmcomp/reloadgen.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1997 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1997 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 class reload_generic : object
   method reload_operation :
diff --git a/asmcomp/s390x/CSE.ml b/asmcomp/s390x/CSE.ml
new file mode 100644
index 00000000..e5805f24
--- /dev/null
+++ b/asmcomp/s390x/CSE.ml
@@ -0,0 +1,42 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt            *)
+(*                          Bill O'Farrell, IBM                           *)
+(*                                                                        *)
+(*   Copyright 2015 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini).    *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* CSE for the Z Processor *)
+
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+  match op with
+  | Ispecific(Imultaddf | Imultsubf) -> Op_pure
+  | _ -> super#class_of_operation op
+
+method! is_cheap_operation op =
+  match op with
+  | Iconst_int n | Iconst_blockheader n ->
+      n >= -0x8000_0000n && n <= 0x7FFF_FFFFn
+  | _ -> false
+
+end
+
+let fundecl f =
+  (new cse)#fundecl f
diff --git a/asmcomp/s390x/NOTES.md b/asmcomp/s390x/NOTES.md
new file mode 100644
index 00000000..679e77f2
--- /dev/null
+++ b/asmcomp/s390x/NOTES.md
@@ -0,0 +1,16 @@
+# Supported platforms
+
+IBM z Systems version 10 and up, in 64-bit flat addressing mode,
+running Linux (Debian architecture: `s390x`).
+
+# Reference documents
+
+* Instruction set architecture:
+   _z/Architecture Principles of Operation_,
+   SA22-7832-07, eight edition (Feb 2009).
+   This is the version that corresponds to z10.
+   Newer versions of this manual include additional instructions
+   that are not in z10.
+* ELF ABI:
+   _zSeries ELF Application Binary Interface Supplement_
+   (http://refspecs.linuxfoundation.org/ELF/zSeries/index.html)
diff --git a/asmcomp/s390x/arch.ml b/asmcomp/s390x/arch.ml
new file mode 100644
index 00000000..954beb93
--- /dev/null
+++ b/asmcomp/s390x/arch.ml
@@ -0,0 +1,89 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt            *)
+(*                          Bill O'Farrell, IBM                           *)
+(*                                                                        *)
+(*   Copyright 2015 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini).    *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Specific operations for the Z processor *)
+
+open Format
+
+(* Machine-specific command-line options *)
+
+let pic_code = ref true
+
+let command_line_options =
+  [ "-fPIC", Arg.Set pic_code,
+      " Generate position-independent machine code (default)";
+    "-fno-PIC", Arg.Clear pic_code,
+      " Generate position-dependent machine code" ]
+
+(* Specific operations *)
+
+type specific_operation =
+    Imultaddf                           (* multiply and add *)
+  | Imultsubf                           (* multiply and subtract *)
+
+(* Addressing modes *)
+
+type addressing_mode =
+  | Iindexed of int                     (* reg + displ *)
+  | Iindexed2 of int                    (* reg + reg + displ *)
+
+(* Sizes, endianness *)
+
+let big_endian = true
+
+let size_addr = 8
+let size_int = size_addr
+let size_float = 8
+
+let allow_unaligned_access = false
+
+(* Behavior of division *)
+
+let division_crashes_on_overflow = true
+
+(* Operations on addressing modes *)
+
+let identity_addressing = Iindexed 0
+
+let offset_addressing addr delta =
+  match addr with
+  | Iindexed n -> Iindexed(n + delta)
+  | Iindexed2 n -> Iindexed2(n + delta)
+
+let num_args_addressing = function
+  | Iindexed n -> 1
+  | Iindexed2 n -> 2
+
+(* Printing operations and addressing modes *)
+
+let print_addressing printreg addr ppf arg =
+  match addr with
+  | Iindexed n ->
+      let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in
+      fprintf ppf "%a%s" printreg arg.(0) idx
+  | Iindexed2 n ->
+      let idx = if n <> 0 then Printf.sprintf " + %i" n else "" in
+      fprintf ppf "%a + %a%s" printreg arg.(0) printreg arg.(1) idx
+
+let print_specific_operation printreg op ppf arg =
+  match op with
+  | Imultaddf ->
+      fprintf ppf "%a *f %a +f %a"
+        printreg arg.(0) printreg arg.(1) printreg arg.(2)
+  | Imultsubf ->
+      fprintf ppf "%a *f %a -f %a"
+        printreg arg.(0) printreg arg.(1) printreg arg.(2)
diff --git a/asmcomp/s390x/emit.mlp b/asmcomp/s390x/emit.mlp
new file mode 100644
index 00000000..8226464b
--- /dev/null
+++ b/asmcomp/s390x/emit.mlp
@@ -0,0 +1,773 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Emission of Linux on Z 64-bit assembly code *)
+
+module StringSet =
+  Set.Make(struct type t = string let compare (x:t) y = compare x y end)
+
+open Misc
+open Cmm
+open Arch
+open Proc
+open Reg
+open Mach
+open Linearize
+open Emitaux
+
+(* Layout of the stack.  The stack is kept 8-aligned. *)
+
+let stack_offset = ref 0
+
+let frame_size () =
+  let size =
+    !stack_offset +                     (* Trap frame, outgoing parameters *)
+    size_int * num_stack_slots.(0) +    (* Local int variables *)
+    size_float * num_stack_slots.(1) +  (* Local float variables *)
+    (if !contains_calls then size_addr else 0) in (* The return address *)
+  Misc.align size 8
+
+let slot_offset loc cls =
+  match loc with
+    Local n ->
+      if cls = 0
+      then !stack_offset + num_stack_slots.(1) * size_float + n * size_int
+      else !stack_offset + n * size_float
+  | Incoming n -> frame_size() + n
+  | Outgoing n -> n
+
+(* Output a symbol *)
+
+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}`
+
+(* Output a label *)
+
+let label_prefix = ".L"
+
+let emit_label lbl =
+  emit_string label_prefix; emit_int lbl
+
+let emit_data_label lbl =
+  emit_string label_prefix; emit_string "d"; emit_int lbl
+
+(* Section switching *)
+
+let data_space = "	.section \".data\"\n"
+
+let code_space = "	.section \".text\"\n"
+
+let rodata_space = "	.section \".rodata\"\n"
+
+(* Output a pseudo-register *)
+
+let emit_reg r =
+  match r.loc with
+  | Reg r -> emit_string (register_name r)
+  | _ -> fatal_error "Emit.emit_reg"
+
+
+let emit_gpr r = emit_string "%r"; emit_int r
+
+let emit_fpr r = emit_string "%f"; emit_int r
+
+(* Special registers *)
+
+let reg_f15 = phys_reg 115
+
+(* Output a stack reference *)
+
+let emit_stack r =
+  match r.loc with
+    Stack s ->
+      let ofs = slot_offset s (register_class r) in `{emit_int ofs}(%r15)`
+  | _ -> fatal_error "Emit.emit_stack"
+
+
+(* Output a load or store operation *)
+
+let emit_load_store instr addressing_mode addr n arg =
+  match addressing_mode with
+  | Iindexed ofs ->
+      `	{emit_string instr}	{emit_reg arg}, {emit_int ofs}({emit_reg addr.(n)})\n`
+  | Iindexed2 ofs ->
+      `	{emit_string instr}	{emit_reg arg}, {emit_int ofs}({emit_reg addr.(n)},{emit_reg addr.(n+1)})\n`
+
+(* Adjust the stack pointer down by N.
+   Choose the shortest instruction possible for the value of N. *)
+
+let emit_stack_adjust n =
+  let n = -n in
+  if n = 0 then ()
+  else if n >= 0 && n < 4096 then
+    `	la	%r15, {emit_int n}(%r15)\n`
+  else if n >= -0x80000 && n < 0x80000 then
+    `	lay	%r15, {emit_int n}(%r15)\n`
+  else
+    `	agfi	%r15, {emit_int n}\n`
+
+(* Emit a 'add immediate' *)
+
+let emit_addimm res arg n =
+  if n >= 0 && n < 4096 then
+    `	la	{emit_reg res}, {emit_int n}({emit_reg arg})\n`
+  else if n >= -0x80000 && n < 0x80000 then
+    `	lay	{emit_reg res}, {emit_int n}({emit_reg arg})\n`
+  else begin
+    if arg.loc <> res.loc then
+      `	lgr	{emit_reg res}, {emit_reg arg}\n`;
+    `	agfi	{emit_reg res}, {emit_int n}\n`
+  end
+
+(* After a comparison, extract the result as 0 or 1 *)
+(* The locgr instruction is not available in the z10 architecture,
+   so this code is currently unused. *)
+(*
+let emit_set_comp cmp res =
+    `	lghi	%r1, 1\n`;
+    `	lghi	{emit_reg res}, 0\n`;
+  begin match cmp with
+      Ceq -> `	locgre	{emit_reg res}, %r1\n`
+    | Cne -> `	locgrne	{emit_reg res}, %r1\n`
+    | Cgt -> `	locgrh	{emit_reg res}, %r1\n`
+    | Cle -> `	locgrnh	{emit_reg res}, %r1\n`
+    | Clt -> `	locgrl	{emit_reg res}, %r1\n`
+    | Cge -> `	locgrnl	{emit_reg res}, %r1\n`
+  end
+*)
+
+(* Record live pointers at call points *)
+
+let record_frame live dbg =
+  let lbl = new_label() in
+  let live_offset = ref [] in
+  Reg.Set.iter
+    (function
+      | {typ = Val; loc = Reg r} ->
+          live_offset := (r lsl 1) + 1 :: !live_offset
+      | {typ = Val; loc = Stack s} as reg ->
+          live_offset := slot_offset s (register_class reg) :: !live_offset
+      | {typ = Addr} as r ->
+          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_debuginfo = dbg } :: !frame_descriptors;
+  lbl
+
+(* Record calls to caml_call_gc, emitted out of line. *)
+
+type gc_call =
+  { gc_lbl: label;                      (* Entry label *)
+    gc_return_lbl: label;               (* Where to branch after GC *)
+    gc_frame_lbl: label }               (* Label of frame descriptor *)
+
+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_frame_lbl}:	brcl	15, {emit_label gc.gc_return_lbl}\n`
+
+(* Record calls to caml_ml_array_bound_error, emitted out of line. *)
+
+type bound_error_call =
+  { bd_lbl: label;                      (* Entry label *)
+    bd_frame: label }                   (* Label of frame descriptor *)
+
+let bound_error_sites = ref ([] : bound_error_call list)
+let bound_error_call = ref 0
+
+let bound_error_label dbg =
+  if !Clflags.debug then begin
+    let lbl_bound_error = new_label() in
+    let lbl_frame = record_frame Reg.Set.empty dbg in
+    bound_error_sites :=
+     { bd_lbl = lbl_bound_error; bd_frame = lbl_frame } :: !bound_error_sites;
+   lbl_bound_error
+ end else begin
+   if !bound_error_call = 0 then bound_error_call := new_label();
+   !bound_error_call
+ end
+
+let emit_call_bound_error bd =
+  `{emit_label bd.bd_lbl}:	{emit_call "caml_ml_array_bound_error"}\n`;
+  `{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`
+
+(* Record floating-point and large integer literals *)
+
+let float_literals = ref ([] : (int64 * int) list)
+let int_literals = ref ([] : (nativeint * int) list)
+
+(* Masks for conditional branches after comparisons *)
+
+let branch_for_comparison = function
+    Ceq -> 8  | Cne -> 7
+  | Cle -> 12 | Cgt -> 2
+  | Cge -> 10 | Clt -> 4
+
+let name_for_int_comparison = function
+    Isigned cmp -> ("cgr", branch_for_comparison cmp)
+  | Iunsigned cmp -> ("clgr", branch_for_comparison cmp)
+
+let name_for_int_comparison_imm = function
+    Isigned cmp -> ("cgfi", branch_for_comparison cmp)
+  | Iunsigned cmp -> ("clgfi", branch_for_comparison cmp)
+
+(* bit 0 = eq, bit 1 = lt, bit 2 = gt, bit 3 = unordered*)
+let branch_for_float_comparison cmp neg =
+   match cmp with
+     Ceq -> if neg then 7  else 8
+   | Cne -> if neg then 8  else 7
+   | Cle -> if neg then 3  else 12
+   | Cgt -> if neg then 13 else 2
+   | Cge -> if neg then 5  else 10
+   | Clt -> if neg then 11 else 4
+
+(* Names for various instructions *)
+
+let name_for_intop = function
+    Iadd  -> "agr"
+  | Isub  -> "sgr"
+  | Imul  -> "msgr"
+  | Iand  -> "ngr"
+  | Ior   -> "ogr"
+  | Ixor  -> "xgr"
+  | _ -> Misc.fatal_error "Emit.Intop"
+
+let name_for_floatop1 = function
+    Inegf -> "lcdbr"
+  | Iabsf -> "lpdbr"
+  | _ -> Misc.fatal_error "Emit.Iopf1"
+
+let name_for_floatop2 = function
+    Iaddf -> "adbr"
+  | Isubf -> "sdbr"
+  | Imulf -> "mdbr"
+  | Idivf -> "ddbr"
+  | _ -> Misc.fatal_error "Emit.Iopf2"
+
+let name_for_specific = function
+    Imultaddf -> "madbr"
+  | Imultsubf -> "msdbr"
+
+(* Name of current function *)
+let function_name = ref ""
+(* Entry point for tail recursive calls *)
+let tailrec_entry_point = ref 0
+
+(* Output the assembly code for an instruction *)
+
+let emit_instr i =
+    emit_debug_info i.dbg;
+    match i.desc with
+      Lend -> ()
+    | Lop(Imove | Ispill | Ireload) ->
+        let src = i.arg.(0) and dst = i.res.(0) in
+        if src.loc <> dst.loc then begin
+           match (src, dst) with
+              {loc = Reg rs; typ = (Val | Int | Addr)}, {loc = Reg rd} ->
+                `	lgr	{emit_reg dst}, {emit_reg src}\n`
+            | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = Float} ->
+                `	ldr	{emit_reg dst}, {emit_reg src}\n`
+            | {loc = Reg rs; typ = (Val | Int | Addr)}, {loc = Stack sd} ->
+                `	stg	{emit_reg src}, {emit_stack dst}\n`
+            | {loc = Reg rs; typ = Float}, {loc = Stack sd} ->
+                `	std	{emit_reg src}, {emit_stack dst}\n`
+            | {loc = Stack ss; typ = (Val | Int | Addr)}, {loc = Reg rd} ->
+                `	lg	{emit_reg dst}, {emit_stack src}\n`
+            | {loc = Stack ss; typ = Float}, {loc = Reg rd} ->
+                `	ldy	{emit_reg dst}, {emit_stack src}\n`
+            | (_, _) ->
+                fatal_error "Emit: Imove"
+        end
+    | Lop(Iconst_int n | Iconst_blockheader n) ->
+        if n >= -0x8000n && n <= 0x7FFFn then begin
+          `	lghi	{emit_reg i.res.(0)}, {emit_nativeint n}\n`;
+        end else if n >= -0x8000_0000n && n <= 0x7FFF_FFFFn then begin
+          `	lgfi	{emit_reg i.res.(0)}, {emit_nativeint n}\n`;
+        end else begin
+          let lbl = new_label() in
+          int_literals := (n, lbl) :: !int_literals;
+          `	lgrl	{emit_reg i.res.(0)}, {emit_label lbl}\n`;
+          end
+    | Lop(Iconst_float f) ->
+        let lbl = new_label() in
+        float_literals := (f, lbl) :: !float_literals;
+        `	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`;
+    | Lop(Icall_ind) ->
+        `	basr	%r14, {emit_reg i.arg.(0)}\n`;
+        let lbl = record_frame i.live i.dbg in
+         `{emit_label lbl}:\n`
+
+    | Lop(Icall_imm s) ->
+        if !pic_code then
+        `	brasl	%r14, {emit_symbol s}@PLT\n`
+        else
+        `	brasl	%r14, {emit_symbol s}\n`;
+        let lbl = record_frame i.live i.dbg in
+         `{emit_label lbl}:\n`;
+    | Lop(Itailcall_ind) ->
+        let n = frame_size() in
+        if !contains_calls then
+          `	lg	%r14, {emit_int(n - size_addr)}(%r15)\n`;
+        emit_stack_adjust (-n);
+        `	br	{emit_reg i.arg.(0)}\n`
+    | Lop(Itailcall_imm s) ->
+        if s = !function_name then
+          `	brcl	15, {emit_label !tailrec_entry_point}\n`
+        else begin
+          let n = frame_size() in
+          if !contains_calls then
+            `	lg	%r14, {emit_int(n - size_addr)}(%r15)\n`;
+          emit_stack_adjust (-n);
+          if !pic_code then
+            `	brcl	15, {emit_symbol s}@PLT\n`
+          else
+            `	brcl	15, {emit_symbol s}\n`
+        end
+
+     | Lop(Iextcall(s, alloc)) ->
+        if alloc then begin
+          if !pic_code then begin
+          `	lgrl	%r7, {emit_symbol s}@GOTENT\n`;
+          `	brasl	%r14, {emit_symbol "caml_c_call"}@PLT\n`
+          end else begin
+          `	larl	%r7, {emit_symbol s}\n`;
+          `	brasl	%r14, {emit_symbol "caml_c_call"}\n`
+          end;
+          let lbl = record_frame i.live i.dbg in
+           `{emit_label lbl}:\n`;
+        end else begin
+          if !pic_code then
+          `	brasl	%r14, {emit_symbol s}@PLT\n`
+          else
+          `	brasl	%r14, {emit_symbol s}\n`
+       end
+
+     | Lop(Istackoffset n) ->
+        emit_stack_adjust n;
+        stack_offset := !stack_offset + n
+
+     | Lop(Iload(chunk, addr)) ->
+        let loadinstr =
+          match chunk with
+            Byte_unsigned -> "llgc"
+          | Byte_signed -> "lgb"
+          | Sixteen_unsigned -> "llgh"
+          | Sixteen_signed -> "lgh"
+          | Thirtytwo_unsigned -> "llgf"
+          | Thirtytwo_signed -> "lgf"
+          | Word_int | Word_val -> "lg"
+          | Single -> "ley"
+          | Double | Double_u -> "ldy" in
+        emit_load_store loadinstr addr i.arg 0 i.res.(0);
+        if chunk = Single then
+          `	ldebr	{emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
+
+    | Lop(Istore(Single, addr, _)) ->
+        `	ledbr	%f15, {emit_reg i.arg.(0)}\n`;
+        emit_load_store "stey" addr i.arg 1 reg_f15
+    | Lop(Istore(chunk, addr, _)) ->
+        let storeinstr =
+          match chunk with
+            Byte_unsigned | Byte_signed -> "stcy"
+          | Sixteen_unsigned | Sixteen_signed -> "sthy"
+          | Thirtytwo_unsigned | Thirtytwo_signed -> "sty"
+          | Word_int | Word_val -> "stg"
+          | Single -> assert false
+          | Double | Double_u -> "stdy" in
+        emit_load_store storeinstr addr i.arg 1 i.arg.(0)
+
+    | Lop(Ialloc n) ->
+        let lbl_redo = new_label() in
+        let lbl_call_gc = new_label() in
+        let lbl_frame = record_frame i.live i.dbg in
+        call_gc_sites :=
+          { gc_lbl = lbl_call_gc;
+            gc_return_lbl = lbl_redo;
+            gc_frame_lbl = lbl_frame } :: !call_gc_sites;
+        `{emit_label lbl_redo}:`;
+        `	lay	%r11, {emit_int(-n)}(%r11)\n`;
+        `	clgr	%r11, %r10\n`;
+        `	brcl	4, {emit_label lbl_call_gc}\n`;  (* less than *)
+        `	la	{emit_reg i.res.(0)}, 8(%r11)\n`
+
+    | Lop(Iintop Imulh) ->
+       (* Hacker's Delight section 8.3:
+            mul-high-signed(a, b) = mul-high-unsigned(a, b)
+                                    - a  if b < 0
+                                    - b  if a < 0
+          or, without branches,
+            mul-high-signed(a, b) = mul-high-unsigned(a, b)
+                                    - (a & (b >>s 63))
+                                    - (b & (a >>s 63))
+       *)
+       `	lgr	%r1, {emit_reg i.arg.(0)}\n`;
+       `	mlgr	%r0, {emit_reg i.arg.(1)}\n`;
+         (* r0:r1 is 128-bit unsigned product; r0 is the high bits *)
+       `	srag	%r1, {emit_reg i.arg.(0)}, 63\n`;
+       `	ngr	%r1, {emit_reg i.arg.(1)}\n`;
+       `	sgr	%r0, %r1\n`;
+       `	srag	%r1, {emit_reg i.arg.(1)}, 63\n`;
+       `	ngr	%r1, {emit_reg i.arg.(0)}\n`;
+       `	sgr	%r0, %r1\n`;
+       `	lgr	{emit_reg i.res.(0)}, %r0\n`
+    | Lop(Iintop Imod) ->
+        `	lgr	%r1, {emit_reg i.arg.(0)}\n`;
+        `	dsgr	%r0, {emit_reg i.arg.(1)}\n`;
+        `	lgr	{emit_reg i.res.(0)}, %r0\n`
+    | Lop(Iintop Idiv) ->
+        `	lgr	%r1, {emit_reg i.arg.(0)}\n`;
+        `	dsgr	%r0, {emit_reg i.arg.(1)}\n`;
+        `	lgr	{emit_reg i.res.(0)}, %r1\n`
+    | Lop(Iintop Ilsl) ->
+        `	sllg	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, 0({emit_reg i.arg.(1)})\n`
+    | Lop(Iintop Ilsr) ->
+        `	srlg	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, 0({emit_reg i.arg.(1)})\n`
+    | Lop(Iintop Iasr) ->
+        `	srag	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, 0({emit_reg i.arg.(1)})\n`
+    | Lop(Iintop(Icomp cmp)) ->
+        let lbl = new_label() in
+        let (comp, mask) = name_for_int_comparison cmp in
+        `	{emit_string comp}	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
+        `	lghi	{emit_reg i.res.(0)}, 1\n`;
+        `	brc	{emit_int mask}, {emit_label lbl}\n`;
+        `	lghi	{emit_reg i.res.(0)}, 0\n`;
+        `{emit_label lbl}:\n`
+    | Lop(Iintop Icheckbound) ->
+        let lbl = bound_error_label i.dbg in
+        `	clgr	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
+        `	brcl	12, {emit_label lbl}\n`  (* branch if unsigned le *)
+    | Lop(Iintop op) ->
+        assert (i.arg.(0).loc = i.res.(0).loc);
+        let instr = name_for_intop op in
+        `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(1)}\n`
+    | Lop(Iintop_imm(Iadd, n)) ->
+        emit_addimm i.res.(0) i.arg.(0) n
+    | Lop(Iintop_imm(Isub, n)) ->
+        emit_addimm i.res.(0) i.arg.(0) (-n)
+    | Lop(Iintop_imm(Icomp cmp, n)) ->
+        let lbl = new_label() in
+        let (comp, mask) = name_for_int_comparison_imm cmp in
+        `	{emit_string comp}	{emit_reg i.arg.(0)}, {emit_int n}\n`;
+        `	lghi	{emit_reg i.res.(0)}, 1\n`;
+        `	brc	{emit_int mask}, {emit_label lbl}\n`;
+        `	lghi	{emit_reg i.res.(0)}, 0\n`;
+        `{emit_label lbl}:\n`
+    | Lop(Iintop_imm(Icheckbound, n)) ->
+       let lbl = bound_error_label i.dbg in
+       if n >= 0 then begin
+        `	clgfi	{emit_reg i.arg.(0)}, {emit_int n}\n`;
+        `	brcl	12, {emit_label lbl}\n`  (* branch if unsigned le *)
+       end else begin
+        `	brcl	15, {emit_label lbl}\n`  (* branch always *)
+       end
+    | Lop(Iintop_imm(Ilsl, n)) ->
+        `	sllg	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)},{emit_int n}(%r0)\n`
+    | Lop(Iintop_imm(Ilsr, n)) ->
+        `	srlg	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)},{emit_int n}(%r0)\n`
+    | Lop(Iintop_imm(Iasr, n)) ->
+        `	srag	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)},{emit_int n}(%r0)\n`
+    | Lop(Iintop_imm(Iand, n)) ->
+        assert (i.arg.(0).loc = i.res.(0).loc);
+        `	nilf	{emit_reg i.res.(0)}, {emit_int (n land 0xFFFF_FFFF)}\n`
+    | Lop(Iintop_imm(Ior, n)) ->
+        assert (i.arg.(0).loc = i.res.(0).loc);
+        `	oilf	{emit_reg i.res.(0)}, {emit_int n}\n`
+    | Lop(Iintop_imm(Ixor, n)) ->
+        assert (i.arg.(0).loc = i.res.(0).loc);
+        `	xilf	{emit_reg i.res.(0)}, {emit_int n}\n`
+    | Lop(Iintop_imm(Imul, n)) ->
+        assert (i.arg.(0).loc = i.res.(0).loc);
+          `	msgfi	{emit_reg i.res.(0)}, {emit_int n}\n`
+    | Lop(Iintop_imm((Imulh | Idiv | Imod), _)) ->
+        assert false
+    | Lop(Inegf | Iabsf as op) ->
+        let instr = name_for_floatop1 op in
+        `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`
+    | Lop(Iaddf | Isubf | Imulf | Idivf as op) ->
+        assert (i.arg.(0).loc = i.res.(0).loc);
+        let instr = name_for_floatop2 op in
+        `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(1)}\n`;
+    | Lop(Ifloatofint) ->
+          `	cdgbr	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`
+    | Lop(Iintoffloat) ->
+        (* rounding method #5 = round toward 0 *)
+        `	cgdbr	{emit_reg i.res.(0)}, 5, {emit_reg i.arg.(0)}\n`
+    | Lop(Ispecific sop) ->
+        assert (i.arg.(2).loc = i.res.(0).loc);
+        let instr = name_for_specific sop in
+        `	{emit_string instr}	{emit_reg i.res.(0)}, {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`
+    | Lreloadretaddr ->
+        let n = frame_size() in
+        `	lg	%r14, {emit_int(n - size_addr)}(%r15)\n`
+    | Lreturn ->
+        let n = frame_size() in
+        emit_stack_adjust (-n);
+        `	br	%r14\n`
+    | Llabel lbl ->
+        `{emit_label lbl}:\n`
+    | Lbranch lbl ->
+        `	brcl	15,{emit_label lbl}\n`
+    | Lcondbranch(tst, lbl) ->
+        begin match tst with
+          Itruetest ->
+            `	cgfi	{emit_reg i.arg.(0)}, 0\n`;
+            `	brcl	7, {emit_label lbl}\n`
+        | Ifalsetest ->
+            `	cgfi	{emit_reg i.arg.(0)}, 0\n`;
+            `	brcl	8, {emit_label lbl}\n`
+        | Iinttest cmp ->
+            let (comp, mask) = name_for_int_comparison cmp in
+            `	{emit_string comp}	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
+            `	brcl	{emit_int mask}, {emit_label lbl}\n`
+        | Iinttest_imm(cmp, n) ->
+            let (comp, mask) = name_for_int_comparison_imm cmp in
+            `	{emit_string comp}	{emit_reg i.arg.(0)}, {emit_int n}\n`;
+            `	brcl	{emit_int mask}, {emit_label lbl}\n`
+        | Ifloattest(cmp, neg) ->
+            `	cdbr	{emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`;
+            let mask = branch_for_float_comparison cmp neg in
+            `	brcl	{emit_int mask}, {emit_label lbl}\n`
+        | Ioddtest ->
+            `	tmll	{emit_reg i.arg.(0)}, 1\n`;
+            `	brcl	1, {emit_label lbl}\n`
+        | Ieventest ->
+            `	tmll	{emit_reg i.arg.(0)}, 1\n`;
+            `	brcl	8, {emit_label lbl}\n`
+        end
+    | Lcondbranch3(lbl0, lbl1, lbl2) ->
+        `	cgfi	{emit_reg i.arg.(0)}, 1\n`;
+        begin match lbl0 with
+          None -> ()
+        | Some lbl -> `	brcl	4, {emit_label lbl}\n`
+        end;
+        begin match lbl1 with
+          None -> ()
+        | Some lbl -> `	brcl	8, {emit_label lbl}\n`
+        end;
+        begin match lbl2 with
+          None -> ()
+        | Some lbl -> `	brcl	2, {emit_label lbl}\n`
+        end
+    | Lswitch jumptbl ->
+        let lbl = new_label() in
+        `	larl	%r0, {emit_label lbl}\n`;
+        `	sllg	%r1, {emit_reg i.arg.(0)}, 2(%r0)\n`;
+        `	agr	%r1, %r0\n`;
+        `	lgf	%r1, 0(%r1)\n`;
+        `	agr	%r1, %r0\n`;
+        `	br	%r1\n`;
+        emit_string rodata_space;
+        `	.align	8\n`;
+        `{emit_label lbl}:`;
+        for i = 0 to Array.length jumptbl - 1 do
+          `	.long	{emit_label jumptbl.(i)} - {emit_label lbl}\n`
+        done;
+        emit_string code_space
+    | Lsetuptrap lbl ->
+        `	brasl	%r14, {emit_label lbl}\n`;
+    | Lpushtrap ->
+        stack_offset := !stack_offset + 16;
+        emit_stack_adjust 16;
+        `	stg	%r14, 0(%r15)\n`;
+        `	stg	%r13, {emit_int size_addr}(%r15)\n`;
+        `	lgr	%r13, %r15\n`
+    | Lpoptrap ->
+        `	lg	%r13, {emit_int size_addr}(%r15)\n`;
+        emit_stack_adjust (-16);
+        stack_offset := !stack_offset - 16
+    | Lraise k ->
+        begin match !Clflags.debug, k with
+        | true, Lambda.Raise_regular ->
+          `	brasl	%r14, {emit_symbol "caml_raise_exn"}\n`;
+          let lbl = record_frame Reg.Set.empty i.dbg in
+          `{emit_label lbl}:\n`
+        | true, Lambda.Raise_reraise ->
+          `	brasl	%r14, {emit_symbol "caml_reraise_exn"}\n`;
+          let lbl = record_frame Reg.Set.empty i.dbg in
+          `{emit_label lbl}:\n`
+        | false, _
+        | true, Lambda.Raise_notrace ->
+          `	lg	%r1, 0(%r13)\n`;
+          `	lgr	%r15, %r13\n`;
+          `	lg	%r13, {emit_int size_addr}(%r15)\n`;
+          emit_stack_adjust (-16);
+          `	br	%r1\n`
+        end
+
+
+(* Emit a sequence of instructions *)
+
+let rec emit_all i =
+  match i with
+    {desc = Lend} -> ()
+  | _ ->
+      emit_instr i;
+      emit_all i.next
+
+(* Emission of a function declaration *)
+
+let fundecl fundecl =
+  function_name := fundecl.fun_name;
+  tailrec_entry_point := new_label();
+  stack_offset := 0;
+  call_gc_sites := [];
+  bound_error_sites := [];
+  bound_error_call := 0;
+  float_literals := [];
+  int_literals := [];
+  `	.globl	{emit_symbol fundecl.fun_name}\n`;
+  emit_debug_info fundecl.fun_dbg;
+  `	.type	{emit_symbol fundecl.fun_name}, @function\n`;
+  emit_string code_space;
+  `	.align	8\n`;
+  `{emit_symbol fundecl.fun_name}:\n`;
+  let n = frame_size() in
+  emit_stack_adjust n;
+  if !contains_calls then
+    `	stg	%r14, {emit_int(n - size_addr)}(%r15)\n`;
+  `{emit_label !tailrec_entry_point}:\n`;
+  emit_all fundecl.fun_body;
+  (* Emit the glue code to call the GC *)
+  List.iter emit_call_gc !call_gc_sites;
+  (* Emit the glue code to handle bound errors *)
+  emit_call_bound_errors();
+  (* Emit the numeric literals *)
+  if !float_literals <> [] || !int_literals <> [] then begin
+    emit_string rodata_space;
+    `	.align	8\n`;
+    List.iter
+      (fun (f, lbl) ->
+        `{emit_label lbl}:`;
+        emit_float64_directive ".quad" f)
+      !float_literals;
+    List.iter
+      (fun (n, lbl) ->
+        `{emit_label lbl}:	.quad	{emit_nativeint n}\n`)
+      !int_literals
+  end
+
+(* Emission of data *)
+
+let declare_global_data s =
+  `	.globl	{emit_symbol s}\n`;
+  `	.type	{emit_symbol s}, @object\n`
+
+let emit_item = function
+    Cglobal_symbol s ->
+      declare_global_data s
+  | Cdefine_symbol s ->
+      `{emit_symbol s}:\n`;
+  | Cdefine_label lbl ->
+      `{emit_data_label lbl}:\n`
+  | Cint8 n ->
+      `	.byte	{emit_int n}\n`
+  | Cint16 n ->
+      `	.short	{emit_int n}\n`
+  | Cint32 n ->
+      `	.long	{emit_nativeint n}\n`
+  | Cint n ->
+      `	.quad	{emit_nativeint n}\n`
+  | Csingle f ->
+      emit_float32_directive ".long" (Int32.bits_of_float f)
+  | Cdouble f ->
+      emit_float64_directive ".quad" (Int64.bits_of_float f)
+  | Csymbol_address s ->
+      `	.quad	{emit_symbol s}\n`
+  | Clabel_address lbl ->
+      `	.quad	{emit_data_label lbl}\n`
+  | Cstring s ->
+      emit_bytes_directive "	.byte	" s
+  | Cskip n ->
+      if n > 0 then `	.space	{emit_int n}\n`
+  | Calign n ->
+      if n < 8 then `	.align	8\n`
+               else `	.align	{emit_int n}\n`
+
+let data l =
+  emit_string data_space;
+  `	.align	8\n`;
+  List.iter emit_item l
+
+(* Beginning / end of an assembly file *)
+
+let begin_assembly() =
+  reset_debug_info();
+  `	.file	\"\"\n`;  (* PR#7037 *)
+  (* Emit the beginning of the segments *)
+  let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
+  emit_string data_space;
+  `	.align	8\n`;
+  declare_global_data lbl_begin;
+  `{emit_symbol lbl_begin}:\n`;
+  let lbl_begin = Compilenv.make_symbol (Some "code_begin") in
+  emit_string code_space;
+  declare_global_data lbl_begin;
+  `{emit_symbol lbl_begin}:\n`
+
+let end_assembly() =
+  (* Emit the end of the segments *)
+  emit_string code_space;
+  let lbl_end = Compilenv.make_symbol (Some "code_end") in
+  declare_global_data lbl_end;
+  `{emit_symbol lbl_end}:\n`;
+  `	.long	0\n`;
+  emit_string data_space;
+  `	.align	8\n`;
+  let lbl_end = Compilenv.make_symbol (Some "data_end") in
+  declare_global_data lbl_end;
+  `{emit_symbol lbl_end}:\n`;
+  `	.quad	0\n`;
+  (* Emit the frame descriptors *)
+  emit_string rodata_space;
+  `	.align	8\n`;
+  let lbl = Compilenv.make_symbol (Some "frametable") in
+  declare_global_data lbl;
+  `{emit_symbol lbl}:\n`;
+  emit_frames
+    { efa_label = (fun l -> `	.quad	{emit_label l}\n`);
+      efa_16 = (fun n -> `	.short	{emit_int n}\n`);
+      efa_32 = (fun n -> `	.long	{emit_int32 n}\n`);
+      efa_word = (fun n -> `	.quad	{emit_int n}\n`);
+      efa_align = (fun n -> `	.align	{emit_int n}\n`);
+      efa_label_rel = (fun lbl ofs ->
+                           `	.long	({emit_label lbl} - .) + {emit_int32 ofs}\n`);
+      efa_def_label = (fun l -> `{emit_label l}:\n`);
+      efa_string = (fun s -> emit_bytes_directive "	.byte	" (s ^ "\000"))
+     };
+   (* Mark stack as non-executable *)
+   `	.section .note.GNU-stack,\"\",%progbits\n`
diff --git a/asmcomp/s390x/proc.ml b/asmcomp/s390x/proc.ml
new file mode 100644
index 00000000..dd162966
--- /dev/null
+++ b/asmcomp/s390x/proc.ml
@@ -0,0 +1,213 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt            *)
+(*                          Bill O'Farrell, IBM                           *)
+(*                                                                        *)
+(*   Copyright 2015 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini).    *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Description of the Z Processor *)
+
+open Misc
+open Cmm
+open Reg
+open Arch
+open Mach
+
+(* Instruction selection *)
+
+let word_addressed = false
+
+(* Registers available for register allocation *)
+
+(* Integer register map:
+    0                   temporary, null register for some operations (volatile)
+    1                   temporary (volatile)
+    2 - 5               function arguments and results (volatile)
+    6                   function arguments and results (persevered by C)
+    7 - 9               general purpose, preserved by C
+    10                  allocation limit (preserved by C)
+    11                  allocation pointer (preserved by C)
+    12                  general purpose  (preserved by C)
+    13                  trap pointer (preserved by C)
+    14                  return address (volatile)
+    15                  stack pointer (preserved by C)
+  Floating-point register map:
+    0, 2, 4, 6          function arguments and results (volatile)
+    1, 3, 5, 7          general purpose (volatile)
+    8 - 14              general purpose, preserved by C
+    15                  temporary, preserved by C
+
+Note: integer register r12 is used as GOT pointer by some C compilers.
+The code generated by OCaml does not need a GOT pointer, using PC-relative
+addressing instead for accessing the GOT.  This frees r12 as a
+general-purpose register. *)
+
+let int_reg_name =
+    [| "%r2"; "%r3"; "%r4"; "%r5"; "%r6"; "%r7"; "%r8"; "%r9"; "%r12" |]
+
+let float_reg_name =
+    [| "%f0"; "%f2"; "%f4"; "%f6"; "%f1"; "%f3"; "%f5"; "%f7";
+       "%f8"; "%f9"; "%f10"; "%f11"; "%f12"; "%f13"; "%f14"; "%f15" |]
+
+let num_register_classes = 2
+
+let register_class r =
+  match r.typ with
+  | Val | Int | Addr -> 0
+  | Float -> 1
+
+let num_available_registers = [| 9; 15 |]
+
+let first_available_register = [| 0; 100 |]
+
+let register_name r =
+  if r < 100 then int_reg_name.(r) else float_reg_name.(r - 100)
+
+let rotate_registers = true
+
+(* Representation of hard registers by pseudo-registers *)
+
+let hard_int_reg =
+  let v = Array.make 9 Reg.dummy in
+  for i = 0 to 8 do v.(i) <- Reg.at_location Int (Reg i) done; v
+
+let hard_float_reg =
+  let v = Array.make 16 Reg.dummy in
+  for i = 0 to 15 do v.(i) <- Reg.at_location Float (Reg(100 + i)) done; v
+
+let all_phys_regs =
+  Array.append hard_int_reg hard_float_reg
+
+let phys_reg n =
+  if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100)
+
+let stack_slot slot ty =
+  Reg.at_location ty (Stack slot)
+
+(* Calling conventions *)
+
+let calling_conventions
+    first_int last_int first_float last_float make_stack stack_ofs arg =
+  let loc = Array.make (Array.length arg) Reg.dummy in
+  let int = ref first_int in
+  let float = ref first_float in
+  let ofs = ref stack_ofs in
+  for i = 0 to Array.length arg - 1 do
+    match arg.(i).typ with
+    | Val | Int | Addr as ty ->
+        if !int <= last_int then begin
+          loc.(i) <- phys_reg !int;
+          incr int
+        end else begin
+          loc.(i) <- stack_slot (make_stack !ofs) ty;
+          ofs := !ofs + size_int
+        end
+    | Float ->
+        if !float <= last_float then begin
+          loc.(i) <- phys_reg !float;
+          incr float
+        end else begin
+          loc.(i) <- stack_slot (make_stack !ofs) Float;
+          ofs := !ofs + size_float
+        end
+  done;
+  (loc, Misc.align !ofs 16)
+  (* Keep stack 16-aligned. *)
+
+let incoming ofs = Incoming ofs
+let outgoing ofs = Outgoing ofs
+let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
+
+let max_arguments_for_tailcalls = 5
+
+let loc_arguments arg =
+  calling_conventions 0 4 100 103 outgoing 0 arg
+let loc_parameters arg =
+  let (loc, ofs) = calling_conventions 0 4 100 103 incoming 0 arg in loc
+let loc_results res =
+  let (loc, ofs) = calling_conventions 0 4 100 103 not_supported 0 res in loc
+
+(*   C calling conventions under SVR4:
+     use GPR 2-6 and FPR 0,2,4,6 just like ML calling conventions.
+     Using a float register does not affect the int registers.
+     Always reserve 160 bytes at bottom of stack, plus whatever is needed
+     to hold the overflow arguments. *)
+
+let loc_external_arguments arg =
+  let arg =
+    Array.map (fun regs -> assert (Array.length regs = 1); regs.(0)) arg in
+  let (loc, ofs) =
+    calling_conventions 0 4 100 103 outgoing 160 arg in
+  (Array.map (fun reg -> [|reg|]) loc, ofs)
+
+let extcall_use_push = false
+
+(* Results are in GPR 2 and FPR 0 *)
+
+let loc_external_results res =
+  let (loc, ofs) = calling_conventions 0 0 100 100 not_supported 0 res in loc
+
+(* Exceptions are in GPR 2 *)
+
+let loc_exn_bucket = phys_reg 0
+
+(* Volatile registers: none *)
+
+let regs_are_volatile rs = false
+
+(* Registers destroyed by operations *)
+
+let destroyed_at_c_call =
+  Array.of_list(List.map phys_reg
+    [0; 1; 2; 3; 4;
+     100; 101; 102; 103; 104; 105; 106; 107])
+
+let destroyed_at_oper = function
+    Iop(Icall_ind | Icall_imm _ | Iextcall(_, true)) -> all_phys_regs
+  | Iop(Iextcall(_, false)) -> destroyed_at_c_call
+  | _ -> [||]
+
+let destroyed_at_raise = all_phys_regs
+
+(* Maximal register pressure *)
+
+let safe_register_pressure = function
+    Iextcall(_, _) -> 4
+  | _ -> 9
+
+let max_register_pressure = function
+    Iextcall(_, _) -> [| 4; 7 |]
+  | _ -> [| 9; 15 |]
+
+(* Pure operations (without any side effect besides updating their result
+   registers). *)
+
+let op_is_pure = function
+  | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+  | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
+  | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+  | Ispecific(Imultaddf | Imultsubf) -> true
+  | _ -> true
+
+(* Layout of the stack *)
+
+let num_stack_slots = [| 0; 0 |]
+let contains_calls = ref false
+
+(* Calling the assembler *)
+
+let assemble_file infile outfile =
+  Ccomp.command (Config.asm ^ " -o " ^
+                 Filename.quote outfile ^ " " ^ Filename.quote infile)
+
+let init () = ()
diff --git a/asmcomp/s390x/reload.ml b/asmcomp/s390x/reload.ml
new file mode 100644
index 00000000..f5d710a1
--- /dev/null
+++ b/asmcomp/s390x/reload.ml
@@ -0,0 +1,50 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Reloading for the Z Processor *)
+
+open Arch
+open Mach
+
+class reload = object (self)
+
+inherit Reloadgen.reload_generic as super
+
+(* For 2-address instructions, reloading must make sure that the
+   temporary result register is the same as the appropriate
+   argument register. *)
+
+method! reload_operation op arg res =
+  match op with
+  (* Two-address binary operations: arg.(0) and res.(0) must be the same *)
+  | Iintop(Iadd|Isub|Imul|Iand|Ior|Ixor)  | Iaddf|Isubf|Imulf|Idivf ->
+      let res = self#makereg res.(0) in
+      ([|res; self#makereg arg.(1)|], [|res|])
+  (* Three-address ternary operations: arg.(2) and res.(0) must be the same *)
+  | Ispecific(Imultaddf|Imultsubf) ->
+      let res = self#makereg res.(0) in
+      ([|self#makereg arg.(0); self#makereg arg.(1); res|], [|res|])
+  (* One-address unary operations: arg.(0) and res.(0) must be the same *)
+  |  Iintop_imm((Imul|Iand|Ior|Ixor), _) ->
+      let res = self#makereg res.(0) in
+      ([|res|], [|res|])
+  (* Other instructions are regular *)
+  | _ ->
+      super#reload_operation op arg res
+
+end
+
+let fundecl f =
+  (new reload)#fundecl f
diff --git a/asmcomp/s390x/scheduling.ml b/asmcomp/s390x/scheduling.ml
new file mode 100644
index 00000000..6ac11d35
--- /dev/null
+++ b/asmcomp/s390x/scheduling.ml
@@ -0,0 +1,63 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt            *)
+(*                          Bill O'Farrell, IBM                           *)
+(*                                                                        *)
+(*   Copyright 2015 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini).    *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Instruction scheduling for the Z processor *)
+
+open Arch
+open Mach
+
+(* The z10 processor is in-order, dual-issue.  It could benefit from some
+   basic-block scheduling, although precise latency information
+   is not available.
+   The z196 and later are out-of-order processors.  Basic-block
+   scheduling probably makes no difference. *)
+
+class scheduler = object
+
+inherit Schedgen.scheduler_generic
+
+(* Latencies (in cycles). Wild guesses.  We multiply all latencies by 2
+   to favor dual-issue. *)
+
+method oper_latency = function
+    Ireload -> 4
+  | Iload(_, _) -> 4
+  | Iconst_float _ -> 4 (* turned into a load *)
+  | Iintop(Imul) -> 10
+  | Iintop_imm(Imul, _) -> 10
+  | Iaddf | Isubf | Imulf -> 8
+  | Idivf -> 40
+  | Ispecific(Imultaddf | Imultsubf) -> 8
+  | _ -> 2
+
+method reload_retaddr_latency = 4
+
+(* Issue cycles.  Rough approximations. *)
+
+method oper_issue_cycles = function
+  | Ialloc _ -> 4
+  | Iintop(Imulh) -> 15
+  | Iintop(Idiv|Imod) -> 20
+  | Iintop(Icomp _) -> 4
+  | Iintop_imm(Icomp _, _) -> 4
+  | _ -> 1
+
+method reload_retaddr_issue_cycles = 1
+
+end
+
+let fundecl f = (new scheduler)#schedule_fundecl f
diff --git a/asmcomp/s390x/selection.ml b/asmcomp/s390x/selection.ml
new file mode 100644
index 00000000..4c0df5f0
--- /dev/null
+++ b/asmcomp/s390x/selection.ml
@@ -0,0 +1,117 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt            *)
+(*                          Bill O'Farrell, IBM                           *)
+(*                                                                        *)
+(*   Copyright 2015 Institut National de Recherche en Informatique et     *)
+(*     en Automatique.                                                    *)
+(*   Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini).    *)
+(*                                                                        *)
+(*   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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(* Instruction selection for the Z processor *)
+
+open Cmm
+open Arch
+open Mach
+
+(* Recognition of addressing modes *)
+
+exception Use_default
+
+type addressing_expr =
+  | Alinear of expression
+  | Aadd of expression * expression
+
+let rec select_addr = function
+  | 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]) ->
+      let (a, n) = select_addr arg in (a, n + m)
+  | 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)
+        | _ ->
+              (Aadd(arg1, arg2), 0)
+      end
+  | exp ->
+      (Alinear exp, 0)
+
+(* Instruction selection *)
+
+let pseudoregs_for_operation op arg res =
+  match op with
+  (* Two-address binary operations: arg.(0) and res.(0) must be the same *)
+  | Iintop(Iadd|Isub|Imul|Iand|Ior|Ixor)  | Iaddf|Isubf|Imulf|Idivf ->
+      ([|res.(0); arg.(1)|], res)
+  | Ispecific(sop) ->
+    ( [| arg.(0); arg.(1); res.(0) |], [| res.(0) |])
+  (* One-address unary operations: arg.(0) and res.(0) must be the same *)
+  |  Iintop_imm((Imul|Iand|Ior|Ixor), _) -> (res, res)
+  (* Other instructions are regular *)
+  | _ -> raise Use_default
+
+class selector = object (self)
+
+inherit Selectgen.selector_generic as super
+
+method is_immediate n = (n <= 2147483647) && (n >= -2147483648)
+
+method select_addressing chunk exp =
+  let (a, d) = select_addr exp in
+  (* 20-bit signed displacement *)
+  if d < 0x80000 && d >= -0x80000 then begin
+    match a with
+    | Alinear e -> (Iindexed d, e)
+    | Aadd(e1, e2) -> (Iindexed2 d, Ctuple [e1; e2])
+  end else
+    (Iindexed 0, exp)
+
+method! select_operation op args =
+  match (op, args) with
+  (* Z does not support immediate operands for multiply high *)
+    (Cmulhi, _) -> (Iintop Imulh, args)
+  (* The and, or and xor instructions have a different range of immediate
+     operands than the other instructions *)
+  | (Cand, _) -> self#select_logical Iand (-0x1_0000_0000) (-1) args
+  | (Cor, _) -> self#select_logical Ior 0 0xFFFF_FFFF args
+  | (Cxor, _) -> self#select_logical Ixor  0 0xFFFF_FFFF args
+  (* Recognize mult-add and mult-sub instructions *)
+  | (Caddf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+      (Ispecific Imultaddf, [arg1; arg2; arg3])
+  | (Caddf, [arg3; Cop(Cmulf, [arg1; arg2])]) ->
+      (Ispecific Imultaddf, [arg1; arg2; arg3])
+  | (Csubf, [Cop(Cmulf, [arg1; arg2]); arg3]) ->
+      (Ispecific Imultsubf, [arg1; arg2; arg3])
+  | _ ->
+      super#select_operation op args
+
+method select_logical op lo hi = function
+    [arg; Cconst_int n] when n >= lo && n <= hi ->
+      (Iintop_imm(op, n), [arg])
+  | [Cconst_int n; arg] when n >= lo && n <= hi ->
+      (Iintop_imm(op, n), [arg])
+  | args ->
+      (Iintop op, args)
+
+
+method! insert_op_debug op dbg rs rd =
+  try
+    let (rsrc, rdst) = pseudoregs_for_operation op rs rd in
+    self#insert_moves rs rsrc;
+    self#insert_debug (Iop op) dbg rsrc rdst;
+    self#insert_moves rdst rd;
+    rd
+  with Use_default ->
+    super#insert_op_debug op dbg rs rd
+
+end
+
+let fundecl f = (new selector)#emit_fundecl f
diff --git a/asmcomp/schedgen.ml b/asmcomp/schedgen.ml
index f7af4436..e228d1c3 100644
--- a/asmcomp/schedgen.ml
+++ b/asmcomp/schedgen.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction scheduling *)
 
@@ -132,7 +135,7 @@ let rec remove_instr node = function
 
 (* We treat Lreloadretaddr as a word-sized load *)
 
-let some_load = (Iload(Cmm.Word, Arch.identity_addressing))
+let some_load = (Iload(Cmm.Word_int, Arch.identity_addressing))
 
 (* The generic scheduler *)
 
diff --git a/asmcomp/schedgen.mli b/asmcomp/schedgen.mli
index 911330f8..0fa16dac 100644
--- a/asmcomp/schedgen.mli
+++ b/asmcomp/schedgen.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1997 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1997 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction scheduling *)
 
diff --git a/asmcomp/scheduling.mli b/asmcomp/scheduling.mli
index 5949661d..93830106 100644
--- a/asmcomp/scheduling.mli
+++ b/asmcomp/scheduling.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction scheduling *)
 
diff --git a/asmcomp/selectgen.ml b/asmcomp/selectgen.ml
index 8871bf49..257327a7 100644
--- a/asmcomp/selectgen.ml
+++ b/asmcomp/selectgen.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Selection of pseudo-instructions, assignment of pseudo-registers,
    sequentialization. *)
@@ -27,16 +30,17 @@ let oper_result_type = function
   | Cextcall(s, ty, alloc, _) -> ty
   | Cload c ->
       begin match c with
-        Word -> typ_addr
+      | Word_val -> typ_val
       | Single | Double | Double_u -> typ_float
       | _ -> typ_int
       end
-  | Calloc -> typ_addr
-  | Cstore c -> typ_void
+  | Calloc -> typ_val
+  | Cstore (c, _) -> typ_void
   | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi |
     Cand | Cor | Cxor | Clsl | Clsr | Casr |
     Ccmpi _ | Ccmpa _ | Ccmpf _ -> typ_int
-  | Cadda | Csuba -> typ_addr
+  | Caddv -> typ_val
+  | Cadda -> typ_addr
   | Cnegf | Cabsf | Caddf | Csubf | Cmulf | Cdivf -> typ_float
   | Cfloatofint -> typ_float
   | Cintoffloat -> typ_int
@@ -113,14 +117,19 @@ let join opt_r1 seq1 opt_r2 seq2 =
       assert (l1 = Array.length r2);
       let r = Array.make l1 Reg.dummy in
       for i = 0 to l1-1 do
-        if Reg.anonymous r1.(i) then begin
+        if Reg.anonymous r1.(i)
+          && Cmm.ge_component r1.(i).typ r2.(i).typ
+        then begin
           r.(i) <- r1.(i);
           seq2#insert_move r2.(i) r1.(i)
-        end else if Reg.anonymous r2.(i) then begin
+        end else if Reg.anonymous r2.(i)
+          && Cmm.ge_component r2.(i).typ r1.(i).typ
+        then begin
           r.(i) <- r2.(i);
           seq1#insert_move r1.(i) r2.(i)
         end else begin
-          r.(i) <- Reg.create r1.(i).typ;
+          let typ = Cmm.lub_component r1.(i).typ r2.(i).typ in
+          r.(i) <- Reg.create typ;
           seq1#insert_move r1.(i) r.(i);
           seq2#insert_move r2.(i) r.(i)
         end
@@ -210,7 +219,7 @@ method virtual select_addressing :
 (* Default instruction selection for stores (of words) *)
 
 method select_store is_assign addr arg =
-  (Istore(Word, addr, is_assign), arg)
+  (Istore(Word_val, addr, is_assign), arg)
 
 (* call marking methods, documented in selectgen.mli *)
 
@@ -253,13 +262,18 @@ method select_operation op args =
   | (Cload chunk, [arg]) ->
       let (addr, eloc) = self#select_addressing chunk arg in
       (Iload(chunk, addr), [eloc])
-  | (Cstore chunk, [arg1; arg2]) ->
+  | (Cstore (chunk, init), [arg1; arg2]) ->
       let (addr, eloc) = self#select_addressing chunk arg1 in
-      if chunk = Word then begin
-        let (op, newarg2) = self#select_store true addr arg2 in
+      let is_assign =
+        match init with
+        | Lambda.Initialization -> false
+        | Lambda.Assignment -> true
+      in
+      if chunk = Word_int || chunk = Word_val then begin
+        let (op, newarg2) = self#select_store is_assign addr arg2 in
         (op, [newarg2; eloc])
       end else begin
-        (Istore(chunk, addr, true), [arg2; eloc])
+        (Istore(chunk, addr, is_assign), [arg2; eloc])
         (* Inversion addr/datum in Istore *)
       end
   | (Calloc, _) -> (Ialloc 0, args)
@@ -276,8 +290,8 @@ method select_operation op args =
   | (Clsr, _) -> self#select_shift Ilsr args
   | (Casr, _) -> self#select_shift Iasr args
   | (Ccmpi comp, _) -> self#select_arith_comp (Isigned comp) args
+  | (Caddv, _) -> self#select_arith_comm Iadd args
   | (Cadda, _) -> self#select_arith_comm Iadd args
-  | (Csuba, _) -> self#select_arith Isub args
   | (Ccmpa comp, _) -> self#select_arith_comp (Iunsigned comp) args
   | (Cnegf, _) -> (Inegf, args)
   | (Cabsf, _) -> (Iabsf, args)
@@ -393,6 +407,24 @@ method insert_moves src dst =
     self#insert_move src.(i) dst.(i)
   done
 
+(* Adjust the types of destination pseudoregs for a [Cassign] assignment.
+   The type inferred at [let] binding might be [Int] while we assign
+   something of type [Val] (PR#6501). *)
+
+method adjust_type src dst =
+  let ts = src.typ and td = dst.typ in
+  if ts <> td then
+    match ts, td with
+    | Val, Int -> dst.typ <- Val
+    | Int, Val -> ()
+    | _, _ -> fatal_error("Selection.adjust_type: bad assignment to "
+                                                           ^ Reg.name dst)
+
+method adjust_types src dst =
+  for i = 0 to min (Array.length src) (Array.length dst) - 1 do
+    self#adjust_type src.(i) dst.(i)
+  done
+
 (* Insert moves and stack offsets for function arguments and results *)
 
 method insert_move_args arg loc stacksize =
@@ -430,15 +462,15 @@ method emit_expr env exp =
       Some(self#insert_op (Iconst_blockheader n) [||] r)
   | Cconst_float n ->
       let r = self#regs_for typ_float in
-      Some(self#insert_op (Iconst_float n) [||] r)
+      Some(self#insert_op (Iconst_float (Int64.bits_of_float n)) [||] r)
   | Cconst_symbol n ->
-      let r = self#regs_for typ_addr in
+      let r = self#regs_for typ_val in
       Some(self#insert_op (Iconst_symbol n) [||] r)
   | Cconst_pointer n ->
-      let r = self#regs_for typ_addr in
+      let r = self#regs_for typ_val in  (* integer as Caml value *)
       Some(self#insert_op (Iconst_int(Nativeint.of_int n)) [||] r)
   | Cconst_natpointer n ->
-      let r = self#regs_for typ_addr in
+      let r = self#regs_for typ_val in  (* integer as Caml value *)
       Some(self#insert_op (Iconst_int n) [||] r)
   | Cvar v ->
       begin try
@@ -459,7 +491,7 @@ method emit_expr env exp =
           fatal_error ("Selection.emit_expr: unbound var " ^ Ident.name v) in
       begin match self#emit_expr env e1 with
         None -> None
-      | Some r1 -> self#insert_moves r1 rv; Some [||]
+      | Some r1 -> self#adjust_types r1 rv; self#insert_moves r1 rv; Some [||]
       end
   | Ctuple [] ->
       Some [||]
@@ -509,15 +541,14 @@ method emit_expr env exp =
               self#insert_move_results loc_res rd stack_ofs;
               Some rd
           | Iextcall(lbl, alloc) ->
-              let (loc_arg, stack_ofs) =
-                self#emit_extcall_args env new_args in
+              let (loc_arg, stack_ofs) = self#emit_extcall_args env new_args in
               let rd = self#regs_for ty in
               let loc_res = self#insert_op_debug (Iextcall(lbl, alloc)) dbg
                                     loc_arg (Proc.loc_external_results rd) in
               self#insert_move_results loc_res rd stack_ofs;
               Some rd
           | Ialloc _ ->
-              let rd = self#regs_for typ_addr in
+              let rd = self#regs_for typ_val in
               let size = size_expr env (Ctuple new_args) in
               self#insert (Iop(Ialloc size)) [||] rd;
               self#emit_stores env new_args rd;
@@ -563,7 +594,7 @@ method emit_expr env exp =
       let rs =
         List.map
           (fun id ->
-            let r = self#regs_for typ_addr in name_regs id r; r)
+            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
@@ -592,7 +623,7 @@ method emit_expr env exp =
       end
   | Ctrywith(e1, v, e2) ->
       let (r1, s1) = self#emit_sequence env e1 in
-      let rv = self#regs_for typ_addr in
+      let rv = self#regs_for typ_val in
       let (r2, s2) = self#emit_sequence (Tbl.add v rv env) e2 in
       let r = join r1 s1 r2 s2 in
       self#insert
@@ -655,7 +686,7 @@ method private emit_parts_list env exp_list =
             None -> None
           | Some(new_exp, fin_env) -> Some(new_exp :: new_rem, fin_env)
 
-method private emit_tuple env exp_list =
+method private emit_tuple_not_flattened env exp_list =
   let rec emit_list = function
     [] -> []
   | exp :: rem ->
@@ -663,14 +694,26 @@ method private emit_tuple env exp_list =
       let loc_rem = emit_list rem in
       match self#emit_expr env exp with
         None -> assert false  (* should have been caught in emit_parts *)
-      | Some loc_exp -> loc_exp :: loc_rem in
-  Array.concat(emit_list exp_list)
+      | Some loc_exp -> loc_exp :: loc_rem
+  in
+  emit_list exp_list
+
+method private emit_tuple env exp_list =
+  Array.concat (self#emit_tuple_not_flattened env exp_list)
 
 method emit_extcall_args env args =
-  let r1 = self#emit_tuple env args in
-  let (loc_arg, stack_ofs as arg_stack) = Proc.loc_external_arguments r1 in
-  self#insert_move_args r1 loc_arg stack_ofs;
-  arg_stack
+  let args = self#emit_tuple_not_flattened env args in
+  let arg_hard_regs, stack_ofs =
+    Proc.loc_external_arguments (Array.of_list args)
+  in
+  (* Flattening [args] and [arg_hard_regs] causes parts of values split
+     across multiple registers to line up correctly, by virtue of the
+     semantics of [split_int64_for_32bit_target] in cmmgen.ml, and the
+     required semantics of [loc_external_arguments] (see proc.mli). *)
+  let args = Array.concat args in
+  let arg_hard_regs = Array.concat (Array.to_list arg_hard_regs) in
+  self#insert_move_args args arg_hard_regs stack_ofs;
+  arg_hard_regs, stack_ofs
 
 method emit_stores env data regs_addr =
   let a =
@@ -685,7 +728,7 @@ method emit_stores env data regs_addr =
             Istore(_, _, _) ->
               for i = 0 to Array.length regs - 1 do
                 let r = regs.(i) in
-                let kind = if r.typ = Float then Double_u else Word in
+                let kind = if r.typ = Float then Double_u else Word_val in
                 self#insert (Iop(Istore(kind, !a, false)))
                             (Array.append [|r|] regs_addr) [||];
                 a := Arch.offset_addressing !a (size_component r.typ)
@@ -781,7 +824,7 @@ method emit_tail env exp =
        let rs =
         List.map
           (fun id ->
-            let r = self#regs_for typ_addr in
+            let r = self#regs_for typ_val in
             name_regs id r  ;
             r)
           ids in
@@ -796,7 +839,7 @@ method emit_tail env exp =
       self#insert (Icatch(nfail, s1, s2)) [||] [||]
   | Ctrywith(e1, v, e2) ->
       let (opt_r1, s1) = self#emit_sequence env e1 in
-      let rv = self#regs_for typ_addr in
+      let rv = self#regs_for typ_val in
       let s2 = self#emit_tail_sequence (Tbl.add v rv env) e2 in
       self#insert
         (Itrywith(s1#extract,
diff --git a/asmcomp/selectgen.mli b/asmcomp/selectgen.mli
index 0de90382..b579b07b 100644
--- a/asmcomp/selectgen.mli
+++ b/asmcomp/selectgen.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Selection of pseudo-instructions, assignment of pseudo-registers,
    sequentialization. *)
@@ -97,6 +100,8 @@ class virtual selector_generic : object
   method insert_move_args : Reg.t array -> Reg.t array -> int -> unit
   method insert_move_results : Reg.t array -> Reg.t array -> int -> unit
   method insert_moves : Reg.t array -> Reg.t array -> unit
+  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
diff --git a/asmcomp/selection.mli b/asmcomp/selection.mli
index f1c9e34c..3c055fe0 100644
--- a/asmcomp/selection.mli
+++ b/asmcomp/selection.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Selection of pseudo-instructions, assignment of pseudo-registers,
    sequentialization. *)
diff --git a/asmcomp/sparc/CSE.ml b/asmcomp/sparc/CSE.ml
index e48d6043..6c4cf458 100644
--- a/asmcomp/sparc/CSE.ml
+++ b/asmcomp/sparc/CSE.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 2014 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* CSE for Sparc *)
 
diff --git a/asmcomp/sparc/NOTES.md b/asmcomp/sparc/NOTES.md
new file mode 100644
index 00000000..18c3db4a
--- /dev/null
+++ b/asmcomp/sparc/NOTES.md
@@ -0,0 +1,17 @@
+# Supported platforms
+
+SPARC v8 and up, in 32-bit mode.
+
+Operating systems: Solaris, Linux
+  (abandoned since major Linux distributions no longer support SPARC).
+
+Status of this port: nearly abandoned
+  (no hardware or virtual machine available for testing).
+
+# Reference documents
+
+* Instruction set architecture:
+  _The SPARC Architecture Manual_ version 8.
+* ELF application binary interface:
+  _System V Application Binary Interface,
+   SPARC Processor Supplement_
diff --git a/asmcomp/sparc/arch.ml b/asmcomp/sparc/arch.ml
index f5c06936..f7e388be 100644
--- a/asmcomp/sparc/arch.ml
+++ b/asmcomp/sparc/arch.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Specific operations for the Sparc processor *)
 
diff --git a/asmcomp/sparc/emit.mlp b/asmcomp/sparc/emit.mlp
index 877a3d52..74d61be2 100644
--- a/asmcomp/sparc/emit.mlp
+++ b/asmcomp/sparc/emit.mlp
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Emission of Sparc assembly code *)
 
@@ -54,7 +57,7 @@ let slot_offset loc cl =
 (* Return the other register in a register pair *)
 
 let next_in_pair = function
-    {loc = Reg r; typ = (Int | Addr)} -> phys_reg (r + 1)
+    {loc = Reg r; typ = (Int | Addr | Val)} -> phys_reg (r + 1)
   | {loc = Reg r; typ = Float} -> phys_reg (r + 16)
   | _ -> fatal_error "Emit.next_in_pair"
 
@@ -165,11 +168,12 @@ let record_frame live =
   let live_offset = ref [] in
   Reg.Set.iter
     (function
-        {typ = Addr; loc = Reg r} ->
+      | {typ = Val; loc = Reg r} ->
           live_offset := ((r lsl 1) + 1) :: !live_offset
-      | {typ = Addr; loc = Stack s} as reg ->
-          live_offset :=
-            slot_offset s (register_class reg) :: !live_offset
+      | {typ = Val; loc = Stack s} as reg ->
+          live_offset := slot_offset s (register_class reg) :: !live_offset
+      | {typ = Addr} as r ->
+          Misc.fatal_error ("bad GC root " ^ Reg.name r)
       | _ -> ())
     live;
   frame_descriptors :=
@@ -274,7 +278,7 @@ let rec emit_instr i dslot =
     | Lop(Imove | Ispill | Ireload) ->
         let src = i.arg.(0) and dst = i.res.(0) in
         begin match (src, dst) with
-            {loc = Reg rs; typ = (Int | Addr)}, {loc = Reg rd} ->
+            {loc = Reg rs; typ = (Int | Addr | Val)}, {loc = Reg rd} ->
               `	mov	{emit_reg src}, {emit_reg dst}\n`
           | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = Float} ->
               if !arch_version = SPARC_V9 then
@@ -283,19 +287,28 @@ let rec emit_instr i dslot =
                 `	fmovs	{emit_reg src}, {emit_reg dst}\n`;
                 `	fmovs	{emit_reg(next_in_pair src)}, {emit_reg(next_in_pair dst)}\n`
               end
-          | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = (Int | Addr)} ->
+          | {loc = Reg rs; typ = Float}, {loc = Reg rd; typ = (Int | Addr | Val)} ->
               (* This happens when calling C functions and passing a float arg
                  in %o0...%o5 *)
               `	sub	%sp, 8, %sp\n`;
               `	std	{emit_reg src}, [%sp + 96]\n`;
               `	ld	[%sp + 96], {emit_reg dst}\n`;
-              `	ld	[%sp + 100], {emit_reg(next_in_pair dst)}\n`;
+              let dst2 = i.res.(1) in
+              begin match dst2 with
+                | {loc = Reg _; typ = Int} ->
+                    `	ld	[%sp + 100], {emit_reg dst2}\n`;
+                | {loc = Stack _; typ = Int} ->
+                    `	ld	[%sp + 100], %g1\n`;
+                    `	st	%g1, {emit_stack dst2}\n`;
+                | _ ->
+                    fatal_error "Emit: Imove Float [| _; _ |]"
+              end;
               `	add	%sp, 8, %sp\n`
-          | {loc = Reg rs; typ = (Int | Addr)}, {loc = Stack sd} ->
+          | {loc = Reg rs; typ = (Int | Addr | Val)}, {loc = Stack sd} ->
               `	st	{emit_reg src}, {emit_stack dst}\n`
           | {loc = Reg rs; typ = Float}, {loc = Stack sd} ->
               `	std	{emit_reg src}, {emit_stack dst}\n`
-          | {loc = Stack ss; typ = (Int | Addr)}, {loc = Reg rd} ->
+          | {loc = Stack ss; typ = (Int | Addr | Val)}, {loc = Reg rd} ->
               `	ld	{emit_stack src}, {emit_reg dst}\n`
           | {loc = Stack ss; typ = Float}, {loc = Reg rd} ->
               `	ldd	{emit_stack src}, {emit_reg dst}\n`
@@ -313,7 +326,7 @@ let rec emit_instr i dslot =
         (* On UltraSPARC, the fzero instruction could be used to set a
            floating point register pair to zero. *)
         let lbl = new_label() in
-        float_constants := (lbl, Int64.bits_of_float f) :: !float_constants;
+        float_constants := (lbl, f) :: !float_constants;
         `	sethi	%hi({emit_label lbl}), %g1\n`;
         `	ldd	[%g1 + %lo({emit_label lbl})], {emit_reg i.res.(0)}\n`
     | Lop(Iconst_symbol s) ->
diff --git a/asmcomp/sparc/proc.ml b/asmcomp/sparc/proc.ml
index 625f517f..78062f31 100644
--- a/asmcomp/sparc/proc.ml
+++ b/asmcomp/sparc/proc.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Description of the Sparc processor *)
 
@@ -65,8 +68,7 @@ let num_register_classes = 2
 
 let register_class r =
   match r.typ with
-    Int -> 0
-  | Addr -> 0
+  | Val | Int | Addr -> 0
   | Float -> 1
 
 let num_available_registers = [| 19; 15 |]
@@ -111,7 +113,7 @@ let calling_conventions first_int last_int first_float last_float make_stack
   let ofs = ref 0 in
   for i = 0 to Array.length arg - 1 do
     match arg.(i).typ with
-      Int | Addr as ty ->
+    | Val | Int | Addr as ty ->
         if !int <= last_int then begin
           loc.(i) <- phys_reg !int;
           incr int
@@ -134,6 +136,8 @@ let incoming ofs = Incoming ofs
 let outgoing ofs = Outgoing ofs
 let not_supported ofs = fatal_error "Proc.loc_results: cannot call"
 
+let max_arguments_for_tailcalls = 10
+
 let loc_arguments arg =
   calling_conventions 6 15 100 105 outgoing arg
 let loc_parameters arg =
@@ -145,29 +149,45 @@ let loc_results res =
    are passed in %o0..%o5, then on the stack *)
 
 let loc_external_arguments arg =
-  let loc = ref [] in
+  let loc = Array.make (Array.length arg) [| |] in
   let reg = ref 0 (* %o0 *) in
   let ofs = ref (-4) in              (* start at sp + 92 = sp + 96 - 4 *)
-  for i = 0 to Array.length arg - 1 do
+  let next_loc typ =
     if !reg <= 5 (* %o5 *) then begin
-      match arg.(i).typ with
-        Int | Addr ->
-          loc := phys_reg !reg :: !loc;
-          incr reg
-      | Float ->
-          if !reg = 5 then fatal_error "Proc_sparc: cannot call";
-          loc := phys_reg (!reg + 1) :: phys_reg !reg :: !loc;
-          reg := !reg + 2
+      assert (size_component typ = size_int);
+      let loc = phys_reg !reg in
+      incr reg;
+      loc
     end else begin
-      loc := stack_slot (outgoing !ofs) arg.(i).typ :: !loc;
-      ofs := !ofs + size_component arg.(i).typ
+      let loc = stack_slot (outgoing !ofs) typ in
+      ofs := !ofs + size_component typ;
+      loc
     end
+  in
+  for i = 0 to Array.length arg - 1 do
+    match arg.(i) with
+    | [| { typ = (Val | Int | Addr as typ) } |] ->
+      loc.(i) <- [| next_loc typ |]
+    | [| { typ = Float } |] ->
+      if !reg <= 5 then begin
+        let loc1 = next_loc Int in
+        let loc2 = next_loc Int in
+        loc.(i) <- [| loc1; loc2 |]
+      end else
+        loc.(i) <- [| next_loc Float |]
+    | [| { typ = Int }; { typ = Int } |] ->
+      (* int64 unboxed *)
+      let loc1 = next_loc Int in
+      let loc2 = next_loc Int in
+      loc.(i) <- [| loc1; loc2 |]
+    | _ ->
+      fatal_error "Proc.loc_external_arguments: cannot call"
   done;
   (* Keep stack 8-aligned *)
-  (Array.of_list(List.rev !loc), Misc.align (!ofs + 4) 8)
+  (loc, Misc.align (!ofs + 4) 8)
 
 let loc_external_results res =
-  let (loc, ofs) = calling_conventions 0 0 100 100 not_supported res in loc
+  let (loc, ofs) = calling_conventions 0 1 100 100 not_supported res in loc
 
 let loc_exn_bucket = phys_reg 0         (* $o0 *)
 
diff --git a/asmcomp/sparc/reload.ml b/asmcomp/sparc/reload.ml
index caae16d7..356dc7f1 100644
--- a/asmcomp/sparc/reload.ml
+++ b/asmcomp/sparc/reload.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Reloading for the Sparc *)
 
diff --git a/asmcomp/sparc/scheduling.ml b/asmcomp/sparc/scheduling.ml
index 497722bb..5935ebf7 100644
--- a/asmcomp/sparc/scheduling.ml
+++ b/asmcomp/sparc/scheduling.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 open Cmm
 open Mach
diff --git a/asmcomp/sparc/selection.ml b/asmcomp/sparc/selection.ml
index d938c1ef..288c0cb6 100644
--- a/asmcomp/sparc/selection.ml
+++ b/asmcomp/sparc/selection.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1997 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1997 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Instruction selection for the Sparc processor *)
 
@@ -26,12 +29,12 @@ method is_immediate n = (n <= 4095) && (n >= -4096)
 method select_addressing chunk = function
     Cconst_symbol s ->
       (Ibased(s, 0), Ctuple [])
-  | Cop(Cadda, [Cconst_symbol s; Cconst_int n]) ->
+  | Cop((Caddv | Cadda), [Cconst_symbol s; Cconst_int n]) ->
       (Ibased(s, n), Ctuple [])
-  | Cop(Cadda, [arg; Cconst_int n]) ->
+  | Cop((Caddv | Cadda), [arg; Cconst_int n]) ->
       (Iindexed n, arg)
-  | Cop(Cadda, [arg1; Cop(Caddi, [arg2; Cconst_int n])]) ->
-      (Iindexed n, Cop(Cadda, [arg1; arg2]))
+  | Cop((Caddv | Cadda as op), [arg1; Cop(Caddi, [arg2; Cconst_int n])]) ->
+      (Iindexed n, Cop(op, [arg1; arg2]))
   | arg ->
       (Iindexed 0, arg)
 
diff --git a/asmcomp/spill.ml b/asmcomp/spill.ml
index 105550d0..7c755fce 100644
--- a/asmcomp/spill.ml
+++ b/asmcomp/spill.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Insertion of moves to suggest possible spilling / reloading points
    before register allocation. *)
@@ -129,8 +132,6 @@ let find_reload_at_exit k =
   with
   | Not_found -> Misc.fatal_error "Spill.find_reload_at_exit"
 
-let reload_at_break = ref Reg.Set.empty
-
 let rec reload i before =
   incr current_date;
   record_use i.arg;
@@ -198,11 +199,13 @@ let rec reload i before =
        finally)
   | Iloop(body) ->
       let date_start = !current_date in
+      let destroyed_at_fork_start = !destroyed_at_fork in
       let at_head = ref before in
       let final_body = ref body in
       begin try
         while true do
           current_date := date_start;
+          destroyed_at_fork := destroyed_at_fork_start;
           let (new_body, new_at_head) = reload body !at_head in
           let merged_at_head = Reg.Set.union !at_head new_at_head in
           if Reg.Set.equal merged_at_head !at_head then begin
@@ -392,7 +395,8 @@ let rec spill i finally =
 let reset () =
   spill_env := Reg.Map.empty;
   use_date := Reg.Map.empty;
-  current_date := 0
+  current_date := 0;
+  destroyed_at_fork := []
 
 let fundecl f =
   reset ();
@@ -403,6 +407,7 @@ let fundecl f =
     add_spills (Reg.inter_set_array tospill_at_entry f.fun_args) body2 in
   spill_env := Reg.Map.empty;
   use_date := Reg.Map.empty;
+  destroyed_at_fork := [];
   { fun_name = f.fun_name;
     fun_args = f.fun_args;
     fun_body = new_body;
diff --git a/asmcomp/spill.mli b/asmcomp/spill.mli
index 598a1755..cb1917e4 100644
--- a/asmcomp/spill.mli
+++ b/asmcomp/spill.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Insertion of moves to suggest possible spilling / reloading points
    before register allocation. *)
diff --git a/asmcomp/split.ml b/asmcomp/split.ml
index 8c553ab9..bac047e9 100644
--- a/asmcomp/split.ml
+++ b/asmcomp/split.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Renaming of registers at reload points to split live ranges. *)
 
diff --git a/asmcomp/split.mli b/asmcomp/split.mli
index 1924a5ad..ed1dea54 100644
--- a/asmcomp/split.mli
+++ b/asmcomp/split.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Renaming of registers at reload points to split live ranges. *)
 
diff --git a/asmcomp/strmatch.ml b/asmcomp/strmatch.ml
index d63e92bf..7af65f64 100644
--- a/asmcomp/strmatch.ml
+++ b/asmcomp/strmatch.ml
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Translation of string matching from closed lambda to C-- *)
 
@@ -69,7 +72,7 @@ module Make(I:I) = struct
 
   let mk_let_cell id str ind body =
     let cell =
-      Cop(Cload Word,[Cop(Cadda,[str;Cconst_int(Arch.size_int*ind)])]) in
+      Cop(Cload Word_int,[Cop(Cadda,[str;Cconst_int(Arch.size_int*ind)])]) in
     Clet(id, cell, body)
 
   let mk_let_size id str body =
@@ -221,10 +224,6 @@ module Make(I:I) = struct
 
     module OMap = Map.Make(O)
 
-    let do_find key env =
-      try OMap.find key env
-      with Not_found -> assert false
-
     let divide cases =
       let env =
         List.fold_left
diff --git a/asmcomp/strmatch.mli b/asmcomp/strmatch.mli
index 143dae5c..4371502c 100644
--- a/asmcomp/strmatch.mli
+++ b/asmcomp/strmatch.mli
@@ -1,14 +1,17 @@
-(***********************************************************************)
-(*                                                                     *)
-(*                                OCaml                                *)
-(*                                                                     *)
-(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
-(*                                                                     *)
-(*  Copyright 1996 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.               *)
-(*                                                                     *)
-(***********************************************************************)
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
 
 (* Translation of string matching from closed lambda to C-- *)
 
diff --git a/asmcomp/un_anf.ml b/asmcomp/un_anf.ml
new file mode 100644
index 00000000..15864c8b
--- /dev/null
+++ b/asmcomp/un_anf.ml
@@ -0,0 +1,757 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+[@@@ocaml.warning "+a-4-30-40-41-42"]
+
+(* We say that an [Ident.t] is "linear" iff:
+   (a) it is used exactly once;
+   (b) it is never assigned to (using [Uassign]).
+*)
+type ident_info =
+  { used : Ident.Set.t;
+    linear : Ident.Set.t;
+    assigned : Ident.Set.t;
+    closure_environment : Ident.Set.t;
+    let_bound_vars_that_can_be_moved : Ident.Set.t;
+  }
+
+let ignore_uconstant (_ : Clambda.uconstant) = ()
+let ignore_ulambda (_ : Clambda.ulambda) = ()
+let ignore_ulambda_list (_ : Clambda.ulambda list) = ()
+let ignore_function_label (_ : Clambda.function_label) = ()
+let ignore_debuginfo (_ : Debuginfo.t) = ()
+let ignore_int (_ : int) = ()
+let ignore_ident (_ : Ident.t) = ()
+let ignore_primitive (_ : Lambda.primitive) = ()
+let ignore_string (_ : string) = ()
+let ignore_int_array (_ : int array) = ()
+let ignore_ident_list (_ : Ident.t list) = ()
+let ignore_direction_flag (_ : Asttypes.direction_flag) = ()
+let ignore_meth_kind (_ : Lambda.meth_kind) = ()
+
+(* CR-soon mshinwell: check we aren't traversing function bodies more than
+   once (need to analyse exactly what the calls are from Cmmgen into this
+   module). *)
+
+let closure_environment_ident (ufunction:Clambda.ufunction) =
+  (* The argument after the arity is the environment *)
+  if List.length ufunction.params = ufunction.arity + 1 then
+    let env_var = List.nth ufunction.params ufunction.arity in
+    assert(Ident.name env_var = "env");
+    Some env_var
+  else
+    (* closed function, no environment *)
+    None
+
+let make_ident_info (clam : Clambda.ulambda) : ident_info =
+  let t : int Ident.Tbl.t = Ident.Tbl.create 42 in
+  let assigned_idents = ref Ident.Set.empty in
+  let environment_idents = ref Ident.Set.empty in
+  let rec loop : Clambda.ulambda -> unit = function
+    (* No underscores in the pattern match, to reduce the chance of failing
+       to traverse some subexpression. *)
+    | Uvar id ->
+      begin match Ident.Tbl.find t id with
+      | n -> Ident.Tbl.replace t id (n + 1)
+      | exception Not_found -> Ident.Tbl.add t id 1
+      end
+    | Uconst const ->
+      (* The only variables that might occur in [const] are those in constant
+         closures---and those are all bound by such closures.  It follows that
+         [const] cannot contain any variables that are bound in the current
+         scope, so we do not need to count them here.  (The function bodies
+         of the closures will be traversed when this function is called from
+         [Cmmgen.transl_function].) *)
+      ignore_uconstant const
+    | Udirect_apply (label, args, dbg) ->
+      ignore_function_label label;
+      List.iter loop args;
+      ignore_debuginfo dbg
+    | Ugeneric_apply (func, args, dbg) ->
+      loop func;
+      List.iter loop args;
+      ignore_debuginfo dbg
+    | Uclosure (functions, captured_variables) ->
+      List.iter loop captured_variables;
+      List.iter (fun ({ Clambda. label; arity; params; body; dbg } as clos) ->
+          (match closure_environment_ident clos with
+           | None -> ()
+           | Some env_var ->
+             environment_idents :=
+               Ident.Set.add env_var !environment_idents);
+          ignore_function_label label;
+          ignore_int arity;
+          ignore_ident_list params;
+          loop body;
+          ignore_debuginfo dbg)
+        functions
+    | Uoffset (expr, offset) ->
+      loop expr;
+      ignore_int offset
+    | Ulet (ident, def, body) ->
+      ignore ident;
+      loop def;
+      loop body
+    | Uletrec (defs, body) ->
+      List.iter (fun (ident, def) ->
+          ignore_ident ident;
+          loop def)
+        defs;
+      loop body
+    | Uprim (prim, args, dbg) ->
+      ignore_primitive prim;
+      List.iter loop args;
+      ignore_debuginfo dbg
+    | Uswitch (cond, { us_index_consts; us_actions_consts;
+          us_index_blocks; us_actions_blocks }) ->
+      loop cond;
+      ignore_int_array us_index_consts;
+      Array.iter loop us_actions_consts;
+      ignore_int_array us_index_blocks;
+      Array.iter loop us_actions_blocks
+    | Ustringswitch (cond, branches, default) ->
+      loop cond;
+      List.iter (fun (str, branch) ->
+          ignore_string str;
+          loop branch)
+        branches;
+      Misc.may loop default
+    | Ustaticfail (static_exn, args) ->
+      ignore_int static_exn;
+      List.iter loop args
+    | Ucatch (static_exn, idents, body, handler) ->
+      ignore_int static_exn;
+      ignore_ident_list idents;
+      loop body;
+      loop handler
+    | Utrywith (body, ident, handler) ->
+      loop body;
+      ignore_ident ident;
+      loop handler
+    | Uifthenelse (cond, ifso, ifnot) ->
+      loop cond;
+      loop ifso;
+      loop ifnot
+    | Usequence (e1, e2) ->
+      loop e1;
+      loop e2
+    | Uwhile (cond, body) ->
+      loop cond;
+      loop body
+    | Ufor (ident, low, high, direction_flag, body) ->
+      ignore_ident ident;
+      loop low;
+      loop high;
+      ignore_direction_flag direction_flag;
+      loop body
+    | Uassign (ident, expr) ->
+      assigned_idents := Ident.Set.add ident !assigned_idents;
+      loop expr
+    | Usend (meth_kind, e1, e2, args, dbg) ->
+      ignore_meth_kind meth_kind;
+      loop e1;
+      loop e2;
+      List.iter loop args;
+      ignore_debuginfo dbg
+    | Uunreachable ->
+      ()
+  in
+  loop clam;
+  let linear =
+    Ident.Tbl.fold (fun id n acc ->
+        assert (n >= 1);
+        if n = 1 && not (Ident.Set.mem id !assigned_idents)
+        then Ident.Set.add id acc
+        else acc)
+      t Ident.Set.empty
+  in
+  let assigned = !assigned_idents in
+  let used =
+    (* This doesn't work transitively and thus is somewhat restricted.  In
+       particular, it does not allow us to get rid of useless chains of [let]s.
+       However it should be sufficient to remove the majority of unnecessary
+       [let] bindings that might hinder [Cmmgen]. *)
+    Ident.Tbl.fold (fun id _n acc -> Ident.Set.add id acc)
+      t assigned
+  in
+  { used; linear; assigned; closure_environment = !environment_idents;
+    let_bound_vars_that_can_be_moved = Ident.Set.empty;
+  }
+
+(* When sequences of [let]-bindings match the evaluation order in a subsequent
+   primitive or function application whose arguments are linearly-used
+   non-assigned variables bound by such lets (possibly interspersed with other
+   variables that are known to be constant), and it is known that there were no
+   intervening side-effects during the evaluation of the [let]-bindings,
+   permit substitution of the variables for their defining expressions. *)
+let let_bound_vars_that_can_be_moved ident_info (clam : Clambda.ulambda) =
+  let obviously_constant = ref Ident.Set.empty in
+  let can_move = ref Ident.Set.empty in
+  let let_stack = ref [] in
+  let examine_argument_list args =
+    let rec loop let_bound_vars (args : Clambda.ulambda list) =
+      match let_bound_vars, args with
+      | _, [] ->
+        (* We've matched all arguments and will not substitute (in the
+           current application being considered) any of the remaining
+           [let_bound_vars].  As such they may stay on the stack. *)
+        let_bound_vars
+      | [], _ ->
+        (* There are no more [let]-bindings to consider, so the stack
+           is left empty. *)
+        []
+      | let_bound_vars, (Uvar arg)::args
+          when Ident.Set.mem arg !obviously_constant ->
+        loop let_bound_vars args
+      | let_bound_var::let_bound_vars, (Uvar arg)::args
+          when Ident.same let_bound_var arg
+            && not (Ident.Set.mem arg ident_info.assigned) ->
+        assert (Ident.Set.mem arg ident_info.used);
+        assert (Ident.Set.mem arg ident_info.linear);
+        can_move := Ident.Set.add arg !can_move;
+        loop let_bound_vars args
+      | _::_, _::_ ->
+        (* The [let] sequence has ceased to match the evaluation order
+           or we have encountered some complicated argument.  In this case
+           we empty the stack to ensure that we do not end up moving an
+           outer [let] across a side effect. *)
+        []
+    in
+    (* Start at the most recent let binding and the leftmost argument
+       (the last argument to be evaluated). *)
+    let_stack := loop !let_stack args
+  in
+  let rec loop : Clambda.ulambda -> unit = function
+    | Uvar ident ->
+      if Ident.Set.mem ident ident_info.assigned then begin
+        let_stack := []
+      end
+    | Uconst const ->
+      ignore_uconstant const
+    | Udirect_apply (label, args, dbg) ->
+      ignore_function_label label;
+      examine_argument_list args;
+      (* We don't currently traverse [args]; they should all be variables
+         anyway.  If this is added in the future, take care to traverse [args]
+         following the evaluation order. *)
+      ignore_debuginfo dbg
+    | Ugeneric_apply (func, args, dbg) ->
+      examine_argument_list (args @ [func]);
+      ignore_debuginfo dbg
+    | 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; } ->
+          ignore_function_label label;
+          ignore_int arity;
+          ignore_ident_list params;
+          let_stack := [];
+          loop body;
+          let_stack := [];
+          ignore_debuginfo dbg)
+        functions
+    | Uoffset (expr, offset) ->
+      (* [expr] should usually be a variable. *)
+      examine_argument_list [expr];
+      ignore_int offset
+    | Ulet (ident, def, body) ->
+      begin match def with
+      | Uconst _ ->
+        (* The defining expression is obviously constant, so we don't
+           have to put this [let] on the stack, and we don't have to
+           traverse the defining expression either. *)
+        obviously_constant := Ident.Set.add ident !obviously_constant;
+        loop body
+      | _ ->
+        loop def;
+        if Ident.Set.mem ident ident_info.linear then begin
+          let_stack := ident::!let_stack
+        end else begin
+          (* If we encounter a non-linear [let]-binding then we must clear
+             the let stack, since we cannot now move any previous binding
+             across the non-linear one. *)
+          let_stack := []
+        end;
+        loop body
+      end
+    | Uletrec (defs, body) ->
+      (* Evaluation order for [defs] is not defined, and this case
+         probably isn't important for [Cmmgen] anyway. *)
+      let_stack := [];
+      List.iter (fun (ident, def) ->
+          ignore_ident ident;
+          loop def;
+          let_stack := [])
+        defs;
+      loop body
+    | Uprim (prim, args, dbg) ->
+      ignore_primitive prim;
+      examine_argument_list args;
+      ignore_debuginfo dbg
+    | Uswitch (cond, { us_index_consts; us_actions_consts;
+          us_index_blocks; us_actions_blocks }) ->
+      examine_argument_list [cond];
+      ignore_int_array us_index_consts;
+      Array.iter (fun action ->
+          let_stack := [];
+          loop action)
+        us_actions_consts;
+      ignore_int_array us_index_blocks;
+      Array.iter (fun action ->
+          let_stack := [];
+          loop action)
+        us_actions_blocks;
+      let_stack := []
+    | Ustringswitch (cond, branches, default) ->
+      examine_argument_list [cond];
+      List.iter (fun (str, branch) ->
+          ignore_string str;
+          let_stack := [];
+          loop branch)
+        branches;
+      let_stack := [];
+      Misc.may loop default;
+      let_stack := []
+    | Ustaticfail (static_exn, args) ->
+      ignore_int static_exn;
+      ignore_ulambda_list args;
+      let_stack := []
+    | Ucatch (static_exn, idents, body, handler) ->
+      ignore_int static_exn;
+      ignore_ident_list idents;
+      let_stack := [];
+      loop body;
+      let_stack := [];
+      loop handler;
+      let_stack := []
+    | Utrywith (body, ident, handler) ->
+      let_stack := [];
+      loop body;
+      let_stack := [];
+      ignore_ident ident;
+      loop handler;
+      let_stack := []
+    | Uifthenelse (cond, ifso, ifnot) ->
+      examine_argument_list [cond];
+      let_stack := [];
+      loop ifso;
+      let_stack := [];
+      loop ifnot;
+      let_stack := []
+    | Usequence (e1, e2) ->
+      loop e1;
+      let_stack := [];
+      loop e2;
+      let_stack := []
+    | Uwhile (cond, body) ->
+      let_stack := [];
+      loop cond;
+      let_stack := [];
+      loop body;
+      let_stack := []
+    | Ufor (ident, low, high, direction_flag, body) ->
+      ignore_ident ident;
+      (* Cmmgen generates code that evaluates low before high,
+         but we don't do anything here at the moment anyway. *)
+      ignore_ulambda low;
+      ignore_ulambda high;
+      ignore_direction_flag direction_flag;
+      let_stack := [];
+      loop body;
+      let_stack := []
+    | Uassign (ident, expr) ->
+      ignore_ident ident;
+      ignore_ulambda expr;
+      let_stack := []
+    | Usend (meth_kind, e1, e2, args, dbg) ->
+      ignore_meth_kind meth_kind;
+      ignore_ulambda e1;
+      ignore_ulambda e2;
+      ignore_ulambda_list args;
+      let_stack := [];
+      ignore_debuginfo dbg
+    | Uunreachable ->
+      let_stack := []
+  in
+  loop clam;
+  !can_move
+
+(* Substitution of an expression for a let-moveable variable can cause the
+   surrounding expression to become fixed.  To avoid confusion, do the
+   let-moveable substitutions first. *)
+let rec substitute_let_moveable is_let_moveable env (clam : Clambda.ulambda)
+      : Clambda.ulambda =
+  match clam with
+  | Uvar id ->
+    if not (Ident.Set.mem id is_let_moveable) then
+      clam
+    else
+      begin match Ident.Map.find id env with
+      | clam -> clam
+      | exception Not_found ->
+        Misc.fatal_errorf "substitute_let_moveable: Unbound identifier %a"
+          Ident.print id
+      end
+  | Uconst _ -> clam
+  | Udirect_apply (label, args, dbg) ->
+    let args = substitute_let_moveable_list is_let_moveable env args in
+    Udirect_apply (label, args, dbg)
+  | Ugeneric_apply (func, args, dbg) ->
+    let func = substitute_let_moveable is_let_moveable env func in
+    let args = substitute_let_moveable_list is_let_moveable env args in
+    Ugeneric_apply (func, args, dbg)
+  | Uclosure (functions, variables_bound_by_the_closure) ->
+    let functions =
+      List.map (fun (ufunction : Clambda.ufunction) ->
+          { ufunction with
+            body = substitute_let_moveable is_let_moveable env ufunction.body;
+          })
+        functions
+    in
+    let variables_bound_by_the_closure =
+      substitute_let_moveable_list is_let_moveable env
+        variables_bound_by_the_closure
+    in
+    Uclosure (functions, variables_bound_by_the_closure)
+  | Uoffset (clam, n) ->
+    let clam = substitute_let_moveable is_let_moveable env clam in
+    Uoffset (clam, n)
+  | Ulet (id, def, body) ->
+    let def = substitute_let_moveable is_let_moveable env def in
+    if Ident.Set.mem id is_let_moveable then
+      let env = Ident.Map.add id def env in
+      substitute_let_moveable is_let_moveable env body
+    else
+      Ulet (id, def, substitute_let_moveable is_let_moveable env body)
+  | Uletrec (defs, body) ->
+    let defs =
+      List.map (fun (id, def) ->
+          id, substitute_let_moveable is_let_moveable env def)
+        defs
+    in
+    let body = substitute_let_moveable is_let_moveable env body in
+    Uletrec (defs, body)
+  | Uprim (prim, args, dbg) ->
+    let args = substitute_let_moveable_list is_let_moveable env args in
+    Uprim (prim, args, dbg)
+  | Uswitch (cond, sw) ->
+    let cond = substitute_let_moveable is_let_moveable env cond in
+    let sw =
+      { sw with
+        us_actions_consts =
+          substitute_let_moveable_array is_let_moveable env
+            sw.us_actions_consts;
+        us_actions_blocks =
+          substitute_let_moveable_array is_let_moveable env
+            sw.us_actions_blocks;
+      }
+    in
+    Uswitch (cond, sw)
+  | Ustringswitch (cond, branches, default) ->
+    let cond = substitute_let_moveable is_let_moveable env cond in
+    let branches =
+      List.map (fun (s, branch) ->
+          s, substitute_let_moveable is_let_moveable env branch)
+        branches
+    in
+    let default =
+      Misc.may_map (substitute_let_moveable is_let_moveable env) default
+    in
+    Ustringswitch (cond, branches, default)
+  | Ustaticfail (n, args) ->
+    let args = substitute_let_moveable_list is_let_moveable env args in
+    Ustaticfail (n, args)
+  | Ucatch (n, ids, body, handler) ->
+    let body = substitute_let_moveable is_let_moveable env body in
+    let handler = substitute_let_moveable is_let_moveable env handler in
+    Ucatch (n, ids, body, handler)
+  | Utrywith (body, id, handler) ->
+    let body = substitute_let_moveable is_let_moveable env body in
+    let handler = substitute_let_moveable is_let_moveable env handler in
+    Utrywith (body, id, handler)
+  | Uifthenelse (cond, ifso, ifnot) ->
+    let cond = substitute_let_moveable is_let_moveable env cond in
+    let ifso = substitute_let_moveable is_let_moveable env ifso in
+    let ifnot = substitute_let_moveable is_let_moveable env ifnot in
+    Uifthenelse (cond, ifso, ifnot)
+  | Usequence (e1, e2) ->
+    let e1 = substitute_let_moveable is_let_moveable env e1 in
+    let e2 = substitute_let_moveable is_let_moveable env e2 in
+    Usequence (e1, e2)
+  | Uwhile (cond, body) ->
+    let cond = substitute_let_moveable is_let_moveable env cond in
+    let body = substitute_let_moveable is_let_moveable env body in
+    Uwhile (cond, body)
+  | Ufor (id, low, high, direction, body) ->
+    let low = substitute_let_moveable is_let_moveable env low in
+    let high = substitute_let_moveable is_let_moveable env high in
+    let body = substitute_let_moveable is_let_moveable env body in
+    Ufor (id, low, high, direction, body)
+  | Uassign (id, expr) ->
+    let expr = substitute_let_moveable is_let_moveable env expr in
+    Uassign (id, expr)
+  | Usend (kind, e1, e2, args, dbg) ->
+    let e1 = substitute_let_moveable is_let_moveable env e1 in
+    let e2 = substitute_let_moveable is_let_moveable env e2 in
+    let args = substitute_let_moveable_list is_let_moveable env args in
+    Usend (kind, e1, e2, args, dbg)
+  | Uunreachable ->
+    Uunreachable
+
+and substitute_let_moveable_list is_let_moveable env clams =
+  List.map (substitute_let_moveable is_let_moveable env) clams
+
+and substitute_let_moveable_array is_let_moveable env clams =
+  Array.map (substitute_let_moveable 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 | Moveable | Moveable_not_into_loops
+
+let both_moveable a b =
+  match a, b with
+  | Moveable, Moveable -> Moveable
+  | Moveable_not_into_loops, Moveable
+  | Moveable, Moveable_not_into_loops
+  | Moveable_not_into_loops, Moveable_not_into_loops -> Moveable_not_into_loops
+  | Moveable, Fixed
+  | Moveable_not_into_loops, Fixed
+  | Fixed, Moveable_not_into_loops
+  | Fixed, Moveable
+  | Fixed, Fixed -> Fixed
+
+let primitive_moveable (prim : Lambda.primitive)
+    (args : Clambda.ulambda list)
+    (ident_info : ident_info) =
+  match prim, args with
+  | Pfield _, [Uconst (Uconst_ref (_, _))] ->
+    (* CR-someday mshinwell: Actually, maybe this shouldn't be needed; these
+       should have been simplified to [Read_symbol_field], which doesn't yield
+       a Clambda let.  This might be fixed when Inline_and_simplify can
+       turn Pfield into Read_symbol_field. *)
+    (* Allow field access of symbols to be moveable.  (The comment in
+       flambda.mli on [Read_symbol_field] may be helpful to the reader.) *)
+    Moveable
+  | Pfield _, [Uvar id] when Ident.Set.mem id ident_info.closure_environment ->
+    (* accesses to the function environment is coeffect free: this block
+       is never mutated *)
+    Moveable
+  | _ ->
+    match Semantics_of_primitives.for_primitive prim with
+    | No_effects, No_coeffects -> Moveable
+    | No_effects, Has_coeffects
+    | Only_generative_effects, No_coeffects
+    | Only_generative_effects, Has_coeffects
+    | Arbitrary_effects, No_coeffects
+    | Arbitrary_effects, Has_coeffects -> Fixed
+
+type moveable_for_env = 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
+    | Moveable -> Some (Moveable, def)
+    | Moveable_not_into_loops -> None)
+
+(** Eliminate, through substitution, [let]-bindings of linear variables with
+    moveable defining expressions. *)
+let rec un_anf_and_moveable ident_info env (clam : Clambda.ulambda)
+      : Clambda.ulambda * moveable =
+  match clam with
+  | Uvar id ->
+    begin match Ident.Map.find id env with
+    | 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
+          Fixed
+        else
+          Moveable
+      in
+      clam, moveable
+    end
+  | Uconst _ ->
+    (* Constant closures are rewritten separately. *)
+    clam, Moveable
+  | Udirect_apply (label, args, dbg) ->
+    let args = un_anf_list ident_info env args in
+    Udirect_apply (label, args, dbg), Fixed
+  | Ugeneric_apply (func, args, dbg) ->
+    let func = un_anf ident_info env func in
+    let args = un_anf_list ident_info env args in
+    Ugeneric_apply (func, args, dbg), Fixed
+  | Uclosure (functions, variables_bound_by_the_closure) ->
+    let functions =
+      List.map (fun (ufunction : Clambda.ufunction) ->
+          { ufunction with
+            body = un_anf ident_info (going_into_loop 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
+    in
+    Uclosure (functions, variables_bound_by_the_closure),
+      both_moveable moveable Moveable_not_into_loops
+  | Uoffset (clam, n) ->
+    let clam, moveable = un_anf_and_moveable ident_info env clam in
+    Uoffset (clam, n), moveable
+  | Ulet (id, def, Uvar id') when Ident.same id id' ->
+    un_anf_and_moveable ident_info env def
+  | Ulet (id, def, body) ->
+    let def, def_moveable = un_anf_and_moveable ident_info env def in
+    let is_linear = Ident.Set.mem id ident_info.linear in
+    let is_used = Ident.Set.mem id ident_info.used in
+    begin match def_moveable, is_linear, is_used with
+    | (Moveable | Moveable_not_into_loops), _, false ->
+      (* A moveable expression that is never used may be eliminated. *)
+      un_anf_and_moveable ident_info env body
+    | Moveable, true, true ->
+      (* A moveable expression bound to a linear [Ident.t] may replace the
+         single occurrence of the identifier. *)
+      let env =
+        let def_moveable : moveable_for_env =
+          match def_moveable with
+          | Moveable -> Moveable
+          | Moveable_not_into_loops -> Moveable_not_into_loops
+          | Fixed -> assert false
+        in
+        Ident.Map.add id (def_moveable, def) env
+      in
+      un_anf_and_moveable ident_info env body
+    | Moveable_not_into_loops, true, true
+        (* 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. *)
+    | (Moveable | Moveable_not_into_loops), false, true
+        (* Moveable but not used linearly. *)
+    | Fixed, _, _ ->
+      let body, body_moveable = un_anf_and_moveable ident_info env body in
+      Ulet (id, def, body), both_moveable def_moveable body_moveable
+    end
+  | Uletrec (defs, body) ->
+    let defs =
+      List.map (fun (id, def) -> id, un_anf ident_info env def) defs
+    in
+    let body = un_anf ident_info env body in
+    Uletrec (defs, body), Fixed
+  | Uprim (prim, args, dbg) ->
+    let args, args_moveable = un_anf_list_and_moveable ident_info env args in
+    let moveable =
+      both_moveable args_moveable (primitive_moveable prim args ident_info)
+    in
+    Uprim (prim, args, dbg), moveable
+  | Uswitch (cond, sw) ->
+    let cond = un_anf ident_info env cond in
+    let sw =
+      { sw with
+        us_actions_consts = un_anf_array ident_info env sw.us_actions_consts;
+        us_actions_blocks = un_anf_array ident_info env sw.us_actions_blocks;
+      }
+    in
+    Uswitch (cond, sw), Fixed
+  | Ustringswitch (cond, branches, default) ->
+    let cond = un_anf ident_info env cond in
+    let branches =
+      List.map (fun (s, branch) -> s, un_anf ident_info env branch)
+        branches
+    in
+    let default = Misc.may_map (un_anf ident_info env) default in
+    Ustringswitch (cond, branches, default), Fixed
+  | Ustaticfail (n, args) ->
+    let args = un_anf_list ident_info env args in
+    Ustaticfail (n, args), Fixed
+  | Ucatch (n, ids, body, handler) ->
+    let body = un_anf ident_info env body in
+    let handler = un_anf ident_info env handler in
+    Ucatch (n, ids, body, handler), Fixed
+  | Utrywith (body, id, handler) ->
+    let body = un_anf ident_info env body in
+    let handler = un_anf ident_info env handler in
+    Utrywith (body, id, handler), Fixed
+  | Uifthenelse (cond, ifso, ifnot) ->
+    let cond, cond_moveable = un_anf_and_moveable ident_info env cond in
+    let ifso, ifso_moveable = un_anf_and_moveable ident_info env ifso in
+    let ifnot, ifnot_moveable = un_anf_and_moveable ident_info env ifnot in
+    let moveable =
+      both_moveable cond_moveable
+        (both_moveable ifso_moveable ifnot_moveable)
+    in
+    Uifthenelse (cond, ifso, ifnot), moveable
+  | Usequence (e1, e2) ->
+    let e1 = un_anf ident_info env e1 in
+    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
+    Ufor (id, low, high, direction, body), Fixed
+  | Uassign (id, expr) ->
+    let expr = un_anf ident_info env expr in
+    Uassign (id, expr), Fixed
+  | Usend (kind, e1, e2, args, dbg) ->
+    let e1 = un_anf ident_info env e1 in
+    let e2 = un_anf ident_info env e2 in
+    let args = un_anf_list ident_info env args in
+    Usend (kind, e1, e2, args, dbg), Fixed
+  | Uunreachable ->
+    Uunreachable, Fixed
+
+and un_anf ident_info env clam : Clambda.ulambda =
+  let clam, _moveable = un_anf_and_moveable ident_info env clam in
+  clam
+
+and un_anf_list_and_moveable ident_info env clams
+      : Clambda.ulambda list * moveable =
+  List.fold_right (fun clam (l, acc_moveable) ->
+      let clam, moveable = un_anf_and_moveable ident_info env clam in
+      clam :: l, both_moveable moveable acc_moveable)
+    clams ([], (Moveable : moveable))
+
+and un_anf_list ident_info env clams : Clambda.ulambda list =
+  let clams, _moveable = un_anf_list_and_moveable ident_info env clams in
+  clams
+
+and un_anf_array ident_info env clams : Clambda.ulambda array =
+  Array.map (un_anf ident_info env) clams
+
+let apply clam ~what =
+  let ident_info = make_ident_info clam in
+  let let_bound_vars_that_can_be_moved =
+    let_bound_vars_that_can_be_moved ident_info clam
+  in
+  let clam =
+    substitute_let_moveable let_bound_vars_that_can_be_moved
+      Ident.Map.empty clam
+  in
+  let ident_info = make_ident_info clam in
+  let clam = un_anf ident_info Ident.Map.empty clam in
+  if !Clflags.dump_clambda then begin
+    Format.eprintf "@.un-anf (%s):@ %a@." what Printclambda.clambda clam
+  end;
+  clam
diff --git a/asmcomp/un_anf.mli b/asmcomp/un_anf.mli
new file mode 100644
index 00000000..004704da
--- /dev/null
+++ b/asmcomp/un_anf.mli
@@ -0,0 +1,22 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*                       Pierre Chambart, OCamlPro                        *)
+(*           Mark Shinwell and Leo White, Jane Street Europe              *)
+(*                                                                        *)
+(*   Copyright 2013--2016 OCamlPro SAS                                    *)
+(*   Copyright 2014--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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Expand ANF-like constructs so that pattern matches in [Cmmgen] will
+    work correctly. *)
+val apply
+   : Clambda.ulambda
+  -> what:string
+  -> Clambda.ulambda
diff --git a/asmcomp/x86_ast.mli b/asmcomp/x86_ast.mli
new file mode 100644
index 00000000..96d87beb
--- /dev/null
+++ b/asmcomp/x86_ast.mli
@@ -0,0 +1,219 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*          Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt        *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Structured representation of Intel assembly language (32 and 64 bit). *)
+
+type condition =
+  | L | GE     (* signed comparisons: less/greater *)
+  | LE | G
+  | B | AE     (* unsigned comparisons: below/above *)
+  | BE | A
+  | E | NE     (* equal *)
+  | O | NO     (* overflow *)
+  | S | NS     (* sign *)
+  | P | NP     (* parity *)
+
+type rounding =
+  | RoundUp
+  | RoundDown
+  | RoundNearest
+  | RoundTruncate
+
+type constant =
+  | Const of int64
+  | ConstThis
+  | ConstLabel of string
+  | ConstAdd of constant * constant
+  | ConstSub of constant * constant
+
+(* data_type is used mainly on memory addressing to specify
+   the size of the addressed memory chunk.  It is directly
+   used by the MASM emitter and indirectly by the GAS emitter
+   to infer the instruction suffix. *)
+
+type data_type =
+  | NONE
+  | REAL4 | REAL8 (* floating point values *)
+  | BYTE | WORD | DWORD | QWORD | OWORD (* integer values *)
+  | NEAR | PROC
+
+type reg64 =
+  | RAX | RBX | RCX | RDX | RSP | RBP | RSI | RDI
+  | R8 | R9 | R10 | R11 | R12 | R13 | R14 | R15
+
+type reg8h =
+  | AH | BH | CH | DH
+
+
+type registerf = XMM of int | TOS | ST of int
+
+type arch = X64 | X86
+
+type addr =
+  {
+    arch: arch;
+    typ: data_type;
+    idx: reg64;
+    scale: int;
+    base: reg64 option;
+    sym: string option;
+    displ: int;
+  }
+  (** Addressing modes:
+      displ + sym + base + idx * scale
+      (if scale = 0, idx is ignored and base must be None)
+  *)
+
+type arg =
+  | Imm of int64
+  (** Operand is an immediate constant integer *)
+
+  | Sym of  string
+  (** Address of a symbol (absolute address except for call/jmp target
+      where it is interpreted as a relative displacement *)
+
+  | Reg8L of reg64
+  | Reg8H of reg8h
+  | Reg16 of reg64
+  | Reg32 of reg64
+  | Reg64 of reg64
+  | Regf of registerf
+
+  | Mem of addr
+  | Mem64_RIP of data_type * string * int
+
+type instruction =
+  | ADD of arg * arg
+  | ADDSD of arg * arg
+  | AND of arg * arg
+  | ANDPD of arg * arg
+  | BSWAP of arg
+  | CALL of arg
+  | CDQ
+  | CMOV of condition * arg * arg
+  | CMP of arg * arg
+  | COMISD of arg * arg
+  | CQO
+  | CVTSD2SI of arg * arg
+  | CVTSD2SS of arg * arg
+  | CVTSI2SD of arg * arg
+  | CVTSS2SD of arg * arg
+  | CVTTSD2SI of arg * arg
+  | DEC of arg
+  | DIVSD of arg * arg
+  | FABS
+  | FADD of arg
+  | FADDP of arg * arg
+  | FCHS
+  | FCOMP of arg
+  | FCOMPP
+  | FCOS
+  | FDIV of arg
+  | FDIVP of arg * arg
+  | FDIVR of arg
+  | FDIVRP of arg * arg
+  | FILD of arg
+  | FISTP of arg
+  | FLD of arg
+  | FLD1
+  | FLDCW of arg
+  | FLDLG2
+  | FLDLN2
+  | FLDZ
+  | FMUL of arg
+  | FMULP of arg * arg
+  | FNSTCW of arg
+  | FNSTSW of arg
+  | FPATAN
+  | FPTAN
+  | FSIN
+  | FSQRT
+  | FSTP of arg
+  | FSUB of arg
+  | FSUBP of arg * arg
+  | FSUBR of arg
+  | FSUBRP of arg * arg
+  | FXCH of arg
+  | FYL2X
+  | HLT
+  | IDIV of arg
+  | IMUL of arg * arg option
+  | INC of arg
+  | J of condition * arg
+  | JMP of arg
+  | LEA of arg * arg
+  | LEAVE
+  | MOV of arg * arg
+  | MOVAPD of arg * arg
+  | MOVLPD of arg * arg
+  | MOVSD of arg * arg
+  | MOVSS of arg * arg
+  | MOVSX of arg * arg
+  | MOVSXD of arg * arg
+  | MOVZX of arg * arg
+  | MULSD of arg * arg
+  | NEG of arg
+  | NOP
+  | OR of arg * arg
+  | POP of arg
+  | PUSH of arg
+  | RET
+  | ROUNDSD of rounding * arg * arg
+  | SAL of arg * arg
+  | SAR of arg * arg
+  | SET of condition * arg
+  | SHR of arg * arg
+  | SQRTSD of arg * arg
+  | SUB of arg * arg
+  | SUBSD of arg * arg
+  | TEST of arg * arg
+  | UCOMISD of arg * arg
+  | XCHG of arg * arg
+  | XOR of arg * arg
+  | XORPD of arg * arg
+
+type asm_line =
+  | Ins of instruction
+
+  | Align of bool * int
+  | Byte of constant
+  | Bytes of string
+  | Comment of string
+  | Global of string
+  | Long of constant
+  | NewLabel of string * data_type
+  | Quad of constant
+  | Section of string list * string option * string list
+  | Space of int
+  | Word of constant
+
+  (* masm only (the gas emitter will fail on them) *)
+  | External of string * data_type
+  | Mode386
+  | Model of string
+
+  (* gas only (the masm emitter will fail on them) *)
+  | Cfi_adjust_cfa_offset of int
+  | Cfi_endproc
+  | Cfi_startproc
+  | File of int * string (* (file_num, file_name) *)
+  | Indirect_symbol of string
+  | Loc of int * int * int (* (file_num, line, col) *)
+  | Private_extern of string
+  | Set of string * constant
+  | Size of string * constant
+  | Type of string * string
+
+type asm_program = asm_line list
diff --git a/asmcomp/x86_dsl.ml b/asmcomp/x86_dsl.ml
new file mode 100644
index 00000000..6351c6a7
--- /dev/null
+++ b/asmcomp/x86_dsl.ml
@@ -0,0 +1,198 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*         Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt         *)
+(*                                                                        *)
+(*   Copyright 1996 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Helpers for Intel code generators *)
+
+(* The DSL* modules expose functions to emit x86/x86_64 instructions
+   using a syntax close to AT&T (in particular, arguments are reversed compared
+   to the official Intel syntax).
+
+   Some notes:
+
+     - Unary floating point instructions such as fadd/fmul/fstp/fld/etc.
+       come with a single version supporting both the single and double
+       precision instructions.  (As with Intel syntax.)
+
+     - A legacy bug in GAS:
+   https://sourceware.org/binutils/docs-2.22/as/i386_002dBugs.html#i386_002dBugs
+       is not replicated here.  It is managed by X86_gas.
+*)
+
+
+open X86_ast
+open X86_proc
+
+let sym s = Sym s
+
+let nat n = Imm (Int64.of_nativeint n)
+let int n = Imm (Int64.of_int n)
+
+let const_32 n = Const (Int64.of_int32 n)
+let const_nat n = Const (Int64.of_nativeint n)
+let const n = Const (Int64.of_int n)
+
+let al  = Reg8L RAX
+let ah  = Reg8H AH
+let cl  = Reg8L RCX
+let ax  = Reg16 RAX
+let rax = Reg64 RAX
+let r10 = Reg64 R10
+let r11 = Reg64 R11
+let r14 = Reg64 R14
+let r15 = Reg64 R15
+let rsp = Reg64 RSP
+let rbp = Reg64 RBP
+let xmm15 = Regf (XMM 15)
+let eax = Reg32 RAX
+let ebx = Reg32 RBX
+let ecx = Reg32 RCX
+let edx = Reg32 RDX
+let ebp = Reg32 RBP
+let esp = Reg32 RSP
+let st0 = Regf (ST 0)
+let st1 = Regf (ST 1)
+
+let mem32 typ ?(scale = 1) ?base ?sym displ idx =
+  assert(scale >= 0);
+  Mem {arch = X86; typ; idx; scale; base; sym; displ}
+
+let mem64 typ ?(scale = 1) ?base ?sym displ idx =
+  assert(scale > 0);
+  Mem {arch = X64; typ; idx; scale; base; sym; displ}
+
+let mem64_rip typ ?(ofs = 0) s =
+  Mem64_RIP (typ, s, ofs)
+
+module D = struct
+  let section segment flags args = directive (Section (segment, flags, args))
+  let align n = directive (Align (false, n))
+  let byte n = directive (Byte n)
+  let bytes s = directive (Bytes s)
+  let cfi_adjust_cfa_offset n = directive (Cfi_adjust_cfa_offset n)
+  let cfi_endproc () = directive Cfi_endproc
+  let cfi_startproc () = directive Cfi_startproc
+  let comment s = directive (Comment s)
+  let data () = section [ ".data" ] None []
+  let extrn s ptr = directive (External (s, ptr))
+  let file ~file_num ~file_name = directive (File (file_num, file_name))
+  let global s = directive (Global s)
+  let indirect_symbol s = directive (Indirect_symbol s)
+  let label ?(typ = NONE) s = directive (NewLabel (s, typ))
+  let loc ~file_num ~line ~col = directive (Loc (file_num, line, col))
+  let long cst = directive (Long cst)
+  let mode386 () = directive Mode386
+  let model name = directive (Model name)
+  let private_extern s = directive (Private_extern s)
+  let qword cst = directive (Quad cst)
+  let setvar (x, y) = directive (Set (x, y))
+  let size name cst = directive (Size (name, cst))
+  let space n = directive (Space n)
+  let text () = section [ ".text" ] None []
+  let type_ name typ = directive (Type (name, typ))
+  let word cst = directive (Word cst)
+end
+
+module I = struct
+  let add x y = emit (ADD (x, y))
+  let addsd x y = emit (ADDSD (x, y))
+  let and_ x y= emit (AND (x, y))
+  let andpd x y = emit (ANDPD (x, y))
+  let bswap x = emit (BSWAP x)
+  let call x = emit (CALL x)
+  let cdq () = emit CDQ
+  let cmp x y = emit (CMP (x, y))
+  let comisd x y = emit (COMISD (x, y))
+  let cqo () = emit CQO
+  let cvtsd2ss x y = emit (CVTSD2SS (x, y))
+  let cvtsi2sd x y = emit (CVTSI2SD (x, y))
+  let cvtss2sd x y = emit (CVTSS2SD (x, y))
+  let cvttsd2si x y = emit (CVTTSD2SI (x, y))
+  let dec x = emit (DEC x)
+  let divsd x y = emit (DIVSD (x, y))
+  let fabs () = emit FABS
+  let fadd x = emit (FADD x)
+  let faddp x y = emit (FADDP (x, y))
+  let fchs () = emit FCHS
+  let fcomp x = emit (FCOMP x)
+  let fcompp () = emit FCOMPP
+  let fcos () = emit FCOS
+  let fdiv x = emit (FDIV x)
+  let fdivp x y = emit (FDIVP (x, y))
+  let fdivr x = emit (FDIVR x)
+  let fdivrp x y = emit (FDIVRP (x, y))
+  let fild x = emit (FILD x)
+  let fistp x = emit (FISTP x)
+  let fld x = emit (FLD x)
+  let fld1 () = emit FLD1
+  let fldcw x = emit (FLDCW x)
+  let fldlg2 () = emit FLDLG2
+  let fldln2 () = emit FLDLN2
+  let fldz () = emit FLDZ
+  let fmul x = emit (FMUL x)
+  let fmulp x y = emit (FMULP (x, y))
+  let fnstcw x = emit (FNSTCW x)
+  let fnstsw x = emit (FNSTSW x)
+  let fpatan () = emit FPATAN
+  let fptan () = emit FPTAN
+  let fsin () = emit FSIN
+  let fsqrt () = emit FSQRT
+  let fstp x = emit (FSTP x)
+  let fsub x = emit (FSUB x)
+  let fsubp x y = emit (FSUBP (x, y))
+  let fsubr x = emit (FSUBR x)
+  let fsubrp x y = emit (FSUBRP (x, y))
+  let fxch x = emit (FXCH x)
+  let fyl2x () = emit FYL2X
+  let hlt () = emit HLT
+  let idiv x = emit (IDIV x)
+  let imul x y = emit (IMUL (x, y))
+  let inc x = emit (INC x)
+  let j cond x = emit (J (cond, x))
+  let ja = j A
+  let jae = j AE
+  let jb = j B
+  let jbe = j BE
+  let je = j E
+  let jg = j G
+  let jmp x = emit (JMP x)
+  let jne = j NE
+  let jp = j P
+  let lea x y = emit (LEA (x, y))
+  let mov x y = emit (MOV (x, y))
+  let movapd x y = emit (MOVAPD (x, y))
+  let movsd x y = emit (MOVSD (x, y))
+  let movss x y = emit (MOVSS (x, y))
+  let movsx x y = emit (MOVSX (x, y))
+  let movsxd x y = emit (MOVSXD  (x, y))
+  let movzx x y = emit (MOVZX (x, y))
+  let mulsd x y = emit (MULSD (x, y))
+  let nop () = emit NOP
+  let or_ x y = emit (OR (x, y))
+  let pop x = emit (POP x)
+  let push x = emit (PUSH x)
+  let ret () = emit RET
+  let sal x y = emit (SAL (x, y))
+  let sar x y = emit (SAR (x, y))
+  let set cond x = emit (SET (cond, x))
+  let shr x y = emit (SHR (x, y))
+  let sqrtsd x y = emit (SQRTSD (x, y))
+  let sub x y = emit (SUB (x, y))
+  let subsd  x y = emit (SUBSD (x, y))
+  let test x y= emit (TEST (x, y))
+  let ucomisd x y = emit (UCOMISD (x, y))
+  let xchg x y = emit (XCHG (x, y))
+  let xor x y= emit (XOR (x, y))
+  let xorpd x y = emit (XORPD (x, y))
+end
diff --git a/asmcomp/x86_dsl.mli b/asmcomp/x86_dsl.mli
new file mode 100644
index 00000000..d73770b2
--- /dev/null
+++ b/asmcomp/x86_dsl.mli
@@ -0,0 +1,191 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*         Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt         *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Helpers for Intel code generators *)
+
+(* The DSL* modules expose functions to emit x86/x86_64 instructions
+   using a syntax close to the official Intel syntax, except that
+   source and destination operands are reversed as in the AT&T
+   syntax:
+
+     mov src dst
+*)
+
+
+open X86_ast
+
+val sym: string -> arg
+val nat: nativeint -> arg
+val int: int -> arg
+val const_32: int32 -> constant
+val const_nat: nativeint -> constant
+val const: int -> constant
+val al: arg
+val ah: arg
+val cl: arg
+val ax: arg
+val rax: arg
+val r10: arg
+val r11: arg
+val r14: arg
+val r15: arg
+val rsp: arg
+val rbp: arg
+val xmm15: arg
+val eax: arg
+val ebx: arg
+val ecx: arg
+val edx: arg
+val ebp: arg
+val esp: arg
+val st0: arg
+val st1: arg
+
+val mem32:
+  data_type -> ?scale:int -> ?base:reg64 -> ?sym:string ->
+  int -> reg64 -> arg
+
+val mem64:
+  data_type -> ?scale:int -> ?base:reg64 -> ?sym:string ->
+  int -> reg64 -> arg
+
+val mem64_rip: data_type -> ?ofs:int -> string -> arg
+
+
+module D : sig
+  (** Directives *)
+
+  val align: int -> unit
+  val byte: constant -> unit
+  val bytes: string -> unit
+  val cfi_adjust_cfa_offset: int -> unit
+  val cfi_endproc: unit -> unit
+  val cfi_startproc: unit -> unit
+  val comment: string -> unit
+  val data: unit -> unit
+  val extrn: string -> data_type -> unit
+  val file: file_num:int -> file_name:string -> unit
+  val global: string -> unit
+  val indirect_symbol: string -> unit
+  val label: ?typ:data_type -> string -> unit
+  val loc: file_num:int -> line:int -> col:int -> unit
+  val long: constant -> unit
+  val mode386: unit -> unit
+  val model: string -> unit
+  val private_extern: string -> unit
+  val qword: constant -> unit
+  val section: string list -> string option -> string list -> unit
+  val setvar: string * constant -> unit
+  val size: string -> constant -> unit
+  val space: int -> unit
+  val text: unit -> unit
+  val type_: string -> string -> unit
+  val word: constant -> unit
+end
+
+module I : sig
+  (* Instructions *)
+
+  val add: arg -> arg -> unit
+  val addsd: arg -> arg -> unit
+  val and_: arg -> arg -> unit
+  val andpd: arg -> arg -> unit
+  val bswap: arg -> unit
+  val call: arg -> unit
+  val cdq: unit -> unit
+  val cmp: arg -> arg -> unit
+  val comisd: arg -> arg -> unit
+  val cqo: unit -> unit
+  val cvtsd2ss: arg -> arg -> unit
+  val cvtsi2sd: arg -> arg -> unit
+  val cvtss2sd: arg -> arg -> unit
+  val cvttsd2si: arg -> arg -> unit
+  val dec: arg -> unit
+  val divsd: arg -> arg -> unit
+  val fabs: unit -> unit
+  val fadd: arg -> unit
+  val faddp: arg -> arg -> unit
+  val fchs: unit -> unit
+  val fcomp: arg -> unit
+  val fcompp: unit -> unit
+  val fcos: unit -> unit
+  val fdiv: arg -> unit
+  val fdivp: arg -> arg -> unit
+  val fdivr: arg -> unit
+  val fdivrp: arg -> arg -> unit
+  val fild: arg -> unit
+  val fistp: arg -> unit
+  val fld1: unit -> unit
+  val fld: arg -> unit
+  val fldcw: arg -> unit
+  val fldlg2: unit -> unit
+  val fldln2: unit -> unit
+  val fldz: unit -> unit
+  val fmul: arg -> unit
+  val fmulp: arg -> arg -> unit
+  val fnstcw: arg -> unit
+  val fnstsw: arg -> unit
+  val fpatan: unit -> unit
+  val fptan: unit -> unit
+  val fsin: unit -> unit
+  val fsqrt: unit -> unit
+  val fstp: arg -> unit
+  val fsub: arg -> unit
+  val fsubp: arg -> arg -> unit
+  val fsubr: arg -> unit
+  val fsubrp: arg -> arg -> unit
+  val fxch: arg -> unit
+  val fyl2x: unit -> unit
+  val hlt: unit -> unit
+  val idiv: arg -> unit
+  val imul: arg -> arg option -> unit
+  val inc: arg -> unit
+  val j: condition -> arg -> unit
+  val ja: arg -> unit
+  val jae: arg -> unit
+  val jb: arg -> unit
+  val jbe: arg -> unit
+  val je: arg -> unit
+  val jg: arg -> unit
+  val jmp: arg -> unit
+  val jne: arg -> unit
+  val jp: arg -> unit
+  val lea: arg -> arg -> unit
+  val mov: arg -> arg -> unit
+  val movapd: arg -> arg -> unit
+  val movsd: arg -> arg -> unit
+  val movss: arg -> arg -> unit
+  val movsx: arg -> arg -> unit
+  val movsxd: arg -> arg -> unit
+  val movzx: arg -> arg -> unit
+  val mulsd: arg -> arg -> unit
+  val nop: unit -> unit
+  val or_: arg -> arg -> unit
+  val pop: arg -> unit
+  val push: arg -> unit
+  val ret: unit -> unit
+  val sal: arg -> arg -> unit
+  val sar: arg -> arg -> unit
+  val set: condition -> arg -> unit
+  val shr: arg -> arg -> unit
+  val sqrtsd: arg -> arg -> unit
+  val sub: arg -> arg -> unit
+  val subsd: arg -> arg -> unit
+  val test: arg -> arg -> unit
+  val ucomisd: arg -> arg -> unit
+  val xchg: arg -> arg -> unit
+  val xor: arg -> arg -> unit
+  val xorpd: arg -> arg -> unit
+end
diff --git a/asmcomp/x86_gas.ml b/asmcomp/x86_gas.ml
new file mode 100644
index 00000000..f905dc33
--- /dev/null
+++ b/asmcomp/x86_gas.ml
@@ -0,0 +1,311 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*         Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt         *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+open X86_ast
+open X86_proc
+
+let bprintf = Printf.bprintf
+
+let print_reg b f r =
+  Buffer.add_char b '%';
+  Buffer.add_string b (f r)
+
+let opt_displ b displ =
+  if displ = 0 then ()
+  else if displ > 0 then bprintf b "+%d" displ
+  else bprintf b "%d" displ
+
+let arg_mem b {arch; typ=_; idx; scale; base; sym; displ} =
+  let string_of_register =
+    match arch with
+    | X86 -> string_of_reg32
+    | X64 -> string_of_reg64
+  in
+  begin match sym with
+  | None ->
+      if displ <> 0 || scale = 0 then
+        Buffer.add_string b (string_of_int displ)
+  | Some s ->
+      Buffer.add_string b s;
+      opt_displ b displ
+  end;
+  if scale <> 0 then begin
+    Buffer.add_char b '(';
+    begin match base with
+    | None -> ()
+    | Some base -> print_reg b string_of_register base
+    end;
+    if base != None || scale <> 1 then Buffer.add_char b ',';
+    print_reg b string_of_register idx;
+    if scale <> 1 then bprintf b ",%s" (string_of_int scale);
+    Buffer.add_char b ')'
+  end
+
+let arg b = function
+  | Sym x -> Buffer.add_char b '$'; Buffer.add_string b x
+  | Imm x -> bprintf b "$%Ld" x
+  | Reg8L x -> print_reg b string_of_reg8l x
+  | Reg8H x -> print_reg b string_of_reg8h x
+  | Reg16 x -> print_reg b string_of_reg16 x
+  | Reg32 x -> print_reg b string_of_reg32 x
+  | Reg64 x -> print_reg b string_of_reg64 x
+  | Regf x  -> print_reg b string_of_registerf x
+  | Mem addr -> arg_mem b addr
+  | Mem64_RIP (_, s, displ) -> bprintf b "%s%a(%%rip)" s opt_displ displ
+
+let rec cst b = function
+  | ConstLabel _ | Const _ | ConstThis as c -> scst b c
+  | ConstAdd (c1, c2) -> bprintf b "%a + %a" scst c1 scst c2
+  | ConstSub (c1, c2) -> bprintf b "%a - %a" scst c1 scst c2
+
+and scst b = function
+  | ConstThis -> Buffer.add_string b "."
+  | ConstLabel l -> Buffer.add_string b l
+  | Const n when n <= 0x7FFF_FFFFL && n >= -0x8000_0000L ->
+      Buffer.add_string b (Int64.to_string n)
+  | Const n -> bprintf b "0x%Lx" n
+  | ConstAdd (c1, c2) -> bprintf b "(%a + %a)" scst c1 scst c2
+  | ConstSub (c1, c2) -> bprintf b "(%a - %a)" scst c1 scst c2
+
+let typeof = function
+  | Mem {typ; _} | Mem64_RIP (typ, _, _) -> typ
+  | Reg8L _ | Reg8H _ -> BYTE
+  | Reg16 _ -> WORD
+  | Reg32 _ -> DWORD
+  | Reg64 _ -> QWORD
+  | Imm _ | Sym _ -> NONE
+  | Regf _ -> assert false
+
+let suf arg =
+  match typeof arg with
+  | BYTE -> "b"
+  | WORD -> "w"
+  | DWORD | REAL8 -> "l"
+  | QWORD -> "q"
+  | REAL4 -> "s"
+  | NONE -> ""
+  | OWORD | NEAR | PROC -> assert false
+
+let i0 b s = bprintf b "\t%s" s
+let i1 b s x = bprintf b "\t%s\t%a" s arg x
+let i1_s b s x = bprintf b "\t%s%s\t%a" s (suf x) arg x
+let i2 b s x y = bprintf b "\t%s\t%a, %a" s arg x arg y
+let i2_s b s x y = bprintf b "\t%s%s\t%a, %a" s (suf y) arg x arg y
+let i2_ss b s x y = bprintf b "\t%s%s%s\t%a, %a" s (suf x) (suf y) arg x arg y
+
+let i1_call_jmp b s = function
+  (* this is the encoding of jump labels: don't use * *)
+  | Mem {arch=X86; idx=_;   scale=0; base=None; sym=Some _; _} as x ->
+      i1 b s x
+  | Reg32 _ | Reg64 _ | Mem _  | Mem64_RIP _ as x ->
+      bprintf b "\t%s\t*%a" s arg x
+  | Sym x -> bprintf b "\t%s\t%s" s x
+  | _ -> assert false
+
+let print_instr b = function
+  | ADD (arg1, arg2) -> i2_s b "add" arg1 arg2
+  | ADDSD (arg1, arg2) -> i2 b "addsd" arg1 arg2
+  | AND (arg1, arg2) -> i2_s b "and" arg1 arg2
+  | ANDPD (arg1, arg2) -> i2 b "andpd" arg1 arg2
+  | BSWAP arg -> i1 b "bswap" arg
+  | CALL arg  -> i1_call_jmp b "call" arg
+  | CDQ -> i0 b "cltd"
+  | CMOV (c, arg1, arg2) -> i2 b ("cmov" ^ string_of_condition c) arg1 arg2
+  | CMP (arg1, arg2) -> i2_s b "cmp" arg1 arg2
+  | COMISD (arg1, arg2) -> i2 b "comisd" arg1 arg2
+  | CQO ->  i0 b "cqto"
+  | CVTSD2SI (arg1, arg2) -> i2 b "cvtsd2si" arg1 arg2
+  | CVTSD2SS (arg1, arg2) -> i2 b "cvtsd2ss" arg1 arg2
+  | CVTSI2SD (arg1, arg2) -> i2 b ("cvtsi2sd" ^ suf arg1) arg1 arg2
+  | CVTSS2SD (arg1, arg2) -> i2 b "cvtss2sd" arg1 arg2
+  | CVTTSD2SI (arg1, arg2) -> i2_s b "cvttsd2si" arg1 arg2
+  | DEC arg -> i1_s b "dec" arg
+  | DIVSD (arg1, arg2) -> i2 b "divsd" arg1 arg2
+  | FABS -> i0 b "fabs"
+  | FADD arg -> i1_s b "fadd" arg
+  | FADDP (arg1, arg2)  -> i2 b "faddp" arg1 arg2
+  | FCHS -> i0 b "fchs"
+  | FCOMP arg -> i1_s b "fcomp" arg
+  | FCOMPP -> i0 b "fcompp"
+  | FCOS -> i0 b "fcos"
+  | FDIV arg -> i1_s b "fdiv" arg
+  | FDIVP (Regf (ST 0), arg2)  -> i2 b "fdivrp" (Regf (ST 0)) arg2 (* bug *)
+  | FDIVP (arg1, arg2)  -> i2 b "fdivp" arg1 arg2
+  | FDIVR arg -> i1_s b "fdivr" arg
+  | FDIVRP (Regf (ST 0), arg2)  -> i2 b "fdivp" (Regf (ST 0)) arg2 (* bug *)
+  | FDIVRP (arg1, arg2)  -> i2 b "fdivrp" arg1 arg2
+  | FILD arg -> i1_s b "fild" arg
+  | FISTP arg -> i1_s b "fistp" arg
+  | FLD (Mem {typ=REAL4; _} as arg) -> i1 b "flds" arg
+  | FLD arg -> i1 b "fldl" arg
+  | FLD1 -> i0 b "fld1"
+  | FLDCW arg -> i1 b "fldcw" arg
+  | FLDLG2 -> i0 b "fldlg2"
+  | FLDLN2 -> i0 b "fldln2"
+  | FLDZ -> i0 b "fldz"
+  | FMUL arg -> i1_s b "fmul" arg
+  | FMULP (arg1, arg2)  -> i2 b "fmulp" arg1 arg2
+  | FNSTCW arg -> i1 b "fnstcw" arg
+  | FNSTSW arg -> i1 b "fnstsw" arg
+  | FPATAN -> i0 b "fpatan"
+  | FPTAN -> i0 b "fptan"
+  | FSIN -> i0 b "fsin"
+  | FSQRT -> i0 b "fsqrt"
+  | FSTP (Mem {typ=REAL4; _} as arg) -> i1 b "fstps" arg
+  | FSTP arg -> i1 b "fstpl" arg
+  | FSUB arg -> i1_s b "fsub" arg
+  | FSUBP (Regf (ST 0), arg2)  -> i2 b "fsubrp" (Regf (ST 0)) arg2 (* bug *)
+  | FSUBP (arg1, arg2)  -> i2 b "fsubp" arg1 arg2
+  | FSUBR arg -> i1_s b "fsubr" arg
+  | FSUBRP (Regf (ST 0), arg2) -> i2 b "fsubp" (Regf (ST 0)) arg2 (* bug *)
+  | FSUBRP (arg1, arg2)  -> i2 b "fsubrp" arg1 arg2
+  | FXCH arg -> i1 b "fxch" arg
+  | FYL2X -> i0 b "fyl2x"
+  | HLT -> i0 b "hlt"
+  | IDIV arg -> i1_s b "idiv" arg
+  | IMUL (arg, None) -> i1_s b "imul" arg
+  | IMUL (arg1, Some arg2) -> i2_s b "imul" arg1 arg2
+  | INC arg -> i1_s b "inc" arg
+  | J (c, arg) -> i1_call_jmp b ("j" ^ string_of_condition c) arg
+  | JMP arg -> i1_call_jmp b "jmp" arg
+  | LEA (arg1, arg2) -> i2_s b "lea" arg1 arg2
+  | LEAVE -> i0 b "leave"
+  | MOV ((Imm n as arg1), (Reg64 _ as arg2))
+    when not (n <= 0x7FFF_FFFFL && n >= -0x8000_0000L) ->
+      i2 b "movabsq" arg1 arg2
+  | MOV ((Sym _ as arg1), (Reg64 _ as arg2)) when windows ->
+      i2 b "movabsq" arg1 arg2
+  | MOV (arg1, arg2) -> i2_s b "mov" arg1 arg2
+  | MOVAPD (arg1, arg2) -> i2 b "movapd" arg1 arg2
+  | MOVLPD (arg1, arg2) -> i2 b "movlpd" arg1 arg2
+  | MOVSD (arg1, arg2) -> i2 b "movsd" arg1 arg2
+  | MOVSS (arg1, arg2) -> i2 b "movss" arg1 arg2
+  | MOVSX (arg1, arg2) -> i2_ss b "movs" arg1 arg2
+  | MOVSXD (arg1, arg2) -> i2 b "movslq" arg1 arg2
+  | MOVZX (arg1, arg2) -> i2_ss b "movz" arg1 arg2
+  | MULSD (arg1, arg2) -> i2 b "mulsd" arg1 arg2
+  | NEG arg -> i1 b "neg" arg
+  | NOP -> i0 b "nop"
+  | OR (arg1, arg2) -> i2_s b "or" arg1 arg2
+  | POP  arg -> i1_s b "pop" arg
+  | PUSH arg -> i1_s b "push" arg
+  | RET ->  i0 b "ret"
+  | ROUNDSD (r, arg1, arg2) -> i2 b (string_of_rounding r) arg1 arg2
+  | SAL (arg1, arg2) -> i2_s b "sal" arg1 arg2
+  | SAR (arg1, arg2) -> i2_s b "sar" arg1 arg2
+  | SET (c, arg) -> i1 b ("set" ^ string_of_condition c) arg
+  | SHR (arg1, arg2) -> i2_s b "shr" arg1 arg2
+  | SQRTSD (arg1, arg2) -> i2 b "sqrtsd" arg1 arg2
+  | SUB (arg1, arg2) -> i2_s b "sub" arg1 arg2
+  | SUBSD (arg1, arg2) -> i2 b "subsd" arg1 arg2
+  | TEST (arg1, arg2) -> i2_s b "test" arg1 arg2
+  | UCOMISD (arg1, arg2) -> i2 b "ucomisd" arg1 arg2
+  | XCHG (arg1, arg2) -> i2 b "xchg" arg1 arg2
+  | XOR (arg1, arg2) -> i2_s b "xor" arg1 arg2
+  | XORPD (arg1, arg2) -> i2 b "xorpd" arg1 arg2
+
+(* bug:
+   https://sourceware.org/binutils/docs-2.22/as/i386_002dBugs.html#i386_002dBugs
+
+   The AT&T syntax has a bug for fsub/fdiv/fsubr/fdivr instructions when
+   the source register is %st and the destination is %st(i).  In those
+   case, AT&T use fsub (resp. fsubr) in place of fsubr (resp. fsub),
+   and idem for fdiv/fdivr.
+
+   Concretely, AT&T syntax interpretation of:
+
+      fsub  %st, %st(3)
+
+   should normally be:
+
+      %st(3) := %st(3) - %st
+
+   but it should actually be interpreted as:
+
+      %st(3) := %st - %st(3)
+
+   which means the FSUBR instruction should be used.
+*)
+
+
+let print_line b = function
+  | Ins instr -> print_instr b instr
+
+  | Align (_data,n) ->
+      (* MacOSX assembler interprets the integer n as a 2^n alignment *)
+      let n = if system = S_macosx then Misc.log2 n else n in
+      bprintf b "\t.align\t%d" n
+  | Byte n -> bprintf b "\t.byte\t%a" cst n
+  | Bytes s ->
+      if system = S_solaris then buf_bytes_directive b ".byte" s
+      else bprintf b "\t.ascii\t\"%s\"" (string_of_string_literal s)
+  | Comment s -> bprintf b "\t\t\t\t/* %s */" s
+  | Global s -> bprintf b "\t.globl\t%s" s;
+  | Long n -> bprintf b "\t.long\t%a" cst n
+  | NewLabel (s, _) -> bprintf b "%s:" s
+  | Quad n -> bprintf b "\t.quad\t%a" cst n
+  | Section ([".data" ], _, _) -> bprintf b "\t.data"
+  | Section ([".text" ], _, _) -> bprintf b "\t.text"
+  | Section (name, flags, args) ->
+      bprintf b "\t.section %s" (String.concat "," name);
+      begin match flags with
+      | None -> ()
+      | Some flags -> bprintf b ",%S" flags
+      end;
+      begin match args with
+      | [] -> ()
+      | _ -> bprintf b ",%s" (String.concat "," args)
+      end
+  | Space n ->
+      if system = S_solaris then bprintf b "\t.zero\t%d" n
+      else bprintf b "\t.space\t%d" n
+  | Word n ->
+      if system = S_solaris then bprintf b "\t.value\t%a" cst n
+      else bprintf b "\t.word\t%a" cst n
+
+  (* gas only *)
+  | Cfi_adjust_cfa_offset n -> bprintf b "\t.cfi_adjust_cfa_offset %d" n
+  | Cfi_endproc -> bprintf b "\t.cfi_endproc"
+  | Cfi_startproc -> bprintf b "\t.cfi_startproc"
+  | File (file_num, file_name) ->
+      bprintf b "\t.file\t%d\t\"%s\""
+        file_num (X86_proc.string_of_string_literal file_name)
+  | Indirect_symbol s -> bprintf b "\t.indirect_symbol %s" s
+  | Loc (file_num, line, col) ->
+      (* PR#7726: Location.none uses column -1, breaks LLVM assembler *)
+      if col >= 0 then bprintf b "\t.loc\t%d\t%d\t%d" file_num line col
+      else bprintf b "\t.loc\t%d\t%d" file_num line
+  | Private_extern s -> bprintf b "\t.private_extern %s" s
+  | Set (arg1, arg2) -> bprintf b "\t.set %s, %a" arg1 cst arg2
+  | Size (s, c) -> bprintf b "\t.size %s,%a" s cst c
+  | Type (s, typ) -> bprintf b "\t.type %s,%s" s typ
+
+  (* masm only *)
+  | External _
+  | Mode386
+  | Model _
+    -> assert false
+
+let generate_asm oc lines =
+  let b = Buffer.create 10000 in
+  output_string oc "\t.file \"\"\n"; (* PR#7037 *)
+  List.iter
+    (fun i ->
+       Buffer.clear b;
+       print_line b i;
+       Buffer.add_char b '\n';
+       Buffer.output_buffer oc b;
+    )
+    lines
diff --git a/asmcomp/x86_gas.mli b/asmcomp/x86_gas.mli
new file mode 100644
index 00000000..3c3a4aee
--- /dev/null
+++ b/asmcomp/x86_gas.mli
@@ -0,0 +1,18 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*         Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt         *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Emit assembly instructions for gas. *)
+
+val generate_asm: out_channel -> X86_ast.asm_line list -> unit
diff --git a/asmcomp/x86_masm.ml b/asmcomp/x86_masm.ml
new file mode 100644
index 00000000..eb010b8b
--- /dev/null
+++ b/asmcomp/x86_masm.ml
@@ -0,0 +1,261 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*         Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt         *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+open X86_ast
+open X86_proc
+
+let bprintf = Printf.bprintf
+
+let string_of_datatype = function
+  | QWORD -> "QWORD"
+  | OWORD -> "OWORD"
+  | NONE -> assert false
+  | REAL4 -> "REAL4"
+  | REAL8 -> "REAL8"
+  | BYTE -> "BYTE"
+  | WORD -> "WORD"
+  | DWORD -> "DWORD"
+  | NEAR -> "NEAR"
+  | PROC -> "PROC"
+
+
+let string_of_datatype_ptr = function
+  | QWORD -> "QWORD PTR "
+  | OWORD -> "OWORD PTR "
+  | NONE -> ""
+  | REAL4 -> "REAL4 PTR "
+  | REAL8 -> "REAL8 PTR "
+  | BYTE -> "BYTE PTR "
+  | WORD -> "WORD PTR "
+  | DWORD -> "DWORD PTR "
+  | NEAR -> "NEAR PTR "
+  | PROC -> "PROC PTR "
+
+let arg_mem b {arch; typ; idx; scale; base; sym; displ} =
+  let string_of_register =
+    match arch with
+    | X86 -> string_of_reg32
+    | X64 -> string_of_reg64
+  in
+  Buffer.add_string b (string_of_datatype_ptr typ);
+  Buffer.add_char b '[';
+  begin match sym with
+  | None -> ()
+  | Some s -> Buffer.add_string b s
+  end;
+  if scale <> 0 then begin
+    if sym <> None then Buffer.add_char b '+';
+    Buffer.add_string b (string_of_register idx);
+    if scale <> 1 then bprintf b "*%d" scale;
+  end;
+  begin match base with
+  | None -> ()
+  | Some r ->
+      assert(scale > 0);
+      Buffer.add_char b '+';
+      Buffer.add_string b (string_of_register r);
+  end;
+  begin if displ > 0 then bprintf b "+%d" displ
+    else if displ < 0 then bprintf b "%d" displ
+  end;
+  Buffer.add_char b ']'
+
+let arg b = function
+  | Sym s -> bprintf b "OFFSET %s" s
+  | Imm n when n <= 0x7FFF_FFFFL && n >= -0x8000_0000L -> bprintf b "%Ld" n
+  | Imm int -> bprintf b "0%LxH" int (* force ml64 to use mov reg, imm64 *)
+  | Reg8L x -> Buffer.add_string b (string_of_reg8l x)
+  | Reg8H x -> Buffer.add_string b (string_of_reg8h x)
+  | Reg16 x -> Buffer.add_string b (string_of_reg16 x)
+  | Reg32 x -> Buffer.add_string b (string_of_reg32 x)
+  | Reg64 x -> Buffer.add_string b (string_of_reg64 x)
+  | Regf x -> Buffer.add_string b (string_of_registerf x)
+
+  (* We don't need to specify RIP on Win64, since EXTERN will provide
+     the list of external symbols that need this addressing mode, and
+     MASM will automatically use RIP addressing when needed. *)
+  | Mem64_RIP (typ, s, displ) ->
+      bprintf b "%s%s" (string_of_datatype_ptr typ) s;
+      if displ > 0 then bprintf b "+%d" displ
+      else if displ < 0 then bprintf b "%d" displ
+  | Mem addr -> arg_mem b addr
+
+let rec cst b = function
+  | ConstLabel _ | Const _ | ConstThis as c -> scst b c
+  | ConstAdd (c1, c2) -> bprintf b "%a + %a" scst c1 scst c2
+  | ConstSub (c1, c2) -> bprintf b "%a - %a" scst c1 scst c2
+
+and scst b = function
+  | ConstThis -> Buffer.add_string b "THIS BYTE"
+  | ConstLabel l -> Buffer.add_string b l
+  | Const n when n <= 0x7FFF_FFFFL && n >= -0x8000_0000L ->
+      Buffer.add_string b (Int64.to_string n)
+  | Const n -> bprintf b "0%LxH" n
+  | ConstAdd (c1, c2) -> bprintf b "(%a + %a)" scst c1 scst c2
+  | ConstSub (c1, c2) -> bprintf b "(%a - %a)" scst c1 scst c2
+
+let i0 b s = bprintf b "\t%s" s
+let i1 b s x = bprintf b "\t%s\t%a" s arg x
+let i2 b s x y = bprintf b "\t%s\t%a, %a" s arg y arg x
+
+let i1_call_jmp b s = function
+  | Sym x -> bprintf b "\t%s\t%s" s x
+  | x -> i1 b s x
+
+let print_instr b = function
+  | ADD (arg1, arg2) -> i2 b "add" arg1 arg2
+  | ADDSD (arg1, arg2) -> i2 b "addsd" arg1 arg2
+  | AND (arg1, arg2) -> i2 b "and" arg1 arg2
+  | ANDPD (arg1, arg2) -> i2 b "andpd" arg1 arg2
+  | BSWAP arg -> i1 b "bswap" arg
+  | CALL arg  -> i1_call_jmp b "call" arg
+  | CDQ -> i0 b "cdq"
+  | CMOV (c, arg1, arg2) -> i2 b ("cmov" ^ string_of_condition c) arg1 arg2
+  | CMP (arg1, arg2) -> i2 b "cmp" arg1 arg2
+  | COMISD (arg1, arg2) -> i2 b "comisd" arg1 arg2
+  | CQO -> i0 b "cqo"
+  | CVTSD2SI (arg1, arg2) -> i2 b "cvtsd2si" arg1 arg2
+  | CVTSD2SS (arg1, arg2) -> i2 b "cvtsd2ss" arg1 arg2
+  | CVTSI2SD (arg1, arg2) -> i2 b "cvtsi2sd" arg1 arg2
+  | CVTSS2SD (arg1, arg2) -> i2 b "cvtss2sd" arg1 arg2
+  | CVTTSD2SI (arg1, arg2) -> i2 b "cvttsd2si" arg1 arg2
+  | DEC arg -> i1 b "dec" arg
+  | DIVSD (arg1, arg2) -> i2 b "divsd" arg1 arg2
+  | FABS -> i0 b "fabs"
+  | FADD arg -> i1 b "fadd" arg
+  | FADDP (arg1, arg2)  -> i2 b "faddp" arg1 arg2
+  | FCHS -> i0 b "fchs"
+  | FCOMP arg -> i1 b "fcomp" arg
+  | FCOMPP -> i0 b "fcompp"
+  | FCOS -> i0 b "fcos"
+  | FDIV arg -> i1 b "fdiv" arg
+  | FDIVP (arg1, arg2)  -> i2 b "fdivp" arg1 arg2
+  | FDIVR arg -> i1 b "fdivr" arg
+  | FDIVRP (arg1, arg2)  -> i2 b "fdivrp" arg1 arg2
+  | FILD arg -> i1 b "fild" arg
+  | FISTP arg -> i1 b "fistp" arg
+  | FLD arg -> i1 b "fld" arg
+  | FLD1 -> i0 b "fld1"
+  | FLDCW arg -> i1 b "fldcw" arg
+  | FLDLG2 -> i0 b "fldlg2"
+  | FLDLN2 -> i0 b "fldln2"
+  | FLDZ -> i0 b "fldz"
+  | FMUL arg -> i1 b "fmul" arg
+  | FMULP (arg1, arg2)  -> i2 b "fmulp" arg1 arg2
+  | FNSTCW arg -> i1 b "fnstcw" arg
+  | FNSTSW arg -> i1 b "fnstsw" arg
+  | FPATAN -> i0 b "fpatan"
+  | FPTAN -> i0 b "fptan"
+  | FSIN -> i0 b "fsin"
+  | FSQRT -> i0 b "fsqrt"
+  | FSTP arg -> i1 b "fstp" arg
+  | FSUB arg -> i1 b "fsub" arg
+  | FSUBP (arg1, arg2)  -> i2 b "fsubp" arg1 arg2
+  | FSUBR arg -> i1 b "fsubr" arg
+  | FSUBRP (arg1, arg2)  -> i2 b "fsubrp" arg1 arg2
+  | FXCH arg -> i1 b "fxch" arg
+  | FYL2X -> i0 b "fyl2x"
+  | HLT -> assert false
+  | IDIV arg -> i1 b "idiv" arg
+  | IMUL (arg, None) -> i1 b "imul" arg
+  | IMUL (arg1, Some arg2) -> i2 b "imul" arg1 arg2
+  | INC arg -> i1 b "inc" arg
+  | J (c, arg) -> i1_call_jmp b ("j" ^ string_of_condition c) arg
+  | JMP arg -> i1_call_jmp b "jmp" arg
+  | LEA (arg1, arg2) -> i2 b "lea" arg1 arg2
+  | LEAVE -> i0 b "leave"
+  | MOV (Imm n as arg1, Reg64 r) when
+      n >= 0x8000_0000L && n <= 0xFFFF_FFFFL ->
+      (* Work-around a bug in ml64.  Use a mov to the corresponding
+         32-bit lower register when the constant fits in 32-bit.
+         The associated higher 32-bit register will be zeroed. *)
+      i2 b "mov" arg1 (Reg32 r)
+  | MOV (arg1, arg2) -> i2 b "mov" arg1 arg2
+  | MOVAPD (arg1, arg2) -> i2 b "movapd" arg1 arg2
+  | MOVLPD (arg1, arg2) -> i2 b "movlpd" arg1 arg2
+  | MOVSD (arg1, arg2) -> i2 b "movsd" arg1 arg2
+  | MOVSS (arg1, arg2) -> i2 b "movss" arg1 arg2
+  | MOVSX (arg1, arg2) -> i2 b "movsx" arg1 arg2
+  | MOVSXD (arg1, arg2) -> i2 b "movsxd" arg1 arg2
+  | MOVZX (arg1, arg2) -> i2 b "movzx" arg1 arg2
+  | MULSD (arg1, arg2) -> i2 b "mulsd" arg1 arg2
+  | NEG arg -> i1 b "neg" arg
+  | NOP -> i0 b "nop"
+  | OR (arg1, arg2) -> i2 b "or" arg1 arg2
+  | POP arg -> i1 b "pop" arg
+  | PUSH arg -> i1 b "push" arg
+  | RET -> i0 b "ret"
+  | ROUNDSD (r, arg1, arg2) -> i2 b (string_of_rounding r) arg1 arg2
+  | SAL (arg1, arg2) -> i2 b "sal" arg1 arg2
+  | SAR (arg1, arg2) -> i2 b "sar" arg1 arg2
+  | SET (c, arg) -> i1 b ("set" ^ string_of_condition c) arg
+  | SHR (arg1, arg2) -> i2 b "shr" arg1 arg2
+  | SQRTSD (arg1, arg2) -> i2 b "sqrtsd" arg1 arg2
+  | SUB (arg1, arg2) -> i2 b "sub" arg1 arg2
+  | SUBSD (arg1, arg2) -> i2 b "subsd" arg1 arg2
+  | TEST (arg1, arg2) -> i2 b "test" arg1 arg2
+  | UCOMISD (arg1, arg2) -> i2 b "ucomisd" arg1 arg2
+  | XCHG (arg1, arg2) -> i2 b "xchg" arg1 arg2
+  | XOR (arg1, arg2) -> i2 b "xor" arg1 arg2
+  | XORPD (arg1, arg2) -> i2 b "xorpd" arg1 arg2
+
+
+let print_line b = function
+  | Ins instr -> print_instr b instr
+
+  | Align (_data,n) -> bprintf b "\tALIGN\t%d" n
+  | Byte n -> bprintf b "\tBYTE\t%a" cst n
+  | Bytes s -> buf_bytes_directive b "BYTE" s
+  | Comment s -> bprintf b " ; %s " s
+  | Global s -> bprintf b "\tPUBLIC\t%s" s
+  | Long n -> bprintf b "\tDWORD\t%a" cst n
+  | NewLabel (s, NONE) -> bprintf b "%s:" s
+  | NewLabel (s, ptr) -> bprintf b "%s LABEL %s" s (string_of_datatype ptr)
+  | Quad n -> bprintf b "\tQWORD\t%a" cst n
+  | Section ([".data"], None, []) -> bprintf b "\t.DATA"
+  | Section ([".text"], None, []) -> bprintf b "\t.CODE"
+  | Section _ -> assert false
+  | Space n -> bprintf b "\tBYTE\t%d DUP (?)" n
+  | Word n -> bprintf b "\tWORD\t%a" cst n
+
+  (* windows only *)
+  | External (s, ptr) -> bprintf b "\tEXTRN\t%s: %s" s (string_of_datatype ptr)
+  | Mode386 -> bprintf b "\t.386"
+  | Model name -> bprintf b "\t.MODEL %s" name (* name = FLAT *)
+
+  (* gas only *)
+  | Cfi_adjust_cfa_offset _
+  | Cfi_endproc
+  | Cfi_startproc
+  | File _
+  | Indirect_symbol _
+  | Loc _
+  | Private_extern _
+  | Set _
+  | Size _
+  | Type _
+    -> assert false
+
+let generate_asm oc lines =
+  let b = Buffer.create 10000 in
+  List.iter
+    (fun i ->
+       Buffer.clear b;
+       print_line b i;
+       Buffer.add_char b '\n';
+       Buffer.output_buffer oc b
+    )
+    lines;
+  output_string oc "\tEND\n"
diff --git a/asmcomp/x86_masm.mli b/asmcomp/x86_masm.mli
new file mode 100644
index 00000000..9027fe67
--- /dev/null
+++ b/asmcomp/x86_masm.mli
@@ -0,0 +1,18 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*         Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt         *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+(** Emit assembly instructions for MASM (Intel syntax). *)
+
+val generate_asm: out_channel -> X86_ast.asm_line list -> unit
diff --git a/asmcomp/x86_proc.ml b/asmcomp/x86_proc.ml
new file mode 100644
index 00000000..30b77af5
--- /dev/null
+++ b/asmcomp/x86_proc.ml
@@ -0,0 +1,275 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*          Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt        *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+open X86_ast
+
+type system =
+  (* 32 bits and 64 bits *)
+  | S_macosx
+  | S_gnu
+  | S_cygwin
+
+  (* 32 bits only *)
+  | S_solaris
+  | S_win32
+  | S_linux_elf
+  | S_bsd_elf
+  | S_beos
+  | S_mingw
+
+  (* 64 bits only *)
+  | S_win64
+  | S_linux
+  | S_mingw64
+
+  | S_unknown
+
+
+let system = match Config.system with
+  | "macosx" -> S_macosx
+  | "solaris" -> S_solaris
+  | "win32" -> S_win32
+  | "linux_elf" -> S_linux_elf
+  | "bsd_elf" -> S_bsd_elf
+  | "beos" -> S_beos
+  | "gnu" -> S_gnu
+  | "cygwin" -> S_cygwin
+  | "mingw" -> S_mingw
+  | "mingw64" -> S_mingw64
+  | "win64" -> S_win64
+  | "linux" -> S_linux
+
+  | _ -> S_unknown
+
+let windows =
+  match system with
+  | S_mingw64 | S_cygwin | S_win64 -> true
+  | _ -> false
+
+let string_of_string_literal s =
+  let b = Buffer.create (String.length s + 2) in
+  let last_was_escape = ref false in
+  for i = 0 to String.length s - 1 do
+    let c = s.[i] in
+    if c >= '0' && c <= '9' then
+      if !last_was_escape
+      then Printf.bprintf b "\\%o" (Char.code c)
+      else Buffer.add_char b c
+    else if c >= ' ' && c <= '~' && c <> '"' (* '"' *) && c <> '\\' then begin
+      Buffer.add_char b c;
+      last_was_escape := false
+    end else begin
+      Printf.bprintf b "\\%o" (Char.code c);
+      last_was_escape := true
+    end
+  done;
+  Buffer.contents b
+
+let string_of_symbol prefix s =
+  let spec = ref false in
+  for i = 0 to String.length s - 1 do
+    match String.unsafe_get s i with
+    | 'A'..'Z' | 'a'..'z' | '0'..'9' | '_' -> ()
+    | _ -> spec := true;
+  done;
+  if not !spec then if prefix = "" then s else prefix ^ s
+  else
+    let b = Buffer.create (String.length s + 10) in
+    Buffer.add_string b prefix;
+    String.iter
+      (function
+        | ('A'..'Z' | 'a'..'z' | '0'..'9' | '_') as c -> Buffer.add_char b c
+        | c -> Printf.bprintf b "$%02x" (Char.code c)
+      )
+      s;
+    Buffer.contents b
+
+let buf_bytes_directive b directive s =
+  let pos = ref 0 in
+  for i = 0 to String.length s - 1 do
+    if !pos = 0
+    then begin
+      if i > 0 then Buffer.add_char b '\n';
+      Buffer.add_char b '\t';
+      Buffer.add_string b directive;
+      Buffer.add_char b '\t';
+    end
+    else Buffer.add_char b ',';
+    Printf.bprintf b "%d" (Char.code s.[i]);
+    incr pos;
+    if !pos >= 16 then begin pos := 0 end
+  done
+
+let string_of_reg64 = function
+  | RAX -> "rax"
+  | RBX -> "rbx"
+  | RDI -> "rdi"
+  | RSI -> "rsi"
+  | RDX -> "rdx"
+  | RCX -> "rcx"
+  | RBP -> "rbp"
+  | RSP -> "rsp"
+  | R8  -> "r8"
+  | R9  -> "r9"
+  | R10 -> "r10"
+  | R11 -> "r11"
+  | R12 -> "r12"
+  | R13 -> "r13"
+  | R14 -> "r14"
+  | R15 -> "r15"
+
+let string_of_reg8l = function
+  | RAX -> "al"
+  | RBX -> "bl"
+  | RCX -> "cl"
+  | RDX -> "dl"
+  | RSP -> "spl"
+  | RBP -> "bpl"
+  | RSI -> "sil"
+  | RDI -> "dil"
+  | R8  -> "r8b"
+  | R9  -> "r9b"
+  | R10 -> "r10b"
+  | R11 -> "r11b"
+  | R12 -> "r12b"
+  | R13 -> "r13b"
+  | R14 -> "r14b"
+  | R15 -> "r15b"
+
+let string_of_reg8h = function
+  | AH -> "ah"
+  | BH -> "bh"
+  | CH -> "ch"
+  | DH -> "dh"
+
+let string_of_reg16 = function
+  | RAX -> "ax"
+  | RBX -> "bx"
+  | RCX -> "cx"
+  | RDX -> "dx"
+  | RSP -> "sp"
+  | RBP -> "bp"
+  | RSI -> "si"
+  | RDI -> "di"
+  | R8  -> "r8w"
+  | R9  -> "r9w"
+  | R10 -> "r10w"
+  | R11 -> "r11w"
+  | R12 -> "r12w"
+  | R13 -> "r13w"
+  | R14 -> "r14w"
+  | R15 -> "r15w"
+
+let string_of_reg32 = function
+  | RAX -> "eax"
+  | RBX -> "ebx"
+  | RCX -> "ecx"
+  | RDX -> "edx"
+  | RSP -> "esp"
+  | RBP -> "ebp"
+  | RSI -> "esi"
+  | RDI -> "edi"
+  | R8  -> "r8d"
+  | R9  -> "r9d"
+  | R10 -> "r10d"
+  | R11 -> "r11d"
+  | R12 -> "r12d"
+  | R13 -> "r13d"
+  | R14 -> "r14d"
+  | R15 -> "r15d"
+
+let string_of_registerf = function
+  | XMM n -> Printf.sprintf "xmm%d" n
+  | TOS -> Printf.sprintf "tos"
+  | ST n -> Printf.sprintf "st(%d)" n
+
+let string_of_condition = function
+  | E -> "e"
+  | AE -> "ae"
+  | A -> "a"
+  | GE -> "ge"
+  | G -> "g"
+  | NE -> "ne"
+  | B -> "b"
+  | BE -> "be"
+  | L -> "l"
+  | LE -> "le"
+  | NP -> "np"
+  | P -> "p"
+  | NS -> "ns"
+  | S -> "s"
+  | NO -> "no"
+  | O -> "o"
+
+let string_of_rounding = function
+  | RoundDown -> "roundsd.down"
+  | RoundUp -> "roundsd.up"
+  | RoundTruncate -> "roundsd.trunc"
+  | RoundNearest -> "roundsd.near"
+
+
+(* These hooks can be used to insert optimization passes on
+   the assembly code. *)
+let assembler_passes = ref ([] : (asm_program -> asm_program) list)
+
+let internal_assembler = ref None
+let register_internal_assembler f = internal_assembler := Some f
+
+(* Which asm conventions to use *)
+let masm =
+  match system with
+  | S_win32 | S_win64 -> true
+  | _ -> false
+
+(* Shall we use an external assembler command ?
+   If [binary_content] contains some data, we can directly
+   save it. Otherwise, we have to ask an external command.
+*)
+let binary_content = ref None
+
+let compile infile outfile =
+  if masm then
+    Ccomp.command (Config.asm ^
+                   Filename.quote outfile ^ " " ^ Filename.quote infile ^
+                   (if !Clflags.verbose then "" else ">NUL"))
+  else
+    Ccomp.command (Config.asm ^ " -o " ^
+                   Filename.quote outfile ^ " " ^ Filename.quote infile)
+
+let assemble_file infile outfile =
+  match !binary_content with
+  | None -> compile infile outfile
+  | Some content -> content outfile; binary_content := None; 0
+
+let asm_code = ref []
+
+let directive dir = asm_code := dir :: !asm_code
+let emit ins = directive (Ins ins)
+
+let reset_asm_code () = asm_code := []
+
+let generate_code asm =
+  let instrs = List.rev !asm_code in
+  let instrs =
+    List.fold_left (fun instrs pass -> pass instrs) instrs !assembler_passes
+  in
+  begin match asm with
+  | Some f -> f instrs
+  | None -> ()
+  end;
+  begin match !internal_assembler with
+  | Some f -> binary_content := Some (f instrs)
+  | None -> binary_content := None
+  end
diff --git a/asmcomp/x86_proc.mli b/asmcomp/x86_proc.mli
new file mode 100644
index 00000000..388420b2
--- /dev/null
+++ b/asmcomp/x86_proc.mli
@@ -0,0 +1,91 @@
+(**************************************************************************)
+(*                                                                        *)
+(*                                 OCaml                                  *)
+(*                                                                        *)
+(*          Fabrice Le Fessant, projet Gallium, INRIA Rocquencourt        *)
+(*                                                                        *)
+(*   Copyright 2014 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.          *)
+(*                                                                        *)
+(**************************************************************************)
+
+
+(** Definitions shared between the 32 and 64 bit Intel backends. *)
+
+open X86_ast
+
+(** Helpers for textual emitters *)
+
+val string_of_reg8l: reg64 -> string
+val string_of_reg8h: reg8h -> string
+val string_of_reg16: reg64 -> string
+val string_of_reg32: reg64 -> string
+val string_of_reg64: reg64 -> string
+val string_of_registerf: registerf -> string
+val string_of_string_literal: string -> string
+val string_of_condition: condition -> string
+val string_of_symbol: (*prefix*) string -> string -> string
+val string_of_rounding: rounding -> string
+val buf_bytes_directive:
+  Buffer.t -> (*directive*) string -> (*data*)string -> unit
+
+
+(** Buffer of assembly code *)
+
+val emit: instruction -> unit
+val directive: asm_line -> unit
+val reset_asm_code: unit -> unit
+
+(** Code emission *)
+
+val generate_code: (X86_ast.asm_line list -> unit) option -> unit
+  (** Post-process the stream of instructions.  Dump it (using
+      the provided syntax emitter) in a file (if provided) and
+      compile it with an internal assembler (if registered
+      through [register_internal_assembler]). *)
+
+val assemble_file: (*infile*) string -> (*outfile*) string -> (*retcode*) int
+(** Generate an object file corresponding to the last call to
+    [generate_code].  An internal assembler is used if available (and
+    the input file is ignored). Otherwise, the source asm file with an
+    external assembler. *)
+
+(** System detection *)
+
+type system =
+  (* 32 bits and 64 bits *)
+  | S_macosx
+  | S_gnu
+  | S_cygwin
+
+  (* 32 bits only *)
+  | S_solaris
+  | S_win32
+  | S_linux_elf
+  | S_bsd_elf
+  | S_beos
+  | S_mingw
+
+  (* 64 bits only *)
+  | S_win64
+  | S_linux
+  | S_mingw64
+
+  | S_unknown
+
+val system: system
+val masm: bool
+val windows:bool
+
+(** Support for plumbing a binary code emitter *)
+
+val register_internal_assembler: (asm_program -> string -> unit) -> unit
+
+
+(** Hooks for rewriting the assembly code *)
+
+val assembler_passes: (asm_program -> asm_program) list ref
diff --git a/asmrun/.depend b/asmrun/.depend
index 5c1a967c..7840f9c2 100644
--- a/asmrun/.depend
+++ b/asmrun/.depend
@@ -3,99 +3,96 @@ alloc.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
   ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
+  ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/stacks.h
 array.o: array.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/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/misc.h ../byterun/caml/mlvalues.h
+  ../byterun/caml/signals.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 \
-  ../byterun/caml/backtrace.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/misc.h \
-  ../byterun/caml/mlvalues.h stack.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/backtrace.h ../byterun/caml/exec.h \
+  ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
+backtrace_prim.o: backtrace_prim.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/backtrace.h \
+  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.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 stack.h
 callback.o: callback.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/mlvalues.h
+  ../byterun/caml/address_class.h
+clambda_checks.o: clambda_checks.c ../byterun/caml/mlvalues.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
 compact.o: compact.c ../byterun/caml/address_class.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/config.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/weak.h
+  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+  ../byterun/caml/weak.h
 compare.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.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/misc.h ../byterun/caml/mlvalues.h
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
 custom.o: custom.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/custom.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/mlvalues.h
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.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/config.h ../byterun/caml/debugger.h \
-  ../byterun/caml/misc.h
+  ../byterun/caml/debugger.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 ../byterun/caml/config.h \
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.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/misc.h ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
   ../byterun/caml/signals.h
 extern.o: extern.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/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/io.h \
-  ../byterun/caml/md5.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/reverse.h
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
 fail.o: fail.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/fail.h ../byterun/caml/io.h ../byterun/caml/gc.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/mlvalues.h ../byterun/caml/printexc.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
   ../byterun/caml/signals.h stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/callback.h
+  ../byterun/caml/callback.h
 finalise.o: finalise.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/roots.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/roots.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 \
@@ -106,56 +103,47 @@ floats.o: floats.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/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
+  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
 freelist.o: freelist.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.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/major_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h
+  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h
 gc_ctrl.o: gc_ctrl.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/backtrace.h ../byterun/caml/exec.h \
   ../byterun/caml/compact.h ../byterun/caml/custom.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h stack.h
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h stack.h \
+  ../byterun/caml/startup_aux.h
 globroots.o: globroots.c ../byterun/caml/memory.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h \
-  ../byterun/caml/globroots.h ../byterun/caml/roots.h
+  ../byterun/caml/roots.h ../byterun/caml/globroots.h
 hash.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/misc.h ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.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/hash.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/hash.h
 intern.o: intern.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/callback.h ../byterun/caml/custom.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
   ../byterun/caml/reverse.h
 ints.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
@@ -164,40 +152,35 @@ ints.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/intext.h ../byterun/caml/io.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/misc.h \
-  ../byterun/caml/mlvalues.h
+  ../byterun/caml/address_class.h
 io.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.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/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/signals.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.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/osdeps.h ../byterun/caml/signals.h \
   ../byterun/caml/sys.h
 lexing.o: lexing.c ../byterun/caml/fail.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/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/stacks.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
 main.o: main.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/misc.h ../byterun/caml/sys.h
+  ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
 major_gc.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/misc.h ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/weak.h
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
 md5.o: md5.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 \
@@ -205,104 +188,85 @@ md5.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.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/mlvalues.h ../byterun/caml/io.h \
   ../byterun/caml/reverse.h
-memory.o: memory.c ../byterun/caml/address_class.h ../byterun/caml/misc.h \
+memory.o: memory.c ../byterun/caml/address_class.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
-  ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
   ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/signals.h
+  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/signals.h
 meta.o: meta.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/config.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
+  ../byterun/caml/fail.h ../byterun/caml/fix_code.h \
+  ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-minor_gc.o: minor_gc.c ../byterun/caml/config.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+  ../byterun/caml/prims.h ../byterun/caml/stacks.h
+minor_gc.o: minor_gc.c ../byterun/caml/custom.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/fail.h ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/weak.h
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
 misc.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.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
 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 \
-  ../byterun/caml/misc.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 stack.h ../byterun/caml/callback.h \
-  ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
-  ../byterun/caml/signals.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 stack.h \
+  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/fail.h ../byterun/caml/signals.h
 obj.o: obj.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/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/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/prims.h
+  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/prims.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/config.h \
-  ../byterun/caml/misc.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/alloc.h
+  ../byterun/caml/mlvalues.h ../byterun/caml/misc.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/alloc.h
 printexc.o: printexc.c ../byterun/caml/backtrace.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/printexc.h
+  ../byterun/caml/misc.h ../byterun/caml/exec.h \
+  ../byterun/caml/callback.h ../byterun/caml/debugger.h \
+  ../byterun/caml/fail.h ../byterun/caml/printexc.h
 roots.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/globroots.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h stack.h ../byterun/caml/roots.h
+  ../byterun/caml/address_class.h ../byterun/caml/globroots.h stack.h
 signals.o: signals.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/callback.h ../byterun/caml/config.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/callback.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h \
-  ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  ../byterun/caml/sys.h
+  ../byterun/caml/roots.h ../byterun/caml/signals.h \
+  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
 signals_asm.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -316,26 +280,32 @@ 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 \
   ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h ../byterun/caml/io.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/printexc.h stack.h \
+  ../byterun/caml/exec.h ../byterun/caml/custom.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
+  ../byterun/caml/io.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/printexc.h stack.h ../byterun/caml/startup_aux.h \
   ../byterun/caml/sys.h
+startup_aux.o: startup_aux.c ../byterun/caml/backtrace.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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
 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 \
-  ../byterun/caml/fail.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/misc.h
+  ../byterun/caml/fail.h
 sys.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/instruct.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
+  ../byterun/caml/io.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/stacks.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
@@ -343,329 +313,624 @@ sys.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/sys.h
 terminfo.o: terminfo.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/alloc.h ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/mlvalues.h
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
 unix.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
-  ../byterun/caml/../../config/s.h ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.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/misc.h ../byterun/caml/osdeps.h
+  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
+  ../byterun/caml/sys.h
 weak.o: weak.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/fail.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h
-alloc.d.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/weak.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 \
   ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-array.d.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/stacks.h
+array.p.o: array.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/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/misc.h ../byterun/caml/mlvalues.h
-backtrace.d.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/signals.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 \
-  ../byterun/caml/backtrace.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/misc.h \
-  ../byterun/caml/mlvalues.h stack.h
-callback.d.o: callback.c ../byterun/caml/callback.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/backtrace.h ../byterun/caml/exec.h \
+  ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
+backtrace_prim.p.o: backtrace_prim.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/backtrace.h \
+  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.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 stack.h
+callback.p.o: callback.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/mlvalues.h
-compact.d.o: compact.c ../byterun/caml/address_class.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/config.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/address_class.h
+clambda_checks.p.o: clambda_checks.c ../byterun/caml/mlvalues.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
+compact.p.o: compact.c ../byterun/caml/address_class.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/weak.h
-compare.d.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+  ../byterun/caml/weak.h
+compare.p.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.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/misc.h ../byterun/caml/mlvalues.h
-custom.d.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+custom.p.o: custom.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/custom.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/mlvalues.h
-debugger.d.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.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/config.h ../byterun/caml/debugger.h \
-  ../byterun/caml/misc.h
-dynlink.d.o: dynlink.c ../byterun/caml/config.h \
+  ../byterun/caml/debugger.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 ../byterun/caml/config.h \
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.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/misc.h ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
   ../byterun/caml/signals.h
-extern.d.o: extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+extern.p.o: extern.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/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/io.h \
-  ../byterun/caml/md5.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/reverse.h
-fail.d.o: fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+fail.p.o: fail.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/fail.h ../byterun/caml/io.h ../byterun/caml/gc.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/mlvalues.h ../byterun/caml/printexc.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
   ../byterun/caml/signals.h stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/callback.h
-finalise.d.o: finalise.c ../byterun/caml/callback.h \
+  ../byterun/caml/callback.h
+finalise.p.o: finalise.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/roots.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/roots.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
-floats.d.o: floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+floats.p.o: floats.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/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/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-freelist.d.o: freelist.c ../byterun/caml/config.h \
+  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
+freelist.p.o: freelist.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.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/major_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h
-gc_ctrl.d.o: gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h
+gc_ctrl.p.o: gc_ctrl.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/backtrace.h ../byterun/caml/exec.h \
   ../byterun/caml/compact.h ../byterun/caml/custom.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h stack.h
-globroots.d.o: globroots.c ../byterun/caml/memory.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h stack.h \
+  ../byterun/caml/startup_aux.h
+globroots.p.o: globroots.c ../byterun/caml/memory.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h \
-  ../byterun/caml/globroots.h ../byterun/caml/roots.h
-hash.d.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/roots.h ../byterun/caml/globroots.h
+hash.p.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/misc.h ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.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/hash.h
-intern.d.o: intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.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/hash.h
+intern.p.o: intern.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/callback.h ../byterun/caml/custom.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
   ../byterun/caml/reverse.h
-ints.d.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ints.p.o: ints.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/custom.h ../byterun/caml/fail.h \
   ../byterun/caml/intext.h ../byterun/caml/io.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/misc.h \
-  ../byterun/caml/mlvalues.h
-io.d.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/address_class.h
+io.p.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.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/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/signals.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.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/osdeps.h ../byterun/caml/signals.h \
   ../byterun/caml/sys.h
-lexing.d.o: lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
+lexing.p.o: lexing.c ../byterun/caml/fail.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/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/stacks.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
-main.d.o: main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+main.p.o: main.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/misc.h ../byterun/caml/sys.h
-major_gc.d.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
+major_gc.p.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/misc.h ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/weak.h
-md5.d.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
+md5.p.o: md5.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/fail.h ../byterun/caml/md5.h ../byterun/caml/io.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/mlvalues.h ../byterun/caml/io.h \
   ../byterun/caml/reverse.h
-memory.d.o: memory.c ../byterun/caml/address_class.h ../byterun/caml/misc.h \
+memory.p.o: memory.c ../byterun/caml/address_class.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
-  ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
   ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/signals.h
+meta.p.o: meta.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/fail.h ../byterun/caml/fix_code.h \
+  ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+  ../byterun/caml/major_gc.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/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/signals.h
-meta.d.o: meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/prims.h ../byterun/caml/stacks.h
+minor_gc.p.o: minor_gc.c ../byterun/caml/custom.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
+misc.p.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.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
+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 \
+  ../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 stack.h \
+  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/fail.h ../byterun/caml/signals.h
+obj.p.o: obj.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/config.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.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
+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 \
+  ../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/alloc.h
+printexc.p.o: printexc.c ../byterun/caml/backtrace.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/misc.h ../byterun/caml/exec.h \
+  ../byterun/caml/callback.h ../byterun/caml/debugger.h \
+  ../byterun/caml/fail.h ../byterun/caml/printexc.h
+roots.p.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+  ../byterun/caml/misc.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/globroots.h stack.h
+signals.p.o: signals.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/callback.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/roots.h ../byterun/caml/signals.h \
+  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
+signals_asm.p.o: signals_asm.c ../byterun/caml/fail.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/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/osdeps.h \
+  ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
+  signals_osdep.h stack.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 \
+  ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
+  ../byterun/caml/exec.h ../byterun/caml/custom.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
+  ../byterun/caml/io.h ../byterun/caml/memory.h \
   ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/printexc.h stack.h ../byterun/caml/startup_aux.h \
+  ../byterun/caml/sys.h
+startup_aux.p.o: startup_aux.c ../byterun/caml/backtrace.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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
+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 \
+  ../byterun/caml/fail.h
+sys.p.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-minor_gc.d.o: minor_gc.c ../byterun/caml/config.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
+  ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/signals.h ../byterun/caml/stacks.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/sys.h
+terminfo.p.o: terminfo.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/fail.h ../byterun/caml/misc.h ../byterun/caml/config.h \
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
+unix.p.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.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/osdeps.h ../byterun/caml/signals.h \
+  ../byterun/caml/sys.h
+weak.p.o: weak.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/fail.h ../byterun/caml/major_gc.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
+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 \
+  ../byterun/caml/custom.h ../byterun/caml/major_gc.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/stacks.h
+array.d.o: array.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/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
+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 \
+  ../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/backtrace.h ../byterun/caml/exec.h \
+  ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
+backtrace_prim.d.o: backtrace_prim.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/backtrace.h \
+  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.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 stack.h
+callback.d.o: callback.c ../byterun/caml/callback.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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
+clambda_checks.d.o: clambda_checks.c ../byterun/caml/mlvalues.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
+compact.d.o: compact.c ../byterun/caml/address_class.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
   ../byterun/caml/roots.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/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/weak.h
-misc.d.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+  ../byterun/caml/weak.h
+compare.d.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.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
-natdynlink.d.o: natdynlink.c ../byterun/caml/misc.h \
+custom.d.o: custom.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/misc.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/custom.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
+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
+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 \
+  ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.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/osdeps.h ../byterun/caml/prims.h \
+  ../byterun/caml/signals.h
+extern.d.o: extern.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/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h stack.h ../byterun/caml/callback.h \
-  ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
+  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+fail.d.o: fail.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/fail.h ../byterun/caml/io.h ../byterun/caml/gc.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
+  ../byterun/caml/signals.h stack.h ../byterun/caml/roots.h \
+  ../byterun/caml/callback.h
+finalise.d.o: finalise.c ../byterun/caml/callback.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/roots.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
-obj.d.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+floats.d.o: floats.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/fail.h ../byterun/caml/gc.h ../byterun/caml/interp.h \
+  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.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/reverse.h ../byterun/caml/stacks.h
+freelist.d.o: freelist.c ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/freelist.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
   ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h
+gc_ctrl.d.o: gc_ctrl.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/backtrace.h ../byterun/caml/exec.h \
+  ../byterun/caml/compact.h ../byterun/caml/custom.h \
+  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/gc_ctrl.h ../byterun/caml/signals.h stack.h \
+  ../byterun/caml/startup_aux.h
+globroots.d.o: globroots.c ../byterun/caml/memory.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+  ../byterun/caml/roots.h ../byterun/caml/globroots.h
+hash.d.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/misc.h ../byterun/caml/custom.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/hash.h
+intern.d.o: intern.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/callback.h ../byterun/caml/custom.h \
+  ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
+  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+  ../byterun/caml/reverse.h
+ints.d.o: ints.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/custom.h ../byterun/caml/fail.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.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
+io.d.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
   ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/prims.h
-parsing.d.o: parsing.c ../byterun/caml/config.h \
+  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.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/osdeps.h ../byterun/caml/signals.h \
+  ../byterun/caml/sys.h
+lexing.d.o: lexing.c ../byterun/caml/fail.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/stacks.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
+main.d.o: main.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/sys.h
+major_gc.d.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/misc.h ../byterun/caml/custom.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
+md5.d.o: md5.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/fail.h ../byterun/caml/md5.h ../byterun/caml/io.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/reverse.h
+memory.d.o: memory.c ../byterun/caml/address_class.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/signals.h
+meta.d.o: meta.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/fail.h ../byterun/caml/fix_code.h \
+  ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
+  ../byterun/caml/major_gc.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/prims.h ../byterun/caml/stacks.h
+minor_gc.d.o: minor_gc.c ../byterun/caml/custom.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/misc.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
+misc.d.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.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/alloc.h
+  ../byterun/caml/address_class.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 \
+  ../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 stack.h \
+  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/fail.h ../byterun/caml/signals.h
+obj.d.o: obj.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/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
+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 \
+  ../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/alloc.h
 printexc.d.o: printexc.c ../byterun/caml/backtrace.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/printexc.h
+  ../byterun/caml/misc.h ../byterun/caml/exec.h \
+  ../byterun/caml/callback.h ../byterun/caml/debugger.h \
+  ../byterun/caml/fail.h ../byterun/caml/printexc.h
 roots.d.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/globroots.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h stack.h ../byterun/caml/roots.h
+  ../byterun/caml/address_class.h ../byterun/caml/globroots.h stack.h
 signals.d.o: signals.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/callback.h ../byterun/caml/config.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/callback.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h \
-  ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  ../byterun/caml/sys.h
+  ../byterun/caml/roots.h ../byterun/caml/signals.h \
+  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
 signals_asm.d.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
@@ -679,26 +944,32 @@ 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 \
   ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h ../byterun/caml/io.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/printexc.h stack.h \
+  ../byterun/caml/exec.h ../byterun/caml/custom.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
+  ../byterun/caml/io.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/printexc.h stack.h ../byterun/caml/startup_aux.h \
   ../byterun/caml/sys.h
+startup_aux.d.o: startup_aux.c ../byterun/caml/backtrace.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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
 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 \
-  ../byterun/caml/fail.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/misc.h
+  ../byterun/caml/fail.h
 sys.d.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/instruct.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
+  ../byterun/caml/io.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/stacks.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
@@ -706,330 +977,293 @@ sys.d.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/sys.h
 terminfo.d.o: terminfo.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/alloc.h ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/mlvalues.h
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
 unix.d.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
-  ../byterun/caml/../../config/s.h ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.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/misc.h ../byterun/caml/osdeps.h
+  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
+  ../byterun/caml/sys.h
 weak.d.o: weak.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/fail.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h
-alloc.p.o: alloc.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/weak.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 \
   ../byterun/caml/custom.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-array.p.o: array.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/stacks.h
+array.i.o: array.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/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/misc.h ../byterun/caml/mlvalues.h
-backtrace.p.o: backtrace.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/signals.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 \
-  ../byterun/caml/backtrace.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/misc.h \
-  ../byterun/caml/mlvalues.h stack.h
-callback.p.o: callback.c ../byterun/caml/callback.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/backtrace.h ../byterun/caml/exec.h \
+  ../byterun/caml/backtrace_prim.h ../byterun/caml/fail.h
+backtrace_prim.i.o: backtrace_prim.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/backtrace.h \
+  ../byterun/caml/exec.h ../byterun/caml/backtrace_prim.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 stack.h
+callback.i.o: callback.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/mlvalues.h
-compact.p.o: compact.c ../byterun/caml/address_class.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/config.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/address_class.h
+clambda_checks.i.o: clambda_checks.c ../byterun/caml/mlvalues.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h
+compact.i.o: compact.c ../byterun/caml/address_class.h \
+  ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/memory.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/weak.h
-compare.p.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/gc_ctrl.h \
+  ../byterun/caml/weak.h
+compare.i.o: compare.c ../byterun/caml/custom.h ../byterun/caml/mlvalues.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.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/misc.h ../byterun/caml/mlvalues.h
-custom.p.o: custom.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h
+custom.i.o: custom.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/custom.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/mlvalues.h
-debugger.p.o: debugger.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.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/config.h ../byterun/caml/debugger.h \
-  ../byterun/caml/misc.h
-dynlink.p.o: dynlink.c ../byterun/caml/config.h \
+  ../byterun/caml/debugger.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 ../byterun/caml/config.h \
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/dynlink.h \
-  ../byterun/caml/fail.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.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/misc.h ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
+  ../byterun/caml/osdeps.h ../byterun/caml/prims.h \
   ../byterun/caml/signals.h
-extern.p.o: extern.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+extern.i.o: extern.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/custom.h ../byterun/caml/fail.h ../byterun/caml/gc.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/io.h \
-  ../byterun/caml/md5.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/reverse.h
-fail.p.o: fail.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/md5.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/reverse.h
+fail.i.o: fail.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/fail.h ../byterun/caml/io.h ../byterun/caml/gc.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/mlvalues.h ../byterun/caml/printexc.h \
+  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
+  ../byterun/caml/freelist.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/printexc.h \
   ../byterun/caml/signals.h stack.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/callback.h
-finalise.p.o: finalise.c ../byterun/caml/callback.h \
+  ../byterun/caml/callback.h
+finalise.i.o: finalise.c ../byterun/caml/callback.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/fail.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/roots.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h ../byterun/caml/roots.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
-floats.p.o: floats.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+floats.i.o: floats.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/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/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/reverse.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-freelist.p.o: freelist.c ../byterun/caml/config.h \
+  ../byterun/caml/reverse.h ../byterun/caml/stacks.h
+freelist.i.o: freelist.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/freelist.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/gc.h ../byterun/caml/gc_ctrl.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/major_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h
-gc_ctrl.p.o: gc_ctrl.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h
+gc_ctrl.i.o: gc_ctrl.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/backtrace.h ../byterun/caml/exec.h \
   ../byterun/caml/compact.h ../byterun/caml/custom.h \
-  ../byterun/caml/finalise.h ../byterun/caml/roots.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
+  ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h stack.h
-globroots.p.o: globroots.c ../byterun/caml/memory.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h stack.h \
+  ../byterun/caml/startup_aux.h
+globroots.i.o: globroots.c ../byterun/caml/memory.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/gc.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h \
-  ../byterun/caml/globroots.h ../byterun/caml/roots.h
-hash.p.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/roots.h ../byterun/caml/globroots.h
+hash.i.o: hash.c ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/misc.h ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.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/hash.h
-intern.p.o: intern.c ../byterun/caml/alloc.h ../byterun/caml/misc.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/hash.h
+intern.i.o: intern.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/callback.h ../byterun/caml/custom.h \
   ../byterun/caml/fail.h ../byterun/caml/gc.h ../byterun/caml/intext.h \
-  ../byterun/caml/io.h ../byterun/caml/io.h ../byterun/caml/md5.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/io.h ../byterun/caml/md5.h ../byterun/caml/memory.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
   ../byterun/caml/reverse.h
-ints.p.o: ints.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+ints.i.o: ints.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/custom.h ../byterun/caml/fail.h \
   ../byterun/caml/intext.h ../byterun/caml/io.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/misc.h \
-  ../byterun/caml/mlvalues.h
-io.p.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/address_class.h
+io.i.o: io.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/custom.h \
-  ../byterun/caml/fail.h ../byterun/caml/io.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/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/signals.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/custom.h ../byterun/caml/fail.h ../byterun/caml/io.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/osdeps.h ../byterun/caml/signals.h \
   ../byterun/caml/sys.h
-lexing.p.o: lexing.c ../byterun/caml/fail.h ../byterun/caml/misc.h \
+lexing.i.o: lexing.c ../byterun/caml/fail.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/mlvalues.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/stacks.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
-main.p.o: main.c ../byterun/caml/misc.h ../byterun/caml/config.h \
+main.i.o: main.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/misc.h ../byterun/caml/sys.h
-major_gc.p.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/sys.h
+major_gc.i.o: major_gc.c ../byterun/caml/compact.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
   ../byterun/caml/misc.h ../byterun/caml/custom.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
-  ../byterun/caml/fail.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/weak.h
-md5.p.o: md5.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
+md5.i.o: md5.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/fail.h ../byterun/caml/md5.h ../byterun/caml/io.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/mlvalues.h ../byterun/caml/io.h \
   ../byterun/caml/reverse.h
-memory.p.o: memory.c ../byterun/caml/address_class.h ../byterun/caml/misc.h \
+memory.i.o: memory.c ../byterun/caml/address_class.h \
   ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
-  ../byterun/caml/../../config/s.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
   ../byterun/caml/gc_ctrl.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/signals.h
-meta.p.o: meta.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/signals.h
+meta.i.o: meta.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/config.h ../byterun/caml/fail.h \
-  ../byterun/caml/fix_code.h ../byterun/caml/interp.h \
-  ../byterun/caml/intext.h ../byterun/caml/io.h \
+  ../byterun/caml/fail.h ../byterun/caml/fix_code.h \
+  ../byterun/caml/interp.h ../byterun/caml/intext.h ../byterun/caml/io.h \
   ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
   ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/prims.h ../byterun/caml/stacks.h \
-  ../byterun/caml/memory.h
-minor_gc.p.o: minor_gc.c ../byterun/caml/config.h \
+  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
+  ../byterun/caml/prims.h ../byterun/caml/stacks.h
+minor_gc.i.o: minor_gc.c ../byterun/caml/custom.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/fail.h ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/finalise.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/misc.h ../byterun/caml/fail.h \
+  ../byterun/caml/finalise.h ../byterun/caml/roots.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/gc.h ../byterun/caml/gc_ctrl.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/memory.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/roots.h \
-  ../byterun/caml/signals.h ../byterun/caml/weak.h
-misc.p.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/signals.h \
+  ../byterun/caml/weak.h
+misc.i.o: misc.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/misc.h \
-  ../byterun/caml/config.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/freelist.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.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 \
-  ../byterun/caml/misc.h ../byterun/caml/memory.h ../byterun/caml/gc.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 stack.h ../byterun/caml/callback.h \
-  ../byterun/caml/alloc.h ../byterun/caml/intext.h ../byterun/caml/io.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/fail.h \
-  ../byterun/caml/signals.h
-obj.p.o: obj.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/address_class.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 \
+  ../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 stack.h \
+  ../byterun/caml/callback.h ../byterun/caml/alloc.h \
+  ../byterun/caml/intext.h ../byterun/caml/io.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/fail.h ../byterun/caml/signals.h
+obj.i.o: obj.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/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/gc.h \
-  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/address_class.h ../byterun/caml/minor_gc.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/prims.h
-parsing.p.o: parsing.c ../byterun/caml/config.h \
+  ../byterun/caml/memory.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/prims.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/config.h \
-  ../byterun/caml/misc.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/alloc.h
-printexc.p.o: printexc.c ../byterun/caml/backtrace.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/misc.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/alloc.h
+printexc.i.o: printexc.c ../byterun/caml/backtrace.h \
   ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/misc.h ../byterun/caml/callback.h \
-  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
-  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/printexc.h
-roots.p.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
+  ../byterun/caml/misc.h ../byterun/caml/exec.h \
+  ../byterun/caml/callback.h ../byterun/caml/debugger.h \
+  ../byterun/caml/fail.h ../byterun/caml/printexc.h
+roots.i.o: roots.c ../byterun/caml/finalise.h ../byterun/caml/roots.h \
   ../byterun/caml/misc.h ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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/globroots.h \
-  ../byterun/caml/memory.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/misc.h \
-  ../byterun/caml/mlvalues.h stack.h ../byterun/caml/roots.h
-signals.p.o: signals.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/globroots.h stack.h
+signals.i.o: signals.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/callback.h ../byterun/caml/config.h \
-  ../byterun/caml/fail.h ../byterun/caml/memory.h ../byterun/caml/gc.h \
+  ../byterun/caml/callback.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/roots.h ../byterun/caml/memory.h \
-  ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
-  ../byterun/caml/sys.h
-signals_asm.p.o: signals_asm.c ../byterun/caml/fail.h \
+  ../byterun/caml/roots.h ../byterun/caml/signals.h \
+  ../byterun/caml/signals_machdep.h ../byterun/caml/sys.h
+signals_asm.i.o: signals_asm.c ../byterun/caml/fail.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/memory.h \
@@ -1038,52 +1272,57 @@ signals_asm.p.o: signals_asm.c ../byterun/caml/fail.h \
   ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/signals_machdep.h \
   signals_osdep.h stack.h
-startup.p.o: startup.c ../byterun/caml/callback.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 \
   ../byterun/caml/misc.h ../byterun/caml/backtrace.h \
-  ../byterun/caml/custom.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/freelist.h ../byterun/caml/gc.h \
-  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h ../byterun/caml/io.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/misc.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/osdeps.h ../byterun/caml/printexc.h stack.h \
+  ../byterun/caml/exec.h ../byterun/caml/custom.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/freelist.h ../byterun/caml/gc.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/intext.h \
+  ../byterun/caml/io.h ../byterun/caml/memory.h \
+  ../byterun/caml/major_gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/printexc.h stack.h ../byterun/caml/startup_aux.h \
   ../byterun/caml/sys.h
-str.p.o: str.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+startup_aux.i.o: startup_aux.c ../byterun/caml/backtrace.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/config.h \
+  ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.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
+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 \
-  ../byterun/caml/fail.h ../byterun/caml/mlvalues.h \
-  ../byterun/caml/misc.h
-sys.p.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/fail.h
+sys.i.o: sys.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
   ../byterun/caml/../../config/s.h ../byterun/caml/alloc.h \
-  ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/debugger.h \
-  ../byterun/caml/fail.h ../byterun/caml/instruct.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/osdeps.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.h \
+  ../byterun/caml/debugger.h ../byterun/caml/fail.h \
+  ../byterun/caml/gc_ctrl.h ../byterun/caml/instruct.h \
+  ../byterun/caml/io.h ../byterun/caml/osdeps.h \
   ../byterun/caml/signals.h ../byterun/caml/stacks.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/sys.h
-terminfo.p.o: terminfo.c ../byterun/caml/config.h \
+terminfo.i.o: terminfo.c ../byterun/caml/config.h \
   ../byterun/caml/../../config/m.h ../byterun/caml/../../config/s.h \
-  ../byterun/caml/alloc.h ../byterun/caml/misc.h ../byterun/caml/config.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h \
-  ../byterun/caml/mlvalues.h
-unix.p.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
-  ../byterun/caml/../../config/s.h ../byterun/caml/memory.h \
-  ../byterun/caml/config.h ../byterun/caml/gc.h \
-  ../byterun/caml/mlvalues.h ../byterun/caml/misc.h \
+  ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/mlvalues.h ../byterun/caml/fail.h ../byterun/caml/io.h
+unix.i.o: unix.c ../byterun/caml/config.h ../byterun/caml/../../config/m.h \
+  ../byterun/caml/../../config/s.h ../byterun/caml/fail.h \
+  ../byterun/caml/misc.h ../byterun/caml/mlvalues.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/misc.h ../byterun/caml/osdeps.h
-weak.p.o: weak.c ../byterun/caml/alloc.h ../byterun/caml/misc.h \
+  ../byterun/caml/osdeps.h ../byterun/caml/signals.h \
+  ../byterun/caml/sys.h
+weak.i.o: weak.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/fail.h ../byterun/caml/major_gc.h \
   ../byterun/caml/freelist.h ../byterun/caml/memory.h \
-  ../byterun/caml/gc.h ../byterun/caml/major_gc.h \
-  ../byterun/caml/minor_gc.h ../byterun/caml/address_class.h \
-  ../byterun/caml/mlvalues.h
+  ../byterun/caml/gc.h ../byterun/caml/minor_gc.h \
+  ../byterun/caml/address_class.h ../byterun/caml/weak.h
diff --git a/asmrun/.ignore b/asmrun/.ignore
deleted file mode 100644
index a7a9d335..00000000
--- a/asmrun/.ignore
+++ /dev/null
@@ -1,40 +0,0 @@
-*.p.c
-*.d.c
-libasmrun.a
-libasmrunp.a
-main.c
-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
-custom.c
-meta.c
-globroots.c
-unix.c
-dynlink.c
-signals.c
-debugger.c
-.depend.nt
diff --git a/asmrun/Makefile b/asmrun/Makefile
index 37b6182d..1673752d 100644
--- a/asmrun/Makefile
+++ b/asmrun/Makefile
@@ -1,42 +1,52 @@
-#########################################################################
-#                                                                       #
-#                                 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 Library General Public License, with     #
-#   the special exception on linking described in file ../LICENSE.      #
-#                                                                       #
-#########################################################################
+#**************************************************************************
+#*                                                                        *
+#*                                 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
 
 CC=$(NATIVECC)
 FLAGS=-I../byterun -DCAML_NAME_SPACE -DNATIVE_CODE \
-      -DTARGET_$(ARCH) -DSYS_$(SYSTEM) $(IFLEXDIR)
+      -DTARGET_$(ARCH) -DMODEL_$(MODEL) -DSYS_$(SYSTEM) $(IFLEXDIR)
 CFLAGS=$(FLAGS) $(NATIVECCCOMPOPTS)
 DFLAGS=$(FLAGS) -g -DDEBUG $(NATIVECCCOMPOPTS)
-PFLAGS=$(FLAGS) -pg -O -DPROFILING $(NATIVECCPROFOPTS)
-PICFLAGS=$(FLAGS) -O $(SHAREDCCCOMPOPTS) $(NATIVECCCOMPOPTS)
+IFLAGS=$(FLAGS) -DCAML_INSTR
+PFLAGS=$(FLAGS) -pg -DPROFILING $(NATIVECCPROFOPTS) $(NATIVECCCOMPOPTS)
+PICFLAGS=$(FLAGS) $(SHAREDCCCOMPOPTS) $(NATIVECCCOMPOPTS)
 
-COBJS=startup.o main.o fail.o roots.o globroots.o signals.o signals_asm.o \
-  misc.o freelist.o major_gc.o minor_gc.o memory.o alloc.o compare.o ints.o \
+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.o natdynlink.o\
-  debugger.o meta.o dynlink.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
 
 ASMOBJS=$(ARCH).o
 
 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)
 
 all: libasmrun.a all-$(RUNTIMED) all-$(PROFILING) all-$(SHARED)
 
+ifeq "$(RUNTIMEI)" "true"
+all: libasmruni.a
+endif
+
 libasmrun.a: $(OBJS)
 	rm -f libasmrun.a
 	$(ARCMD) rc libasmrun.a $(OBJS)
@@ -53,6 +63,11 @@ libasmrund.a: $(DOBJS)
 	$(ARCMD) rc libasmrund.a $(DOBJS)
 	$(RANLIB) libasmrund.a
 
+libasmruni.a: $(IOBJS)
+	rm -f $@
+	$(ARCMD) rc $@ $^
+	$(RANLIB) $@
+
 all-noprof:
 
 all-prof: libasmrunp.a
@@ -68,7 +83,7 @@ all-shared: libasmrun_pic.a libasmrun_shared.so
 
 libasmrun_pic.a: $(PICOBJS)
 	rm -f libasmrun_pic.a
-	ar rc libasmrun_pic.a $(PICOBJS)
+	$(ARCMD) rc libasmrun_pic.a $(PICOBJS)
 	$(RANLIB) libasmrun_pic.a
 
 libasmrun_shared.so: $(PICOBJS)
@@ -76,54 +91,46 @@ libasmrun_shared.so: $(PICOBJS)
 
 INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
 
-install: install-default install-$(RUNTIMED) install-$(PROFILING) install-$(SHARED)
-
-install-default:
+install::
 	cp libasmrun.a $(INSTALL_LIBDIR)/libasmrun.a
 	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrun.a
 .PHONY: install-default
 
-install-noruntimed:
-.PHONY: install-noruntimed
-
-install-runtimed:
+ifeq "$(RUNTIMED)" "runtimed"
+install::
 	cp libasmrund.a $(INSTALL_LIBDIR)/libasmrund.a
 	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrund.a
-.PHONY: install-runtimed
+endif
 
-install-noprof:
-	rm -f $(INSTALL_LIBDIR)/libasmrunp.a
-	ln -s libasmrun.a $(INSTALL_LIBDIR)/libasmrunp.a
-.PHONY: install-noprof
+ifeq "$(RUNTIMEI)" "true"
+install::
+	cp libasmruni.a $(INSTALL_LIBDIR)/libasmruni.a
+	cd $(INSTALL_LIBDIR); $(RANLIB) libasmruni.a
+endif
 
-install-prof:
+ifeq "$(PROFILING)" "prof"
+install::
 	cp libasmrunp.a $(INSTALL_LIBDIR)/libasmrunp.a
 	cd $(INSTALL_LIBDIR); $(RANLIB) libasmrunp.a
-.PHONY: install-prof
-
-install-noshared:
-.PHONY: install-noshared
+else
+install::
+	rm -f $(INSTALL_LIBDIR)/libasmrunp.a
+	ln -s libasmrun.a $(INSTALL_LIBDIR)/libasmrunp.a
+endif
 
-install-shared:
+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
-.PHONY: install-prof
-
-power-bsd_elf.S: power-elf.S
-	cp power-elf.S power-bsd_elf.S
-
-power.o: power-$(SYSTEM).o
-	cp power-$(SYSTEM).o power.o
-
-power.p.o: power-$(SYSTEM).o
-	cp power-$(SYSTEM).o power.p.o
-
-power.pic.o: power-$(SYSTEM).pic.o
-	cp power-$(SYSTEM).pic.o power.pic.o
+endif
 
 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
@@ -202,6 +209,18 @@ LINKEDFILES=misc.c freelist.c major_gc.c minor_gc.c memory.c alloc.c array.c \
 clean::
 	rm -f $(LINKEDFILES)
 
+%.d.o: %.c
+	$(CC) -c $(DFLAGS) -o $@ $<
+
+%.i.o : %.c
+	$(CC) -c $(IFLAGS) -o $@ $<
+
+%.p.o: %.c
+	$(CC) -c $(PFLAGS) -o $@ $<
+
+%.pic.o: %.c
+	$(CC) -c $(PICFLAGS) -o $@ $<
+
 %.o: %.S
 	$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) -o $@ $< || \
 	{ echo "If your assembler produced syntax errors, it is probably";\
@@ -215,15 +234,6 @@ clean::
 %.pic.o: %.S
 	$(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) $(SHAREDCCCOMPOPTS) -o $@ $<
 
-%.d.o: %.c
-	$(CC) -c $(DFLAGS) -o $@ $<
-
-%.p.o: %.c
-	$(CC) -c $(PFLAGS) -o $@ $<
-
-%.pic.o: %.c
-	$(CC) -c $(PICFLAGS) -o $@ $<
-
 %.o: %.s
 	$(ASPP) -DSYS_$(SYSTEM) -o $@ $<
 
@@ -234,11 +244,12 @@ clean::
 	$(ASPP) -DSYS_$(SYSTEM) $(SHAREDCCCOMPOPTS) -o $@ $<
 
 clean::
-	rm -f *.o *.a *~
+	rm -f *.o *.a *.so *~
 
 depend: $(COBJS:.o=.c) ${LINKEDFILES}
 	$(CC) -MM $(FLAGS) *.c > .depend
-	$(CC) -MM $(FLAGS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' >> .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
 
 include .depend
diff --git a/asmrun/Makefile.nt b/asmrun/Makefile.nt
index dba8343c..39a2f7e8 100644
--- a/asmrun/Makefile.nt
+++ b/asmrun/Makefile.nt
@@ -1,15 +1,17 @@
-#########################################################################
-#                                                                       #
-#                                 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 Library General Public License, with     #
-#   the special exception on linking described in file ../LICENSE.      #
-#                                                                       #
-#########################################################################
+#**************************************************************************
+#*                                                                        *
+#*                                 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
 
@@ -17,19 +19,21 @@ CC=$(NATIVECC)
 CFLAGS=-I../byterun -DNATIVE_CODE -DTARGET_$(ARCH) -DSYS_$(SYSTEM) \
        $(NATIVECCCOMPOPTS)
 
-COBJS=startup.$(O) main.$(O) fail.$(O) roots.$(O) signals.$(O) signals_asm.$(O)\
+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.$(O) natdynlink.$(O) debugger.$(O) meta.$(O) dynlink.$(O)
+  backtrace_prim.$(O) backtrace.$(O) \
+  natdynlink.$(O) debugger.$(O) meta.$(O) dynlink.$(O) clambda_checks.$(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
+  dynlink.c signals.c debugger.c startup_aux.c backtrace.c
 
 ifeq ($(TOOLCHAIN),mingw)
 ASMOBJS=$(ARCH).o
@@ -59,14 +63,15 @@ amd64.o: amd64.S
 INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)
 
 install:
-	cp libasmrun.$(A) $(INSTALL_LIBDIR)
+	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
+	$(CC) -c $(NATIVECCCOMPOPTS) -DNATIVE_CODE $(IFLEXDIR) \
+	      ../byterun/win32.c
 
 %.$(O): %.c
 	$(CC) $(CFLAGS) -c $<
diff --git a/asmrun/amd64.S b/asmrun/amd64.S
index be38848e..5b2291ea 100644
--- a/asmrun/amd64.S
+++ b/asmrun/amd64.S
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 2003 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 2003 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Asm part of the runtime system, AMD64 processor */
 /* Must be preprocessed by cpp */
@@ -67,10 +69,14 @@
 #define CFI_STARTPROC .cfi_startproc
 #define CFI_ENDPROC .cfi_endproc
 #define CFI_ADJUST(n) .cfi_adjust_cfa_offset n
+#define CFI_OFFSET(r, n) .cfi_offset r, n
+#define CFI_SAME_VALUE(r) .cfi_same_value r
 #else
 #define CFI_STARTPROC
 #define CFI_ENDPROC
 #define CFI_ADJUST(n)
+#define CFI_OFFSET(r, n)
+#define CFI_SAME_VALUE(r)
 #endif
 
 #ifdef WITH_FRAME_POINTERS
@@ -184,14 +190,15 @@
 /* Win64 API: callee-save regs are rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15 */
 
 #define PUSH_CALLEE_SAVE_REGS \
-        pushq   %rbx; CFI_ADJUST (8); \
-        pushq   %rbp; CFI_ADJUST (8); \
-        pushq   %rsi; CFI_ADJUST (8); \
-        pushq   %rdi; CFI_ADJUST (8); \
-        pushq   %r12; CFI_ADJUST (8); \
-        pushq   %r13; CFI_ADJUST (8); \
-        pushq   %r14; CFI_ADJUST (8); \
-        pushq   %r15; CFI_ADJUST (8); \
+        pushq   %rbx; CFI_ADJUST (8); CFI_OFFSET(rbx, -16); \
+        pushq   %rbp; CFI_ADJUST (8); CFI_OFFSET(rbp, -24); \
+                      /* Allows debugger to walk the stack */ \
+        pushq   %rsi; CFI_ADJUST (8); CFI_OFFSET(rsi, -32); \
+        pushq   %rdi; CFI_ADJUST (8); CFI_OFFSET(rdi, -40); \
+        pushq   %r12; CFI_ADJUST (8); CFI_OFFSET(r12, -48); \
+        pushq   %r13; CFI_ADJUST (8); CFI_OFFSET(r13, -56); \
+        pushq   %r14; CFI_ADJUST (8); CFI_OFFSET(r14, -64); \
+        pushq   %r15; CFI_ADJUST (8); CFI_OFFSET(r15, -72); \
         subq    $(8+10*16), %rsp; CFI_ADJUST (8+10*16); \
         movupd  %xmm6, 0*16(%rsp); \
         movupd  %xmm7, 1*16(%rsp); \
@@ -216,36 +223,36 @@
         movupd  8*16(%rsp), %xmm14; \
         movupd  9*16(%rsp), %xmm15; \
         addq    $(8+10*16), %rsp; CFI_ADJUST (-8-10*16); \
-        popq    %r15; CFI_ADJUST(-8); \
-        popq    %r14; CFI_ADJUST(-8); \
-        popq    %r13; CFI_ADJUST(-8); \
-        popq    %r12; CFI_ADJUST(-8); \
-        popq    %rdi; CFI_ADJUST(-8); \
-        popq    %rsi; CFI_ADJUST(-8); \
-        popq    %rbp; CFI_ADJUST(-8); \
-        popq    %rbx; CFI_ADJUST(-8)
+        popq    %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \
+        popq    %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \
+        popq    %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \
+        popq    %r12; CFI_ADJUST(-8); CFI_SAME_VALUE(r12); \
+        popq    %rdi; CFI_ADJUST(-8); CFI_SAME_VALUE(rdi); \
+        popq    %rsi; CFI_ADJUST(-8); CFI_SAME_VALUE(rsi); \
+        popq    %rbp; CFI_ADJUST(-8); CFI_SAME_VALUE(rbp); \
+        popq    %rbx; CFI_ADJUST(-8); CFI_SAME_VALUE(rbx)
 
 #else
 
 /* Unix API: callee-save regs are rbx, rbp, r12-r15 */
 
 #define PUSH_CALLEE_SAVE_REGS \
-        pushq   %rbx; CFI_ADJUST(8); \
-        pushq   %rbp; CFI_ADJUST(8); \
-        pushq   %r12; CFI_ADJUST(8); \
-        pushq   %r13; CFI_ADJUST(8); \
-        pushq   %r14; CFI_ADJUST(8); \
-        pushq   %r15; CFI_ADJUST(8); \
+        pushq   %rbx; CFI_ADJUST(8); CFI_OFFSET(rbx, -16); \
+        pushq   %rbp; CFI_ADJUST(8); CFI_OFFSET(rbp, -24); \
+        pushq   %r12; CFI_ADJUST(8); CFI_OFFSET(r12, -32); \
+        pushq   %r13; CFI_ADJUST(8); CFI_OFFSET(r13, -40); \
+        pushq   %r14; CFI_ADJUST(8); CFI_OFFSET(r14, -48); \
+        pushq   %r15; CFI_ADJUST(8); CFI_OFFSET(r15, -56); \
         subq    $8, %rsp; CFI_ADJUST(8)
 
 #define POP_CALLEE_SAVE_REGS \
         addq    $8, %rsp; CFI_ADJUST(-8); \
-        popq    %r15; CFI_ADJUST(-8); \
-        popq    %r14; CFI_ADJUST(-8); \
-        popq    %r13; CFI_ADJUST(-8); \
-        popq    %r12; CFI_ADJUST(-8); \
-        popq    %rbp; CFI_ADJUST(-8); \
-        popq    %rbx; CFI_ADJUST(-8);
+        popq    %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \
+        popq    %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \
+        popq    %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \
+        popq    %r12; CFI_ADJUST(-8); CFI_SAME_VALUE(r12); \
+        popq    %rbp; CFI_ADJUST(-8); CFI_SAME_VALUE(rbp); \
+        popq    %rbx; CFI_ADJUST(-8); CFI_SAME_VALUE(rbx)
 
 #endif
 
@@ -425,6 +432,7 @@ LBL(caml_allocN):
         addq    $8, %rsp; CFI_ADJUST (-8)  /* drop desired size */
         ret
 LBL(103):
+        CFI_ADJUST(8)
         RECORD_STACK_FRAME(8)
 #ifdef WITH_FRAME_POINTERS
         /* Do we need 16-byte alignment here ? */
@@ -486,7 +494,6 @@ LBL(caml_start_program):
         lea     LBL(108)(%rip), %r13
         pushq   %r13; CFI_ADJUST(8)
         pushq   %r14; CFI_ADJUST(8)
-        CFI_ADJUST(16)
         movq    %rsp, %r14
     /* Call the OCaml code */
         call    *%r12
@@ -494,7 +501,6 @@ LBL(107):
     /* Pop the exception handler */
         popq    %r14; CFI_ADJUST(-8)
         popq    %r12; CFI_ADJUST(-8)   /* dummy register */
-        CFI_ADJUST(-16)
 LBL(109):
     /* Update alloc ptr and exception ptr */
         STORE_VAR(%r15,caml_young_ptr)
diff --git a/asmrun/amd64nt.asm b/asmrun/amd64nt.asm
index 4883ba97..fe80895a 100644
--- a/asmrun/amd64nt.asm
+++ b/asmrun/amd64nt.asm
@@ -1,15 +1,17 @@
-;***********************************************************************
-;*                                                                     *
-;*                                OCaml                                *
-;*                                                                     *
-;*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         *
-;*                                                                     *
-;*  Copyright 2006 Institut National de Recherche en Informatique et   *
-;*  en Automatique.  All rights reserved.  This file is distributed    *
-;*  under the terms of the GNU Library General Public License, with    *
-;*  the special exception on linking described in file ../LICENSE.     *
-;*                                                                     *
-;***********************************************************************
+;**************************************************************************
+;*                                                                        *
+;*                                 OCaml                                  *
+;*                                                                        *
+;*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           *
+;*                                                                        *
+;*   Copyright 2006 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.          *
+;*                                                                        *
+;**************************************************************************
 
 ; Asm part of the runtime system, AMD64 processor, Intel syntax
 
diff --git a/asmrun/arm.S b/asmrun/arm.S
index 9720665a..8305cfe9 100644
--- a/asmrun/arm.S
+++ b/asmrun/arm.S
@@ -1,16 +1,18 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*                  Benedikt Meurer, University of Siegen              */
-/*                                                                     */
-/*    Copyright 1998 Institut National de Recherche en Informatique    */
-/*    et en Automatique. Copyright 2012 Benedikt Meurer. All rights    */
-/*    reserved. This file is distributed under the terms of the GNU    */
-/*    Library General Public License, with the special exception on    */
-/*    linking described in file ../LICENSE.                            */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*                 Benedikt Meurer, University of Siegen                  */
+/*                                                                        */
+/*   Copyright 1998 Institut National de Recherche en Informatique et     */
+/*     en Automatique.                                                    */
+/*   Copyright 2012 Benedikt Meurer.                                      */
+/*                                                                        */
+/*   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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Asm part of the runtime system, ARM processor */
 /* Must be preprocessed by cpp */
@@ -44,6 +46,26 @@
         cmp     \reg, #0
         beq     \lbl
         .endm
+#elif defined(SYS_netbsd)
+
+  #if defined(MODEL_armv6)
+        .arch   armv6
+        .fpu    vfpv2
+        .arm
+
+    /* Compatibility macros */
+        .macro  cbz reg, lbl
+        cmp     \reg, #0
+        beq     \lbl
+        .endm
+  #elif defined(MODEL_armv7)
+        .arch   armv7-a
+        .fpu    vfpv3-d16
+        .thumb
+  #else
+    #error "Only NetBSD eabihf supported"
+  #endif
+
 #elif defined(SYS_freebsd)
         .arch   armv6
         .arm
@@ -73,7 +95,9 @@ alloc_limit     .req    r11
 
 /* Support for profiling with gprof */
 
-#if defined(PROFILING) && (defined(SYS_linux_eabihf) || defined(SYS_linux_eabi))
+#if defined(PROFILING) && (defined(SYS_linux_eabihf) \
+        || defined(SYS_linux_eabi) \
+        || defined(SYS_netbsd))
 #define PROFILE \
         push    {lr}; CFI_ADJUST(4); \
         bl      __gnu_mcount_nc; CFI_ADJUST(-4)
@@ -98,7 +122,7 @@ caml_call_gc:
     /* Record lowest stack address */
         ldr     r12, =caml_bottom_of_stack
         str     sp, [r12]
-#if defined(SYS_linux_eabihf)
+#if defined(SYS_linux_eabihf) || defined(SYS_netbsd)
     /* Save caller floating-point registers on the stack */
         vpush   {d0-d7}; CFI_ADJUST(64)
 #endif
@@ -117,7 +141,7 @@ caml_call_gc:
         bl      caml_garbage_collection
     /* Restore integer registers and return address from the stack */
         pop     {r0-r7,r12,lr}; CFI_ADJUST(-40)
-#if defined(SYS_linux_eabihf)
+#if defined(SYS_linux_eabihf) || defined(SYS_netbsd)
     /* Restore floating-point registers from the stack */
         vpop    {d0-d7}; CFI_ADJUST(-64)
 #endif
@@ -272,7 +296,7 @@ caml_start_program:
 /* Arguments to the OCaml code are in r0...r3 */
 
 .Ljump_to_caml:
-#if defined(SYS_linux_eabihf)
+#if defined(SYS_linux_eabihf) || defined(SYS_netbsd)
     /* Save callee-save floating-point registers */
         vpush   {d8-d15}; CFI_ADJUST(64)
 #endif
@@ -327,7 +351,7 @@ caml_start_program:
         str     alloc_ptr, [r4]
     /* Reload callee-save registers and return address */
         pop     {r4-r8,r10,r11,lr}; CFI_ADJUST(-32)
-#if defined(SYS_linux_eabihf)
+#if defined(SYS_linux_eabihf) || defined(SYS_netbsd)
     /* Reload callee-save floating-point registers */
         vpop    {d8-d15}; CFI_ADJUST(-64)
 #endif
@@ -498,3 +522,6 @@ caml_system__frametable:
         .align  2
         .type   caml_system__frametable, %object
         .size   caml_system__frametable, .-caml_system__frametable
+
+/* Mark stack as non-executable */
+        .section .note.GNU-stack,"",%progbits
diff --git a/asmrun/arm64.S b/asmrun/arm64.S
index 9b4b9ab7..60342fe1 100644
--- a/asmrun/arm64.S
+++ b/asmrun/arm64.S
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 2013 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 2013 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Asm part of the runtime system, ARM processor, 64-bit mode */
 /* Must be preprocessed by cpp */
@@ -175,11 +177,12 @@ caml_alloc1:
         ret
 2:      stp     x29, x30, [sp, -16]!
         CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.  This is the address
-       immediately above the pair of words (x29 and x30) we just pushed.  Those must
-       not be included since otherwise the distance from [caml_bottom_of_stack] to the
-       highest address in the caller's stack frame won't match the frame size contained
-       in the relevant frame descriptor. */
+    /* Record the lowest address of the caller's stack frame.  This is the
+       address immediately above the pair of words (x29 and x30) we just
+       pushed.  Those must not be included since otherwise the distance from
+       [caml_bottom_of_stack] to the highest address in the caller's stack
+       frame won't match the frame size contained in the relevant frame
+       descriptor. */
         add     x29, sp, #16
         STOREGLOBAL(x29, caml_bottom_of_stack)
         add     x29, sp, #0
@@ -207,7 +210,8 @@ caml_alloc2:
         ret
 2:      stp     x29, x30, [sp, -16]!
         CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.  See comment above. */
+    /* Record the lowest address of the caller's stack frame.
+       See comment above. */
         add     x29, sp, #16
         STOREGLOBAL(x29, caml_bottom_of_stack)
         add     x29, sp, #0
@@ -235,7 +239,8 @@ caml_alloc3:
         ret
 2:      stp     x29, x30, [sp, -16]!
         CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.  See comment above. */
+    /* Record the lowest address of the caller's stack frame.
+       See comment above. */
         add     x29, sp, #16
         STOREGLOBAL(x29, caml_bottom_of_stack)
         add     x29, sp, #0
@@ -263,7 +268,8 @@ caml_allocN:
         ret
 2:      stp     x29, x30, [sp, -16]!
         CFI_ADJUST(16)
-    /* Record the lowest address of the caller's stack frame.  See comment above. */
+    /* Record the lowest address of the caller's stack frame.
+       See comment above. */
         add     x29, sp, #16
         STOREGLOBAL(x29, caml_bottom_of_stack)
         add     x29, sp, #0
@@ -549,3 +555,6 @@ caml_system__frametable:
         .align  3
         .type   caml_system__frametable, %object
         .size   caml_system__frametable, .-caml_system__frametable
+
+/* Mark stack as non-executable */
+        .section .note.GNU-stack,"",%progbits
diff --git a/asmrun/backtrace.c b/asmrun/backtrace.c
deleted file mode 100644
index fafe13a0..00000000
--- a/asmrun/backtrace.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 2006 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
-
-/* Stack backtrace for uncaught exceptions */
-
-#include 
-#include 
-#include 
-
-#include "caml/alloc.h"
-#include "caml/backtrace.h"
-#include "caml/memory.h"
-#include "caml/misc.h"
-#include "caml/mlvalues.h"
-#include "stack.h"
-
-int caml_backtrace_active = 0;
-int caml_backtrace_pos = 0;
-code_t * caml_backtrace_buffer = NULL;
-value caml_backtrace_last_exn = Val_unit;
-#define BACKTRACE_BUFFER_SIZE 1024
-
-/* In order to prevent the GC from walking through the debug information
-   (which have no headers), we transform frame_descr pointers into
-   31/63 bits ocaml integers by shifting them by 1 to the right. We do
-   not lose information as descr pointers are aligned.
-
-   In particular, we do not need to use [caml_initialize] when setting
-   an array element with such a value.
-*/
-#define Val_Descrptr(descr) Val_long((uintnat)descr>>1)
-#define Descrptr_Val(v) ((frame_descr *) (Long_val(v)<<1))
-
-/* Start or stop the backtrace machinery */
-
-CAMLprim value caml_record_backtrace(value vflag)
-{
-  int flag = Int_val(vflag);
-
-  if (flag != caml_backtrace_active) {
-    caml_backtrace_active = flag;
-    caml_backtrace_pos = 0;
-    if (flag) {
-      caml_register_global_root(&caml_backtrace_last_exn);
-    } else {
-      caml_remove_global_root(&caml_backtrace_last_exn);
-    }
-  }
-  return Val_unit;
-}
-
-/* Return the status of the backtrace machinery */
-
-CAMLprim value caml_backtrace_status(value vunit)
-{
-  return Val_bool(caml_backtrace_active);
-}
-
-/* returns the next frame descriptor (or NULL if none is available),
-   and updates *pc and *sp to point to the following one.  */
-
-frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp)
-{
-  frame_descr * d;
-  uintnat h;
-
-  if (caml_frame_descriptors == NULL) caml_init_frame_descriptors();
-
-  while (1) {
-    h = Hash_retaddr(*pc);
-    while (1) {
-      d = caml_frame_descriptors[h];
-      if (d == 0) return NULL; /* can happen if some code compiled without -g */
-      if (d->retaddr == *pc) break;
-      h = (h+1) & caml_frame_descriptors_mask;
-    }
-    /* Skip to next frame */
-    if (d->frame_size != 0xFFFF) {
-      /* Regular frame, update sp/pc and return the frame descriptor */
-#ifndef Stack_grows_upwards
-      *sp += (d->frame_size & 0xFFFC);
-#else
-      *sp -= (d->frame_size & 0xFFFC);
-#endif
-      *pc = Saved_return_address(*sp);
-#ifdef Mask_already_scanned
-      *pc = Mask_already_scanned(*pc);
-#endif
-      return d;
-    } else {
-      /* Special frame marking the top of a stack chunk for an ML callback.
-         Skip C portion of stack and continue with next ML stack chunk. */
-      struct caml_context * next_context = Callback_link(*sp);
-      *sp = next_context->bottom_of_stack;
-      *pc = next_context->last_retaddr;
-      /* A null sp means no more ML stack chunks; stop here. */
-      if (*sp == NULL) return NULL;
-    }
-  }
-}
-
-/* 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
-   preserved the global, statically bounded buffer of the old
-   implementation -- before the more flexible
-   [caml_get_current_callstack] was implemented. */
-
-void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp)
-{
-  if (exn != caml_backtrace_last_exn) {
-    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(code_t));
-    if (caml_backtrace_buffer == NULL) return;
-  }
-
-  /* iterate on each frame  */
-  while (1) {
-    frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
-    if (descr == NULL) return;
-    /* store its descriptor in the backtrace buffer */
-    if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return;
-    caml_backtrace_buffer[caml_backtrace_pos++] = (code_t) descr;
-
-    /* Stop when we reach the current exception handler */
-#ifndef Stack_grows_upwards
-    if (sp > trapsp) return;
-#else
-    if (sp < trapsp) return;
-#endif
-  }
-}
-
-/* Stores upto [max_frames_value] frames of the current call stack to
-   return to the user. This is used not in an exception-raising
-   context, but only when the user requests to save the trace
-   (hopefully less often). Instead of using a bounded buffer as
-   [caml_stash_backtrace], we first traverse the stack to compute the
-   right size, then allocate space for the trace. */
-
-CAMLprim value caml_get_current_callstack(value max_frames_value) {
-  CAMLparam1(max_frames_value);
-  CAMLlocal1(trace);
-
-  /* we use `intnat` here because, were it only `int`, passing `max_int`
-     from the OCaml side would overflow on 64bits machines. */
-  intnat max_frames = Long_val(max_frames_value);
-  intnat trace_size;
-
-  /* first compute the size of the trace */
-  {
-    uintnat pc = caml_last_return_address;
-    /* note that [caml_bottom_of_stack] always points to the most recent
-     * frame, independently of the [Stack_grows_upwards] setting */
-    char * sp = caml_bottom_of_stack;
-    char * limitsp = caml_top_of_stack;
-
-    trace_size = 0;
-    while (1) {
-      frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
-      if (descr == NULL) break;
-      if (trace_size >= max_frames) break;
-      ++trace_size;
-
-#ifndef Stack_grows_upwards
-      if (sp > limitsp) break;
-#else
-      if (sp < limitsp) break;
-#endif
-    }
-  }
-
-  trace = caml_alloc((mlsize_t) trace_size, 0);
-
-  /* then collect the trace */
-  {
-    uintnat pc = caml_last_return_address;
-    char * sp = caml_bottom_of_stack;
-    intnat trace_pos;
-
-    for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
-      frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
-      Assert(descr != NULL);
-      Field(trace, trace_pos) = Val_Descrptr(descr);
-    }
-  }
-
-  CAMLreturn(trace);
-}
-
-/* Extract location information for the given frame descriptor */
-
-CAMLexport void extract_location_info(frame_descr * d,
-                                  /*out*/ struct caml_loc_info * li)
-{
-  uintnat infoptr;
-  uint32 info1, info2;
-
-  /* If no debugging information available, print nothing.
-     When everything is compiled with -g, this corresponds to
-     compiler-inserted re-raise operations. */
-  if ((d->frame_size & 1) == 0) {
-    li->loc_valid = 0;
-    li->loc_is_raise = 1;
-    return;
-  }
-  /* Recover debugging info */
-  infoptr = ((uintnat) d +
-             sizeof(char *) + sizeof(short) + sizeof(short) +
-             sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
-            & -sizeof(frame_descr *);
-  info1 = ((uint32 *)infoptr)[0];
-  info2 = ((uint32 *)infoptr)[1];
-  /* Format of the two info words:
-       llllllllllllllllllll aaaaaaaa bbbbbbbbbb nnnnnnnnnnnnnnnnnnnnnnnn kk
-                          44       36         26                       2  0
-                       (32+12)    (32+4)
-     k ( 2 bits): 0 if it's a call, 1 if it's a raise
-     n (24 bits): offset (in 4-byte words) of file name relative to infoptr
-     l (20 bits): line number
-     a ( 8 bits): beginning of character range
-     b (10 bits): end of character range */
-  li->loc_valid = 1;
-  li->loc_is_raise = (info1 & 3) != 0;
-  li->loc_filename = (char *) infoptr + (info1 & 0x3FFFFFC);
-  li->loc_lnum = info2 >> 12;
-  li->loc_startchr = (info2 >> 4) & 0xFF;
-  li->loc_endchr = ((info2 & 0xF) << 6) | (info1 >> 26);
-}
-
-/* Print location information -- same behavior as in Printexc
-
-   note that the test for compiler-inserted raises is slightly redundant:
-     (!li->loc_valid && li->loc_is_raise)
-   extract_location_info above guarantees that when li->loc_valid is
-   0, then li->loc_is_raise is always 1, so the latter test is
-   useless. We kept it to keep code identical to the byterun/
-   implementation. */
-
-static void print_location(struct caml_loc_info * li, int index)
-{
-  char * info;
-
-  /* Ignore compiler-inserted raise */
-  if (!li->loc_valid && li->loc_is_raise) return;
-
-  if (li->loc_is_raise) {
-    /* Initial raise if index == 0, re-raise otherwise */
-    if (index == 0)
-      info = "Raised at";
-    else
-      info = "Re-raised at";
-  } else {
-    if (index == 0)
-      info = "Raised by primitive operation at";
-    else
-      info = "Called from";
-  }
-  if (! li->loc_valid) {
-    fprintf(stderr, "%s unknown location\n", info);
-  } else {
-    fprintf (stderr, "%s file \"%s\", line %d, characters %d-%d\n",
-             info, li->loc_filename, li->loc_lnum,
-             li->loc_startchr, li->loc_endchr);
-  }
-}
-
-/* Print a backtrace */
-
-void caml_print_exception_backtrace(void)
-{
-  int i;
-  struct caml_loc_info li;
-
-  for (i = 0; i < caml_backtrace_pos; i++) {
-    extract_location_info((frame_descr *) (caml_backtrace_buffer[i]), &li);
-    print_location(&li, i);
-  }
-}
-
-/* Convert the raw backtrace to a data structure usable from OCaml */
-
-CAMLprim value caml_convert_raw_backtrace_slot(value backtrace_slot) {
-  CAMLparam1(backtrace_slot);
-  CAMLlocal2(p, fname);
-  struct caml_loc_info li;
-
-  extract_location_info(Descrptr_Val(backtrace_slot), &li);
-
-  if (li.loc_valid) {
-    fname = caml_copy_string(li.loc_filename);
-    p = caml_alloc_small(5, 0);
-    Field(p, 0) = Val_bool(li.loc_is_raise);
-    Field(p, 1) = fname;
-    Field(p, 2) = Val_int(li.loc_lnum);
-    Field(p, 3) = Val_int(li.loc_startchr);
-    Field(p, 4) = Val_int(li.loc_endchr);
-  } else {
-    p = caml_alloc_small(1, 1);
-    Field(p, 0) = Val_bool(li.loc_is_raise);
-  }
-
-  CAMLreturn(p);
-}
-
-/* Get a copy of the latest backtrace */
-
-CAMLprim value caml_get_exception_raw_backtrace(value unit)
-{
-  CAMLparam0();
-  CAMLlocal1(res);
-  const int tag = 0;
-
-  /* Beware: the allocations below may cause finalizers to be run, and another
-     backtrace---possibly of a different length---to be stashed (for example
-     if the finalizer raises then catches an exception).  We choose to ignore
-     any such finalizer backtraces and return the original one. */
-
-  if (caml_backtrace_buffer == NULL || caml_backtrace_pos == 0) {
-    res = caml_alloc(0, tag);
-  }
-  else {
-    code_t saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE];
-    int saved_caml_backtrace_pos;
-    intnat i;
-
-    saved_caml_backtrace_pos = caml_backtrace_pos;
-
-    if (saved_caml_backtrace_pos > BACKTRACE_BUFFER_SIZE) {
-      saved_caml_backtrace_pos = BACKTRACE_BUFFER_SIZE;
-    }
-
-    memcpy(saved_caml_backtrace_buffer, caml_backtrace_buffer,
-           saved_caml_backtrace_pos * sizeof(code_t));
-
-    res = caml_alloc(saved_caml_backtrace_pos, tag);
-    for (i = 0; i < saved_caml_backtrace_pos; i++) {
-      /* [Val_Descrptr] always returns an immediate. */
-      Field(res, i) = Val_Descrptr(saved_caml_backtrace_buffer[i]);
-    }
-  }
-
-  CAMLreturn(res);
-}
-
-/* the function below is deprecated: we previously returned directly
-   the OCaml-usable representation, instead of the raw backtrace as an
-   abstract type, but this has a large performance overhead if you
-   store a lot of backtraces and print only some of them.
-
-   It is not used by the Printexc library anymore, or anywhere else in
-   the compiler, but we have kept it in case some user still depends
-   on it as an external.
-*/
-
-CAMLprim value caml_get_exception_backtrace(value unit)
-{
-  CAMLparam0();
-  CAMLlocal3(arr, res, backtrace);
-  intnat i;
-
-  backtrace = caml_get_exception_raw_backtrace(Val_unit);
-
-  arr = caml_alloc(Wosize_val(backtrace), 0);
-  for (i = 0; i < Wosize_val(backtrace); i++) {
-    Store_field(arr, i, caml_convert_raw_backtrace_slot(Field(backtrace, i)));
-  }
-
-  res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */
-  CAMLreturn(res);
-}
diff --git a/asmrun/backtrace_prim.c b/asmrun/backtrace_prim.c
new file mode 100644
index 00000000..1078da1f
--- /dev/null
+++ b/asmrun/backtrace_prim.c
@@ -0,0 +1,232 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 2006 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.          */
+/*                                                                        */
+/**************************************************************************/
+
+/* Stack backtrace for uncaught exceptions */
+
+#include 
+#include 
+#include 
+
+#include "caml/alloc.h"
+#include "caml/backtrace.h"
+#include "caml/backtrace_prim.h"
+#include "caml/memory.h"
+#include "caml/misc.h"
+#include "caml/mlvalues.h"
+#include "stack.h"
+
+/* In order to prevent the GC from walking through the debug information
+   (which have no headers), we transform frame_descr pointers into
+   31/63 bits ocaml integers by shifting them by 1 to the right. We do
+   not lose information as descr pointers are aligned.  */
+value caml_val_raw_backtrace_slot(backtrace_slot pc)
+{
+  return Val_long((uintnat)pc>>1);
+}
+
+backtrace_slot caml_raw_backtrace_slot_val(value v)
+{
+  return ((backtrace_slot)(Long_val(v)<<1));
+}
+
+/* Returns the next frame descriptor (or NULL if none is available),
+   and updates *pc and *sp to point to the following one.  */
+frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp)
+{
+  frame_descr * d;
+  uintnat h;
+
+  while (1) {
+    h = Hash_retaddr(*pc);
+    while (1) {
+      d = caml_frame_descriptors[h];
+      if (d == NULL) return NULL; /* happens if some code compiled without -g */
+      if (d->retaddr == *pc) break;
+      h = (h+1) & caml_frame_descriptors_mask;
+    }
+    /* Skip to next frame */
+    if (d->frame_size != 0xFFFF) {
+      /* Regular frame, update sp/pc and return the frame descriptor */
+#ifndef Stack_grows_upwards
+      *sp += (d->frame_size & 0xFFFC);
+#else
+      *sp -= (d->frame_size & 0xFFFC);
+#endif
+      *pc = Saved_return_address(*sp);
+#ifdef Mask_already_scanned
+      *pc = Mask_already_scanned(*pc);
+#endif
+      return d;
+    } else {
+      /* Special frame marking the top of a stack chunk for an ML callback.
+         Skip C portion of stack and continue with next ML stack chunk. */
+      struct caml_context * next_context = Callback_link(*sp);
+      *sp = next_context->bottom_of_stack;
+      *pc = next_context->last_retaddr;
+      /* A null sp means no more ML stack chunks; stop here. */
+      if (*sp == NULL) return NULL;
+    }
+  }
+}
+
+/* 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
+   preserved the global, statically bounded buffer of the old
+   implementation -- before the more flexible
+   [caml_get_current_callstack] was implemented. */
+void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp)
+{
+  if (exn != caml_backtrace_last_exn) {
+    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;
+  }
+
+  /* iterate on each frame  */
+  while (1) {
+    frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
+    if (descr == NULL) return;
+    /* store its descriptor in the backtrace buffer */
+    if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return;
+    caml_backtrace_buffer[caml_backtrace_pos++] = (backtrace_slot) descr;
+
+    /* Stop when we reach the current exception handler */
+#ifndef Stack_grows_upwards
+    if (sp > trapsp) return;
+#else
+    if (sp < trapsp) return;
+#endif
+  }
+}
+
+/* Stores upto [max_frames_value] frames of the current call stack to
+   return to the user. This is used not in an exception-raising
+   context, but only when the user requests to save the trace
+   (hopefully less often). Instead of using a bounded buffer as
+   [caml_stash_backtrace], we first traverse the stack to compute the
+   right size, then allocate space for the trace. */
+CAMLprim value caml_get_current_callstack(value max_frames_value)
+{
+  CAMLparam1(max_frames_value);
+  CAMLlocal1(trace);
+
+  /* we use `intnat` here because, were it only `int`, passing `max_int`
+     from the OCaml side would overflow on 64bits machines. */
+  intnat max_frames = Long_val(max_frames_value);
+  intnat trace_size;
+
+  /* first compute the size of the trace */
+  {
+    uintnat pc = caml_last_return_address;
+    /* note that [caml_bottom_of_stack] always points to the most recent
+     * frame, independently of the [Stack_grows_upwards] setting */
+    char * sp = caml_bottom_of_stack;
+    char * limitsp = caml_top_of_stack;
+
+    trace_size = 0;
+    while (1) {
+      frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
+      if (descr == NULL) break;
+      if (trace_size >= max_frames) break;
+      ++trace_size;
+
+#ifndef Stack_grows_upwards
+      if (sp > limitsp) break;
+#else
+      if (sp < limitsp) break;
+#endif
+    }
+  }
+
+  trace = caml_alloc((mlsize_t) trace_size, 0);
+
+  /* then collect the trace */
+  {
+    uintnat pc = caml_last_return_address;
+    char * sp = caml_bottom_of_stack;
+    intnat trace_pos;
+
+    for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
+      frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
+      Assert(descr != NULL);
+      Store_field(trace, trace_pos,
+                  caml_val_raw_backtrace_slot((backtrace_slot) descr));
+    }
+  }
+
+  CAMLreturn(trace);
+}
+
+/* Extract location information for the given frame descriptor */
+void caml_extract_location_info(backtrace_slot slot,
+                                /*out*/ struct caml_loc_info * li)
+{
+  uintnat infoptr;
+  uint32_t info1, info2;
+  frame_descr * d = (frame_descr *)slot;
+
+  /* If no debugging information available, print nothing.
+     When everything is compiled with -g, this corresponds to
+     compiler-inserted re-raise operations. */
+  if ((d->frame_size & 1) == 0) {
+    li->loc_valid = 0;
+    li->loc_is_raise = 1;
+    return;
+  }
+  /* Recover debugging info */
+  infoptr = ((uintnat) d +
+             sizeof(char *) + sizeof(short) + sizeof(short) +
+             sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
+            & -sizeof(frame_descr *);
+  info1 = ((uint32_t *)infoptr)[0];
+  info2 = ((uint32_t *)infoptr)[1];
+  /* Format of the two info words:
+       llllllllllllllllllll aaaaaaaa bbbbbbbbbb nnnnnnnnnnnnnnnnnnnnnnnn kk
+                          44       36         26                       2  0
+                       (32+12)    (32+4)
+     k ( 2 bits): 0 if it's a call, 1 if it's a raise
+     n (24 bits): offset (in 4-byte words) of file name relative to infoptr
+     l (20 bits): line number
+     a ( 8 bits): beginning of character range
+     b (10 bits): end of character range */
+  li->loc_valid = 1;
+  li->loc_is_raise = (info1 & 3) != 0;
+  li->loc_filename = (char *) infoptr + (info1 & 0x3FFFFFC);
+  li->loc_lnum = info2 >> 12;
+  li->loc_startchr = (info2 >> 4) & 0xFF;
+  li->loc_endchr = ((info2 & 0xF) << 6) | (info1 >> 26);
+}
+
+CAMLprim value caml_add_debug_info(backtrace_slot start, value size,
+                                   value events)
+{
+  return Val_unit;
+}
+
+CAMLprim value caml_remove_debug_info(backtrace_slot start)
+{
+  return Val_unit;
+}
+
+int caml_debug_info_available(void)
+{
+  return 1;
+}
diff --git a/asmrun/clambda_checks.c b/asmrun/clambda_checks.c
new file mode 100644
index 00000000..7409fa1d
--- /dev/null
+++ b/asmrun/clambda_checks.c
@@ -0,0 +1,86 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*                       Pierre Chambart, OCamlPro                        */
+/*                   Mark Shinwell, Jane Street Europe                    */
+/*                                                                        */
+/*   Copyright 2013--2016 OCamlPro SAS                                    */
+/*   Copyright 2014--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.          */
+/*                                                                        */
+/**************************************************************************/
+
+/* Runtime checks to try to catch errors in code generation.
+   See flambda_to_clambda.ml for more information. */
+
+#include 
+#include 
+
+#include 
+
+value caml_check_value_is_closure(value v, value v_descr)
+{
+  const char* descr = String_val(v_descr);
+  value orig_v = v;
+
+  if (v == (value) 0) {
+    fprintf(stderr, "NULL is not a closure: %s\n",
+      descr);
+    abort();
+  }
+  if (!Is_block(v)) {
+    fprintf(stderr,
+      "Expecting a closure, got a non-boxed value %p: %s\n",
+      (void*) v, descr);
+    abort();
+  }
+  if (!(Tag_val(v) == Closure_tag || Tag_val(v) == Infix_tag)) {
+    fprintf(stderr,
+      "Expecting a closure, got a boxed value with tag %i: %s\n",
+      Tag_val(v), descr);
+    abort();
+  }
+  if (Tag_val(v) == Infix_tag) {
+    v -= Infix_offset_val(v);
+    assert(Tag_val(v) == Closure_tag);
+  }
+  assert(Wosize_val(v) >= 2);
+
+  return orig_v;
+}
+
+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);
+    abort();
+  }
+  if (!Is_block(v)) {
+    fprintf(stderr,
+      "Access to field %lld of non-boxed value %p is illegal: %s\n",
+      (ARCH_UINT64_TYPE) Long_val(pos), (void*) v, descr);
+    abort();
+  }
+  if (Tag_val(v) == Infix_tag) {
+    uintnat offset = Infix_offset_val(v);
+    v -= offset;
+    pos += offset / sizeof(value);
+  }
+  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",
+      (ARCH_UINT64_TYPE) Long_val(pos), (void*) v,
+      (ARCH_UINT64_TYPE) Wosize_val(v),
+      descr);
+    abort();
+  }
+  return orig_v;
+}
diff --git a/asmrun/fail.c b/asmrun/fail.c
index c674d1a8..4f03cc38 100644
--- a/asmrun/fail.c
+++ b/asmrun/fail.c
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Raising exceptions from C. */
 
@@ -47,7 +49,9 @@ extern caml_generated_constant
 
 /* Exception raising */
 
-extern void caml_raise_exception (value bucket) Noreturn;
+CAMLnoreturn_start
+  extern void caml_raise_exception (value bucket)
+CAMLnoreturn_end;
 
 char * caml_exception_pointer = NULL;
 
diff --git a/asmrun/i386.S b/asmrun/i386.S
index e55969ee..55b6947d 100644
--- a/asmrun/i386.S
+++ b/asmrun/i386.S
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Asm part of the runtime system, Intel 386 processor */
 /* Must be preprocessed by cpp */
@@ -116,7 +118,7 @@
 #endif
 
 /* PR#6038: GCC and Clang seem to require 16-byte alignment nowadays,
-   even if only MacOS X's ABI formally requires it. */	
+   even if only MacOS X's ABI formally requires it. */
 #define ALIGN_STACK(amount) subl $ amount, %esp ; CFI_ADJUST(amount)
 #define UNDO_ALIGN_STACK(amount) addl $ amount, %esp ; CFI_ADJUST(-amount)
 
diff --git a/asmrun/i386nt.asm b/asmrun/i386nt.asm
index 61ec3416..74d3ddfd 100644
--- a/asmrun/i386nt.asm
+++ b/asmrun/i386nt.asm
@@ -1,15 +1,17 @@
-;***********************************************************************
-;*                                                                     *
-;*                                OCaml                                *
-;*                                                                     *
-;*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *
-;*                                                                     *
-;*  Copyright 1996 Institut National de Recherche en Informatique et   *
-;*  en Automatique.  All rights reserved.  This file is distributed    *
-;*  under the terms of the GNU Library General Public License, with    *
-;*  the special exception on linking described in file ../LICENSE.     *
-;*                                                                     *
-;***********************************************************************
+;**************************************************************************
+;*                                                                        *
+;*                                 OCaml                                  *
+;*                                                                        *
+;*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *
+;*                                                                        *
+;*   Copyright 1996 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.          *
+;*                                                                        *
+;**************************************************************************
 
 ; Asm part of the runtime system, Intel 386 processor, Intel syntax
 
diff --git a/asmrun/natdynlink.c b/asmrun/natdynlink.c
index 82e8795f..a502d449 100644
--- a/asmrun/natdynlink.c
+++ b/asmrun/natdynlink.c
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Alain Frisch, projet Gallium, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 2007 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Alain Frisch, projet Gallium, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 2007 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 "caml/misc.h"
 #include "caml/mlvalues.h"
@@ -90,7 +92,7 @@ CAMLprim value caml_natdynlink_run(void *handle, value symbol) {
   sym = optsym("__frametable");
   if (NULL != sym) caml_register_frametable(sym);
 
-  sym = optsym("");
+  sym = optsym("__gc_roots");
   if (NULL != sym) caml_register_dyn_global(sym);
 
   sym = optsym("__data_begin");
diff --git a/asmrun/power-elf.S b/asmrun/power-elf.S
deleted file mode 100644
index facbfbf0..00000000
--- a/asmrun/power-elf.S
+++ /dev/null
@@ -1,480 +0,0 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
-
-#define Addrglobal(reg,glob) \
-        addis   reg, 0, glob@ha; \
-        addi    reg, reg, glob@l
-#define Loadglobal(reg,glob,tmp) \
-        addis   tmp, 0, glob@ha; \
-        lwz     reg, glob@l(tmp)
-#define Storeglobal(reg,glob,tmp) \
-        addis   tmp, 0, glob@ha; \
-        stw     reg, glob@l(tmp)
-
-        .section ".text"
-
-/* Invoke the garbage collector. */
-
-        .globl  caml_system__code_begin
-caml_system__code_begin:
-
-        .globl  caml_call_gc
-        .type   caml_call_gc, @function
-caml_call_gc:
-    /* Set up stack frame */
-        stwu    1, -0x1A0(1)
-    /* 0x1A0 = 4*32 (int regs) + 8*32 (float regs) + 32 (space for C call) */
-    /* Record return address into OCaml code */
-        mflr    0
-        Storeglobal(0, caml_last_return_address, 11)
-    /* Record lowest stack address */
-        addi    0, 1, 0x1A0
-        Storeglobal(0, caml_bottom_of_stack, 11)
-    /* Record pointer to register array */
-        addi    0, 1, 8*32 + 32
-        Storeglobal(0, caml_gc_regs, 11)
-    /* Save current allocation pointer for debugging purposes */
-        Storeglobal(31, caml_young_ptr, 11)
-    /* Save exception pointer (if e.g. a sighandler raises) */
-        Storeglobal(29, caml_exception_pointer, 11)
-    /* Save all registers used by the code generator */
-        addi    11, 1, 8*32 + 32 - 4
-        stwu    3, 4(11)
-        stwu    4, 4(11)
-        stwu    5, 4(11)
-        stwu    6, 4(11)
-        stwu    7, 4(11)
-        stwu    8, 4(11)
-        stwu    9, 4(11)
-        stwu    10, 4(11)
-        stwu    14, 4(11)
-        stwu    15, 4(11)
-        stwu    16, 4(11)
-        stwu    17, 4(11)
-        stwu    18, 4(11)
-        stwu    19, 4(11)
-        stwu    20, 4(11)
-        stwu    21, 4(11)
-        stwu    22, 4(11)
-        stwu    23, 4(11)
-        stwu    24, 4(11)
-        stwu    25, 4(11)
-        stwu    26, 4(11)
-        stwu    27, 4(11)
-        stwu    28, 4(11)
-        addi    11, 1, 32 - 8
-        stfdu   1, 8(11)
-        stfdu   2, 8(11)
-        stfdu   3, 8(11)
-        stfdu   4, 8(11)
-        stfdu   5, 8(11)
-        stfdu   6, 8(11)
-        stfdu   7, 8(11)
-        stfdu   8, 8(11)
-        stfdu   9, 8(11)
-        stfdu   10, 8(11)
-        stfdu   11, 8(11)
-        stfdu   12, 8(11)
-        stfdu   13, 8(11)
-        stfdu   14, 8(11)
-        stfdu   15, 8(11)
-        stfdu   16, 8(11)
-        stfdu   17, 8(11)
-        stfdu   18, 8(11)
-        stfdu   19, 8(11)
-        stfdu   20, 8(11)
-        stfdu   21, 8(11)
-        stfdu   22, 8(11)
-        stfdu   23, 8(11)
-        stfdu   24, 8(11)
-        stfdu   25, 8(11)
-        stfdu   26, 8(11)
-        stfdu   27, 8(11)
-        stfdu   28, 8(11)
-        stfdu   29, 8(11)
-        stfdu   30, 8(11)
-        stfdu   31, 8(11)
-    /* Call the GC */
-        bl      caml_garbage_collection
-    /* Reload new allocation pointer and allocation limit */
-        Loadglobal(31, caml_young_ptr, 11)
-        Loadglobal(30, caml_young_limit, 11)
-    /* Restore all regs used by the code generator */
-        addi    11, 1, 8*32 + 32 - 4
-        lwzu    3, 4(11)
-        lwzu    4, 4(11)
-        lwzu    5, 4(11)
-        lwzu    6, 4(11)
-        lwzu    7, 4(11)
-        lwzu    8, 4(11)
-        lwzu    9, 4(11)
-        lwzu    10, 4(11)
-        lwzu    14, 4(11)
-        lwzu    15, 4(11)
-        lwzu    16, 4(11)
-        lwzu    17, 4(11)
-        lwzu    18, 4(11)
-        lwzu    19, 4(11)
-        lwzu    20, 4(11)
-        lwzu    21, 4(11)
-        lwzu    22, 4(11)
-        lwzu    23, 4(11)
-        lwzu    24, 4(11)
-        lwzu    25, 4(11)
-        lwzu    26, 4(11)
-        lwzu    27, 4(11)
-        lwzu    28, 4(11)
-        addi    11, 1, 32 - 8
-        lfdu    1, 8(11)
-        lfdu    2, 8(11)
-        lfdu    3, 8(11)
-        lfdu    4, 8(11)
-        lfdu    5, 8(11)
-        lfdu    6, 8(11)
-        lfdu    7, 8(11)
-        lfdu    8, 8(11)
-        lfdu    9, 8(11)
-        lfdu    10, 8(11)
-        lfdu    11, 8(11)
-        lfdu    12, 8(11)
-        lfdu    13, 8(11)
-        lfdu    14, 8(11)
-        lfdu    15, 8(11)
-        lfdu    16, 8(11)
-        lfdu    17, 8(11)
-        lfdu    18, 8(11)
-        lfdu    19, 8(11)
-        lfdu    20, 8(11)
-        lfdu    21, 8(11)
-        lfdu    22, 8(11)
-        lfdu    23, 8(11)
-        lfdu    24, 8(11)
-        lfdu    25, 8(11)
-        lfdu    26, 8(11)
-        lfdu    27, 8(11)
-        lfdu    28, 8(11)
-        lfdu    29, 8(11)
-        lfdu    30, 8(11)
-        lfdu    31, 8(11)
-    /* Return to caller, restarting the allocation */
-        Loadglobal(0, caml_last_return_address, 11)
-        addic   0, 0, -16     /* Restart the allocation (4 instructions) */
-        mtlr    0
-    /* Say we are back into OCaml code */
-        li      12, 0
-        Storeglobal(12, caml_last_return_address, 11)
-    /* Deallocate stack frame */
-        addi    1, 1, 0x1A0
-    /* Return */
-        blr
-
-/* Call a C function from OCaml */
-
-        .globl  caml_c_call
-        .type   caml_c_call, @function
-caml_c_call:
-    /* Save return address */
-        mflr    25
-    /* Get ready to call C function (address in 11) */
-        mtctr   11
-    /* Record lowest stack address and return address */
-        Storeglobal(1, caml_bottom_of_stack, 12)
-        Storeglobal(25, caml_last_return_address, 12)
-    /* Make the exception handler and alloc ptr available to the C code */
-        Storeglobal(31, caml_young_ptr, 11)
-        Storeglobal(29, caml_exception_pointer, 11)
-    /* Call the function (address in CTR register) */
-        bctrl
-    /* Restore return address (in 25, preserved by the C function) */
-        mtlr    25
-    /* Reload allocation pointer and allocation limit*/
-        Loadglobal(31, caml_young_ptr, 11)
-        Loadglobal(30, caml_young_limit, 11)
-    /* Return to caller */
-        blr
-
-/* Raise an exception from OCaml */
-        .globl  caml_raise_exn
-        .type   caml_raise_exn, @function
-caml_raise_exn:
-        Loadglobal(0, caml_backtrace_active, 11)
-        cmpwi   0, 0
-        bne     .L111
-.L110:
-    /* Pop trap frame */
-        lwz     0, 0(29)
-        mr      1, 29
-        mtctr   0
-        lwz     29, 4(29)
-        addi    1, 1, 16
-    /* Branch to handler */
-        bctr
-.L111:
-        li      0, 0
-        Storeglobal(0, caml_backtrace_pos, 11)
-.L112:
-        mr      28, 3           /* preserve exn bucket in callee-save reg */
-                                /* arg1: exception bucket, already in r3 */
-        mflr    4               /* arg2: PC of raise */
-        mr      5, 1            /* arg3: SP of raise */
-        mr      6, 29           /* arg4: SP of handler */
-        addi    1, 1, -16       /* reserve stack space for C call */
-        bl      caml_stash_backtrace
-        mr      3, 28           /* restore exn bucket */
-        b       .L110           /* raise the exn */
-
-        .globl  caml_reraise_exn
-        .type   caml_reraise_exn, @function
-caml_reraise_exn:
-        Loadglobal(0, caml_backtrace_active, 11)
-        cmpwi   0, 0
-        bne-    .L112
-    /* Pop trap frame */
-        lwz     0, 0(29)
-        mr      1, 29
-        mtctr   0
-        lwz     29, 4(29)
-        addi    1, 1, 16
-    /* Branch to handler */
-        bctr
-
-/* Raise an exception from C */
-
-        .globl  caml_raise_exception
-        .type   caml_raise_exception, @function
-caml_raise_exception:
-        Loadglobal(0, caml_backtrace_active, 11)
-        cmpwi   0, 0
-        bne     .L121
-.L120:
-    /* Reload OCaml global registers */
-        Loadglobal(1, caml_exception_pointer, 11)
-        Loadglobal(31, caml_young_ptr, 11)
-        Loadglobal(30, caml_young_limit, 11)
-    /* Pop trap frame */
-        lwz     0, 0(1)
-        lwz     29, 4(1)
-        mtctr   0
-        addi    1, 1, 16
-    /* Branch to handler */
-        bctr
-.L121:
-        li      0, 0
-        Storeglobal(0, caml_backtrace_pos, 11)
-        mr      28, 3           /* preserve exn bucket in callee-save reg */
-                                /* arg1: exception bucket, already in r3 */
-        Loadglobal(4, caml_last_return_address, 11) /* arg2: PC of raise */
-        Loadglobal(5, caml_bottom_of_stack, 11)     /* arg3: SP of raise */
-        Loadglobal(6, caml_exception_pointer, 11)   /* arg4: SP of handler */
-        addi    1, 1, -16       /* reserve stack space for C call */
-        bl      caml_stash_backtrace
-        mr      3, 28           /* restore exn bucket */
-        b       .L120           /* raise the exn */
-
-
-/* Start the OCaml program */
-
-        .globl  caml_start_program
-        .type   caml_start_program, @function
-caml_start_program:
-        Addrglobal(12, caml_program)
-
-/* Code shared between caml_start_program and caml_callback */
-.L102:
-    /* Allocate and link stack frame */
-        stwu    1, -256(1)
-    /* Save return address */
-        mflr    0
-        stw     0, 256+4(1)
-    /* Save all callee-save registers */
-    /* GPR 14 at sp+16 ... GPR 31 at sp+84
-       FPR 14 at sp+92 ... FPR 31 at sp+228 */
-        addi    11, 1, 16-4
-        stwu    14, 4(11)
-        stwu    15, 4(11)
-        stwu    16, 4(11)
-        stwu    17, 4(11)
-        stwu    18, 4(11)
-        stwu    19, 4(11)
-        stwu    20, 4(11)
-        stwu    21, 4(11)
-        stwu    22, 4(11)
-        stwu    23, 4(11)
-        stwu    24, 4(11)
-        stwu    25, 4(11)
-        stwu    26, 4(11)
-        stwu    27, 4(11)
-        stwu    28, 4(11)
-        stwu    29, 4(11)
-        stwu    30, 4(11)
-        stwu    31, 4(11)
-        stfdu   14, 8(11)
-        stfdu   15, 8(11)
-        stfdu   16, 8(11)
-        stfdu   17, 8(11)
-        stfdu   18, 8(11)
-        stfdu   19, 8(11)
-        stfdu   20, 8(11)
-        stfdu   21, 8(11)
-        stfdu   22, 8(11)
-        stfdu   23, 8(11)
-        stfdu   24, 8(11)
-        stfdu   25, 8(11)
-        stfdu   26, 8(11)
-        stfdu   27, 8(11)
-        stfdu   28, 8(11)
-        stfdu   29, 8(11)
-        stfdu   30, 8(11)
-        stfdu   31, 8(11)
-    /* Set up a callback link */
-        addi    1, 1, -16
-        Loadglobal(9, caml_bottom_of_stack, 11)
-        Loadglobal(10, caml_last_return_address, 11)
-        Loadglobal(11, caml_gc_regs, 11)
-        stw     9, 0(1)
-        stw     10, 4(1)
-        stw     11, 8(1)
-    /* Build an exception handler to catch exceptions escaping out of OCaml */
-        bl      .L103
-        b       .L104
-.L103:
-        addi    1, 1, -16
-        mflr    0
-        stw     0, 0(1)
-        Loadglobal(11, caml_exception_pointer, 11)
-        stw     11, 4(1)
-        mr      29, 1
-    /* Reload allocation pointers */
-        Loadglobal(31, caml_young_ptr, 11)
-        Loadglobal(30, caml_young_limit, 11)
-    /* Say we are back into OCaml code */
-        li      0, 0
-        Storeglobal(0, caml_last_return_address, 11)
-    /* Call the OCaml code */
-        mtlr    12
-.L105:
-        blrl
-    /* Pop the trap frame, restoring caml_exception_pointer */
-        lwz     9, 4(1)
-        Storeglobal(9, caml_exception_pointer, 11)
-        addi    1, 1, 16
-    /* Pop the callback link, restoring the global variables */
-.L106:
-        lwz     9, 0(1)
-        lwz     10, 4(1)
-        lwz     11, 8(1)
-        Storeglobal(9, caml_bottom_of_stack, 12)
-        Storeglobal(10, caml_last_return_address, 12)
-        Storeglobal(11, caml_gc_regs, 12)
-        addi    1, 1, 16
-    /* Update allocation pointer */
-        Storeglobal(31, caml_young_ptr, 11)
-    /* Restore callee-save registers */
-        addi    11, 1, 16-4
-        lwzu    14, 4(11)
-        lwzu    15, 4(11)
-        lwzu    16, 4(11)
-        lwzu    17, 4(11)
-        lwzu    18, 4(11)
-        lwzu    19, 4(11)
-        lwzu    20, 4(11)
-        lwzu    21, 4(11)
-        lwzu    22, 4(11)
-        lwzu    23, 4(11)
-        lwzu    24, 4(11)
-        lwzu    25, 4(11)
-        lwzu    26, 4(11)
-        lwzu    27, 4(11)
-        lwzu    28, 4(11)
-        lwzu    29, 4(11)
-        lwzu    30, 4(11)
-        lwzu    31, 4(11)
-        lfdu    14, 8(11)
-        lfdu    15, 8(11)
-        lfdu    16, 8(11)
-        lfdu    17, 8(11)
-        lfdu    18, 8(11)
-        lfdu    19, 8(11)
-        lfdu    20, 8(11)
-        lfdu    21, 8(11)
-        lfdu    22, 8(11)
-        lfdu    23, 8(11)
-        lfdu    24, 8(11)
-        lfdu    25, 8(11)
-        lfdu    26, 8(11)
-        lfdu    27, 8(11)
-        lfdu    28, 8(11)
-        lfdu    29, 8(11)
-        lfdu    30, 8(11)
-        lfdu    31, 8(11)
-    /* Reload return address */
-        lwz     0, 256+4(1)
-        mtlr    0
-    /* Return */
-        addi    1, 1, 256
-        blr
-
-    /* The trap handler: */
-.L104:
-    /* Update caml_exception_pointer */
-        Storeglobal(29, caml_exception_pointer, 11)
-    /* Encode exception bucket as an exception result and return it */
-        ori     3, 3, 2
-        b       .L106
-
-/* Callback from C to OCaml */
-
-        .globl  caml_callback_exn
-        .type   caml_callback_exn, @function
-caml_callback_exn:
-    /* Initial shuffling of arguments */
-        mr      0, 3            /* Closure */
-        mr      3, 4            /* Argument */
-        mr      4, 0
-        lwz     12, 0(4)        /* Code pointer */
-        b       .L102
-
-        .globl  caml_callback2_exn
-        .type   caml_callback2_exn, @function
-caml_callback2_exn:
-        mr      0, 3            /* Closure */
-        mr      3, 4            /* First argument */
-        mr      4, 5            /* Second argument */
-        mr      5, 0
-        Addrglobal(12, caml_apply2)
-        b       .L102
-
-        .globl  caml_callback3_exn
-        .type   caml_callback3_exn, @function
-caml_callback3_exn:
-        mr      0, 3            /* Closure */
-        mr      3, 4            /* First argument */
-        mr      4, 5            /* Second argument */
-        mr      5, 6            /* Third argument */
-        mr      6, 0
-        Addrglobal(12, caml_apply3)
-        b       .L102
-
-        .globl  caml_system__code_end
-caml_system__code_end:
-
-/* Frame table */
-
-        .section ".data"
-        .globl  caml_system__frametable
-        .type   caml_system__frametable, @object
-caml_system__frametable:
-        .long   1               /* one descriptor */
-        .long   .L105 + 4       /* return address into callback */
-        .short  -1              /* negative size count => use callback link */
-        .short  0               /* no roots here */
diff --git a/asmrun/power-rhapsody.S b/asmrun/power-rhapsody.S
deleted file mode 100644
index 6fcb43cc..00000000
--- a/asmrun/power-rhapsody.S
+++ /dev/null
@@ -1,510 +0,0 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
-
-#ifdef __ppc64__
-#define X(a,b) b
-#else
-#define X(a,b) a
-#endif
-
-#define WORD X(4,8)
-#define lg X(lwz,ld)
-#define lgu X(lwzu,ldu)
-#define stg X(stw,std)
-#define stgu X(stwu,stdu)
-#define gdata X(.long,.quad)
-
-.macro Addrglobal       /* reg, glob */
-        addis   $0, 0, ha16($1)
-        addi    $0, $0, lo16($1)
-.endmacro
-.macro Loadglobal       /* reg,glob,tmp */
-        addis   $2, 0, ha16($1)
-        lg      $0, lo16($1)($2)
-.endmacro
-.macro Storeglobal      /* reg,glob,tmp */
-        addis   $2, 0, ha16($1)
-        stg     $0, lo16($1)($2)
-.endmacro
-.macro Loadglobal32       /* reg,glob,tmp */
-        addis   $2, 0, ha16($1)
-        lwz     $0, lo16($1)($2)
-.endmacro
-.macro Storeglobal32      /* reg,glob,tmp */
-        addis   $2, 0, ha16($1)
-        stw     $0, lo16($1)($2)
-.endmacro
-
-        .text
-
-        .globl  _caml_system__code_begin
-_caml_system__code_begin:
-
-/* Invoke the garbage collector. */
-
-        .globl  _caml_call_gc
-_caml_call_gc:
-    /* Set up stack frame */
-#define FRAMESIZE (32*WORD + 32*8 + 32)
-        stwu    r1, -FRAMESIZE(r1)
-    /* Record return address into OCaml code */
-        mflr    r0
-        Storeglobal r0, _caml_last_return_address, r11
-    /* Record lowest stack address */
-        addi    r0, r1, FRAMESIZE
-        Storeglobal r0, _caml_bottom_of_stack, r11
-    /* Touch the stack to trigger a recoverable segfault
-       if insufficient space remains */
-        addi    r1, r1, -4096*WORD
-        stg     r0, 0(r1)
-        addi    r1, r1, 4096*WORD
-    /* Record pointer to register array */
-        addi    r0, r1, 8*32 + 32
-        Storeglobal r0, _caml_gc_regs, r11
-    /* Save current allocation pointer for debugging purposes */
-        Storeglobal r31, _caml_young_ptr, r11
-    /* Save exception pointer (if e.g. a sighandler raises) */
-        Storeglobal r29, _caml_exception_pointer, r11
-    /* Save all registers used by the code generator */
-        addi    r11, r1, 8*32 + 32 - WORD
-        stgu    r3, WORD(r11)
-        stgu    r4, WORD(r11)
-        stgu    r5, WORD(r11)
-        stgu    r6, WORD(r11)
-        stgu    r7, WORD(r11)
-        stgu    r8, WORD(r11)
-        stgu    r9, WORD(r11)
-        stgu    r10, WORD(r11)
-        stgu    r14, WORD(r11)
-        stgu    r15, WORD(r11)
-        stgu    r16, WORD(r11)
-        stgu    r17, WORD(r11)
-        stgu    r18, WORD(r11)
-        stgu    r19, WORD(r11)
-        stgu    r20, WORD(r11)
-        stgu    r21, WORD(r11)
-        stgu    r22, WORD(r11)
-        stgu    r23, WORD(r11)
-        stgu    r24, WORD(r11)
-        stgu    r25, WORD(r11)
-        stgu    r26, WORD(r11)
-        stgu    r27, WORD(r11)
-        stgu    r28, WORD(r11)
-        addi    r11, r1, 32 - 8
-        stfdu   f1, 8(r11)
-        stfdu   f2, 8(r11)
-        stfdu   f3, 8(r11)
-        stfdu   f4, 8(r11)
-        stfdu   f5, 8(r11)
-        stfdu   f6, 8(r11)
-        stfdu   f7, 8(r11)
-        stfdu   f8, 8(r11)
-        stfdu   f9, 8(r11)
-        stfdu   f10, 8(r11)
-        stfdu   f11, 8(r11)
-        stfdu   f12, 8(r11)
-        stfdu   f13, 8(r11)
-        stfdu   f14, 8(r11)
-        stfdu   f15, 8(r11)
-        stfdu   f16, 8(r11)
-        stfdu   f17, 8(r11)
-        stfdu   f18, 8(r11)
-        stfdu   f19, 8(r11)
-        stfdu   f20, 8(r11)
-        stfdu   f21, 8(r11)
-        stfdu   f22, 8(r11)
-        stfdu   f23, 8(r11)
-        stfdu   f24, 8(r11)
-        stfdu   f25, 8(r11)
-        stfdu   f26, 8(r11)
-        stfdu   f27, 8(r11)
-        stfdu   f28, 8(r11)
-        stfdu   f29, 8(r11)
-        stfdu   f30, 8(r11)
-        stfdu   f31, 8(r11)
-    /* Call the GC */
-        bl      _caml_garbage_collection
-    /* Reload new allocation pointer and allocation limit */
-        Loadglobal r31, _caml_young_ptr, r11
-        Loadglobal r30, _caml_young_limit, r11
-    /* Restore all regs used by the code generator */
-        addi    r11, r1, 8*32 + 32 - WORD
-        lgu     r3, WORD(r11)
-        lgu     r4, WORD(r11)
-        lgu     r5, WORD(r11)
-        lgu     r6, WORD(r11)
-        lgu     r7, WORD(r11)
-        lgu     r8, WORD(r11)
-        lgu     r9, WORD(r11)
-        lgu     r10, WORD(r11)
-        lgu     r14, WORD(r11)
-        lgu     r15, WORD(r11)
-        lgu     r16, WORD(r11)
-        lgu     r17, WORD(r11)
-        lgu     r18, WORD(r11)
-        lgu     r19, WORD(r11)
-        lgu     r20, WORD(r11)
-        lgu     r21, WORD(r11)
-        lgu     r22, WORD(r11)
-        lgu     r23, WORD(r11)
-        lgu     r24, WORD(r11)
-        lgu     r25, WORD(r11)
-        lgu     r26, WORD(r11)
-        lgu     r27, WORD(r11)
-        lgu     r28, WORD(r11)
-        addi    r11, r1, 32 - 8
-        lfdu    f1, 8(r11)
-        lfdu    f2, 8(r11)
-        lfdu    f3, 8(r11)
-        lfdu    f4, 8(r11)
-        lfdu    f5, 8(r11)
-        lfdu    f6, 8(r11)
-        lfdu    f7, 8(r11)
-        lfdu    f8, 8(r11)
-        lfdu    f9, 8(r11)
-        lfdu    f10, 8(r11)
-        lfdu    f11, 8(r11)
-        lfdu    f12, 8(r11)
-        lfdu    f13, 8(r11)
-        lfdu    f14, 8(r11)
-        lfdu    f15, 8(r11)
-        lfdu    f16, 8(r11)
-        lfdu    f17, 8(r11)
-        lfdu    f18, 8(r11)
-        lfdu    f19, 8(r11)
-        lfdu    f20, 8(r11)
-        lfdu    f21, 8(r11)
-        lfdu    f22, 8(r11)
-        lfdu    f23, 8(r11)
-        lfdu    f24, 8(r11)
-        lfdu    f25, 8(r11)
-        lfdu    f26, 8(r11)
-        lfdu    f27, 8(r11)
-        lfdu    f28, 8(r11)
-        lfdu    f29, 8(r11)
-        lfdu    f30, 8(r11)
-        lfdu    f31, 8(r11)
-    /* Return to caller, restarting the allocation */
-        Loadglobal r0, _caml_last_return_address, r11
-        addic   r0, r0, -16     /* Restart the allocation (4 instructions) */
-        mtlr    r0
-    /* Say we are back into OCaml code */
-        li      r12, 0
-        Storeglobal r12, _caml_last_return_address, r11
-    /* Deallocate stack frame */
-        addi    r1, r1, FRAMESIZE
-    /* Return */
-        blr
-#undef FRAMESIZE
-
-/* Call a C function from OCaml */
-
-        .globl  _caml_c_call
-_caml_c_call:
-    /* Save return address */
-        mflr    r25
-    /* Get ready to call C function (address in 11) */
-        mtctr   r11
-    /* Record lowest stack address and return address */
-        Storeglobal r1, _caml_bottom_of_stack, r12
-        Storeglobal r25, _caml_last_return_address, r12
-    /* Touch the stack to trigger a recoverable segfault
-       if insufficient space remains */
-        addi    r1, r1, -4096*WORD
-        stg     r0, 0(r1)
-        addi    r1, r1, 4096*WORD
-    /* Make the exception handler and alloc ptr available to the C code */
-        Storeglobal r31, _caml_young_ptr, r11
-        Storeglobal r29, _caml_exception_pointer, r11
-    /* Call the function (address in link register) */
-        bctrl
-    /* Restore return address (in 25, preserved by the C function) */
-        mtlr    r25
-    /* Reload allocation pointer and allocation limit*/
-        Loadglobal r31, _caml_young_ptr, r11
-        Loadglobal r30, _caml_young_limit, r11
-    /* Say we are back into OCaml code */
-        li      r12, 0
-        Storeglobal r12, _caml_last_return_address, r11
-    /* Return to caller */
-        blr
-
-/* Raise an exception from OCaml */
-        .globl  _caml_raise_exn
-_caml_raise_exn:
-        Loadglobal32 r11, _caml_backtrace_active, r11
-        cmpwi   r11, 0
-        bne     L110
-L111:
-    /* Pop trap frame */
-        lg      r0, 0(r29)
-        mr      r1, r29
-        mtctr    r0
-        lg      r29, WORD(r1)
-        addi    r1, r1, 16
-    /* Branch to handler */
-        bctr
-L110:
-        li      r0, 0
-        Storeglobal32 r0, _caml_backtrace_pos, r11
-L114:
-        mr      r28, r3        /* preserve exn bucket in callee-save */
-                               /* arg 1: exception bucket (already in r3) */
-        mflr    r4             /* arg 2: PC of raise */
-        mr      r5, r1         /* arg 3: SP of raise */
-        mr      r6, r29        /* arg 4: SP of handler */
-        addi    r1, r1, -(16*WORD)    /* reserve stack space for C call */
-        bl      _caml_stash_backtrace
-        mr      r3, r28
-        b       L111
-
-        .globl  _caml_reraise_exn
-_caml_reraise_exn:
-        Loadglobal32 r11, _caml_backtrace_active, r11
-        cmpwi   r11, 0
-        bne-    L114
-    /* Pop trap frame */
-        lg      r0, 0(r29)
-        mr      r1, r29
-        mtctr    r0
-        lg      r29, WORD(r1)
-        addi    r1, r1, 16
-    /* Branch to handler */
-        bctr
-
-        /* Raise an exception from C */
-
-        .globl  _caml_raise_exception
-_caml_raise_exception:
-        Loadglobal32 r11, _caml_backtrace_active, r11
-        cmpwi   r11, 0
-        bne     L112
-L113:
-    /* Reload OCaml global registers */
-        Loadglobal r1, _caml_exception_pointer, r11
-        Loadglobal r31, _caml_young_ptr, r11
-        Loadglobal r30, _caml_young_limit, r11
-    /* Say we are back into OCaml code */
-        li      r0, 0
-        Storeglobal r0, _caml_last_return_address, r11
-    /* Pop trap frame */
-        lg      r0, 0(r1)
-        lg      r29, WORD(r1)
-        mtctr   r0
-        addi    r1, r1, 16
-    /* Branch to handler */
-        bctr
-L112:
-        mr      r28, r3        /* preserve exn bucket in callee-save */
-                               /* arg 1: exception bucket (already in r3) */
-        Loadglobal r4, _caml_last_return_address, r11 /* arg 2: PC of raise */
-        Loadglobal r5, _caml_bottom_of_stack, r11 /* arg 3: SP of raise */
-        Loadglobal r6, _caml_exception_pointer, r11 /* arg 4: SP of handler */
-        addi    r1, r1, -(16*WORD)    /* reserve stack space for C call */
-        bl      _caml_stash_backtrace
-        mr      r3, r28
-        b       L113
-
-/* Start the OCaml program */
-
-        .globl  _caml_start_program
-_caml_start_program:
-        Addrglobal r12, _caml_program
-
-/* Code shared between caml_start_program and caml_callback */
-L102:
-    /* Allocate and link stack frame */
-#define FRAMESIZE (16 + 20*WORD + 18*8)
-        stgu    r1, -FRAMESIZE(r1)
-    /* Save return address */
-        mflr    r0
-        stg     r0,  WORD(r1)
-    /* Save all callee-save registers */
-    /* GPR14 ... GPR31, then FPR14 ... FPR31 starting at sp+16 */
-        addi    r11, r1, 16-WORD
-        stgu    r14, WORD(r11)
-        stgu    r15, WORD(r11)
-        stgu    r16, WORD(r11)
-        stgu    r17, WORD(r11)
-        stgu    r18, WORD(r11)
-        stgu    r19, WORD(r11)
-        stgu    r20, WORD(r11)
-        stgu    r21, WORD(r11)
-        stgu    r22, WORD(r11)
-        stgu    r23, WORD(r11)
-        stgu    r24, WORD(r11)
-        stgu    r25, WORD(r11)
-        stgu    r26, WORD(r11)
-        stgu    r27, WORD(r11)
-        stgu    r28, WORD(r11)
-        stgu    r29, WORD(r11)
-        stgu    r30, WORD(r11)
-        stgu    r31, WORD(r11)
-        stfdu   f14, 8(r11)
-        stfdu   f15, 8(r11)
-        stfdu   f16, 8(r11)
-        stfdu   f17, 8(r11)
-        stfdu   f18, 8(r11)
-        stfdu   f19, 8(r11)
-        stfdu   f20, 8(r11)
-        stfdu   f21, 8(r11)
-        stfdu   f22, 8(r11)
-        stfdu   f23, 8(r11)
-        stfdu   f24, 8(r11)
-        stfdu   f25, 8(r11)
-        stfdu   f26, 8(r11)
-        stfdu   f27, 8(r11)
-        stfdu   f28, 8(r11)
-        stfdu   f29, 8(r11)
-        stfdu   f30, 8(r11)
-        stfdu   f31, 8(r11)
-    /* Set up a callback link */
-        addi    r1, r1, -32
-        Loadglobal r9, _caml_bottom_of_stack, r11
-        Loadglobal r10, _caml_last_return_address, r11
-        Loadglobal r11, _caml_gc_regs, r11
-        stg     r9, 0(r1)
-        stg     r10, WORD(r1)
-        stg     r11, 2*WORD(r1)
-    /* Build an exception handler to catch exceptions escaping out of OCaml */
-        bl      L103
-        b       L104
-L103:
-        addi    r1, r1, -16
-        mflr    r0
-        stg     r0, 0(r1)
-        Loadglobal r11, _caml_exception_pointer, r11
-        stg     r11, WORD(r1)
-        mr      r29, r1
-    /* Reload allocation pointers */
-        Loadglobal r31, _caml_young_ptr, r11
-        Loadglobal r30, _caml_young_limit, r11
-    /* Say we are back into OCaml code */
-        li      r0, 0
-        Storeglobal r0, _caml_last_return_address, r11
-    /* Call the OCaml code */
-        mtctr    r12
-L105:
-        bctrl
-    /* Pop the trap frame, restoring caml_exception_pointer */
-        lg      r9, WORD(r1)
-        Storeglobal r9, _caml_exception_pointer, r11
-        addi    r1, r1, 16
-    /* Pop the callback link, restoring the global variables */
-L106:
-        lg      r9, 0(r1)
-        lg      r10, WORD(r1)
-        lg      r11, 2*WORD(r1)
-        Storeglobal r9, _caml_bottom_of_stack, r12
-        Storeglobal r10, _caml_last_return_address, r12
-        Storeglobal r11, _caml_gc_regs, r12
-        addi    r1, r1, 32
-    /* Update allocation pointer */
-        Storeglobal r31, _caml_young_ptr, r11
-    /* Restore callee-save registers */
-        addi    r11, r1, 16-WORD
-        lgu     r14, WORD(r11)
-        lgu     r15, WORD(r11)
-        lgu     r16, WORD(r11)
-        lgu     r17, WORD(r11)
-        lgu     r18, WORD(r11)
-        lgu     r19, WORD(r11)
-        lgu     r20, WORD(r11)
-        lgu     r21, WORD(r11)
-        lgu     r22, WORD(r11)
-        lgu     r23, WORD(r11)
-        lgu     r24, WORD(r11)
-        lgu     r25, WORD(r11)
-        lgu     r26, WORD(r11)
-        lgu     r27, WORD(r11)
-        lgu     r28, WORD(r11)
-        lgu     r29, WORD(r11)
-        lgu     r30, WORD(r11)
-        lgu     r31, WORD(r11)
-        lfdu    f14, 8(r11)
-        lfdu    f15, 8(r11)
-        lfdu    f16, 8(r11)
-        lfdu    f17, 8(r11)
-        lfdu    f18, 8(r11)
-        lfdu    f19, 8(r11)
-        lfdu    f20, 8(r11)
-        lfdu    f21, 8(r11)
-        lfdu    f22, 8(r11)
-        lfdu    f23, 8(r11)
-        lfdu    f24, 8(r11)
-        lfdu    f25, 8(r11)
-        lfdu    f26, 8(r11)
-        lfdu    f27, 8(r11)
-        lfdu    f28, 8(r11)
-        lfdu    f29, 8(r11)
-        lfdu    f30, 8(r11)
-        lfdu    f31, 8(r11)
-    /* Reload return address */
-        lg      r0, WORD(r1)
-        mtlr    r0
-    /* Return */
-        addi    r1, r1, FRAMESIZE
-        blr
-
-    /* The trap handler: */
-L104:
-    /* Update caml_exception_pointer */
-        Storeglobal r29, _caml_exception_pointer, r11
-    /* Encode exception bucket as an exception result and return it */
-        ori     r3, r3, 2
-        b       L106
-#undef FRAMESIZE
-
-/* Callback from C to OCaml */
-
-        .globl  _caml_callback_exn
-_caml_callback_exn:
-    /* Initial shuffling of arguments */
-        mr      r0, r3            /* Closure */
-        mr      r3, r4            /* Argument */
-        mr      r4, r0
-        lg      r12, 0(r4)        /* Code pointer */
-        b       L102
-
-        .globl  _caml_callback2_exn
-_caml_callback2_exn:
-        mr      r0, r3            /* Closure */
-        mr      r3, r4            /* First argument */
-        mr      r4, r5            /* Second argument */
-        mr      r5, r0
-        Addrglobal r12, _caml_apply2
-        b       L102
-
-        .globl  _caml_callback3_exn
-_caml_callback3_exn:
-        mr      r0, r3            /* Closure */
-        mr      r3, r4            /* First argument */
-        mr      r4, r5            /* Second argument */
-        mr      r5, r6            /* Third argument */
-        mr      r6, r0
-        Addrglobal r12, _caml_apply3
-        b       L102
-
-        .globl  _caml_system__code_end
-_caml_system__code_end:
-
-/* Frame table */
-
-        .const
-        .globl  _caml_system__frametable
-_caml_system__frametable:
-        gdata   1               /* one descriptor */
-        gdata   L105 + 4       /* return address into callback */
-        .short  -1              /* negative size count => use callback link */
-        .short  0               /* no roots here */
-        .align  X(2,3)
diff --git a/asmrun/power.S b/asmrun/power.S
new file mode 100644
index 00000000..7bfca532
--- /dev/null
+++ b/asmrun/power.S
@@ -0,0 +1,697 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
+
+#if defined(MODEL_ppc64le)
+        .abiversion 2
+#endif
+
+#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
+#define EITHER(a,b) b
+#else
+#define EITHER(a,b) a
+#endif
+
+#define WORD EITHER(4,8)
+#define lg EITHER(lwz,ld)
+#define lgu EITHER(lwzu,ldu)
+#define stg EITHER(stw,std)
+#define stgu EITHER(stwu,stdu)
+#define datag EITHER(.long,.quad)
+#define wordalign EITHER(2,3)
+
+/* Stack layout */
+#if defined(MODEL_ppc)
+#define RESERVED_STACK 16
+#define PARAM_SAVE_AREA 0
+#define LR_SAVE 4
+#define TRAP_SIZE 16
+#define TRAP_HANDLER_OFFSET 0
+#define TRAP_PREVIOUS_OFFSET 4
+#define CALLBACK_LINK_SIZE 16
+#define CALLBACK_LINK_OFFSET 0
+#endif
+#if defined(MODEL_ppc64)
+#define RESERVED_STACK 48
+#define PARAM_SAVE_AREA (8*8)
+#define LR_SAVE 16
+#define TOC_SAVE 40
+#define TOC_SAVE_PARENT 8
+#define TRAP_SIZE 32
+#define TRAP_HANDLER_OFFSET 56
+#define TRAP_PREVIOUS_OFFSET 64
+#define CALLBACK_LINK_SIZE 32
+#define CALLBACK_LINK_OFFSET 48
+#endif
+#if defined(MODEL_ppc64le)
+#define RESERVED_STACK 32
+#define PARAM_SAVE_AREA 0
+#define LR_SAVE 16
+#define TOC_SAVE_PARENT 8
+#define TOC_SAVE 24
+#define TRAP_SIZE 32
+#define TRAP_HANDLER_OFFSET 40
+#define TRAP_PREVIOUS_OFFSET 48
+#define CALLBACK_LINK_SIZE 32
+#define CALLBACK_LINK_OFFSET 32
+#endif
+
+/* Function definitions */
+
+#if defined(MODEL_ppc)
+#define FUNCTION(name) \
+  .section ".text"; \
+  .globl name; \
+  .type name, @function; \
+  .align 2; \
+  name:
+
+#define ENDFUNCTION(name) \
+  .size name, . - name
+
+#endif
+
+#if defined(MODEL_ppc64)
+#define FUNCTION(name) \
+  .section ".opd","aw"; \
+  .align 3; \
+  .globl name; \
+  .type name, @function; \
+  name: .quad .L.name,.TOC.@tocbase; \
+  .text; \
+  .align 2; \
+  .L.name:
+
+#define ENDFUNCTION(name) \
+  .size name, . - .L.name
+
+#endif
+
+#if defined(MODEL_ppc64le)
+#define FUNCTION(name) \
+  .section ".text"; \
+  .globl name; \
+  .type name, @function; \
+  .align 2; \
+  name: ; \
+  0: addis 2, 12, (.TOC. - 0b)@ha; \
+  addi 2, 2, (.TOC. - 0b)@l; \
+  .localentry name, . - 0b
+
+#define ENDFUNCTION(name) \
+  .size name, . - name
+
+#endif
+
+/* Accessing global variables.  */
+
+#if defined(MODEL_ppc)
+
+#define Addrglobal(reg,glob) \
+        addis   reg, 0, glob@ha; \
+        addi    reg, reg, glob@l
+#define Loadglobal(reg,glob,tmp) \
+        addis   tmp, 0, glob@ha; \
+        lg      reg, glob@l(tmp)
+#define Storeglobal(reg,glob,tmp) \
+        addis   tmp, 0, glob@ha; \
+        stg     reg, glob@l(tmp)
+#define Loadglobal32(reg,glob,tmp) \
+        addis   tmp, 0, glob@ha; \
+        lwz     reg, glob@l(tmp)
+#define Storeglobal32(reg,glob,tmp) \
+        addis   tmp, 0, glob@ha; \
+        stw     reg, glob@l(tmp)
+
+#endif
+
+#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
+
+#define LSYMB(glob) .L##glob
+
+#define Addrglobal(reg,glob) \
+        ld      reg, LSYMB(glob)@toc(2)
+#define Loadglobal(reg,glob,tmp) \
+        Addrglobal(tmp,glob); \
+        lg      reg, 0(tmp)
+#define Storeglobal(reg,glob,tmp) \
+        Addrglobal(tmp,glob); \
+        stg     reg, 0(tmp)
+#define Loadglobal32(reg,glob,tmp) \
+        Addrglobal(tmp,glob); \
+        lwz     reg, 0(tmp)
+#define Storeglobal32(reg,glob,tmp) \
+        Addrglobal(tmp,glob); \
+        stw     reg, 0(tmp)
+
+#endif
+
+#if defined(MODEL_ppc64)
+        .section ".opd","aw"
+#else
+        .section ".text"
+#endif
+        .globl  caml_system__code_begin
+caml_system__code_begin:
+
+/* Invoke the garbage collector. */
+
+FUNCTION(caml_call_gc)
+#define STACKSIZE (WORD*32 + 8*32 + PARAM_SAVE_AREA + RESERVED_STACK)
+    /* 32 integer registers + 32 float registers + space for C call */
+    /* Set up stack frame */
+        stwu    1, -STACKSIZE(1)
+    /* Record return address into OCaml code */
+        mflr    0
+        Storeglobal(0, caml_last_return_address, 11)
+    /* Record lowest stack address */
+        addi    0, 1, STACKSIZE
+        Storeglobal(0, caml_bottom_of_stack, 11)
+    /* Record pointer to register array */
+        addi    0, 1, 8*32 + PARAM_SAVE_AREA + RESERVED_STACK
+        Storeglobal(0, caml_gc_regs, 11)
+    /* Save current allocation pointer for debugging purposes */
+        Storeglobal(31, caml_young_ptr, 11)
+    /* Save exception pointer (if e.g. a sighandler raises) */
+        Storeglobal(29, caml_exception_pointer, 11)
+    /* Save all registers used by the code generator */
+        addi    11, 1, 8*32 + PARAM_SAVE_AREA + RESERVED_STACK - WORD
+        stgu    3, WORD(11)
+        stgu    4, WORD(11)
+        stgu    5, WORD(11)
+        stgu    6, WORD(11)
+        stgu    7, WORD(11)
+        stgu    8, WORD(11)
+        stgu    9, WORD(11)
+        stgu    10, WORD(11)
+        stgu    14, WORD(11)
+        stgu    15, WORD(11)
+        stgu    16, WORD(11)
+        stgu    17, WORD(11)
+        stgu    18, WORD(11)
+        stgu    19, WORD(11)
+        stgu    20, WORD(11)
+        stgu    21, WORD(11)
+        stgu    22, WORD(11)
+        stgu    23, WORD(11)
+        stgu    24, WORD(11)
+        stgu    25, WORD(11)
+        stgu    26, WORD(11)
+        stgu    27, WORD(11)
+        stgu    28, WORD(11)
+        addi    11, 1, PARAM_SAVE_AREA + RESERVED_STACK - 8
+        stfdu   1, 8(11)
+        stfdu   2, 8(11)
+        stfdu   3, 8(11)
+        stfdu   4, 8(11)
+        stfdu   5, 8(11)
+        stfdu   6, 8(11)
+        stfdu   7, 8(11)
+        stfdu   8, 8(11)
+        stfdu   9, 8(11)
+        stfdu   10, 8(11)
+        stfdu   11, 8(11)
+        stfdu   12, 8(11)
+        stfdu   13, 8(11)
+        stfdu   14, 8(11)
+        stfdu   15, 8(11)
+        stfdu   16, 8(11)
+        stfdu   17, 8(11)
+        stfdu   18, 8(11)
+        stfdu   19, 8(11)
+        stfdu   20, 8(11)
+        stfdu   21, 8(11)
+        stfdu   22, 8(11)
+        stfdu   23, 8(11)
+        stfdu   24, 8(11)
+        stfdu   25, 8(11)
+        stfdu   26, 8(11)
+        stfdu   27, 8(11)
+        stfdu   28, 8(11)
+        stfdu   29, 8(11)
+        stfdu   30, 8(11)
+        stfdu   31, 8(11)
+    /* Call the GC */
+        bl      caml_garbage_collection
+#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
+        nop
+#endif
+    /* Reload new allocation pointer and allocation limit */
+        Loadglobal(31, caml_young_ptr, 11)
+        Loadglobal(30, caml_young_limit, 11)
+    /* Restore all regs used by the code generator */
+        addi    11, 1, 8*32 + PARAM_SAVE_AREA + RESERVED_STACK - WORD
+        lgu     3, WORD(11)
+        lgu     4, WORD(11)
+        lgu     5, WORD(11)
+        lgu     6, WORD(11)
+        lgu     7, WORD(11)
+        lgu     8, WORD(11)
+        lgu     9, WORD(11)
+        lgu     10, WORD(11)
+        lgu     14, WORD(11)
+        lgu     15, WORD(11)
+        lgu     16, WORD(11)
+        lgu     17, WORD(11)
+        lgu     18, WORD(11)
+        lgu     19, WORD(11)
+        lgu     20, WORD(11)
+        lgu     21, WORD(11)
+        lgu     22, WORD(11)
+        lgu     23, WORD(11)
+        lgu     24, WORD(11)
+        lgu     25, WORD(11)
+        lgu     26, WORD(11)
+        lgu     27, WORD(11)
+        lgu     28, WORD(11)
+        addi    11, 1, PARAM_SAVE_AREA + RESERVED_STACK - 8
+        lfdu    1, 8(11)
+        lfdu    2, 8(11)
+        lfdu    3, 8(11)
+        lfdu    4, 8(11)
+        lfdu    5, 8(11)
+        lfdu    6, 8(11)
+        lfdu    7, 8(11)
+        lfdu    8, 8(11)
+        lfdu    9, 8(11)
+        lfdu    10, 8(11)
+        lfdu    11, 8(11)
+        lfdu    12, 8(11)
+        lfdu    13, 8(11)
+        lfdu    14, 8(11)
+        lfdu    15, 8(11)
+        lfdu    16, 8(11)
+        lfdu    17, 8(11)
+        lfdu    18, 8(11)
+        lfdu    19, 8(11)
+        lfdu    20, 8(11)
+        lfdu    21, 8(11)
+        lfdu    22, 8(11)
+        lfdu    23, 8(11)
+        lfdu    24, 8(11)
+        lfdu    25, 8(11)
+        lfdu    26, 8(11)
+        lfdu    27, 8(11)
+        lfdu    28, 8(11)
+        lfdu    29, 8(11)
+        lfdu    30, 8(11)
+        lfdu    31, 8(11)
+    /* Return to caller, restarting the allocation */
+        Loadglobal(11, caml_last_return_address, 11)
+        addi    11, 11, -16     /* Restart the allocation (4 instructions) */
+        mtlr    11
+    /* For PPC64: restore the TOC that the caller saved at the usual place */
+#ifdef TOC_SAVE
+        ld      2, (STACKSIZE + TOC_SAVE)(1)
+#endif
+    /* Deallocate stack frame */
+        addi    1, 1, STACKSIZE
+        blr
+#undef STACKSIZE
+ENDFUNCTION(caml_call_gc)
+
+/* Call a C function from OCaml */
+
+FUNCTION(caml_c_call)
+        .cfi_startproc
+    /* Save return address in a callee-save register */
+        mflr    27
+        .cfi_register 65, 27
+    /* Record lowest stack address and return address */
+        Storeglobal(1, caml_bottom_of_stack, 11)
+        Storeglobal(27, caml_last_return_address, 11)
+    /* Make the exception handler and alloc ptr available to the C code */
+        Storeglobal(31, caml_young_ptr, 11)
+        Storeglobal(29, caml_exception_pointer, 11)
+    /* Call C function (address in r28) */
+#if defined(MODEL_ppc)
+        mtctr   28
+        bctrl
+#elif defined(MODEL_ppc64)
+        ld      0, 0(28)
+        mr      26, 2   /* save current TOC in a callee-save register */
+        mtctr   0
+        ld      2, 8(28)
+        bctrl
+        mr      2, 26   /* restore current TOC */
+#elif defined(MODEL_ppc64le)
+        mtctr   28
+        mr      12, 28
+        mr      26, 2   /* save current TOC in a callee-save register */
+        bctrl
+        mr      2, 26   /* restore current TOC */
+#else
+#error "wrong MODEL"
+#endif
+    /* Restore return address (in 27, preserved by the C function) */
+        mtlr    27
+    /* Reload allocation pointer and allocation limit*/
+        Loadglobal(31, caml_young_ptr, 11)
+        Loadglobal(30, caml_young_limit, 11)
+    /* Return to caller */
+        blr
+        .cfi_endproc
+ENDFUNCTION(caml_c_call)
+
+/* Raise an exception from OCaml */
+
+FUNCTION(caml_raise_exn)
+        Loadglobal32(0, caml_backtrace_active, 11)
+        cmpwi   0, 0
+        bne     .L111
+.L110:
+    /* Pop trap frame */
+        lg      0, TRAP_HANDLER_OFFSET(29)
+        mr      1, 29
+        mtctr   0
+        lg      29, TRAP_PREVIOUS_OFFSET(1)
+        addi    1, 1, TRAP_SIZE
+    /* Branch to handler */
+        bctr
+.L111:
+        li      0, 0
+        Storeglobal32(0, caml_backtrace_pos, 11)
+.L112:
+        mr      28, 3           /* preserve exn bucket in callee-save reg */
+                                /* arg1: exception bucket, already in r3 */
+        mflr    4               /* arg2: PC of raise */
+        mr      5, 1            /* arg3: SP of raise */
+        mr      6, 29           /* arg4: SP of handler */
+        addi    1, 1, -(PARAM_SAVE_AREA + RESERVED_STACK)
+                                /* reserve stack space for C call */
+        bl      caml_stash_backtrace
+#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
+        nop
+#endif
+        mr      3, 28           /* restore exn bucket */
+        b       .L110           /* raise the exn */
+ENDFUNCTION(caml_raise_exn)
+
+FUNCTION(caml_reraise_exn)
+        Loadglobal32(0, caml_backtrace_active, 11)
+        cmpwi   0, 0
+        bne-    .L112
+    /* Pop trap frame */
+        lg      0, TRAP_HANDLER_OFFSET(29)
+        mr      1, 29
+        mtctr   0
+        lg      29, TRAP_PREVIOUS_OFFSET(1)
+        addi    1, 1, TRAP_SIZE
+    /* Branch to handler */
+        bctr
+ENDFUNCTION(caml_reraise_exn)
+
+/* Raise an exception from C */
+
+FUNCTION(caml_raise_exception)
+        Loadglobal32(0, caml_backtrace_active, 11)
+        cmpwi   0, 0
+        bne     .L121
+.L120:
+    /* Reload OCaml global registers */
+        Loadglobal(1, caml_exception_pointer, 11)
+        Loadglobal(31, caml_young_ptr, 11)
+        Loadglobal(30, caml_young_limit, 11)
+    /* Pop trap frame */
+        lg      0, TRAP_HANDLER_OFFSET(1)
+        mtctr   0
+        lg      29, TRAP_PREVIOUS_OFFSET(1)
+        addi    1, 1, TRAP_SIZE
+    /* Branch to handler */
+        bctr
+.L121:
+        li      0, 0
+        Storeglobal32(0, caml_backtrace_pos, 11)
+        mr      28, 3           /* preserve exn bucket in callee-save reg */
+                                /* arg1: exception bucket, already in r3 */
+        Loadglobal(4, caml_last_return_address, 11) /* arg2: PC of raise */
+        Loadglobal(5, caml_bottom_of_stack, 11)     /* arg3: SP of raise */
+        Loadglobal(6, caml_exception_pointer, 11)   /* arg4: SP of handler */
+        addi    1, 1, -(PARAM_SAVE_AREA + RESERVED_STACK)
+                                         /* reserve stack space for C call */
+        bl      caml_stash_backtrace
+#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
+        nop
+#endif
+        mr      3, 28           /* restore exn bucket */
+        b       .L120           /* raise the exn */
+ENDFUNCTION(caml_raise_exception)
+
+/* Start the OCaml program */
+
+FUNCTION(caml_start_program)
+        .cfi_startproc
+#define STACKSIZE (WORD*18 + 8*18 + CALLBACK_LINK_SIZE + RESERVED_STACK)
+  /* 18 callee-save GPR14...GPR31 + 18 callee-save FPR14...FPR31 */
+        Addrglobal(12, caml_program)
+/* Code shared between caml_start_program and caml_callback */
+.L102:
+    /* Allocate and link stack frame */
+        stgu    1, -STACKSIZE(1)
+        .cfi_adjust_cfa_offset STACKSIZE
+    /* Save return address */
+        mflr    0
+        stg     0, (STACKSIZE + LR_SAVE)(1)
+        .cfi_offset 65, LR_SAVE
+    /* Save TOC pointer if applicable */
+#ifdef TOC_SAVE_PARENT
+        std     2, (STACKSIZE + TOC_SAVE_PARENT)(1)
+#endif
+    /* Save all callee-save registers */
+        addi    11, 1, CALLBACK_LINK_SIZE + RESERVED_STACK - WORD
+        stgu    14, WORD(11)
+        stgu    15, WORD(11)
+        stgu    16, WORD(11)
+        stgu    17, WORD(11)
+        stgu    18, WORD(11)
+        stgu    19, WORD(11)
+        stgu    20, WORD(11)
+        stgu    21, WORD(11)
+        stgu    22, WORD(11)
+        stgu    23, WORD(11)
+        stgu    24, WORD(11)
+        stgu    25, WORD(11)
+        stgu    26, WORD(11)
+        stgu    27, WORD(11)
+        stgu    28, WORD(11)
+        stgu    29, WORD(11)
+        stgu    30, WORD(11)
+        stgu    31, WORD(11)
+        stfdu   14, 8(11)
+        stfdu   15, 8(11)
+        stfdu   16, 8(11)
+        stfdu   17, 8(11)
+        stfdu   18, 8(11)
+        stfdu   19, 8(11)
+        stfdu   20, 8(11)
+        stfdu   21, 8(11)
+        stfdu   22, 8(11)
+        stfdu   23, 8(11)
+        stfdu   24, 8(11)
+        stfdu   25, 8(11)
+        stfdu   26, 8(11)
+        stfdu   27, 8(11)
+        stfdu   28, 8(11)
+        stfdu   29, 8(11)
+        stfdu   30, 8(11)
+        stfdu   31, 8(11)
+    /* Set up a callback link */
+        Loadglobal(11, caml_bottom_of_stack, 11)
+        stg     11, CALLBACK_LINK_OFFSET(1)
+        Loadglobal(11, caml_last_return_address, 11)
+        stg     11, (CALLBACK_LINK_OFFSET + WORD)(1)
+        Loadglobal(11, caml_gc_regs, 11)
+        stg     11, (CALLBACK_LINK_OFFSET + 2 * WORD)(1)
+    /* Build an exception handler to catch exceptions escaping out of OCaml */
+        bl      .L103
+        b       .L104
+.L103:
+        addi    1, 1, -TRAP_SIZE
+        .cfi_adjust_cfa_offset TRAP_SIZE
+        mflr    0
+        stg     0, TRAP_HANDLER_OFFSET(1)
+        Loadglobal(11, caml_exception_pointer, 11)
+        stg     11, TRAP_PREVIOUS_OFFSET(1)
+        mr      29, 1
+    /* Reload allocation pointers */
+        Loadglobal(31, caml_young_ptr, 11)
+        Loadglobal(30, caml_young_limit, 11)
+    /* Call the OCaml code (address in r12) */
+#if defined(MODEL_ppc)
+        mtctr   12
+.L105:  bctrl
+#elif defined(MODEL_ppc64)
+        ld      0, 0(12)
+        mtctr   0
+        std     2, TOC_SAVE(1)
+        ld      2, 8(12)
+.L105:  bctrl
+        ld      2, TOC_SAVE(1)
+#elif defined(MODEL_ppc64le)
+        mtctr   12
+        std     2, TOC_SAVE(1)
+.L105:  bctrl
+        ld      2, TOC_SAVE(1)
+#else
+#error "wrong MODEL"
+#endif
+    /* Pop the trap frame, restoring caml_exception_pointer */
+        lg      0, TRAP_PREVIOUS_OFFSET(1)
+        Storeglobal(0, caml_exception_pointer, 11)
+        addi    1, 1, TRAP_SIZE
+        .cfi_adjust_cfa_offset -TRAP_SIZE
+    /* Pop the callback link, restoring the global variables */
+.L106:
+        lg      0, CALLBACK_LINK_OFFSET(1)
+        Storeglobal(0, caml_bottom_of_stack, 11)
+        lg      0, (CALLBACK_LINK_OFFSET + WORD)(1)
+        Storeglobal(0, caml_last_return_address, 11)
+        lg      0, (CALLBACK_LINK_OFFSET + 2 * WORD)(1)
+        Storeglobal(0, caml_gc_regs, 11)
+    /* Update allocation pointer */
+        Storeglobal(31, caml_young_ptr, 11)
+    /* Restore callee-save registers */
+        addi    11, 1, CALLBACK_LINK_SIZE + RESERVED_STACK - WORD
+        lgu     14, WORD(11)
+        lgu     15, WORD(11)
+        lgu     16, WORD(11)
+        lgu     17, WORD(11)
+        lgu     18, WORD(11)
+        lgu     19, WORD(11)
+        lgu     20, WORD(11)
+        lgu     21, WORD(11)
+        lgu     22, WORD(11)
+        lgu     23, WORD(11)
+        lgu     24, WORD(11)
+        lgu     25, WORD(11)
+        lgu     26, WORD(11)
+        lgu     27, WORD(11)
+        lgu     28, WORD(11)
+        lgu     29, WORD(11)
+        lgu     30, WORD(11)
+        lgu     31, WORD(11)
+        lfdu    14, 8(11)
+        lfdu    15, 8(11)
+        lfdu    16, 8(11)
+        lfdu    17, 8(11)
+        lfdu    18, 8(11)
+        lfdu    19, 8(11)
+        lfdu    20, 8(11)
+        lfdu    21, 8(11)
+        lfdu    22, 8(11)
+        lfdu    23, 8(11)
+        lfdu    24, 8(11)
+        lfdu    25, 8(11)
+        lfdu    26, 8(11)
+        lfdu    27, 8(11)
+        lfdu    28, 8(11)
+        lfdu    29, 8(11)
+        lfdu    30, 8(11)
+        lfdu    31, 8(11)
+    /* Reload return address */
+        lg      0, (STACKSIZE + LR_SAVE)(1)
+        mtlr    0
+    /* Return */
+        addi    1, 1, STACKSIZE
+        blr
+
+    /* The trap handler: */
+.L104:
+    /* Restore TOC pointer */
+#ifdef TOC_SAVE_PARENT
+        ld      2, (STACKSIZE + TOC_SAVE_PARENT)(1)
+#endif
+    /* Update caml_exception_pointer */
+        Storeglobal(29, caml_exception_pointer, 11)
+    /* Encode exception bucket as an exception result and return it */
+        ori     3, 3, 2
+        b       .L106
+#undef STACKSIZE
+        .cfi_endproc
+ENDFUNCTION(caml_start_program)
+
+/* Callback from C to OCaml */
+
+FUNCTION(caml_callback_exn)
+    /* Initial shuffling of arguments */
+        mr      0, 3            /* Closure */
+        mr      3, 4            /* Argument */
+        mr      4, 0
+        lg      12, 0(4)        /* Code pointer */
+        b       .L102
+ENDFUNCTION(caml_callback_exn)
+
+FUNCTION(caml_callback2_exn)
+        mr      0, 3            /* Closure */
+        mr      3, 4            /* First argument */
+        mr      4, 5            /* Second argument */
+        mr      5, 0
+        Addrglobal(12, caml_apply2)
+        b       .L102
+ENDFUNCTION(caml_callback2_exn)
+
+FUNCTION(caml_callback3_exn)
+        mr      0, 3            /* Closure */
+        mr      3, 4            /* First argument */
+        mr      4, 5            /* Second argument */
+        mr      5, 6            /* Third argument */
+        mr      6, 0
+        Addrglobal(12, caml_apply3)
+        b       .L102
+ENDFUNCTION(caml_callback3_exn)
+
+#if defined(MODEL_ppc64)
+        .section ".opd","aw"
+#else
+        .section ".text"
+#endif
+
+        .globl  caml_system__code_end
+caml_system__code_end:
+
+/* Frame table */
+
+        .section ".data"
+        .globl  caml_system__frametable
+        .type   caml_system__frametable, @object
+caml_system__frametable:
+        datag   1               /* one descriptor */
+        datag   .L105 + 4       /* return address into callback */
+        .short  -1              /* negative size count => use callback link */
+        .short  0               /* no roots here */
+
+/* TOC entries */
+
+#if defined(MODEL_ppc64) || defined(MODEL_ppc64le)
+
+        .section ".toc", "aw"
+
+#define TOCENTRY(glob) LSYMB(glob): .quad glob
+
+TOCENTRY(caml_apply2)
+TOCENTRY(caml_apply3)
+TOCENTRY(caml_backtrace_active)
+TOCENTRY(caml_backtrace_pos)
+TOCENTRY(caml_bottom_of_stack)
+TOCENTRY(caml_exception_pointer)
+TOCENTRY(caml_gc_regs)
+TOCENTRY(caml_last_return_address)
+TOCENTRY(caml_program)
+TOCENTRY(caml_young_limit)
+TOCENTRY(caml_young_ptr)
+
+#endif
+
+/* Mark stack as non-executable */
+        .section .note.GNU-stack,"",%progbits
diff --git a/asmrun/roots.c b/asmrun/roots.c
index 32325e2e..7bf25b2e 100644
--- a/asmrun/roots.c
+++ b/asmrun/roots.c
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* To walk the memory roots for garbage collection */
 
@@ -32,9 +34,8 @@ struct caml__roots_block *caml_local_roots = NULL;
 void (*caml_scan_roots_hook) (scanning_action) = NULL;
 
 /* The hashtable of frame descriptors */
-
 frame_descr ** caml_frame_descriptors = NULL;
-int caml_frame_descriptors_mask;
+int caml_frame_descriptors_mask = 0;
 
 /* Linked-list */
 
@@ -56,52 +57,43 @@ static link *cons(void *data, link *tl) {
 /* Linked-list of frametables */
 
 static link *frametables = NULL;
+static intnat num_descr = 0;
 
-void caml_register_frametable(intnat *table) {
-  frametables = cons(table,frametables);
+static int count_descriptors(link *list) {
+  intnat num_descr = 0;
+  link *lnk;
+  iter_list(list,lnk) {
+    num_descr += *((intnat*) lnk->data);
+  }
+  return num_descr;
+}
 
-  if (NULL != caml_frame_descriptors) {
-    caml_stat_free(caml_frame_descriptors);
-    caml_frame_descriptors = NULL;
-    /* force caml_init_frame_descriptors to be called */
+static link* frametables_list_tail(link *list) {
+  link *lnk, *tail = NULL;
+  iter_list(list,lnk) {
+    tail = lnk;
   }
+  return tail;
 }
 
-void caml_init_frame_descriptors(void)
-{
-  intnat num_descr, tblsize, i, j, len;
+static frame_descr * next_frame_descr(frame_descr * d) {
+  uintnat nextd;
+  nextd =
+    ((uintnat)d +
+     sizeof(char *) + sizeof(short) + sizeof(short) +
+     sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
+    & -sizeof(frame_descr *);
+  if (d->frame_size & 1) nextd += 8;
+  return((frame_descr *) nextd);
+}
+
+static void fill_hashtable(link *frametables) {
+  intnat len, j;
   intnat * tbl;
   frame_descr * d;
-  uintnat nextd;
   uintnat h;
-  link *lnk;
-
-  static int inited = 0;
-
-  if (!inited) {
-    for (i = 0; caml_frametable[i] != 0; i++)
-      caml_register_frametable(caml_frametable[i]);
-    inited = 1;
-  }
-
-  /* Count the frame descriptors */
-  num_descr = 0;
-  iter_list(frametables,lnk) {
-    num_descr += *((intnat*) lnk->data);
-  }
+  link *lnk = NULL;
 
-  /* The size of the hashtable is a power of 2 greater or equal to
-     2 times the number of descriptors */
-  tblsize = 4;
-  while (tblsize < 2 * num_descr) tblsize *= 2;
-
-  /* Allocate the hash table */
-  caml_frame_descriptors =
-    (frame_descr **) caml_stat_alloc(tblsize * sizeof(frame_descr *));
-  for (i = 0; i < tblsize; i++) caml_frame_descriptors[i] = NULL;
-  caml_frame_descriptors_mask = tblsize - 1;
-
-  /* Fill the hash table */
   iter_list(frametables,lnk) {
     tbl = (intnat*) lnk->data;
     len = *tbl;
@@ -112,17 +104,118 @@ void caml_init_frame_descriptors(void)
         h = (h+1) & caml_frame_descriptors_mask;
       }
       caml_frame_descriptors[h] = d;
-      nextd =
-        ((uintnat)d +
-         sizeof(char *) + sizeof(short) + sizeof(short) +
-         sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
-        & -sizeof(frame_descr *);
-      if (d->frame_size & 1) nextd += 8;
-      d = (frame_descr *) nextd;
+      d = next_frame_descr(d);
     }
   }
 }
 
+static void init_frame_descriptors(link *new_frametables)
+{
+  intnat tblsize, increase, i;
+  link *tail = NULL;
+
+  Assert(new_frametables);
+
+  tail = frametables_list_tail(new_frametables);
+  increase = count_descriptors(new_frametables);
+  tblsize = caml_frame_descriptors_mask + 1;
+
+  /* Reallocate the caml_frame_descriptor table if it is too small */
+  if(tblsize < (num_descr + increase) * 2) {
+
+    /* Merge both lists */
+    tail->next = frametables;
+    frametables = NULL;
+
+    /* [num_descr] can be less than [num_descr + increase] if frame
+       tables where unregistered */
+    num_descr = count_descriptors(new_frametables);
+
+    tblsize = 4;
+    while (tblsize < 2 * num_descr) tblsize *= 2;
+
+    caml_frame_descriptors_mask = tblsize - 1;
+    if(caml_frame_descriptors) caml_stat_free(caml_frame_descriptors);
+    caml_frame_descriptors =
+      (frame_descr **) caml_stat_alloc(tblsize * sizeof(frame_descr *));
+    for (i = 0; i < tblsize; i++) caml_frame_descriptors[i] = NULL;
+
+    fill_hashtable(new_frametables);
+  } else {
+    num_descr += increase;
+    fill_hashtable(new_frametables);
+    tail->next = frametables;
+  }
+
+  frametables = new_frametables;
+}
+
+void caml_init_frame_descriptors(void) {
+  intnat i;
+  link *new_frametables = NULL;
+  for (i = 0; caml_frametable[i] != 0; i++)
+    new_frametables = cons(caml_frametable[i],new_frametables);
+  init_frame_descriptors(new_frametables);
+}
+
+void caml_register_frametable(intnat *table) {
+  link *new_frametables = cons(table,NULL);
+  init_frame_descriptors(new_frametables);
+}
+
+static void remove_entry(frame_descr * d) {
+  uintnat i;
+  uintnat r;
+  uintnat j;
+
+  i = Hash_retaddr(d->retaddr);
+  while (caml_frame_descriptors[i] != d) {
+    i = (i+1) & caml_frame_descriptors_mask;
+  }
+
+ r1:
+  j = i;
+  caml_frame_descriptors[i] = NULL;
+ r2:
+  i = (i+1) & caml_frame_descriptors_mask;
+  // r3
+  if(caml_frame_descriptors[i] == NULL) return;
+  r = Hash_retaddr(caml_frame_descriptors[i]->retaddr);
+  /* If r is between i and j (cyclically), i.e. if
+     caml_frame_descriptors[i]->retaddr don't need to be moved */
+  if(( ( j < r )  && ( r <= i ) ) ||
+     ( ( i < j )  && ( j < r )  ) ||      /* i cycled, r not */
+     ( ( r <= i ) && ( i < j ) )     ) {  /* i and r cycled */
+    goto r2;
+  }
+  // r4
+  caml_frame_descriptors[j] = caml_frame_descriptors[i];
+  goto r1;
+}
+
+void caml_unregister_frametable(intnat *table) {
+  intnat len, j;
+  link *lnk;
+  link *previous = frametables;
+  frame_descr * d;
+
+  len = *table;
+  d = (frame_descr *)(table + 1);
+  for (j = 0; j < len; j++) {
+    remove_entry(d);
+    d = next_frame_descr(d);
+  }
+
+  iter_list(frametables,lnk) {
+    if(lnk->data == table) {
+      previous->next = lnk->next;
+      caml_stat_free(lnk);
+      break;
+    }
+    previous = lnk;
+  }
+}
+
 /* Communication with [caml_start_program] and [caml_call_gc]. */
 
 char * caml_top_of_stack;
@@ -152,7 +245,7 @@ void caml_oldify_local_roots (void)
 #else
   unsigned short * p;
 #endif
-  value glob;
+  value * glob;
   value * root;
   struct caml__roots_block *lr;
   link *lnk;
@@ -161,23 +254,24 @@ void caml_oldify_local_roots (void)
   for (i = caml_globals_scanned;
        i <= caml_globals_inited && caml_globals[i] != 0;
        i++) {
-    glob = caml_globals[i];
-    for (j = 0; j < Wosize_val(glob); j++){
-      Oldify (&Field (glob, j));
+    for(glob = caml_globals[i]; *glob != 0; glob++) {
+      for (j = 0; j < Wosize_val(*glob); j++){
+        Oldify (&Field (*glob, j));
+      }
     }
   }
   caml_globals_scanned = caml_globals_inited;
 
   /* Dynamic global roots */
   iter_list(caml_dyn_globals, lnk) {
-    glob = (value) lnk->data;
-    for (j = 0; j < Wosize_val(glob); j++){
-      Oldify (&Field (glob, j));
+    for(glob = (value *) lnk->data; *glob != 0; glob++) {
+      for (j = 0; j < Wosize_val(*glob); j++){
+        Oldify (&Field (*glob, j));
+      }
     }
   }
 
   /* The stack and local roots */
-  if (caml_frame_descriptors == NULL) caml_init_frame_descriptors();
   sp = caml_bottom_of_stack;
   retaddr = caml_last_return_address;
   regs = caml_gc_regs;
@@ -243,44 +337,100 @@ void caml_oldify_local_roots (void)
   if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one);
 }
 
-/* Call [darken] on all roots */
+uintnat caml_incremental_roots_count = 0;
 
-void caml_darken_all_roots (void)
+/* Call [caml_darken] on all roots, incrementally:
+   [caml_darken_all_roots_start] does the non-incremental part and
+   sets things up for [caml_darken_all_roots_slice].
+*/
+void caml_darken_all_roots_start (void)
 {
-  caml_do_roots (caml_darken);
+  caml_do_roots (caml_darken, 0);
 }
 
-void caml_do_roots (scanning_action f)
+/* Call [caml_darken] on at most [work] global roots. Return the
+   amount of work not done, if any. If this is strictly positive,
+   the darkening is done.
+ */
+intnat caml_darken_all_roots_slice (intnat work)
 {
-  int i, j;
-  value glob;
-  link *lnk;
-
-  /* The global roots */
+  static int i, j;
+  static value *glob;
+  static int do_resume = 0;
+  static mlsize_t roots_count = 0;
+  intnat remaining_work = work;
+  CAML_INSTR_SETUP (tmr, "");
+
+  /* If the loop was started in a previous call, resume it. */
+  if (do_resume) goto resume;
+
+  /* This is the same loop as in [caml_do_roots], but we make it
+     suspend itself when [work] reaches 0. */
   for (i = 0; caml_globals[i] != 0; i++) {
-    glob = caml_globals[i];
-    for (j = 0; j < Wosize_val(glob); j++)
-      f (Field (glob, j), &Field (glob, j));
+    for(glob = caml_globals[i]; *glob != 0; glob++) {
+      for (j = 0; j < Wosize_val(*glob); j++){
+        caml_darken (Field (*glob, j), &Field (*glob, j));
+        -- remaining_work;
+        if (remaining_work == 0){
+          roots_count += work;
+          do_resume = 1;
+          goto suspend;
+        }
+      resume: ;
+      }
+    }
   }
 
+  /* The loop finished normally, so all roots are now darkened. */
+  caml_incremental_roots_count = roots_count + work - remaining_work;
+  /* Prepare for the next run. */
+  do_resume = 0;
+  roots_count = 0;
+
+ suspend:
+  /* Do this in both cases. */
+  CAML_INSTR_TIME (tmr, "major/mark/global_roots_slice");
+  return remaining_work;
+}
+
+void caml_do_roots (scanning_action f, int do_globals)
+{
+  int i, j;
+  value * glob;
+  link *lnk;
+  CAML_INSTR_SETUP (tmr, "major_roots");
+
+  if (do_globals){
+    /* The global roots */
+    for (i = 0; caml_globals[i] != 0; i++) {
+      for(glob = caml_globals[i]; *glob != 0; glob++) {
+        for (j = 0; j < Wosize_val(*glob); j++)
+          f (Field (*glob, j), &Field (*glob, j));
+      }
+    }
+  }
   /* Dynamic global roots */
   iter_list(caml_dyn_globals, lnk) {
-    glob = (value) lnk->data;
-    for (j = 0; j < Wosize_val(glob); j++){
-      f (Field (glob, j), &Field (glob, j));
+    for(glob = (value *) lnk->data; *glob != 0; glob++) {
+      for (j = 0; j < Wosize_val(*glob); j++){
+        f (Field (*glob, j), &Field (*glob, j));
+      }
     }
   }
-
+  CAML_INSTR_TIME (tmr, "major_roots/dynamic_global");
   /* The stack and local roots */
-  if (caml_frame_descriptors == NULL) caml_init_frame_descriptors();
   caml_do_local_roots(f, caml_bottom_of_stack, caml_last_return_address,
                       caml_gc_regs, caml_local_roots);
+  CAML_INSTR_TIME (tmr, "major_roots/local");
   /* Global C roots */
   caml_scan_global_roots(f);
+  CAML_INSTR_TIME (tmr, "major_roots/C");
   /* Finalised values */
   caml_final_do_strong_roots (f);
+  CAML_INSTR_TIME (tmr, "major_roots/finalised");
   /* Hook */
   if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f);
+  CAML_INSTR_TIME (tmr, "major_roots/hook");
 }
 
 void caml_do_local_roots(scanning_action f, char * bottom_of_stack,
diff --git a/asmrun/s390x.S b/asmrun/s390x.S
new file mode 100644
index 00000000..175ea6a0
--- /dev/null
+++ b/asmrun/s390x.S
@@ -0,0 +1,358 @@
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*            Xavier Leroy, projet Gallium, INRIA Rocquencourt            */
+/*                          Bill O'Farrell, IBM                           */
+/*                                                                        */
+/*   Copyright 2015 Institut National de Recherche en Informatique et     */
+/*     en Automatique.                                                    */
+/*   Copyright 2015 IBM (Bill O'Farrell with help from Tristan Amini).    */
+/*                                                                        */
+/*   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.          */
+/*                                                                        */
+/**************************************************************************/
+#define Addrglobal(reg,glob) \
+        larl    reg, glob
+#define Loadglobal(reg,glob) \
+        lgrl    reg, glob
+#define Storeglobal(reg,glob) \
+        stgrl   reg, glob
+#define Loadglobal32(reg,glob) \
+        lgfrl   reg, glob
+#define Storeglobal32(reg,glob) \
+        strl   reg, glob
+
+
+        .section ".text"
+
+/* Invoke the garbage collector. */
+
+        .globl  caml_system__code_begin
+caml_system__code_begin:
+
+        .globl  caml_call_gc
+        .type   caml_call_gc, @function
+caml_call_gc:
+    /* Set up stack frame */
+#define FRAMESIZE (16*8 + 16*8)
+        lay     %r15, -FRAMESIZE(%r15)
+    /* Record return address into OCaml code */
+        Storeglobal(%r14, caml_last_return_address)
+    /* Record lowest stack address */
+        lay     %r0, FRAMESIZE(%r15)
+        Storeglobal(%r0, caml_bottom_of_stack)
+    /* Record pointer to register array */
+        lay     %r0, (8*16)(%r15)
+        Storeglobal(%r0, caml_gc_regs)
+    /* Save current allocation pointer for debugging purposes */
+        Storeglobal(%r11, caml_young_ptr)
+    /* Save exception pointer (if e.g. a sighandler raises) */
+        Storeglobal(%r13, caml_exception_pointer)
+    /* Save all registers used by the code generator */
+        stmg    %r2,%r9, (8*16)(%r15)
+        stg     %r12, (8*16 + 8*8)(%r15)
+        std     %f0, 0(%r15)
+        std     %f1, 8(%r15)
+        std     %f2, 16(%r15)
+        std     %f3, 24(%r15)
+        std     %f4, 32(%r15)
+        std     %f5, 40(%r15)
+        std     %f6, 48(%r15)
+        std     %f7, 56(%r15)
+        std     %f8, 64(%r15)
+        std     %f9, 72(%r15)
+        std     %f10, 80(%r15)
+        std     %f11, 88(%r15)
+        std     %f12, 96(%r15)
+        std     %f13, 108(%r15)
+        std     %f14, 112(%r15)
+        std     %f15, 120(%r15)
+    /* Call the GC */
+        lay %r15, -160(%r15)
+        stg     %r15, 0(%r15)
+        brasl   %r14, caml_garbage_collection@PLT
+        lay %r15, 160(%r15)
+    /* Reload new allocation pointer and allocation limit */
+        Loadglobal(%r11, caml_young_ptr)
+        Loadglobal(%r10, caml_young_limit)
+    /* Restore all regs used by the code generator */
+        lmg     %r2,%r9, (8*16)(%r15)
+        lg      %r12, (8*16 + 8*8)(%r15)
+        ld      %f0, 0(%r15)
+        ld      %f1, 8(%r15)
+        ld      %f2, 16(%r15)
+        ld      %f3, 24(%r15)
+        ld      %f4, 32(%r15)
+        ld      %f5, 40(%r15)
+        ld      %f6, 48(%r15)
+        ld      %f7, 56(%r15)
+        ld      %f8, 64(%r15)
+        ld      %f9, 72(%r15)
+        ld      %f10, 80(%r15)
+        ld      %f11, 88(%r15)
+        ld      %f12, 96(%r15)
+        ld      %f13, 108(%r15)
+        ld      %f14, 112(%r15)
+        ld      %f15, 120(%r15)
+    /* Return to caller */
+        Loadglobal(%r1, caml_last_return_address)
+    /* Deallocate stack frame */
+        lay     %r15, FRAMESIZE(%r15)
+    /* Return */
+        br    %r1
+
+/* Call a C function from OCaml */
+
+        .globl  caml_c_call
+        .type   caml_c_call, @function
+caml_c_call:
+        Storeglobal(%r15, caml_bottom_of_stack)
+    /* Save return address */
+        ldgr    %f15, %r14
+    /* Get ready to call C function (address in r7) */
+    /* Record lowest stack address and return address */
+        Storeglobal(%r14, caml_last_return_address)
+    /* Make the exception handler and alloc ptr available to the C code */
+        Storeglobal(%r11, caml_young_ptr)
+        Storeglobal(%r13, caml_exception_pointer)
+    /* Call the function */
+        basr %r14, %r7
+    /* restore return address */
+        lgdr    %r14,%f15
+    /* Reload allocation pointer and allocation limit*/
+        Loadglobal(%r11, caml_young_ptr)
+        Loadglobal(%r10, caml_young_limit)
+    /* Say we are back into OCaml code */
+        lgfi   %r0, 0
+        Storeglobal(%r0, caml_last_return_address)
+
+    /* Return to caller */
+        br %r14
+
+/* Raise an exception from OCaml */
+        .globl  caml_raise_exn
+        .type   caml_raise_exn, @function
+caml_raise_exn:
+        Loadglobal32(%r0, caml_backtrace_active)
+        cgfi    %r0, 0
+        jne     .L110
+.L111:
+    /* Pop trap frame */
+        lg      %r1, 0(%r13)
+        lgr     %r15, %r13
+        lg     %r13, 8(13)
+        agfi   %r15, 16
+    /* Branch to handler */
+        br      %r1
+.L110:
+        lgfi      %r0, 0
+        Storeglobal32(%r0, caml_backtrace_pos)
+.L114:
+        ldgr    %f15, %r2       /* preserve exn bucket in callee-save reg */
+                                /* arg1: exception bucket, already in r3 */
+        lgr     %r3,%r14        /* arg2: PC of raise */
+        lgr     %r4, %r15       /* arg3: SP of raise */
+        lgr     %r5, %r13           /* arg4: SP of handler */
+        agfi    %r15, -160       /* reserve stack space for C call */
+        brasl   %r14, caml_stash_backtrace@PLT
+        agfi    %r15, 160
+        lgdr    %r2,%f15        /* restore exn bucket */
+        j       .L111           /* raise the exn */
+
+        .globl  caml_reraise_exn
+        .type   caml_reraise_exn, @function
+caml_reraise_exn:
+        Loadglobal32(%r0, caml_backtrace_active)
+        cgfi    %r0, 0
+        jne    .L114
+    /* Pop trap frame */
+        lg     %r1, 0(%r13)
+        lgr    %r15, %r13
+        lg    %r13, 8(%r13)
+        agfi   %r15, 16
+    /* Branch to handler */
+        br     %r1;
+
+/* Raise an exception from C */
+
+        .globl  caml_raise_exception
+        .type   caml_raise_exception, @function
+caml_raise_exception:
+        Loadglobal32(0, caml_backtrace_active)
+        cgfi    %r0, 0
+        jne    .L112
+.L113:
+    /* Reload OCaml global registers */
+        Loadglobal(%r15, caml_exception_pointer)
+        Loadglobal(%r11, caml_young_ptr)
+        Loadglobal(%r10, caml_young_limit)
+    /* Say we are back into OCaml code */
+        lgfi   %r0, 0
+        Storeglobal(%r0, caml_last_return_address)
+    /* Pop trap frame */
+        lg      %r1, 0(%r15)
+        lg      %r13, 8(%r15)
+        agfi    %r15, 16
+    /* Branch to handler */
+        br      %r1;
+.L112:
+        ldgr    %f15,%r2        /* preserve exn bucket in callee-save reg */
+                                /* arg1: exception bucket, already in r2 */
+        Loadglobal(%r3, caml_last_return_address) /* arg2: PC of raise */
+        Loadglobal(%r4, caml_bottom_of_stack)     /* arg3: SP of raise */
+        Loadglobal(%r5, caml_exception_pointer)   /* arg4: SP of handler */
+             /* reserve stack space for C call */
+        lay %r15, -160(%r15)
+        brasl   %r14, caml_stash_backtrace@PLT
+        lay %r15, 160(%r15)
+        lgdr    %r2,%f15        /* restore exn bucket */
+        j       .L113           /* raise the exn */
+
+/* Start the OCaml program */
+
+        .globl  caml_start_program
+        .type   caml_start_program, @function
+caml_start_program:
+        Addrglobal(%r0, caml_program)
+
+/* Code shared between caml_start_program and caml_callback */
+.L102:
+    /* Allocate stack frame */
+        lay     %r15, -144(%r15)
+    /* Save all callee-save registers + return address */
+    /* GPR 6..14 at sp + 0 ... sp + 64
+       FPR 10..15 at sp + 72 ... sp + 128 */
+        stmg    %r6,%r14, 0(%r15)
+        std     %f8, 72(%r15)
+        std     %f9, 80(%r15)
+        std     %f10, 88(%r15)
+        std     %f11, 96(%r15)
+        std     %f12, 104(%r15)
+        std     %f13, 112(%r15)
+        std     %f14, 120(%r15)
+        std     %f15, 128(%r15)
+
+    /* Set up a callback link */
+        lay     %r15, -32(%r15)
+        Loadglobal(%r1, caml_bottom_of_stack)
+        stg     %r1, 0(%r15)
+        Loadglobal(%r1, caml_last_return_address)
+        stg     %r1, 8(%r15)
+        Loadglobal(%r1, caml_gc_regs)
+        stg     %r1, 16(%r15)
+    /* Build an exception handler to catch exceptions escaping out of OCaml */
+        brasl   %r14, .L103
+        j       .L104
+.L103:
+        lay     %r15, -16(%r15)
+        stg     %r14, 0(%r15)
+        Loadglobal(%r1, caml_exception_pointer)
+        stg     %r1, 8(%r15)
+        lgr     %r13, %r15
+    /* Reload allocation pointers */
+        Loadglobal(%r11, caml_young_ptr)
+        Loadglobal(%r10, caml_young_limit)
+    /* Call the OCaml code */
+        lgr %r1,%r0
+        basr %r14, %r1
+.L105:
+    /* Pop the trap frame, restoring caml_exception_pointer */
+        lg     %r0, 8(%r15)
+        Storeglobal(%r0, caml_exception_pointer)
+        la      %r15, 16(%r15)
+    /* Pop the callback link, restoring the global variables */
+.L106:
+        lg      %r5, 0(%r15)
+        lg      %r6, 8(%r15)
+        lg      %r1, 16(%r15)
+        Storeglobal(%r5, caml_bottom_of_stack)
+        Storeglobal(%r6, caml_last_return_address)
+        Storeglobal(%r1, caml_gc_regs)
+        la      %r15, 32(%r15)
+
+    /* Update allocation pointer */
+        Storeglobal(%r11, caml_young_ptr)
+
+        /* Restore registers */
+        lmg    %r6,%r14, 0(%r15)
+        ld     %f8, 72(%r15)
+        ld     %f9, 80(%r15)
+        ld     %f10, 88(%r15)
+        ld     %f11, 96(%r15)
+        ld     %f12, 104(%r15)
+        ld     %f13, 112(%r15)
+        ld     %f14, 120(%r15)
+        ld     %f15, 128(%r15)
+
+    /* Return */
+        lay     %r15, 144(%r15)
+        br      %r14
+
+    /* The trap handler: */
+.L104:
+    /* Update caml_exception_pointer */
+        Storeglobal(%r13, caml_exception_pointer)
+    /* Encode exception bucket as an exception result and return it */
+        oill     %r2,  2
+        j       .L106
+
+/* Callback from C to OCaml */
+
+        .globl  caml_callback_exn
+        .type   caml_callback_exn, @function
+caml_callback_exn:
+    /* Initial shuffling of arguments */
+        lgr     %r0, %r2            /* Closure */
+        lgr     %r2, %r3            /* Argument */
+        lgr     %r3, %r0
+        lg      %r0, 0(%r3)        /* Code pointer */
+        j       .L102
+
+        .globl  caml_callback2_exn
+        .type   caml_callback2_exn, @function
+caml_callback2_exn:
+        lgr      %r0, %r2            /* Closure */
+        lgr      %r2, %r3            /* First argument */
+        lgr      %r3, %r4            /* Second argument */
+        lgr      %r4, %r0
+        Addrglobal(%r0, caml_apply2)
+        j       .L102
+
+        .globl  caml_callback3_exn
+        .type   caml_callback3_exn, @function
+caml_callback3_exn:
+        lgr      %r0, %r2            /* Closure */
+        lgr      %r2, %r3            /* First argument */
+        lgr      %r3, %r4            /* Second argument */
+        lgr      %r4, %r5            /* Third argument */
+        lgr      %r5, %r0
+        Addrglobal(%r0, caml_apply3)
+        j        .L102
+
+        .globl  caml_ml_array_bound_error
+        .type   caml_ml_array_bound_error, @function
+caml_ml_array_bound_error:
+        lay     %r15, -160(%r15)    /* Reserve stack space for C call */
+        larl    %r7, caml_array_bound_error
+        j       caml_c_call
+        .globl  caml_system__code_end
+caml_system__code_end:
+
+/* Frame table */
+
+        .section ".data"
+        .align 8
+        .globl  caml_system__frametable
+        .type   caml_system__frametable, @object
+caml_system__frametable:
+        .quad   1               /* one descriptor */
+        .quad   .L105           /* return address into callback */
+        .short  -1              /* negative size count => use callback link */
+        .short  0               /* no roots here */
+        .align  8
+
+/* Mark stack as non-executable */
+        .section .note.GNU-stack,"",%progbits
diff --git a/asmrun/signals_asm.c b/asmrun/signals_asm.c
index 4ac2a64f..449e2dad 100644
--- a/asmrun/signals_asm.c
+++ b/asmrun/signals_asm.c
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Gallium, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 2007 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Gallium, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 2007 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Signal handling, code specific to the native-code compiler */
 
@@ -67,9 +69,10 @@ extern char caml_system__code_begin, caml_system__code_end;
 
 void caml_garbage_collection(void)
 {
-  caml_young_limit = caml_young_start;
-  if (caml_young_ptr < caml_young_start || caml_force_major_slice) {
-    caml_minor_collection();
+  caml_young_limit = caml_young_trigger;
+  if (caml_requested_major_slice || caml_requested_minor_gc ||
+      caml_young_ptr - caml_young_trigger < Max_young_whsize){
+    caml_gc_dispatch ();
   }
   caml_process_pending_signals();
 }
@@ -144,7 +147,9 @@ int caml_set_signal_action(int signo, int action)
 
 /* Machine- and OS-dependent handling of bound check trap */
 
-#if defined(TARGET_power) || (defined(TARGET_sparc) && defined(SYS_solaris))
+#if defined(TARGET_power) \
+  || defined(TARGET_s390x) \
+  || (defined(TARGET_sparc) && defined(SYS_solaris))
 DECLARE_SIGNAL_HANDLER(trap_handler)
 {
 #if defined(SYS_solaris)
@@ -167,7 +172,7 @@ DECLARE_SIGNAL_HANDLER(trap_handler)
   }
 #endif
   caml_exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER;
-  caml_young_ptr = (char *) CONTEXT_YOUNG_PTR;
+  caml_young_ptr = (value *) CONTEXT_YOUNG_PTR;
   caml_bottom_of_stack = (char *) CONTEXT_SP;
   caml_last_return_address = (uintnat) CONTEXT_PC;
   caml_array_bound_error();
@@ -226,7 +231,7 @@ DECLARE_SIGNAL_HANDLER(segv_handler)
     /* Raise a Stack_overflow exception straight from this signal handler */
 #if defined(CONTEXT_YOUNG_PTR) && defined(CONTEXT_EXCEPTION_POINTER)
     caml_exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER;
-    caml_young_ptr = (char *) CONTEXT_YOUNG_PTR;
+    caml_young_ptr = (value *) CONTEXT_YOUNG_PTR;
 #endif
     caml_raise_stack_overflow();
 #endif
@@ -267,6 +272,14 @@ void caml_init_signals(void)
   }
 #endif
 
+#if defined(TARGET_s390x)
+  { struct sigaction act;
+    sigemptyset(&act.sa_mask);
+    SET_SIGACT(act, trap_handler);
+    sigaction(SIGFPE, &act, NULL);
+  }
+#endif
+
   /* Stack overflow handling */
 #ifdef HAS_STACK_OVERFLOW_DETECTION
   {
diff --git a/asmrun/signals_osdep.h b/asmrun/signals_osdep.h
index 627e3b72..dc2236ab 100644
--- a/asmrun/signals_osdep.h
+++ b/asmrun/signals_osdep.h
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 2004 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 2004 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Processor- and OS-dependent signal interface */
 
@@ -284,6 +286,23 @@
   #define CONTEXT_YOUNG_PTR (context->regs->gpr[31])
   #define CONTEXT_SP (context->regs->gpr[1])
 
+/****************** s390x, ELF (Linux) */
+#elif defined(TARGET_s390x) && defined(SYS_elf)
+
+  #define DECLARE_SIGNAL_HANDLER(name) \
+    static void name(int sig, struct sigcontext * context)
+
+  #define SET_SIGACT(sigact,name) \
+     sigact.sa_handler = (void (*)(int)) (name); \
+     sigact.sa_flags = 0
+
+  typedef unsigned long context_reg;
+  #define CONTEXT_PC (context->sregs->regs.psw.addr)
+  #define CONTEXT_EXCEPTION_POINTER (context->sregs->regs.gprs[13])
+  #define CONTEXT_YOUNG_LIMIT (context->sregs->regs.gprs[10])
+  #define CONTEXT_YOUNG_PTR (context->sregs->regs.gprs[11])
+  #define CONTEXT_SP (context->sregs->regs.gprs[15])
+
 /****************** PowerPC, BSD */
 
 #elif defined(TARGET_power) && (defined(SYS_bsd) || defined(SYS_bsd_elf))
diff --git a/asmrun/sparc.S b/asmrun/sparc.S
index 7f24b4b4..b46e71f0 100644
--- a/asmrun/sparc.S
+++ b/asmrun/sparc.S
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Asm part of the runtime system for the Sparc processor.  */
 /* Must be preprocessed by cpp */
diff --git a/asmrun/stack.h b/asmrun/stack.h
index 6e559429..8556b336 100644
--- a/asmrun/stack.h
+++ b/asmrun/stack.h
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Machine-dependent interface with the asm code */
 
@@ -33,16 +35,26 @@
 #endif
 
 #ifdef TARGET_power
-#define Saved_return_address(sp) *((intnat *)((sp) - SIZEOF_PTR))
+#if defined(MODEL_ppc)
+#define Saved_return_address(sp) *((intnat *)((sp) - 4))
+#define Callback_link(sp) ((struct caml_context *)((sp) + 16))
+#elif defined(MODEL_ppc64)
+#define Saved_return_address(sp) *((intnat *)((sp) + 16))
+#define Callback_link(sp) ((struct caml_context *)((sp) + (48 + 32)))
+#elif defined(MODEL_ppc64le)
+#define Saved_return_address(sp) *((intnat *)((sp) + 16))
+#define Callback_link(sp) ((struct caml_context *)((sp) + (32 + 32)))
+#else
+#error "TARGET_power: wrong MODEL"
+#endif
 #define Already_scanned(sp, retaddr) ((retaddr) & 1)
-#define Mark_scanned(sp, retaddr) \
-          (*((intnat *)((sp) - SIZEOF_PTR)) = (retaddr) | 1)
 #define Mask_already_scanned(retaddr) ((retaddr) & ~1)
-#ifdef SYS_aix
-#define Trap_frame_size 32
-#else
-#define Trap_frame_size 16
+#define Mark_scanned(sp, retaddr) Saved_return_address(sp) = (retaddr) | 1
 #endif
+
+#ifdef TARGET_s390x
+#define Saved_return_address(sp) *((intnat *)((sp) - SIZEOF_PTR))
+#define Trap_frame_size 16
 #define Callback_link(sp) ((struct caml_context *)((sp) + Trap_frame_size))
 #endif
 
@@ -78,15 +90,6 @@ typedef struct {
   unsigned short live_ofs[1];
 } frame_descr;
 
-struct caml_loc_info {
-  int loc_valid;
-  int loc_is_raise;
-  char * loc_filename;
-  int loc_lnum;
-  int loc_startchr;
-  int loc_endchr;
-};
-
 /* Hash table of frame descriptors */
 
 extern frame_descr ** caml_frame_descriptors;
@@ -97,12 +100,9 @@ extern int caml_frame_descriptors_mask;
 
 extern void caml_init_frame_descriptors(void);
 extern void caml_register_frametable(intnat *);
+extern void caml_unregister_frametable(intnat *);
 extern void caml_register_dyn_global(void *);
 
-CAMLextern void extract_location_info(frame_descr * d,
-                                      /*out*/ struct caml_loc_info * li);
-
-
 extern uintnat caml_stack_usage (void);
 extern uintnat (*caml_stack_usage_hook)(void);
 
@@ -112,7 +112,7 @@ extern char * caml_bottom_of_stack;
 extern uintnat caml_last_return_address;
 extern value * caml_gc_regs;
 extern char * caml_exception_pointer;
-extern value caml_globals[];
+extern value * caml_globals[];
 extern intnat caml_globals_inited;
 extern intnat * caml_frametable[];
 
diff --git a/asmrun/startup.c b/asmrun/startup.c
index 1fefe7fd..da61ffcd 100644
--- a/asmrun/startup.c
+++ b/asmrun/startup.c
@@ -1,15 +1,17 @@
-/***********************************************************************/
-/*                                                                     */
-/*                                OCaml                                */
-/*                                                                     */
-/*         Xavier Leroy and Damien Doligez, INRIA Rocquencourt         */
-/*                                                                     */
-/*  Copyright 1996 Institut National de Recherche en Informatique et   */
-/*  en Automatique.  All rights reserved.  This file is distributed    */
-/*  under the terms of the GNU Library General Public License, with    */
-/*  the special exception on linking described in file ../LICENSE.     */
-/*                                                                     */
-/***********************************************************************/
+/**************************************************************************/
+/*                                                                        */
+/*                                 OCaml                                  */
+/*                                                                        */
+/*          Xavier Leroy and Damien Doligez, INRIA Rocquencourt           */
+/*                                                                        */
+/*   Copyright 1996 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.          */
+/*                                                                        */
+/**************************************************************************/
 
 /* Start-up code */
 
@@ -30,6 +32,7 @@
 #include "caml/osdeps.h"
 #include "caml/printexc.h"
 #include "stack.h"
+#include "caml/startup_aux.h"
 #include "caml/sys.h"
 #ifdef HAS_UI
 #include "caml/ui.h"
@@ -43,18 +46,13 @@ char * caml_code_area_start, * caml_code_area_end;
 
 struct segment { char * begin; char * end; };
 
-static void init_atoms(void)
+static void init_static(void)
 {
   extern struct segment caml_data_segments[], caml_code_segments[];
   int i;
   struct code_fragment * cf;
 
-  for (i = 0; i < 256; i++) {
-    caml_atom_table[i] = Make_header(0, i, Caml_white);
-  }
-  if (caml_page_table_add(In_static_data,
-                          caml_atom_table, caml_atom_table + 256) != 0)
-    caml_fatal_error("Fatal error: not enough memory for initial page table");
+  caml_init_atom_table ();
 
   for (i = 0; caml_data_segments[i].begin != 0; i++) {
     /* PR#5509: we must include the zero word at end of data segment,
@@ -82,63 +80,6 @@ static void init_atoms(void)
   caml_ext_table_add(&caml_code_fragments_table, cf);
 }
 
-/* Configuration parameters and flags */
-
-static uintnat percent_free_init = Percent_free_def;
-static uintnat max_percent_free_init = Max_percent_free_def;
-static uintnat minor_heap_init = Minor_heap_def;
-static uintnat heap_chunk_init = Heap_chunk_def;
-static uintnat heap_size_init = Init_heap_def;
-static uintnat max_stack_init = Max_stack_def;
-
-/* Parse the CAMLRUNPARAM variable */
-/* The option letter for each runtime option is the first letter of the
-   last word of the ML name of the option (see [stdlib/gc.mli]).
-   Except for l (maximum stack size) and h (initial heap size).
-*/
-/* Note: option l is irrelevant to the native-code runtime. */
-
-/* If you change these functions, see also their copy in byterun/startup.c */
-
-static void scanmult (char *opt, uintnat *var)
-{
-  char mult = ' ';
-  int val;
-  sscanf (opt, "=%u%c", &val, &mult);
-  sscanf (opt, "=0x%x%c", &val, &mult);
-  switch (mult) {
-  case 'k':   *var = (uintnat) val * 1024; break;
-  case 'M':   *var = (uintnat) val * 1024 * 1024; break;
-  case 'G':   *var = (uintnat) val * 1024 * 1024 * 1024; break;
-  default:    *var = (uintnat) val; break;
-  }
-}
-
-static void parse_camlrunparam(void)
-{
-  char *opt = getenv ("OCAMLRUNPARAM");
-  uintnat p;
-
-  if (opt == NULL) opt = getenv ("CAMLRUNPARAM");
-
-  if (opt != NULL){
-    while (*opt != '\0'){
-      switch (*opt++){
-      case 's': scanmult (opt, &minor_heap_init); break;
-      case 'i': scanmult (opt, &heap_chunk_init); break;
-      case 'h': scanmult (opt, &heap_size_init); break;
-      case 'l': scanmult (opt, &max_stack_init); break;
-      case 'o': scanmult (opt, &percent_free_init); break;
-      case 'O': scanmult (opt, &max_percent_free_init); break;
-      case 'v': scanmult (opt, &caml_verb_gc); break;
-      case 'b': caml_record_backtrace(Val_true); break;
-      case 'p': caml_parser_trace = 1; break;
-      case 'a': scanmult (opt, &p); caml_set_allocation_policy (p); break;
-      }
-    }
-  }
-}
-
 /* These are termination hooks used by the systhreads library */
 struct longjmp_buffer caml_termination_jmpbuf;
 void (*caml_termination_hook)(void *) = NULL;
@@ -162,20 +103,26 @@ void caml_main(char **argv)
   value res;
   char tos;
 
+  caml_init_frame_descriptors();
   caml_init_ieee_floats();
 #ifdef _MSC_VER
   caml_install_invalid_parameter_handler();
 #endif
   caml_init_custom_operations();
+  caml_top_of_stack = &tos;
 #ifdef DEBUG
-  caml_verb_gc = 63;
+  caml_verb_gc = 0x3F;
 #endif
-  caml_top_of_stack = &tos;
-  parse_camlrunparam();
-  caml_init_gc (minor_heap_init, heap_size_init, heap_chunk_init,
-                percent_free_init, max_percent_free_init);
-  init_atoms();
+  caml_parse_ocamlrunparam();
+#ifdef DEBUG
+  caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0);
+#endif
+  caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz,
+                caml_init_heap_chunk_sz, caml_init_percent_free,
+                caml_init_max_percent_free, caml_init_major_window);
+  init_static();
   caml_init_signals();
+  caml_init_backtrace();
   caml_debugger_init (); /* force debugger.o stub to be linked */
   exe_name = argv[0];
   if (exe_name == NULL) exe_name = "";
diff --git a/boot/.ignore b/boot/.ignore
deleted file mode 100644
index 30c5866b..00000000
--- a/boot/.ignore
+++ /dev/null
@@ -1,6 +0,0 @@
-Saved
-ocamlrun
-ocamlrun.exe
-ocamlyacc
-ocamlyacc.exe
-camlheader
diff --git a/boot/ocamlc b/boot/ocamlc
index 41eb9b40de1e2a8edfe7e6177b2704c8bea529d8..6ec07c9e3a4c9252ccbb36d466ec4c71b35f9d08 100755
GIT binary patch
literal 2072761
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 !+c&1&ACS*B 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

t)_>iN# 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

4O`mJ-B#wXY~_Ky||q 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�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%0D_rzUI)HIzi%Rj1Q4PPtWLQrw`<7Ul6D#wR+Pu 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

x)6e0Vb0m#Do*p9;kLa^c+o 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%0Ab*IbMT_{>QbLDj>rTWs} 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∋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 W1Ol~T&_oI6eA>Ku^Olfl)BX#Nkl@+? diff --git a/boot/ocamldep b/boot/ocamldep index 383b3d187bb69087432e03b65ebed037b6265b07..ea6697ccd654751d8bb83eb3ec162654dfac5703 100755 GIT binary patch literal 696193 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℘gZp?AO8m*+o}-+iHuN4vjovfCQ}`L_1gk01ZcA3EWm zoM40sIePYF&*fA9{HYfwbT1Cr%CC?7KgW-cHUHN#cV_I%$#>7@ z@6UX^10J67pON|K>v#Uf3EM7;EV|w0`j-ZDsE7hJD=?D+BB`4W^}+Fg@fWc56Gwv)wf zxHseaZ@2s-L`FPf3OY?Gf{s4K5 z^T+bLX2$uS&wM-w@0jMj4}1RE%fDNv-kCD@OxC|4pp)z~CmFqCdS^7w&z)$UiJSAw ze4d=XdPW*@`Asg`XNH!1@w+(azWycC+`hTG(f5A3W}06+^*2v_>Dhpu-}=_yMz!;d ziSClA_b!6(3#R_wsekKiZrwZj1%akU#nM?@Pa)ix{zn3BZ=g0bc8Y_RYxKDK5(Bk$ zX`q(TvSTe^|Azu?HF!$EN9**+`K~}KEq=6Q?+JXC8fDu*7?8sj^IwWB=0_%oUv;=Q zoM&?6OtVMk1;OY;rYHB*%Y1J=YmLX;Ci-^PGwT$zOY&PY^@#7ppN| z+cRggzC2o8L2=-hTGAN9R7^YOlXdgf0KJsQm& zU|+0_?ddzWXU;~wc#d>*o4XI)6Zkdvgt2?#a2#__{Ffw7to8-Xm3z(EGCvg1(|R)} z!<;?FKBInSfX_L_=bWhtHN{@{_~pUH0YBx$zGuOxKhve3&Dl;ao9S?;<0FH8YIrrE zORah*RO{f`wmU$_UTb*SrVhLAo+qPx*4Zn*qmAqs<09Uk4W7GqX0tKzJAH1-8hb%Z z+$GM|YXT=1?^eNgwD{R3ru6c;{#*Af_-McmPzz{0H^BJI1C4LuKo(pbXl%uMSFkdT z#pU`y6F0UT3Gj7~EU{J_)@uvB@}MT?wCo|vx;Ue2Ugm3j*%`DS?WI$k=P@~&wUvNB z^s|NCm5qnK`vdmZz6?*=fw%OvPrl!H#_wHU7E5uS*AP49>rlY|g8@B{r8eZhwb5E2 ztMR`lWAUjEd{*0@6I$suqB%b_{8Ik%=x5`sme*InTIst41r1eGtg=-dH&0yV6S z{Ix+nh|7Th587YM9r?QSd~8jQwPalmF^xCaK zdDk;Wi-&EE>1Z3B^c@b^d0ntK5Lay(ExD(n9et*sj;+{JzRI8TY>OQ2U?A@E_?q*R zzQ+>dqY3B}9pn1Mo~_y^56z?Z6E>-VFZg}1&-r+)@w?|!#J-K+{InNFNz$lFqAxko=zeBufh)(5OZ42d@vF9(exq@BRQUS)QG@1@&vX#R-#d-FR@>0Cr*pQ-Q)NCaW3eB7pdTMP zvd29!t#6|)Iq{rvZ;AmM-MQv;kmn2=lXpe%MKNBC$h3tRAQ3)X{C2S3P`huUb& zH+}WiKDi>tz4679t`pC@vljO4&-%-QTLQXk*V`vra(vceJ3GnwlG)x(Sz{MlTN@pF zmZ?*IvqR1C`yG+N)*XR*^e!e|D}jEz_YP&A?Zq>h9CPP_t$Ze*T=A#RJ73=)>3ZiT zy3`w8Y-9VS0bQf)x$XCDB5!WH+BucHcb$ejvRcRD$7i-SmfkIP2lDi#A!fTAer6y~ z;%)EUv%Th*?B?V{8Pm5KsL!=PyEWK|PVKG*8anaZ7l?~S5BVCqov$(1+cK|gw%-sO z4L%a66E)l-%Tj;PZuFGt~Uz_lvC!0-UKKEw6 z%r?I8vpSvGWp*_NWLFAH8m0?C_x{(_KQw{s7OP%Ad!#o_d$C zLtI*8c+j)ujiEQUkIp(BH)Xv!-<>&sD^IS`)1y~odbOb!A8{93J-K@F^z=IG2Le8j z^Y`+@<>UfB@oYR=D{Lc6Zk+>ktrtF!r7qCOjd-xfe3U1C=LhJ?V#_GYSPUwQ3~O^4 zu5>R_3TXlo;T+40`M zdhO;5e(`u$;J*EMYG6J6-heG^mP0nXN6_{Rup1qjwcFXDZ;UP8%G{Q5ZJW#f*6clz zve`g)-yg+%bqhM!xE1>^4c)$gKY&M#?h3@=Jz4C#f|y(!uxI4EEAx*8%bpc-4rJ~Q zw9?VHCm7|?0d(IV0=(6ajtqRBDXT&4HAV;W$WHYlKaC-o?+tVPThAQSfck!VfW|o= zW2e5**?S=TbT`M=zAS53r`OgN|2-jZ+ca(shwS9@h0_+LpuYy4hHzlFAT;y`HB#b^S@2~pG+@D zD*+k!?0;p}oyi@+T$lWk>3%Vu$A`SeSB;4|`f+W3-qaL`8GhqKfqR%gdNBqvM_J^H z$^IZ_Kk1+4JxvpFO=FcYe{dFDBOb`jdIa z;Su+)eRx_c-#5+X@5`J&y}L#m?#$jef5mM6>`9jV$Xnm3*r5K|rtdqI=d<~FQ}4aN z+#SolCkH>5cPIR#U$;*`H#nDtM{b{*eKy!Hytj4#Z{-I;Mn66<{d}E$vAr>Kx;y`o z_gZf+C+6)dTimV;=+ngLg5br$*Ty){pwGwwyEOg2 zptW;D#$>!FaPHkDYWM3xus6MWK-+W0&dY;c0Y2#SMSVXKV)gG#@bi*@Oiiu-RzNP9 znl*Wwuf1-`8vEvStHavp8~z;u-C|iAZ^@VpejS;{?40wyJ!^RBbT5ge7+PBoyt5nA zFOT%;?eU+yn*#fE;w6X9zF(@_gMpmUBY&E;QKoxH&c#{{iG5{WmNA*5J!tXsnf@z+ zuRr5=^TKyB*i&2ir^c*@^ijOuu!J`xOL;wO`A%MCvymPArn~-&i5T#2wDnId(Z{CB z8*SZ+KCx=f#X?iZ?+nC!N1*1vanj5FJrl%8dnAx!pS$H)-I`Z6`}j~j8J@fgtzS3o zq0_9b26D%i+XDC7$X}YfH=$8GZ25TbV4&5;jpSB``%|r*J`_-1(w%_L>JK0n_ z#xXkWHH-hAu>btU_{8tQSBqr7Ja89W6L=0BntJ2HU4mZQNOyBF>TA6DKhNQ^wZ?C( z2|D@yGJ`aHM-5_-GyEarG%-37@MVmjxLbR7paw1pe1FGY&$-qK8v1ty&7ZqotF2dL z?03hyH|g&C`tFR!dr0iphc&v`A*aUY255}$3)uBflKb-5)9N3(J%Jp&Ao!*%v_|pt z{*X^TTpVl*=I5#LMJLAS$eh!OH(%*J7>FyLt;SW|oNipdIm+BwjcbOB_v|Msu01Q_ z_h+JuKclY3f?odf;k@9%Ky$Y6zJG|l`L_)7W%S=V?4$p{FdyTdt&{J1zmQr`kKTWHjp#+y*yCE&aPTL6sS!(Q*ReebLUWOM|iH2u^Pzr2V+;`p>|e+bAs`_@5r1D zuK}XR>!?Z%j<-E`7+KF~sK%eLGn3F!E<(?gEt9r zok3-MZpM28cAbt5d>r+B+Y&u5oMc{*zWPQx`K_t@KC=#GEMDR#_KgK!$5jE1N;1A(=~y8b2VGO z|0D984|g_O)L9|k;@Hn67iG*>{G)F2AB*k}4Z6v#Uj0V8**fZ`_p#{y&c~peU3Bx; z8UA>1EYQS%Jz$Gxf;*^nVEsrSZry8-zVB|vty{Hsai9(~HG}Rz5YrcD`Bk|e+{JQ< zch9t*Zt)Cb=fiXuz?)s^6o%9#oFBY{jLZfbACzI)P?q%VB3V&n_B&I;o&Pi z=HETc4`)v2sN;KPI{0~3Fy03tc~mSL^Iy;UO@XtjvH5$K$Yb*h12&5dG-o|~ql`a) z3K@J@CPN&w=FK~gJn%;>{zBx6jkuYUq34fYe)WxAhKo75)}1}Q*y#DA|IpOmkzRfE zIU^q57aqRt547(|ozQn6$kqZM&EHqeaFH8y^nc+*r_R-jb#~t|t()Wj`h55F+J@&q)<$2SKAZpN ze5d6dK%6W0?+nvyS;3V7do@0+1}_f2Kk@KR@apv1{edBw z;^gNadaobN+`aOYrViLFboo82P-uIM;GJZp#zO?rRcLnZFy*+hvZ@?CL z8|9(DHlQCp*_+Xmk-tW|$p6C`i=P@9Kc{TZoUG>re50FAwf}X8rV-yPf( zJU!@V>Af{rt5^Tk0HCmh5 z(^})B8k5s63FMjG{6fb!G5EZIK4Y|R3zpHgp3Bp`pAmX-?7p+XH|ugJu0Ov8ztx1M zF4bz|pq8Ag&fkzRUHNPGi+k~&j9b_IkZXR3>!pFa#F-%9T)fx@BON{H#7rx{^S&DJ z@pV&APt-4dpM-e-h2WNeo$7Uz`^wDmYmWpQ?eSr>Q4B$y!B{8c$KdO`y+<;pca#y8 zi?c2c&iwUL&p-3EslP7$3j_O}S9BUbBao;4f#&zR^VytibvW+-#o7M1&Gz3jo4<87 zKRlbiI`dKAADQj{?dcsTrYwASmijzomuHOJ=-umjH2Tsxcjo5>Y7@O?T|7OD{z{xx zi(fkh-E&91jAy|!(b~0vv(+4}XDmm1Bg1~zGd%guQF+&7t!K;rvh`7qvpLEuJsbGB zOqM-fZFd2kqOl z*0V*n+O~dqK)*H38FKe*q*G4b9?B&+T`9YjXUX`0sq-*{*J(Xz%FyPUlIJ( zI43X8(3=DH*#FY0e^dJUGOoWN>o*7J&kp3TK8dZyC;OZE^lbO`BK{YKGKiAe{E>RiY#NcHV$8ru{iud;^2&lgE%)1-;goB_XcAex<1AMk61Pi zJ2TeAfz5{lGDf?PWG+`|V#1?hWj@lg1)%N>+<}|B|QIl10Fv8^)RxZJ>MRvvmJrGAIzQ{(W5!5 zY^SSs@o8>9-XGdT?hijkx%7T{;QTuWoo9H`=D%?ovhNC?XB%G*1-(z4S8J~bG<)U; z1938TMlPKCr>7S~?|#mQ{VxvCkncQH{skG6Z*7!!Pv+?PhMyegO6}lvj?jCCThm%Q z>lwGs@q+ta&1kI`bn0sUyxA(hc(MP@0e{89XDw%#?are+tml8+Q&V>bY#;fK%+|!A zV7DC4>%2Aj8QEJ6_}evc;S=anI>CW_>=T|W;zW2BxYY!qwbJvK` zRVHbk_vCI1zAqrB|JDn6 z_MEdH2|?{*1NrPwca6ze8Sk3b*(bhp8_8m0&jdN@RKDcXn6K{bo`KdRf9%m=?Ye** zwLH?$xf+m%hYm5Qyf4mJ-CMUWuVakrx0swNR{orOJ#^(UR-dm3)YbOj(qLae-h}~M z>%Ummc4PMJ2-qX8cLZ!$33?Yfr);hcIieSTbHdl}4b}o}Z$Q8Jvq%5H)H_$^Z=QPf zY<@@3di|AI{pQzEJ*u7$WiB^jj)zTWO>5?K`@Poo`CFP_o8F(R=PzeY&Vc|Ad_%tP zOSj-L|HjbB-AMCYGny|6jhY&1etJgp+R%vc1A(*W9Iga%#{SxUb?BT$@z=WktgNfk z&ObeKws*cQbNQ6NuKnip-DQ>*^~Xl_(!A@*(DPA`MqfH(aCY_QPyGc`?~bwnCy%FPfkDP`I%Wm!_Lw@HEZ)+pOdxv zTe?r=drS4uIMVU)tkqX%p|ro0b##1dOws>r)~%t{HwX6qPWISKhT8eziFS-}<$rkE zLr>1=J)26w5 z*IfQz9>_77n)S-7p4xM&x+-1$(UZ-7js0Z!eEMSvt~2s0G1mREFA#4K&-Vm32W-{$ z2J++iaYKOSO#z*62|Ux5(UUjQU7q>H0l9O%_{9v*H38X&0`|LK#e@B~1uMaWfkqY{ zHi|Vn(N)*>jNOm&a%-?mFWJ>=On0BTmDBsAv8bGFp#^ppcVxUCpk<$SMesMH#CaD3 zJe5H=*yHn_z`k}c5byl~8o#G(XL^mDYX)h3rjfB4@T0tBq7_#*zB~{k^~pZ9(pv4g z5U-vIF>Gz3+cC}AVXn7Nr@7vo-R638Hkj+p*S>-YCfev1KmHjnoU`s%4X zG}cQeM&{0{-kH>USJ!(#*3<9o;Me5Q`aEA-tywvdi(LU8G3N)lTdCQQE%?}=$s=FM zWV7+8ezr z(ML7@x@ny)YKk3wp4dl!d!T-93E1r%Is1BXdS}2_de}e?)DL>e9A(ibZoQM#<#oZ~ zz!>cf!P}=f+TO|Z;^&*(UL3HMZQBFwkrUm*E;QQd9dommxi-(8IypO7pZ3Jy z(qLa;4D%ZNM?;RbQiF4O;$A*u@oMeLwS4ebTjn06kfzZp#wjjTD_xIdi>}g(F2XxU(hM1_4 zp5^LpU9p*bw5=;L$rx*k9HlwLAK{5`SR;tKP%wF{(xMcH~D7IePbQpU(UK1x!=0>4Oufk z5a5OV`RtW$Aya*lg9G4di(m?S-ScA#%7=St_(kaG;t?SI}*r?oUlnAZVUJ$96K<<9i4??+DQF zNi!BZJnCE=4hCXUo5Vz3N1rlX+)3=wmfcC@k`HWQw=;Bk(6hon^2eANYX<`R;P)0= zXD7K=1)5lq&vrQp+2S4Dnse%X%>DQJ06*XC@w2()!>*ubpFZ{19Q(Y9*ZO?{nZF)A z>*>{*J&kO>IER|&2cNZN@sXqEiGDSPhkY7(d=;&}}uw^)oDs_{g2Mm6-COF*rNp zjbcDv{b$?1K286h8Xh&ak^fuq_cx}Rn)|E9wEC+qoF_RE=aoQ?yx*!#e$rRJontc9 z!$$t2AN?Ocd(fpm?SG@kBSzKG}Pe(sppS#w6-JTGfm z)8=_oBWiN1wfB#Q{A{K6ns509by+@RHQ1W%9eYjIG<|8*i8@8&nb5OUpVcDy{8MZE zSM$%F#$>ts=yTUqmb*c`Hj~$QlDE~*9Gl7G3;XCcRtxHYT|FzeZZgi+!nYNJv}JK3 zQ|#t;h~Ieu|NBgqkLv<9&Ff<|Yixw81FbZh)ePMS0y!Z!|76F>bKU&2r8!|I9(w3B z77zLAbE$e;Q{Qm zEl>wq= zLE~V~?w1FAk&B*>em?Mwpw~LyD+4mMF{fhKShd#B;b&)c^m{k>W{9yV|1dZdtjLDTJ&Hir%Y@kyigb|*>E^e3v$`DF{Wtf7ALfN zcHR-tgNNMm7z5kH1nvk*yDekQ{$?`i?K4uZw)NLfy?B|^s~2Pa9l`!U`{kVbo#{KD z|NO0=Yq9VBaz}vw|B77sz9{`I>E-L9;ELd!KrDKe#BJpL@g=-+yo^_#==)pYX0uk&?r`x60MHuv)oBmIHQ$)lG}_4SGA&-UxbKgoP< z?{`i1Iy2>a&GhH`dHv)2H%)(@jz_z3HvhEQ{KM1V?-^tF?UOCl z`^M1l$@!>$&meZ_i16lzVz-hzG`B?mKO(qdpalY zU~Jm80e!F-oIf)7%pYUC;%|)q-oU%ZYXf{MLHX$A z7v1YY%vo31C!0U^b_bP3uR6FVV9TolYxXY>_5|AladHP;8i*C0z_-35 zd5&58^5E5hIw%dB>ERzemjra&6`&<&PQy<8_Xi)&IcFD}U!5NXrR}mKYB}}_URLEt+rNmr~X;}sjk zW3&43EN^`{W9~EY>|J6$-m_@!!=AvsR{oL4{^fx?ay_VAcc(M&t{i!{qFar-Cq0j} z>UVdOug0r0!-b92>pj4INoVQVJ<{KuIr-NI8r%6nhI^(mtg&T&rZJeJT|*S zpZ*6h9$S6J{$S#>EFSZCjxqeZ6VLyM^>J*2cx+Z5U$;p-Jb&=&H$%2hp3lc~fAsT$ zJKTBi-EV#{V2eB6oz9*_@-uSE>pCO|iWR5cM zTEpwP>G|_N-y@d4N90;sg7Lirz1Yhun*D)yB|le$??~WtA9?a9 zzx~`Q7Z(L&x*JBhnJ&I#aYvAIZO}X#t0l6G)xnhkIojTU4V7ozTnzv_cL&=7vR@UD zjjnTg$#Lgt#(dR03-&KYPkK^*)%oJzd>0$?suL}c*H~tF@?DP&;wx_6Ntf{+%=(d_ zv2)Jwi6gn<+VemToA~gHu}N(3>S0;T$UKC(}~#&_iUNzXqU z{H(8=`NL-eQD71AFXzOkUtJO zes_AlmTp_dmjrTuLBPl6#Q5H6E@$R^#(RB$cXz;t+S&Wyy;);J=XjgD>oV?H8{>rj z^Mj8DYWJ!@8^^sL#1rV8P{AUM$@sIJuM^|%`;mN$Sg)ii`7WiOIqk}x()pkF_g$?4Pk&linIneS)YKwP( z@-${_sEw7$*2@BZRVF#){q`US-SYyrjdC)5lnwLw7z^KZh;8lkJDGP5^M99lYf3y< z0yVEj=%ib$UKMz6(0X>e-dbwxs$U$%s&bBGd`0kg;^@)zQGJ}w-2qw9y18JQ-<^If z(AF0JJ;D1q8I!@z-eEg3cGlF2UajcW65YTD_xVOW`#uu;fxKaflhp*t?I$q)8;lb&M(g% z{%ZofhXVC~FmM*+Tx=Wn&go)v=j>o_=WL`?y)W}Y3^%gr?(BVOaC7jSfUV6bo7l@H zGVJl)xN+E?arx;ljdjl$XGo6U6f|D=-#X0ki9==In{jJWOm{7rvyD7;c5y()G9RAu z_B8u=?0ZjgA9roEH(Lw;)kyvnl zcF?noFUu$8j&@Xzwe{f01UcCqG$+j|eaqyRS6U&SOyls=L$@vhkHpjdiXTijd=}7NBI30TDek=6+ z?C0T)e0Cp#{gK8qvi927HoGsjXMZC(?x%T8c^|>^`k*!FGln?r3N-rMRbL*6m(N^i z`y75%#%$Jn4iFP`EUdOK-#@7#HHn6#L<~wI|K4|@cQtEAQGp2l7gXxmYhd7g=7&mSgtKW72(RX4!t_i^)bZMw*S} zR1X>Isdw(tjOFl1aCM-K{+Wvnx%k9OlSeYF$%!VHc$-Uk#Vhu!0Xwa!H@?!V&bIR0 zuYS4GT1RV(*$KVmHWu{CGrgL5eV2QB_1*zC^1u09mY1+CWU}Y(;9Y@Os0od}jh=UX z7s0nt+z)53bwwt7$9bkF_4i%MzB*x3ZGL0MbnvzBoz8d9rFzuZi;t|vu(GnWsXyLJ z*@qw2f^7kvLSZ4?Ndjj7f@Lz1Z z-+1u5vL3IT^~l;A^sX|NU+0*=)yeNmgMEQ9jPD6(`P2FrztZyoJst9JRiGKW({~5_ z#;eZey!h?I)qz$!tD`otqjiXme7WP(>w@jUS%LM{;Ff?a{P^(qETC(A*q}WU%yr5^ z@7LDW!K|^DyxW310(4|*bQ;quZkGr3{RJ6|!L7kEUF^g+>JnRW==zR;F23^H`dXkZ z)4MC{>|6`9((rx0E)KQH7KqJFi>K zHn#RFn+$XN^s=80^4KYNm1|yKz9?hOo;7=;PbX^mM4ZTXuIYSsa5y+C`1C;h#9vlaKmb-gjqBuE^PpcOzRWvp$RYsc7jsUH$y$U-|f9P44aq#L1fa zd%QkvWWPF)dp{*kf(1 zWA>;6em7R=%*CsGWVF8NTMy)b{L{?=J+-Sf!XJLKO>D$iJlKbxjr?QNvA`ZX)JXT8 z#mcizo_LXWS3pPOcQ|AGhXVBsYk{`5`0t6c{fdnFNk2ai24bO(^lO2J|CIq+x=SnG z_SkrSz%Oh3=)H#4KEBZoG_RW0$z{KW7B5uZXczg78ym&VoGkNsT;;g?{HzZdF5*Mp zyzZ@u9eH$DAAUYG4{Av}cA{JOZTL{YA3m=K^{;vLyt_EqzGR=@dxCAjrNO=cAFxM! z*uigeew%k6KiPE8`Hy6c{b();*jO5Q(i-=}8CSk|kS}M=H(oY~ul=s`=|us#eApG( z$II58L2JU;I-e@9bbOlAjd82p^VqmI8b7gb%;d^CnRDLH&)P==@u9yqIdhHE7!NYX zIo~yYh#zdE>zeG1@xm*H`d3XopDK$jDgBr_rNOxjep~v zEI#(H3+UV%&_U*{fmS(m$%!`Vq7&a)LHWk`(!rj!Ka^c+_wiag608Lpxz_IrZp%PD90>ZkMSuM?=bO2|KdS#wus_h||8~hg z&%6E3tatwhGynhCyAyc5ud+_yv}v1^AYf@j3$)F>H+w=`3KUzQecPLE5GY$hH(DTp zrcm1o$kIX!wo(*Oth)j_j)S9vGvla?>!>s0T9t7{Q3Mx6aaRygr}O*1IZr%2y!YmY zO`Xr2Pk(*R@|#1b!C{#|(aUE?pwSS{4}#TkoH zjW5smhK%q3bKms%Ugt%b@5hfH#;0dYub7i1-v8Ks=RwK-i;QcXZSTu?ZD{GY=bf3W zXK?L%Q9BN|`%X78FdS3Z0^zbiq`T=<32u5YI`@gy<0;|?#XR!OIzF4t^Ij^K#{Jpr(gS-to1s7xbc!}&m%iI zZ_Qd?yI($xZyUxp4&&zyJY>Fur{l-#Cn)GmM{-vHNI!fIcnoPPQx1)COO61Z;-2`D0cg2k&Av@$f2Qt_S`-FoU_MXbL_7^Th0zj*T?clLCQxw=Gpis znddY9#{}fm{Z`|OM~%zZ8rv%ty$pRZM|TC}>a$^-gdnTpxpy+t1B6zVkzCz3$C^&VA3m ze$G8V&iOns&ei?h+qb3h_5M0DV+^*`2lw4?TUas-qX<+1$D09@izya4eHoh-C0Mb zzq_sV_Zgn&HQv3Al4t(bMsEux-}~=h|MfrLCwQJ8ptXme#xH5qUgIwb$`?NHgux+Red7xoy(F~ue)O;IyZ1LU#>;PK zPJKTkmmI5*<@7dRXY-Y9 zd`qL>Hqe@Xb(=5#yW0568hvA{y?MO-)PzOjy4|Y zx3~GC-_ge3JJ3=754ZKAKhwrP*XTWsj{AP7&HqTF|D(~bYqa9mhb>BD#>iAn5t$0^FE8Z*3`&TtNU)^Zw zdwUzdtd z`13N>-22|2jt;Ebi+>!`w>Q`lkcp4Y?mzY#pBZcn+-=3THT`XYb)fJ50o!Z5KK<2g zZ0!NTqk~NWJG4^*JSE@UV*+;7T(8TzJ4&3%msJM0drZIveEcAXJWYJ)H16%F zJe5rLmQUVSHDmkPtKAUbbElF;CcS<9uFJT5cUR8hTguNn!>^U?75ma52G%MDln%Aa;ua86KlM$ff@_g*z1o+WEd`tt$5#aJ!y;g~=p>x_U-jj#GpGVm_6xn9QV z%<-kSO)MvYX2005Nwc;+FwRH6>Aw#o4`0Q#uNAVr6CRPD+`uF60Ryans&E+gm&+8_Rxu{PV$sf~qlR*L?Z=sq7br+D8xB+k;iX!*d4f?BZK4_RH1l zDBoGG^I;#ocq(UdQqPD!FH7kU`}FRZ=%lUWUa4mU-T3KYlXkdw)KaqQu9741J8)M$ zXnHTJNB8l@;E};&gC_=jd`hr8a96!Dcx~{8;4Q&72jq!WJ#W}ud8~UJmCHVUV*LN| zx>{P!Ke3hX;_GW});;0gSQmch&a+fq+K(62YOP}JIqs^Dk3yYADK`I)lqGc89gRPD=~x{-srBM#T^KG(I^-C6hPG3ozH z^HgoRBWKyNe+BlQ6`uc{;2p{@e80Q`J~28k(3X-ZSN*%KXN5cF;^2=12YYky)ZmMQ zw+4S0{C)7iBx5c(Be*g6v*2%oe+Z6Cu|G3-Veo=YqNyQ8q3F_Duqf%>EhG%k&)lbY-e(_i@=zu8#pKDTcVl9v0uBKMDXJ7;nd;3Z>qz&ANKF0dEH3)S}yyCJ|&E}Kf1 zc+f&m#hRYcX8d%PU1VGwyULEr+vjJVUin7X1m^0wSbB=5x6K^6E7gDUXF-3|f0Cb{ z$QNQpKg++0IX~HN-1~%&PklVe^1PE@YrnOO{A06TG1c#7i%OvR4g%5lBF zsEN6NezNqd-mF!`_;hTmy1FBB)XnLEc2`jEa?ZKBlp}RXr!%1Ts;;^Za*L7>kKILC*{p0(&Nbwj~&!jrH})<6d7C*vn3`HV5W? zcKnqnruV2|V^A{tJ4w9l#b=#;?u}gmIrD-2y}fksgvEgJ%WufsY>VWk&{d)z^^q%O`vlJ9-|{*2rN4 zzPkhS-{8byPaX z+=>;{-BNzZclm3*^38WKngrTp`u_vxS)QE9UyWjNwzjp6p+^PQer<`h@{jEDqvFZ7 zxqxoIe=29VWcKfb;?B=8et2&PCV_e{o%88m7u-5yUc4(dV+`3Ze(n_c`BZdXm3^Zv zhoe(``Nc;5s@EE;9q|==^JVWs`qn0awk1$YWX(F?_KUCYOFT97GXeMGa&jt`{NhiY zkEK3?R1E9hRkP~Aes$i*z-J$=&b&G}F<2j{XZ-e?7Z))UJ29LDVpn_new`({@M&Ue zpV;CpKSn#Pm0tY&13Ju&_NkBFHhk=@_YnQEh1^M?v4wuNs1hHP2piY)08^y?kJ^b5K~y zW_va9SPb~c4`Z^_F4+|y^JH5S`;jiChaA5B)(qe1v-Z9jYvNzEm*r`E-F@tKcU;^k zo18n(Am^m^h&$k)wTCQw_@}88dbS&+<)3rh>#Y2CCehys6@$uynv+Ls@6Xye&qng) zMl1PcU#}}aqCfpvJa*RoUiKc)-l&`Y z44v_7g581hes#buzFia4@0l*S^{%a6uM608RTEFH9gjPdRw8~6)VKkL$;3;J59{NUFruj)jdu|cam@nfmaFk*xM%E0?6 zee&nLsT(@vs^V&m{q75WcCxSHHooIlZ1Bn%zpI|vXFpkWKGb6QM-Ske6_eVd{%Q|< z;c((ude~xL#k!YUJbN0CF}v}Ll^B6|&IM-%n}YJy*SlaD!;|gRiC z@9mh+*qoTDtKW?g{8}BT-(7)Nib2(Le}8=-{Np_N<6MoiG_x+*aCcBK87ZIns)@5$ z6^|JApJ9wOKI_XppWHot?rXjBh>BnFR85E=*^cWkgDV2Adc+&QRqsAp)&t~0eg zYwUPI_{CMM)DN9xYIg?ei!E~e!6;FurAsV*KiYG5F1S7*=bFI1t6z7%doo`Ny!S<+ z?6Ox*#d{$TA9hRvjh>3LGsOPD-xMeoMIx>ob- zpEb|^njdwsZ#-jbGFN%yr+P6~OWr~B?VEL<+RH9Euf4|hqHtBf*4}RUFbCxRUIHQJ z`$Fwm2;`d|M+dzh56!q_$wA55pZ=|Zd>kM2e08r~-qyub6N{=7PDn2{XPY9-SKbgH`(Jc=8i-9<+5qX{u z$SoU2KTjCeD_&%baBRQ_yxtf1M<*WZ?nABYVVnHWcSrET zKwdQCmjzYtc+LubKLO}#fsgc)Q+JvAqKgfDs(Le~lRaXpCgf{#z~++zadY4B<>Fwp zk-qZ%hV+f`vyYGTl^l9{S@z+7bRdRuiym%@m`fSw1@gdmcI9SMiSVTaNcJ*(WEx zY_^u&WRG^M+3SKnuKM!8j*2hYes*S*&9~xR%4T}mfUnoTK4bEobMo^~#P1{DKJx1f zmHa-}TeH3`AOqBi7|`Xc*t;Vj3oeL`YlAljKOFpaVBXo=7|DS8l zx)@emrmdZ6mpQQy`ak)rUE@ z+D~@PZAqW)E0MP@eBPxrx_+tCMJ7BXI5Kb_dw1x^`kKA@XVwSpWaGG3o@#Hp_pzV7 z8lTuNHe+n7p2)7VcUR;8;!w@_oZzVjY3%y;&Ms%E>=G|N-56-k4*Yx(i2sPC=10C7 zkNh<*T6`O$OI(f!*mK!1z9?hys5@YL8^0lb?N47^$kJD*`r@cxXH~rFy3DPpmJ^e`hcx$*2Xhn zPLA2Y78w1sw`xmW9}(OcXlg^NbH#2vCBwL6*Bl?sd8f0VJT}N{$rDR^OD`Uv$6o$c z|AzFP$(sYU$wxWSO5PjNzc-L$_MzUh{vbm8_bf4ICtK*(>OGf^exBav1#G!3;7`R_ zp1w0V=Ldb)1?LA#@&4?2AyAG7tD6RV0_#e9sLd2u)+=zWX0X_GT{%^w&}Yu7!ssg1?-?!<|I?w-{RWEDKi z_1zD2;jQ@fcZRcVUA@=3@v+@F-D#aaKeTLL)7Hyod-W?f`cSoQ-&`OUQ1fECIjC6O znZ8yvS90r_ba7iF%ULNo4@}>j+OwDL@@HL}_fDg~7>EZuUKQBGA3FMTzdBS?fn_;U6u7dPL;blSLE<@ zN8`i)^{G4S);0!o_xm!O-tFSLJD?MP#Y|oHdD@$Co!OGxKYQe9f6&Wg$4cb&d~!oC zd3Oaqe=G#r>w|NGO@fhz#~GiM>sj{jaV7TPBUjz=QGIO=$kf>7PB^OBAy%{UH_HZj zScwfiUmue@vj6gcZJO~b1LvabX3H$Q-61Qrlg}%$6Q3HRkDc?u=rKoHvA2?&0wJaTcM=hJwm-8v6{ds*_8%v}0O9D+y-yb=}U+X(FukRg)&r8*v z{hGU(FL;;oJ4;jDn?pz5-fuG5OO9rIbKst=eQKhfVXM-Y3%1Jnm?LA)YHMhJPdVTG zthtej72Ea(bte>$+_Oz9|Iy|A-;#Cv_|fyu@*j^@{^MaQ8GOh{ z@ihjr-x#b9#8I1duEdRAev5;%A`bGW7TBy#;W^W<*j`&ifR zvdRHJDlX1|dgcdt`us31{<2klRGdFsIjcLU>>F#K&j(-S+j|b5$~JR7U!S+Tvi8*A z+(477?-}mE?bDS5&#m?8^S{ok9G#N{$blG%D?6%|sT*;llXS!G7+o|DG zSA6`V=qVq?OHG%L>(l3>dG=~+0=kycgU9))vsQfM%mrl0_b+$nR-GLmXydtEpSg-@ zolo}n=k%7-kEczVrk^OR8_ZPYJ+f%$_T$Zb?Y@5cVWY3BV zdru3*s%$$ieXXy-+S}K8<%e%{pv5=Vd6uSe+7vqS_IV=nX~9W>W_)uX-nDP3=eL+b z#ZUjHKyJ{A;jFmUTG2kv6(eKG=}H*sxP` zR)4I!x7A4>JLl!P;CaCf!TCYu|Hky|`N$XktqQgV+gg8nsP>1^!Pn;m_XKLL&IMnM z*%G!-`dO&6GkH9r&8o-cWn2X=HB+)M3Tb8dQym!F-@z z?hG{i#WOLHMh@OpLD^gJ>+4TnJorxze({|I8ad*p-4UD?(2Y+#)J5GDlk~NIPw|uu zea!e&wL~7jeYFkqu*{DNQ>uh_Cv454&X48@53#-A(u)%5s1B({qUKg$ns zV7q+6Qnrt^9@gpCFZl#yIM2SuRk^0CV$Og0tGWIj9_Ps$`74GaFF!_J`fIL_chwgk z=Yy)RUiQde@t}7uaHiD489|+Aa_SB*y_uSxIkizTj!AzZ=I_0S5 zma1F!X?F#C19{Nc>O8VlyEAxYz<=)s8v}Z(26|m(FW>O+t>lnQkZeItLx)>`G*`T4cn{c`oD;K;ywJv+pX4(-{2 zyaC~x!j*q>ZV>3P!zxDop8qfE-tUJG&wZr|MuCuGzd#LZ}s*8Fa?oFRv z?AzD%)1Aud@1V+U?Ge-3qpyvAk*h|Q+Ecj{dou0}G&XwQ`r`;tZyN*o!#6A6&gop> z`6_=J3dK+6LYu2R*V&NQ%A>Wjf~v;o zZmBzgubLXB*FOI7Rhw0x{4>voGlNZmys_bq;M#x?7NI_g4m$??dsv;xKsM*YT!%Fedz-3+P@9=w{cUbib|f%2m&s;eFl* z&dC_u6YGOV2IN;xO22sjSr){bJm*bJ+^@^+`ST_Atk1rs^!&vVd+IKpW!qmau}9s_ z(xZmzbCkX_qd60M1GRRIaW-4q9ym{A$w8fcb(*7a@AaY1g81wTRt4@FXHvuWAG_z& z`i#|k`6P}{3^dQFxdwO8p&%c4cFf>Cea0MKcg8Ha&S=fEp|{Vu?Z=))VpZp1U)O&@ z*MDKxzb<{Tt3CAnRf4L%_PC>*9lnS)d9(P$aS zeEV3|N``Z8?(c@VOilgy_#mg(Z?8t5-_11o-Rmg6Ppp8?zKIQK^4a@%MaE*WE?5k_ z6VVHE0sF2Ds!rJEEZgI2I(vc>0=7GM=LMQRy$gXjlWmXtY7%IZ>HiO`U)uWg)S14! z&B^PUKwUbMeml|ep@7#Nq0xbd?R$q z4S(h4$e`BwV|{N>dap^}-Oql$Yz?*r_L0L6@$?KKkIj|0rTX~g!aIq2udlnH=20=& z9@qwUqbH|7H>`_korT-dpB4Y|iH`E!p4SHa*TjPV;#9t}rGJi= ze|%UKe6aa&efnj;yj46)cIEjUS=0ESPQ|hZ8OG-Z#|B#2RWjKKY;lIgQVo%9&wM~H z+sh_3Q2VXb`t9k*h3U^@Zc6{C8GK~0S1Vie=_c14d0N>cuVs@p``J@-Y&OS_lEW6f z;_{S$Y>j-emKQRf9L&;Lve#r?&62H=&#!*Zg&C_8c4!v`6^owFd_N|OeE!v)Nwzup zQ1@#0ALEF9Y%u<(Vf=r(ah4CBH+%T1(Y-%-RbXChw8fwwSAN7tTWVeGtj#(f_K{gJ ztN2t7cDD7hfzFEY73r%T`rV;obWAW8h?AH+DcINg@<%TJD(8511=@z?6z?aK5kK4+zGo$n>j{d7V=hgxGB+x6MTPW?**jjUDE-hqEBDWCSDWTX5= zE8qBy`GorHjXHyfaTjbfWJFt_w7}wg+PWAKHCWx}ta_I)Vh-oN(_D&kC?# ztiNO6|Ei4lXPyrAS9{M(U+ZmoQF#0D-i+;2izWZ@ZEkJm$g^Iu<#21TF6jGe&L04p zgvyyS0Sf^i$Wnu);@kM})af0D7> z6#s8$TyeJlS2C_#8~bbzigwA%hzU%M|>+5ug@GC zYy8TLdz-G$xR1@1O@{Y5ewE+H$Da(R_MXt_iH*uD`R?I|wf!fxIr~>_4bVIQyWJlDeRsP`rP^ZuEld?c+~#L^SF*@Rd~b@5B+k48dr?|F@M{X z%!*sK-0vfqGZriR?J1w+&3J1-hUd^rnv9Ay8PDtHYES83n{_fO7i4S+zqvZkThb?= ztiR4LKf&AUHUA@-FWJ_L|GP3@KGnWQwsm=XM%Ihp9(nuw{P27EShd>QS-R0j1@^J~ z3-V0^I?9g9`L@jUyxu2%{GW&F?-R+1m;!;&&uDcG5k z7xFjm`nvgsVf+;tm#=5Ged2lfz;{;1S9aiAn|XGK1N!JjJwMp$Zuo=ztv9uNR5tK+ zE-*eiW3^>$UhKviJ12AGx<|G_36Uj2 zWA38uA3pHC0cT^3RryhMUUlT2VuL#eJ+;yKM#tx2#X&sFcJ%xCe&3ogKK7K|Z_FH@ zjn%}B8Ixc4%`@8?d6&1fwdv!j=g{uP!=DSnV=r0w_*D5XnYF)S?RiOFjmy{L+x#_+ zJ~wn{>pw5lGrV}8-^QhDZyT4)eQjLN%ontA-Hk77<8`5Ixvq`N$NgIeUe z+PHjqaT{BM8v^y}Y^npT@7pJi-sO%-u%8urL@sFZ-8H8K?rYSY;rYD~i0Kspzs&pk zy>mt%{z;&*XQGqF_K8lK`*CZqBOp(_CV}R>c;+1$s2lcA-vvVD@KwQ{fIq8(yMhm= zqc8t=2l}_S@tL6;19sIq-P;1TYviq&_73QyS8VW$33-nVR>vrHT>NZY3}*4m;{5tRlPCVIo#9{E$OriyeGuPXXNCv$&~b-}w2DR9EJtF}$C!`i=^)d6D2M9I znt1eU_AbSrrGxkNT>5O0ca&at1bOnn2d(b+o?qM+1GL|_kTF@a^j95`PnH_;tkWt7 z;*c-xOn*OD$=H=SIVAfa*8GuqyICi3gLU_Ovj`A|3S2>7L@Rt1`MzLyR5-VxYaIWxXGaQA4lWa5_# zu|?~7OONsX;L!oyVmE6}&2MXKCx-I9d~)`BpV-{{M88JI#-Q}7^I5)m9%$v8c(cj= zx!}m)Q2|-(H7?)SRegT)i9Pnq@y$W4m%KyS-plXxssXu`H+o+a><%6h$O*Y9KgW2m z$G)=V`1I*9e@j44K2}WMA=HzYX>~@`g1z>Y>~yE`QH%2d+iHz2a~fOK%Z`9t*d1M8 z7W_ifDW_s>tz@uG%++jP59Z4*I;($M`p%P@?0M)fp1$wyH>Ph_K=(q>&$$oSRleb? zIkmJpio~D3I)~{_?^FBObD4>>vO!(ECJ=MF9vggKl40K27@sX{qN{%1(O>7X*Y9q&zw96Dx3~BH;VYZnaq7alW}YoI?{3k| z(_x+twL9u4d&#Q)ZRv|i)$9YhHFZ~fecw4*swUMx{YmGvJuLsPx*zMRj~l(}{__u` zPFGS_$9<0KY9)D8uJo}9idUZa zvDABwT4kGfy(19E`CxBAe#OJQ@oNJ2_lDr=fUc^m`aDb~em2*=N;X@__B8?hac|FC zcHq&kT+Di}dw=4{UiYW?UKcFoSC$U?O1AikuQS3X)I2J#=w*%WYV;?9p@*SwAk+-nl@ZJ~g4QX69R; z{l1>l&zsZmd55ljWZ>gt@uPUq;?oCpac;m4jg9(je0Xd`AJOQ^p?xfWIp25h$8Q_H z55IF*U)RQcY)^^I!;S5!*|St^dwYI;_#XK}#(nNT(0$*z;wGNrBEQ=MXYqfAPfW~{ zk2-UxycFL%!)IOlOyq_9bph&`EKl@m@}w_6>sx;28l4Zdc2OYj7YF>{lfD{N2m0!l zeEu7+ZexBJS6tAl9Wv(w`|wq5*8FEO2D56@o$GFKw)npgf92=Tn&_MMh__gmR#k3Jn0NA{K7 z>?^z3S8-%p*{Sb!l34X(&m_>U3hG`qU$&D~wwE8|lpky_ zKiFP=u)X|XJ3q>9`^#=Vl-=~Qn{3z~sKJ*FKkxF)jOnp1&XZyNK^dQy`Hux;vae+Q zO8Z$6zTnaDl&p7WeQh`X(Twr-GTxp!_LU86JUerI;hUN+-~s#V-thity{L6#G3w`Q zz394S)}0aiHF@-|e0H!o#yK-Tz{oVQ<}b?6iZ{wnXN#TK&EYlA2G3`8vn7l5PWzrD zz#X$8I4Zy|C-j>?Ap?5){acsWFNS*q&%#G$@BUD_<^poWoviJ_s^I7I{^K45x;F*v z*cxmL*aG~uUVe^ave|onuq9B-B||Jg9AFY?lj;8t@Uw;8Y~us_wEW1&)V`mJ5%w+w z?C5!Zz4L+Y@*&;n&ut%(@5sqL*&Bk>0{&hQ>S#Mj(t4{Tu)$@kEn=|Jg)1DppH*-gYt_j>l?iA;Ll6`gljnD7K8Q$kU zxM0w+)P1nH1fS15?iO~i-&u4wdS93it_(b{*vBXK^RGTv+P61gZ&Xa%-T6P6;)Cu9 z_^8z#RnL0+dKs%S?(cbfDz4MuF%G+cx_~Xq<+|sucwW4O-FUM!eb1;oifP40e-dc*?ol;c zu~DO+P7RUW$ILtRd?24yV|*`PE?L5tz2WJ7=w((ODt3L{+?jpaEM1o_p$orv+N!Nt z@lt!e4HYkb^tSHLxR0|l*Y9JO8sx(XLB(I4ZwzAMw05dS%R3qyYy6&!*;(VS%ou;ovFX*BtIrK&JT7A~sXc$yz6RIt zd4J}dk>dHj;p=j5ZhLC|75Q3{&kVh-*R-!c^>VkjuQ`SF;O7u~=(3+(=LTY|ITz~v z?BGdpM*V#x0{c4WlNu#Me`i4FV!&^G^vqx(Slh;Pp_4${63{7L`m2J{LFRHg*w04t zdR_Aw(=`dS(xK+`=_(!ibdX~Ye|&b)^iQ4k4)|uBZ+Q92H)Fc3iQ}4petY%#W4+eI zLM@wPi!-6^4%GR+z`U50z4~Qu#pFvfr`c0{<;(4vOQ}ukl|J^2@xVLEWOF?~_{YZH zKWF{%0X}-!!q)1G%ToGAJHxtUd@B!Prm=%ud6sjwRW49azmq_lO#gqtHg~DEKbYvG zu~}Z+0Z&dK&I%=W5@_|D6=Od3wj1vY=zL{Rc3q$TjRDzs+$&ED+$rw}H1@NDKkn&! zg36UTF#noBEu0cu9gwBY#J;|FFV43F^1$wq$9m}{cfRrH(}&-k7uTnKvgrJS)QnoH zXJWbs<=C?^5VsQpbwU4zz#jIB)1`s<(C>a-A37JD6sTkGP}YF$Y}34-k_~GD@g>(; zwBP+Bmt^bHWnDjNrq2ty%~cM(laM9PyW*^vAI|qKo{~M}vq`%RznJlJTM$*#_hNQb4Y1K&vlyr& zxfQpkB@pF9#oqkWGk;}h#Y+6eQ#@W3kU@6Xrsrs5X!$R1qb)HqAinD@^|H7XD8VmT*6{eZh|K9ILPvEQ7Uq0_uvuLeXt>5+jBbGjISBS*AC<74&&zyVG~^8)8w<(3{e)=P14PjH~-eovjKM0_*z&_hregwMphQ_L}Q`a#z_~ zca1(DZW5}I3GNnm5IOE~wyX=(WSt9k8MEuWK)W(f-|QpX`RMhk*}VZCvbFxX zRA-QGZ7~q5UWT!~hI|EHE(6K){DsRTuXH2#{yeNITcLicjxA_-m{g$Yp^FUCQl5@mPz{BWcvRD`aQ$N-QND3*h|Kt_VR~a z;Si38*j(=ZJ z{9=vY8lB?0y^X&uy5v)y*es7?HVHImU2N109;ov#52L?y^!|!r`K}LqrL)(|=J}xP z5EEne(htsGt&2OGUK7Z-{rqIlnn0`bZ11c-SaQe`V#Sa>;ITZftz~_jQ-zBS(%$-@Y+(70;6I9MUPKK2wst)LNb6s);%WVp;W6 zd(~p~>#SGain5;{#b?h_yzJs*@#5oO$tpU=;QH{;GtSHD8v?Q09Ee$s)vPgH`4Zdo zYijhWIQ)8@4RVS0zQ-+a`y&e zEq2*9{n-$E>YnpHS?5yBD=(mDrSDH88CaHhCtNO)H7hiQ(^UIaHi{J!BzRiCyw3Ph+ga3HW+h zpbq%{lAxax$1iGY>J{I$!RJT$SQG4dTu}1lca%p5dDcoE>i!{*O<{R~=N?j%##P%@KfP>rZESqvc5T34dh9Qq zv+kIxpSojuxs{h*K3Oqq`Yu*_GIcN~`WFTARdFzP;f%SRGv*d&%zZk0$*Y)(w^nv- zO@CV;P7e(#zv6vcQ15H$9^8ZX5kb`sKgA@!rfB*u{KoX1J@<-cO&;;RDX`zYSn>8O zI%yb-yLLywuHv^B|2URobwn2)`{B`nXR&*sU+3SM!KQ$$iUS_?RdFDr;_#sKHG9?A zO@Z~g`*)?kDp&|6fhNx8$i?@sEoN*RV(j%Wrw*yLc?;`=hchzGAQK2*g2t z_NE^E{>HuOt4(nnbAj)QKyKwo&AET+TnMfV)WXSu&$9HmN9uh^9_h2M@>w}E=li!^y?wTyPQ0>mR|hsMSki}0*GTPz8!(Sc)h#D#@S>;#Ub5keEh7cJ7_MjSIo?*FLS7RJ3Y8AI4w}) z6mQTJe=ky4X?or*p6+ zFhA=Yh^sX`mG8ULud`*YWYfvsl6ge>{9O#lCP(ZlpZ0R6^y4R6Q%AoMSTnDgdtXp< z+fAnB$D60m`5ODVRykB#?xM2W{x1(|f4WndU)jx-jKh)nvTlFLd_^~RxH7-6+gtM9 z*3B&?FTVorll<=MzGU5#&K(A6Yl6MO+Mv$co#{U^P=A`*bB9$NU1d?bleo!_r;Bt9b{GdoA z0ogA`Ul`aA^tdBaF897Pv}`Iqd;0lPGdAa5^J2yq&p_v^?7blU^?@33=GBlUXX^rd z?+EBn8}0&f@#>dM_kQup#rl9uHF{=Hd#AQUTJdIS8uJ@;VxzN;mwZ0E*LMW;)8}XN z$>bNlqXX?r50Ha8#l{}CdUvT9kXOEwr~b=_mBfWlo`vXD!E&)szkFXG;Me%1{`#0y zovZn>vyVg7cOQrUl{k=Dad3t{oqUreuHwdy!|}_$S^kLsO8xoYOXPKDWbkpZQT@u3 zpSffA=79edM|w4Rm1}&OT#G*$+XK`2b(Z(}w;p&jaZn$1E$g%BJ~XbmZJE0=V|(m%mKKAv z+L)gHS%ZKe4jZ@Ku>FBWAFT}#EcVi=bDeP8Mr9b@a?9nFd@ z+aGE}+DdHyOxY~96;Hm2$L>I0tSwb{eCXqVxBS=l973yx#Ib78Uf}cU)^~3BMDNCc zE%sN<^n1z>Q_yg;kHdt0BpvZI&7hfxk6_&jSb zIrz(FzUXWEp2r%y!~^9USmU2FsL2&Q`vUfgTj|s7Lif*ik(I$d#?*pI`3t z=`{9!W6V!$y)X9iYgJ&q*2->k?D|w3`&=*yG3&j-`twP4Z}a=wy~Ad4A@iu9?8VPscCmwv3xPQ{+QWXd z_o-~gqo&J8ay;+n1AD68@mre&TIIsJT-+E#&I(->Oae_V*lOQ$bupgnupf*8KYl7P zAeWrVoxF){#Q`7ik^Q6p@@IZ7s9f?%<2%`W;qxTWDu-**k9*TvtU0>1-mi@rv$MAe z&yJw%^ShA9>hszAkI!?{bLyUeJ+}q?5=(7MKn7m-M7@Wel0F_j;%7G==Lh9)*^jSZ zqX+71>Ag*KISXZzSd~p;rrGPP-V|6DYq8lCh{-}Q2{iVbBNt!UU+-{iudjRcwpWhm zpldlD^>t}}&{J~C&#GT%pKoI09hq(7(&x~4dz=4g@~3{t*%6QpUzPcH1$)!qAFy>k z80%xaYrNmr9U+!;!Igop4dN|X=C!+nagNR6sZ~t;{MmIGyDzLcqc_D+_VA6ol38== z*PM7byY}!ERWE47PAS`rOZH`LEZ^q8x>34}U)Shc8>Q3y%Nu=hqy4|DvhK4HdTCpK zN2AXT6>BwlNpMzhb9g7A9}n1FIs1v0vl`3Ov28u%es61I`Q)GW-u%6Xe*9;{_{jVX zihh0DFn;_n-kmZ1+KZY#{kr?rJKgN+<-R-r=Bgk6ZN??%kMa$--jDw}jBgyq{!M=;lWT%EDl(5KdRW-R_S-k!00tH#G=JjT7Rm!YV7=QgRzAa<^Rg7~z-S3&1tFatx%easE5gChd<=`V9TRsQQE*&VjsBQ*Hr{D9v!+7&Bepnkv#3$Wr?)$H{kTw_ea#tNoMUq2 zQXI=aYwyV#oh4Ttd|l>>C&T-_Fymg&{>+J)=lJQNlR&Gv9qCU@q}3c-CMMEKUw_A! z-|o}((Wfrh!VZmnJwN~WVjo(5<1wzgKp&28bX}t-HtL;3J=&+ytKa+o?tD|Mx8vfh zS3LE_)gFD%BkxN3d|}5$f$v4R^XaPRmpx_YXVM@3diO?8X>@&~^Nnt3bW@{S8r{~Y z9NK?cz!&dW#`4V{{WAhS>3gU3eB&Qpt$5Hg+xRh!s(th713jnFCp1cq`AMS}G)jm0 zvf+|8eo~{m8hu*mV(ULWwCsFF`edk^%8^`>r-sT`IkiWQ@XINAeg4#nd-D81W7lPk z(rN5n8Qs(9<&AoeHh*=a*EIUvM)x(kx6v1b(k*@(-TG$-FUdin=ixDCYp5Ku3-~71 zFAYzWi0OQ=uFbu?oAbF6 z-z&N~XVly)yE$KTKDy1nYMAE-{#%Cm)ouRPVcwa;|LS4hSvUWhVP4IczipVW7~ek3 zt0(-g9p=lg*A4T0!~Z42e8upNVcus_{C5uX&c69C%{&|C1F}yJ%)fq^Kc&szHOM)& z&A(xoU*G1xY?z;G^IzW0`~HJ7;aNlX8@n|&sX_B^8s;~)`8Q|2_hG)xf5pJR(B{8# zm{)V;zh#i)T$}%@f!{edfA=u&o;Ls0!@PUl{MQWg&bIll9p;@|^Itd2AK&J`ewaU@ z&40r%zpl-H<1k<6=$pFvbf@>MGycdxY@K^eZMl2=46gdVGdMkP#;yz8Po52AXw~<* z*Lg$b7v0rp{XP=Ku>zv3({XEvQ)8{WfvHH&NR;=W!?%Fr!uEq0RSr;#LkMEvf>3PV0XV#p>am^fC)Uce=qc6|o>RYEr4z3KuT5XU!<_SMvzdM_)|K~>k zOK9mKr}U`R(nD71p~Ky#jd?B||Fy~fo<{#$r$ddDj;bB|=%d3r9pm^B*|azFZ2#US z_xl?C{zl&w>JHk|_Vf3@XO28_jej6xIqG?SaNzl&jOqE|Mt`KyA8qu1gsQdre1Z4J zGFRgpGX7|QeymYW8yEFXX5WuDnLp9!|7`SsgZn}2tsKh@|@H~KS;{%mMp z_xAo==G3n<@Zi|7C)Al2kDs5hrXH-_Gpy~-oaerHszW@#5FTUm#=qFc74KilSYG9v zKV++IdHQUzy^WsUsP}E-M>onJV`mDLGgO|@^BY}k^uk6j zZuHVdpWNtE8g(bxU+=TeOrK5ceO>!nnKQpWkT><}nOM|b^Qb!swT9wD#T-4M(T6rF z@8-Sdpx$3l?PnNn_7o^xELufc=`dZD>?%+5MhY)9-N+rg^@LlUinvTvcDZ<;MK+fm+um zm%OrH{p(j=^&i}zZ{3=H<(M90GTH778doip4XE|91D|o(LXL6Sv$~DTCT?0+Q{*4r z#_Th8Z(C>IMXhgKx#R23HZKOwhZu{EX8nku?4!SI7uTBKlz!RlY?Qt7Q?{zpvU7d< zWutno_<3Hjui{rVU-5fHTQ3{xY?K}HZGYKPXQ=Esv8|U)b=JzRb#1+Dt20^li4plA zzT%^g8rK>=WBbgJV@$3wJ;rqxu)~;L*4b%X^~4Y3swaLL^Bcc77*{=slX2CPI2u$Qzt({ky|%7+~2ivd~stAnaM*VPGi)V zPGi)VFUF`b-;Gh@I?t$aowGU%Y^nI;5tF!hKi~T;c_=%riSgZ8Bj4VdyESvAgRl0u zcdf4qu5I#)r{DXitgQ`?wbEnH$(iT3MjxB)BfH{LaVUR#zwj06S)q2#xzka;qv{>4 zXWsfYo^NzRqnjFa7VvKi+$H2{=E>d~SQAUA81qvd0h`HpUdOw{9u1GZ^j2-UFU)D` zj?Aha2nF>eqW7YOdb%>a5p$9%@~!*pC|5dtSYFp4iq=>*@%t zbCY!4?{&$cxw^-km8#RLvgSTAmjA~z-jZMMzuy1wxZ@ts_K;b7>GAuD|1I2o?A{Te zr!{&;qh~hym`0s1d}CYIDm5`-p=Xf;Fv&8%~x*3JKutyzPI3U zx0D=fQ2cZ0%WcUU&o$ZBq2#l}yNGj@aR67k}9O zq39-`jeWfNp;_zsy;q7GS!{T37@hsm2C~?oi7Wo{U7yUkU=nEJ-p8?gFFt#=2j)FX z=mT+?57@ae7-iJEJbTRlecwX!SS`@E}LV@t(iPx|t!>6_R1 z%*N4oHq>*0j@1Eq?vMIR_pJ1*Hv4&fd)Qn#W{*}e`i+(+c2w=Cb$V(KeOj&0s)5l* zXI|sunrZKVZ@qo&cK+<;_qgU+t{qB-9PADFDh}lIG3))O3*_+FKpeDROdRB#?_`wk z;w4{fut%S*;#Dz|qdph*u!kMH1J5)%$-g*Y?^(fbhOy4W^D|xu>@nwi>zZ0+zhUna z8NH3x<)?DQFLVBusha24tT^n(V2zu8`AtKKO`n<~!s%?ErF zM{(Ealw)y4EB@+bRUn_eO!DekAogVsKYu^=xU<+?XW_#1D`sqcYoN^qY@wg-iUEFd zFACUmaX^2)yO3M&En->kEMlbI*=-MM%ui#~m`-EVm~La#Slo?KW40Kh#$^*~Ty~+x zWgBW-_Wet}QCWL+M2~2V~&+f%g57bf>kWKB@+)7OUn;SJhDQkqPxaUB0v5 zeCc<_jJ?O9>l-cGH?%PytZ!*_TcbM~J+09*8a=bo<=!93dqU&$E@?bz^nym6W%JH3 zdP$>CYIIkqz2c{_&pirkR8LTM!eaVs19y$H=splb@u=}x>HpS|2hN*&W_-sI`{m@5 zN1yXTpD~?u7>n(mV09qh*4blCoaLAw#{?Q#_FFI8&8f?hTjNRQGh0)2>+?j1TKmoHHLw5JK%7wb z2`YxDcLLON43#sq|MwweY9DU))c6Uxd)Qaw-_Ot8uWe&`|3`kVU0nIketc?eZTIu; z=J2k`&!qEf5@>3Me`g239UHyZT^Wq^L*F&QIRSs=K^tq&{J2+L{Z1CxhrjA-bNY0T z{H1Gs)_Ps9&sb9{Cj=J<;_a+d4${5PzptFjm^}F|{)^Jz6o}C*-98`mdQ0}m%dhtz zre8O8vgN<(L+qET2k&dghF1=?-yOz22lVUrWGv3^GIy>uZMoX6I`gdYuXxWOvjFZUbr(pgdD8tde-&)_OS(J z16q9g&Mvtc|JdKh$?tRP$Il$bmki@4WL$B5Vv`l}DaZA*8Pm$S_*CA-WF_$vx7sgm zVpwDHre@t; zPYTtX_o`p^%01|l-}|AC&9kw5s#<0rAK1qJvWw4USH)&a=BVEqYzx%!6#@BVlO;}U zvzIJ-*9G&zl>r~l2;42l1Z;L6?FmXgTlioOk4Bz3Jam=b)#=m2_Cx7q=PbSCi3c4e zKi%oqN_w5++^S5Bu~?Hi^2EV&zW1Ar{-go=NlP`Gcvtij|?e1WIV6N9KC*nbd zc+u@$xYx~=(yia?R)?iqeOPl3{5O+nbAh;hAd1Yp)9GIb_^~mN2kgC#Vmii$?CS#e zi@GCkS0FdNy{BY6D_83>&sR0cSNg?FOxby5pvKt4Uvk(n3AC#MXM-K$uqmh-W4kr` zo)g^D#&?BkbZTt9HP{o7y*Hp!{5|77m^iVWoJpY3o9Su(s^00s|9g$!`Xtb1*ygm2$ME62qFF!90oHu;pOCR0p7jMOZ z9y+W3*fOhr$=Mf>DW6(@X3UkJ`at$Yjp|o!ceZ){)KCl7Z zAM`euqkr5hrrP#E-}i!#ZR3#py)R?BYyHPECa1>VHSm9J#{94KR}Je|X3REs)+K?u z`~3uX68iB#T*)WHUB5OUON@48uXXnD%{+3H^97wUdTYkpT7*Jl&YIqT%2^;wo&@z6fl;$+P4H?$mB ztGRDVEb9EY%ji2h_=9vjA70+{{9(pocunx&%z2LZdLZ2&nz1Gh*8XT%+nqUavG(Dt zi4)t5|9BYxNjKh`_2M1RNN*ROY`f1nIw50qk57C+-OLC4aKEk#il?u8-=~|)TJ1YI zef#)l@9ID^p6H~B8yhtFba!7GRD8?EL)oR)`Q1OKKN7)bWsclQpm|RB_Lr@E+!U+| z`j}-neYVIS-^AsV;KVkTAF&V@^X?j02*`4`m}ejAjP~p9bn{0y>Yb@ycMn=u+>(K^54DcsL5oix+#}}({Lq{`d&J>igRgge4ty0`O)kW( z-Vyp3RGzHspBRXlzGsV=={s9$K>viG>Oh>U4#c?XKn|)7P~)nD%2m~Y{npEd%4yj_ zul2H}a$ok~vtBk;jg(#VSTEbE4$HpPZ5Uyaqiu{byr`r_l9=!=`P zqc5J$lUh6}(CQgb_Oo|lA#F1K{{bFHQm&j)&E3-H&c1)Cv-->JdnfFY53#SjR(vZD zm9NTc@re%{>a4maKij_c_t4jUhJ2HAc58C3PWv;d|NqbAfiqP#^KbD??(g#W|N99> z+P_pB&Wi3o%Y9kr%J|Q_ac|f4Su4JNeyRT9@-HQ4sregX&)?>oU(dD6g6)Cl*PrHh1e$wVH}~Gm^}74mdCq%BUmvQ5{~~?Qk81*7yV)J;J!D_- ztRTzN&ouRJQ8i@mUoKJqOX=?Cm+JSndd7Li^OYT66Tiy-(=*-^c!%%Z8>Zwbe&gldIjyg2d?z;QYbNG>-3&dY(e;ha zH@cxw^@?vxquUzY(dcQ7p3&%;jjDZq(YrQ2sMC+8PSKAw`ge_fJhaY6A1AR|4(E~` zXlz^`h`G-pHwPt)&cBZivh+XE`o^{IMd|l@%+Ck2=EY{#yjabe-!fxC$xO9|HZ>zJ}fLTzj2BA%}dO0oiX40z>bP{-@kw6)v8*Ex%czC zSmn%T!qmxFRA^e^-=sAr(p;7TS zKWVh=SgHO?+CI-Ka>}pr_sTYZb))6~bKAK5sQH()dCvp#-0SG88gT{`*G%L!;l(=yx{y zpBnw{M*mBr-_z*#Hv0XI{`W?Iu+blG^hX>0u||KQ(f`%xyBq!KMt`=^pKtUR8vUh4 zf4R|LZS>b0eQ%?`)#z_G`u;{g(CF_q`Uj1EsL>BM`a6w&q|rZX^e-Cyt49B((T_Iz zca8piqyNz8KQ(%9qemQZpdMB=dUT_HADKEiw$ZhXeqN&wYSiC`##eRlrY83*8vUw) zo*4d%Gqy+xTH^d`!mY2O9Y`U;F&-OLA(T-@#?v?{hZUqdg>eOK^5@?~w=2 zvA!>wJA0=dYjEIxS{u3;py1v=B7E)u-&f6l)BB9Bb%Cwh1Fiq}Iqu#0z#VdA+rKsa zQ-ZnRy5RYNXU;7FIqvD#1iJ%wfOAhD-IGAGm+Xgi{XOZ^qq!5Un|nl1`{@=3vVbo3 z@o!bLZ&&*KGXHr&={-7qdhs4L#9|?HV)*$1U5f$z4-97QKYGS~cG+8$yd#6XZBF01 z7`e0bj}K~I{KV}0@-^>%k3Jjt{`6pDV9yD`Vz57OCyJF^*ZjlNp9C5nvA)zG?W$l) zzy|Vbt>)<3*4FXJ!CWBTl{0>v+UAZ56)UklX4QduUz0w&>)$l2PahwBl^1JrJs)Un z=94+k1OD*Kz7vDj2JB&{IqliOLo)OD(DMTOouelQmj%xZ@bLNCfPQuR;^3y>rNJwL z+k!6*zASii@Xf)yf{z62qx7-Cg~98Cw+8PF-WB|K@b2KHF$jJw{XY&q5!^qCdRVY6 zI4AJ)p?3y;$KAtLLUr~3KEItP4z z=rU_34suTF#@RZp7iXPpKU?zX(78Y@%aM8K;X%QsAmN|3#rz-7!^5La)oXpt!Ck|y zM>Jg#I~||gczc=iStI9^to8GwuDTDMOKoRRb0?%v->H$|jFPv$$?NaKUViDFo1vHe zDc@;q$eIriA7|}fn6cme%bpEcv!9)lKywbY#h~o(eWJ%2x+mb9R(@@a%*k}-08jPl z+0?BWZ_b#_6$3F{9k6Xn)|T>VYunf7y?ol1wdH)Ww!O)oRTDe1=G-0`X!svFL*H0u zr!|?ga&Y<~_E((g($vlv=Z8;M4%l->@9S%^`ElNiy=CJhYrXBg?u)Wt%q|S%U+t(3a?u{*b$*jo z_wjjvCeZA`w-~;qYGr4WQFYb(RQoSnX8%Pi*njad z`!89+{!5qH|D+Y{fATW>cP+DD?8R-d(K|x52Ol8Q*gj<$*-xDz`S>}7hE z$k%1d$b8xinRQn`J!@*EuhFXAXUy2g7HuVdK64qHp0$MRL;1OT8JT-#$SgmfowcR> zynM#KrTp9z-_^aii-CNYa}N8@C+jng*iXt?@$u8=n01YBF;pI}$fo*iROhSmaphpA z`SFZ8i_Y?_IC}T0dbz6Uq4Vk{cUSuSCU;gnJZA;^%hqcKUUpS3uFV>~VmAr2S??~7 zI6!`ur@F2k~Yb9d%~zNMG~* z<$Y;y$VS|BIH{Uojwu z&*k@v+n##1ZO$5hw59gk@G0#1!cSq(jmzv=jD6}@Om1p?ef?Bjh_mJl-WjM1H7Z{> zXP>(uWIFz$bjW*2lh?<@9&L=tp3JFhO|2~k?9wOer88vJGvE5l+IrQrdMaHdi;lAS zi^E@Mj}I^J#u*;ePxdRC?DB)`qcEkFY<#a=A>XT3z$f1F;Oi^;z+U%L-P!uutXO(p z9~rRgmZq=ItNB~oe8r4BdFKQzq6J!^!_`N24WR7=YJyWX2Zfo-TSdMuj=k^(V zvts_*@KufWevt9HCZp!7CXBZQYWRd;F%UyBes18NSLeQ-Wevu)V>9P#T%L8#xp?mh z*vKET5hG(?AMo`37iLCkD`m6nz@NiTGcf9Wcr+0 ze-GvM^xu=OAOW+!)*xoEeC>*qjuI zN%_F<@`0Yc0iE<{o^|+p+waQw{9yWZ?NH}nWKDuzN8cBR!_mjT(}KDajVHmjptqA>&a1CYZ3^hr@NW;S zYyA4PmV00Gw~HZ_V)Xo#kqj)F)zJu-r?9#aV1k7JS7-q zjy3S9>X3)=oQ^qoWO(FHjOCv%>iEJyPIm@;TWn)z)){A`JlH!Q$Pd2yzKnb9>fngL z_ol3qZLD84a(w#yH-Ag8JMgm&0|13rtbvr2}BcP_ARG5Ejioe7woRgw2Y5=aM}5fuVD0!e4-5o&WJWu7Es#B--I`4aLH_ecM`-9jxR$BfQAG~dR2ZXbJcZjl1M4-k@0XD@w zYD{k4vRpHEVMiliWWG0-c)UV;JmdNV)X51m>hD?F8vR)oJ_G#%VnI%K63~a7r~mgB zJWQ}cz4KQoX9@o|!7&1!1uqr6Oz?66 zHTY`5>jbYCyixEL!8-)+7Q9z*j^KR3hXo%KTqL+eaH-&O!Igrq3a%DhEBKD!2ZEmn zekS;(;J1RC1b-HAVaycptiOkVpPy|d;CC$eeTcb&5wQ)7v5xxU^^u}&8uq}sTjGAa z1K7Vu+ULHB{97h`tAuZzaNcj?`M!kTKjGUYd~w2g$BFWGPxylpPLG@ah_J@jnF-%4 z;j625c7cS$(Uf_R?iQN+1#BECn$ z_e}VM6TVl#kwxz@A6RBS`-2k)=J(|=0?E$v@-KLU)OY*oYET6xdfo$#rXgteq6b-r5xoO`K z&F?X$oh2H!#xBM*GG0GW(^_5ZPlH`@Ps)snXeK=I-Szyu@vqc+rg=(D3zo{SkW3{I|~F3$p27?>|TT*w-h( zPwRKgOoN9#Qcd^~LWL^3H@E#A^=$_bUD! zBS0?k9~Qu)kG|(Dxxx44GMc;h00Hud(Q*OzA2u@v1>D!n_7A%l(Ci1c z?;t=1`kA4zW_FzrTb`YB1=tk*BUat`M;sWZ2!;jthrRgb+94k+1=xX|=%>fQ8v$dv zzZ**2on#$UH1?UWhd@rAP6Ldw4I+@b8cF>J|=zdetP0XY2xx(?& zedm58chrRGPt=;)KqfhOxqyK_26BPp1q%J>=Q`JbNTag0)l9vT5A1rF0No6HYFKC- zE{MKEBgf=~fuHzp+nhh*fNb*;w>I8k?NN8;#f}>94AH5*GqgY_^4)jKwC3Dp@^`gn zd?I(zPW&QXzW3Opc7_DV^RsF|Yjh0@SYx|m06&17bprYmxx|+>V^Bbz&1ZeY-1=M_ z^e4LDf3p^=H3Qg>9AwWE*f!rW=rYarBAYYR6we;&Gy02ue8JzE{_Xf6eR}BmBhy1-==kh&A-iRgf-(U~=EDwFygshhcI0GMZ zmW7@{fqMu$@Y#IG25b|&$fkCQIsDwCnIBttj-V5MVn^<7d+Y2wiKD^k0jrO<3&wIp~Qi$#7 z0I-SAOZZ7_kimWc-^JX0`R zu!8_Qh!L?P#>Dd7Gsd1@$cgcsD;!>JkG?}3r`f(}Ia~R}xtOChvfd+E*^c?5!|S+Y8Tdhb$ie@V^MhIglg+`ll7T(0yZ1^yeVhFxPBs6w z7o8Yj-&E$4SiP_K8hzyZ)nNfO&>&#swg(*Bk$p~)O?^i@=L(01 z+W3HYuq*B_5>9XMnV~I{tHqW8)zO*EAaIXrFbkhcEm+Km430z*f_^Q=p*>`cnkH zv+$XLESWPJBjhmPkG$B$;2DV>oF%64<6Gv(76$z2kM{UH=ddaBU<-M(PM<|5vWN@k z7^?+*hcjQo%*XkDfj?VnIU1WCHKUVpuAar#Z+o0CLckume};ewZ8NbWE-w+l7kQDJdGYHdg%4h2;uGtw1dh?MT4VQD@x>-= zbbP^25HRB-1Du>aN3fY-P=F3*=fU@6Z4X(D?CZls!x!rHr-C-wJfr#q)IRdb8TPzT z;GQ^A>jwxr>G-nt8J&1Or+sR$=0~){d5v~-qYZ`jC(XlvPdyGy# zzFPak0^!Oy(tF}hth%M9{G2K@{KXFIo8l}IeQQ|XK z;B&5h*NaMd+`i;*zvH9(GS`n~JCEJigkL^46*lF#zgY6A=UUv4D|`3VOx!=zA@26o zzQr0P=A6Hva^82#Ozpo!K%BYLhz)DrZw?R;Q}Ax`@cr_;Jp;4iJ;qfU7zX}f3Zbj9Q|1y_PS1LKG{c}i^PYx?If5dU~vA)f?Z_L zux9(t^XS7;<}<{fGw@J9_)1)k7PQ6YK;tT93;G9Zf+E7JCK-*v^`|fEOMBzt~?am?emMhJ|A*x#B(Q zaLvfXA7oKe*m8~Z!UvtZf;DxG4dk6%K1_g*4BvI=x9lfsjcj_Ex4-)pI)1VyA1ee5c#(aiKpeHzhenM@#Xsk-hKK6I|?{Y zZJny$G2uMpafKf~o)^%`#pZ=>J%7;e%y=I;H~zjb(^7 zUm;l$zeqUtb0+!_ae5q^xjV5DA6FI|x6qopW1sg^_VIg8vH4TQwu?2x%Uu8ue*am2 zr_MUF4zW)=Q~UYMe~U)U(YHgH7i&f)XHL*Qwi7>ioKN-+FK1l?mb1O~Y}3Bt@jXT! zBQJ3>-*WLGpSp!cp87?Lv7J-&!M9W48_jp(yITKmSlhC5;Crp;TL|YoJ~8hqKp*}* zO8d}uDKu=@RJ2&<_Mg4q-n3yo|42CJw-zuD2wc0^d6H^Z(*`ksFZ%L9$%wW3R^j$# zH}S&1x4<^PvgjmE?CoCWhXkG#MJBPOwvZp~I;Ys>xbG-_eCB;%e*r!6X$7d!e3Kx? z;GRW4aYa5ecDP;|t!?Yqqz5~RH9Y3cvuoHhbppS0)>rUt%gpnZecqRtmz0^_0O#Ii zruLXul({MM1Iq09QvdLICI;ZtMV$95xX*ikd7(QO)IaC;Dzo(u6`bcY`@G9C^Nz&) zv@-uonOCLxsDd-|oFdK)dVe3mg9Vo;*pJuzb^&o&D%hmJp_<7C`5*_}N9+w299kn_ z3<%(3AG^s3eAEIp1vCQ2aslrfeh&Vx4iW>NbBu)oWJP-p6FyIHq=0ymdw_EX3drSr z0s4*?UK9ON*mSgj*ttfSEd!m%Xao%6gdF0Jf0#$DV>iD0T^8BH0{cl{TrNNt zH3_uoaNNW)`ujc6XLLKptZf6jpi|fQhR=rx@QXqG*&i%3Yu~H0wO%G*@c-e$E`az^ z&$9%)OMGU=ZTf_c{`UZ`1!9J;40NF1wn0OGq#^IKl82s{W8%qJEx;FQLTsb@T^r<< z^YI;MN8!YS@p$>bj8D*hCOrDcdk=U#vo@XayN=jK{UR1CKs2ZU-bLw^OJy9r!uO=Z znz8u+!5jg;@&7o-r+ET;CDXR8(C#Z5@-r`VVi4){g<}SNy?}h74_j*c$jJNH?(^vG zv_G@5kH6#TBmeM_7i{Lg`Jx7YCy2FTJ8E`jJ<)F4)s3Foxitd@meCEmI^iz zFls&#WA?pgJ$!~FZ!-i@kNv|=&c;34;IqVcTLCz{_ZRqFqcww=qklYG?;)OSBQb`K zeCHJVzMpamEy{267aO^gtS9E4y+*)ropkG4jFIEV-C{kCTbn=Jhp|R;PJG^Rj}`h!=U>SHPWi0*D58{3-#@kpl(3V@4`8kv8~lig!Bd20-Q_0e5rGFZbJa0`9j# z0lX{Aj2+N<7w7DdV2yzH*hdN&ephcsvD-eU@T~S3WWwjqFzhjGA9cM@0RN5xbTY1z z53H#{Vt^0y1jBZ-9u(B<=Gnpb2Jmu@xbZGJUEsLl2Ri(&PmHkx9{fcvc4HrQ4h!Jn zOpK+_TWx3W>#`jgJTo|p{>Tqce4Y>se58k2!;9_q8NKjh6Y(Gi_}vK5gZ;={Az)y) zd6C-)7|rOvV=|Cu-2QW4n&wzUyR|(UPh!i!2JEpf^R#XR3~bE45JT)l_H;p(jXZ28 zXYunA>zWSV>&`1OO>?{~&!6>rvAI9UvkvUH4rJpC`5hKmCo#D_b0l@6`NkIPW8kOp z7-#IXeb^Ykk0<|}!;eP5fOf#>YE0gYvR8D(l;w~_OLz5{$h*lZ|G+ZQO0M}&mb;H_(=(WtnhWx z#XW1i#Ea1{h_V-omsn8`<0H6`J!2-@jJQ4p+_|QfT-B%qcT>F!$WXh3JVH_(S}V&Qs*&iO6M?7TRZ4=D6q%Dh{dxw|;Gb(#5&4*bDo-n+~XEi<22 z*yra}%yY|3AA>I_GtU5Uo*~TpmH826-m%QKXZM2RFZ|r2%#SVe+y1x>1)9;<+U^Am8=c^NtgB{rL zwQ!brw%IUKd(;{u+dz(xbybi>-?qs@4*6i%j<1Ka6SV^yt`2f06Vq?>D2IErv+#}xsE1n3(2w@rJ&N7&Ud%n&Z5*g$>J`7ciG}^@CI&HX+(q5SVz}6X zJ?H|r#EQ7wRbxSJxMRMh1wM9)2luh#!Q81fxZ4=6d)DOt&i-t3?U8ftj`04(_%G0+{~lvQzf(8VPp+GI7yLcOrrUe+ zt{xlLhiB@L;I5Hp5-Z$`0+_ZY`*2emg(5N#v>(8xIh9`}Ip ziS&wV*nY&iZ|fEJ7jf#;E0e8z^ZSwVa)=usI;(R{SCz|i8D4)D!-YCCTXPH0V;mBjS=9^J$Ovg&C=|k-3 z_4$a+jE$9JY7oEpys|>T7!Xj`wYU+Z9EVPELr&(8ajWGKT0Rr=m~&IBm8b(70QWny zd%jjPv$bFI{qC9>`x#rOno;QPkY^6}B+oWK!>FN{LvrUHVm&CpkN7i3YGJt0c_(TF z{tRxpvDT3T@XVlI+w@01c)H=kwr=>S)o%FcpKkc*n{N1sLpOZ%T{nE>tBsGmxKA6c z>G#Ns4(B??nlq6v*F==bxyT!3!pHtZ>PN>$Yoo1x*tcBPwYtP#o*Uky)*AtXyPAE* z9r3P5%wpVfj3*kmc>gbwj<&wLyHD!1PffJtWn=V6lquC6b+bPeHSeCMKLPGx>Lk|A z;zFzO(&L?Yi6P*AqqZ}De9y@I;GOu92gJ|d_>s@Vcc17hG0(iQPa>~aJMtonv07k% z!I8gGa94SM9WUoGX0?3B_}-cG-Af-h&*ZxHS?lkiHrz)m2!@8AtMT3#7TtWcIK|qT zHx6&D_vcp5wDtZD72Zy@xqXE{-d)l5?JB&TWb?b$IWBFo`FUmLjk2R1#JCf0Er$24 zoN0^UwiVuJOYU!e=RDif=I5LWZztKj-*u8*^L4Arndob_-@mtr9@lTQANv5l3y9#K z3;5>*@jUNe?vbpI-=FB@Q|3o!C;nOt_$;5##2CbS@@Khdf6PfuKF`8V^0N=-jXGkC zGe7TWK2ys{<|p30@XsEHKgNf+W!W)4*%tiD{GEJ7RxkXuXLXbxZO67OJKBycp!OXQ zdCzBwo9nt(7wFDs+UkzyXXcHzML)#ak@xT6S=egZ-?!ZnwVv%HyVkdDvd8ONbPo$$Q?+`!EA}>V85B_O z{I_tM=$nCf2e++>llO?rfPfgXUR{8`9};k1Fo@{_0W}o!8tbdpcab;usYH#+AMZJu z&()r#v39T#h@bu0&-D?XDOm@0Xa1-o^N;sD&HUKci+s*^;*WV?oq1y(YVoP{V~kIf zFYz7a!#g|<&t0(}{Z3=w$U!3@9s_08G+OiUKx1w@N6vjN^K|na-;p~1OaXTA9n(t% z^yoYR&(zr4i-c3d6V-E|&RWm&w4N>47<$$PJ!^Z^L#+K>8=u!~A9ox6(-+x)d};)Y zS}y#v1LBFC0|bW&co(7v_?(6w?pyC`dF#){o~Si)$#s+=bo9UHeV}G+Vt#3v`EMh^ z@r9XqGZPPHepieC2G4)j!FeY4%LK&X%Jknjep-0kKTkOJnEzDa#KQRVh2x`f{`Lep z2WK3Z@O=`#N5SDmE_XGbQTZI)S7z+-=VE4f_`J+MgB-GscHL6`+f3W>!}7NzZ0FU& zBmd`wM?XF+96jbgOE|eRe!6h%H2$B$$+7Wcgxd$xRu`J%L;MdZv>5Z1g|3g$>6o(y_}+t=?^u}m9*3FQW#;=RazIQN{AawS z{QV2Z562gtWx`_|?=L*Y@E?T7`2AUb+ak)lUU$YON7V!;eNtx-$d%P=3kWmbN&AY;@$Xd;nBY3woQOc>M{>+JIvf48BH=L?U1y;FGf=``Un4=)!U^Kh*2n1^-3V;-I&Jm%ps z!m~{)3N7Ygd7;I4&M&lR?^cBtZQiudqTM(A-MYTX>AafbbZDZH34D%@Q8-_xs;&n7^M0pG=Hu z_XIx1Je*y0*vHoik3OC#Jo@-=!lREP!lRD|3-88eY}<^WY7l?c*cNsFqhv)}Z`L2% zkNZCo9&Niqc(m=K!lP~P5gy}zy6`A}y>RDWrcC>ng0n^svd9;9a<@5_%pw6=Zv3pWzR==lmAypEy4+iQ-^V~F>!@>nIG1ZB@@+W|AM&Y1bYd@c zv!8$-0*4NcOmOlK?)w26_$&cyYz6myN3Ov6?v{P>0ggZ56anz;ELpLlU* zi?YY(x18Vu$Yl_j|lQZENHs9^icbWajfFGoK%s`FzNX zPt3%VdHXUCXvX)21z%F|1qEMPaLb{O;P>|^I~Lsfb}IN>&FFbR!EM*h1-JfP3U2#% zEjXXCIlsK%d=3ZSt>DBDeD{KrbMOZioO%G~^CI?AE8u$;+;QM@B>RrzgA49F@cEK` z$8Ya~BMabjC;NV1dT7DjAJiQC^a=d*9=P+`6r6jVeeMnRoqs;Rg1eTfV{rEyH4pB7 zqaVOsXY>mAECKRa1Mau|3+{e9py2MeM+kSnJyL7;+kslU-yWs4`)iTb40KUD%+v_8 zYr(o)3)V#~SQm9*UCXt$F7l5q~D&AG=n;!X@0@FJTTS?p0i4D!mFynlPf*xwV} zQbC~)uz!;RhiFDOIJS@<>>w}X4!QKiQ37c20PHctOKusf1)OgL40swA8q^1Nn+Kdh zonjxcL)Lr&daOU{wQbgikJyc$iv`pUqnk7E(nH^o?nW~M+tAwxW(&aaq0LrwlA|Sp zJ1V9#rMoSr?A;MD{ccN4$#GjuZEIUh$;&zc@h0EY&3XYfu|U9i`XlGU=h&ObIc%QD zIqd26+}a78Su=q%^hYP#xNp9v91>&VNslcQOc#s@h^gaGfAkCJC(B)=HU3XEFM8aI z16q$~k9qJ1dkz=0+2kI|enH1y{3K@B&5=e*G#qf^}J^Bhy;xqhe0 z=CzVZ@8JtS$LASLZ7_QA1sSy(Le_YGPNZIJTO;|599!%mUb%*BPi@cj-m5*GVi@cC z_Oxkp`95BZ+$%Xo6O9A%fLblZI80P8J`D(_3)*tjD-S(JUU-N4zUn{sEc&?9ju7;6 zM_`9*68W`z7uizT)&0ud{{u1Go;Lqii?4QPVLQ+W7~|#H%e1(76NXG5d}j zVoFWT6!dy;5y!QHD3^TTqjgyRrlR#Kf1S=?7y198;!AC^{*l(mT_9k;_I^AhI(7_} znKiINK&+zgn+b2LA?ky3`FXI|?>BKC;Mp@@z*+c+9r4G9HXHD} zW&`nu-Ut+u4SebpZ({gk9dHb&32bQuSq|~-)vk3q!#VW)L;{H+>+7}7dFxen^cfxY zff(X*ukx^!bJ%x->~oF%v|{Usc!*Q31#B7+P*-g{Yqf`tp9LL1PdYZ!ey=@(Zh8$L zsD)bJ9Vt4os@aZRoXb8DhgyAG-)!ykJ<~h^=Nkc^mHnP!n~;%h!cS~suG!?A)a=6E znqAn-_d?l^HhZxt`d}N8!5zVOSlJi$%;$TJzTMdI^jk@i9c2HeBD<|WiE%9^)Q{S?g8I{ z^g6ZN)&o%{KaWBt1Dnx-&B&07DZ9V1k$y)0pa9>fg&hQQ1=MG>%f4b0gYSd-!c0t- z2)NIQf%zuXU_ze|B_T$Gv>d zA%j@<38tdn7f25Ej*Y`*&h##dqwcPPsRh3eXP>3EXeYhT0uU{Cce+a$LJZi8FwG%LLfc z?RREv@j(~%*WwS|u_iXZQ*7Yl`N*?#o}lJ)r+jqMhiriJ$VPu7kh;HmE{%vrEVA95 zY``Dtr;|PSfgR+6IMWCI3_KaT8p&aFl5acPVue5K4VIa;Yt^wE zFWyrjV`b5gEMks5%#MGpo{76{_i`3}PJP>^_=oe2D90 zWsu*=%IKS+MfmO(!pA*k8BMs)Y|daZdrV+(g!?OBb^+UFf)(9@h56c96Vv4dcV;79?!_&pBW z(BpSx-*M3=WN}A(4_;(?CVt4C$md;t#}qr~3b>OS0b@WwZLbp4;&qhhwRmB7Enc1C zGFNBNHJ;CX;&I$2pEj{%h+8TzTD1vNom&@;I&7Kujw*9zPR?hE_?d`HxJ0e^jNGIfD$_X5v`M!*;l zU|*-4V|%S1$U&_i@Tqoxbcz$dUyKd(srw+tX+8w>@gpf zjkO*l=hPE>`DcIg2r{|98aq zFOJIs*+h?GBXvF?*rcqX<$9#%ohNvw3yu)fc-M%&v1<(*sCU=dY^@z*-%r#U;CSPE zypvpKo+ndpezwe&4&vGf7}!Zq+?DPU_jfJF)H`v`^+Qe6o;f_Dc;CqUMl z+xSrHuRAjS*n@s-i}xCNaU6Na^_rNHL+<-t?mO~3m2u|2BhJ{_sTYYqciSpKE%x~1 z+^^S~`spvc@HYZt10Qv_sNf@-dzH6RXV68xqlbE7j=+BlHdBDjQD>iU{2UN)uea%^ zKgbV&-3tXu)r9t2o)EDxR zH(48<7vAmp4q!;&n(q`_?gyTe(T|zJd-cOUyMBq&Isvkv#m^$P71|u_(YK9&5$zzJ zZMMV5GYeV%T-#{Ph%!3);`7)S?+|iATsOvi%H;(wIi@Ui}r*2rBT zz*e4{M+h9xXjhwT*HEK##4P#`-m5%p z$1O<*wb^zaKgmxmf6xH@pcdB%h%>e3GxQ4oz4xGCkpSK{UHHTKg#sPxIi@j3QPxb! z8WvbK@d77y)L)xDZN8HW`-0O z@0Qrg^FH&V6FIzNtPn8Zg|GIx6kGf*YCp(l?9au*XA340w;`QF2lYUXdrPj~g5#KdjYw=yfcTK}#4gACQiTbxz zXKOuy-!=d6&2~k<;jQ`2`wf225JbP>x8KMkKHP^j|HvEu;b&X^h;uD}Q{^8qLN|AK zBiKY>AJE;c4-=_D;)IS`p75`hC-PUz6FKs8DCQ5}0KboN7M#z|eS$`S&z!YA^lYcR zac-h@iTyQyvA^aoyzF(`cksIY?uvcq`=(RhP1JAqBQ;5lASc$+TH&=`Y|AOn>sn69 zQLToZYjiXMz7w*)ZT&e}UuQ{2%~xuOc+~u5k2|YY$LtZmn%~5!<~Q-E^)52d?`JRT zMiApduR^1Tk!}4sE|x#uGlzK4+nWp8;xb!%*pll5-Fx=Au z&BP4fvklmdZRp|7n=gPiB*33Rf$u)}I>i<~&NKqz3y$x$H^-QLbeTR!YiwO1U^Juu zjy>CvJ1nTh7#RbC=>l@m){kqnhYvXh#HN-5e$y~=c~$tCCK3EJw+HpO0U#LtL%L{3|c!N>iKEWaBx zS~H>yYOl=~pU?G2d|Y41caOQgu&Y;@js@S%&=BZmy@}SyT`)!-{jO?6YsYiF*7O2> zh+mFfq&uJZ!S^rxchW-wdZAMc?Wd0XRm>)01NvkB*9gZqY`5Lmx2^C&f$eM4g?$48 z`g>S_tc3w*k2|34d|SMTt!<-Dv8@p>uz!glexK88uF+e&ztHPif(Kn~-^ut{Vq1uz z&k~2l0-i@xZ5#2ND%-dZslQq+yB}N^>&53fUt8A1C(`Me+VdBC9k0lbJo|Cekz1ANlMQBW%cZ%JZ21 zt<^!4MNa5P1~O&}*auwm=%31GJF>|u5bI$;IQpkj7xm{FuIXy47i=W1xgRz!^6W#F zNxk$c6Itlt*^K|>gS=t;3IT)IOhh*J;zuK3SWa7Qz&|8F|6rN1FUn|yGmwS7BZ9U% ztHlsrbg*X~(5Qz-z-UJQ9n(Smaj#L+H9hM@ho`2CJ!~YFIhSiiLuaN_FYf7hw-JZh z=L&f7hduluhO-4b2zD0m%&?7q-}f^b9G~33;Mi&$od7o0o?Gzaw`cfj_mE}88nX`0 z@Q%>U?~vSCb3hCoV{+>Fk{kQUUFWsq@wf7OB-9r^x?ixLyf*?yGy3n{JxTBM3%cz| z>Y3i5XI(SkclYGv@5Q@%PY$R~rVB<&z2xVJYignPb-nidUchu1w?Qn4L$9%{$!N2qTi>$G8ROW6Tp-p(Ctt`L z`SEu`e#W|9t8_zr2aJ;rh(wMVZ3#0OukAKW!CQ|ncNS}xo2WM7c6NPxUf z_sm-D*Ydqa^x8dx-rDB@c(IdtodDZ?ANOm$Lcs4|QUBP*`~K}=7rtQ^HW7>X-iv+M zHCGVrYKwW>bAy=FVrAVq*YxWQfpf(B)l})k*OdZv)34Y?zw)k!?-BgDoLt$K*;In#?QY-d(@icW8Y-tqrVZLGs^5# z%j?98-kR+bz5nblwMox$zc6FdA^|y_NFHmoj@^zub)0ok)A)~%wY;qrz2>`fm3tgs zmNJ$`SEl$EqQh>sol0*jwfrz6v~=8 zg|arCLRp(lp{!X`D64M@WzC*KS({IxtSzQc);*?B);~<4tbd$BS@)bmSzA_Qjp(kZ zJ>xpv6FfWo+}>2{sgQA` zGP2g`Jh7p^x7GrktmkNr+yw&mc`qFi)a>k(7w3zgBhw#4f<*$>4-{-8;pnsveCBTZ z%nl#=eV4cgIZMxVI!lefzloq5etdHLt*;Snb`R&Vl{4s$I@{vdE#F$nBS+ho*s;E^ z*63Iu&~o%HooHPl$DhHRs}a#^xyNQ=1^6=@`Z|-z9ci<}o za|PIK`A2A7%bV+)m~AIRY-b~Uw!k%D8@ylBL*Grr4|2Gv02{WK4aAJ~4wW2EL_R*^ zJ98soG^78vzXzayuJkj{)7mB8recmbgiTqW9TC9C{<@?jT(1|nt@NVGm;TCEw zH9gD4X3mk12Wa8k>|C*#cb{Df9evXU#0h(B-+HaN}h+3;ODNz2g}38PV)S$m?}SsIkk>0%Vo>jvfeGlyifF10>>rBwwF3_j)^PZ zccUBM?X&w=>U-8_+4!=%1h{@4n0#?hO;rpXlUOT`YxZ+{*@kb_B+mtW_g%ox8XN~~ zUm=()a7>6*TP?-+kv*iqavGhPU1Xrkx$=HZ&&I5=J!P9~>_I6n)Yyo?@r*TwfA z&JmzzkpLZSa;YQuw-wmOPIjORKlYLz)B)?gwdU*sftI8F$zA)9LSLx$biqWPN!dQv zW6V*l9oy#Wu?$e$Goxp6eUA#5~s&XKJ;!PITgr&WGu+AYQe&qNipr zyw)>YYjR4C;f=bXH3I%yLGDy+*-X$@Gi$V0vtwO3M}8Xx9=lkt&^q=6F~iS30rutk zK@NGV=^zF*U(rQgvMgl882I^-e2Vo1Di^K9a*4|3q`tNFIaO;LAkh;3xfsKmCG6z_3humb(tS^W8xY&J@&Y ze2wU}z9j~=d&qU?J#=xu5aUMBC-5DF&GGj*+2_3PZ*T@aAfwa0v$1@@*7*YLigj&2 z@xj066Jy`z2mZG`r-^AT2iDbSpFupR6XHSMYB^madQBEOYWcJd^418z-5cNx^rCNA zP}9j7c%}U6OH+uL%=Im?W?v8gQ&rbio)!5M5o=PW@td1$k%Ef3@shI#= z&Gc-WT)tNs5(9GJ=RF(#PPXDVu&IF0aKw@`);B}z5kW0Rt3}7gPO)>p*r!JP=(2ot zO-8=oM^0 z_aXsxJsDYkPES;pV?rJCJ}p;AKYLkT+dbfClY7+nsbk6=&~`T7ckuX(@7h{iIfD*( z%#V(?9%<`Y``hR&=Pe7r+w4V_d&vGaqLDkFM^>lv_|ynC6LfQCjrcfYefSO@&$iVK zJ`NTB!7^JvePbD&YHzLhsQm*J7<^~_2(3B0K%nKQFKzL6yz)Jd9nb*ubLY9wp~cUF z_TBcPvsZnVjs1_50Q+*F*3p+v_en3lkSFf2XfrfDmsO|12PCz4I3#faqbY=OS?ho6R>jW8D z4!(ENYgvu>7|rOvw|!O_5su8Pi*w_hJ)*7C+d)7tao4OB@bfqJ=rQ7nJOFuZf3p#O zpM!6Sz(4Qd{$W@~{LJS)&hQSsnPzO8D`4FS7y|&V! zmNi2(@`PPA8`gedGf>ok#y%)iEb# z$iE|VioL^vT0HS>W!b}L=Y$#C<9!Bgg@7?2AP>Ff9UIVxEc79t7=r`xZp-?piHX+6 zI-Q*%6sJ3wyrO0?p*R)%RBk4<(;_H^4^wT+vL9sgHG%K9RIj>?yw)Ie?PUa?TxR*Xv|+xIj9{;Z}lGf?AHSx0WAxfkwa>5X=w^m-Qx^`HcDmH86YN?A3H& zgJVD*(HZNAXH_?6IoHcsc+qG7YWeHd4(skk7V$YO#ODa%wfICEV=tf+eE{(z#?fB# zF%g;6UhYTh(AKRw+iE`AAop5pE9V_Q<5}|F>Hb(-Y{|AFr&}Ltal__V$8EJo{BsXr z^GKm*yYM&0Y@u*+)W+}pW;y80dXdwsom1KK*puyy`Q;gCf3efJdwW1M>bF-P+G4k{ zV@>R$&0b@V*KNLZic2kyt0gn%o49T4{I%(A^Q(=&El2SCzFe<0J=-t9*X-{M(c1j& zbU)Va0b~ye&^;*NJns&EPlF!sJM5&k`8+U3^E`o{SG-$zZN5&Q<9L5U_W}X$#^~8t zeyx%0JJPSVI-&jt1k`Y+`+c4EX9|c>zFY9EmRoXJdp{&Mwf94K$p?GX0=CT->>$`x zVEcH_gYFtxt2H!g$uxAh2FCmBXrGqojK2>+9{TY$(tD||KAqiHFjqi*H3G(ffIa*n zrr4chichv{z1Hr>sfsnSi8XSGHN6AQ`)n=tyt@z+&N;^5_~ALmX0_<mbG$x?>XQQ9iOe^)_~`6wDRS=Z%0dARw>2?>$k$2j4`{)*twREscNyKfTg+PrzTx z8#--2`;CBsycvQv{qY>%EgvqM8_f*c(&;R50yY)I9Qf>r=#KSztzBo?3~*zcH!d~d^pjAI4l0lT^Do+Lxay?-8|<*m=wWm@Aq`2l=a*f-zD&J8$u zc22-!j$-XYkN1vcc}8FDj)%^7?R}aD1#<=X(g+v>0&KXe=k3XN(Y$T!XUWEvKcd>J z-4)b+?Vf-aXao%ESLJ<&ec#Y)e5T6ZRr0wOH}0%j+=yrGZbimWIWwr4^W3MtqmTvo zjzSK1O6_^fUVPq|x6?DZPiOoL;qJu7jpdu46?dd>N65da$lF@UAuslYyzzWA?%22G zsn>TW^0cpDfq>@+&y1<^Wu0Wr6hwc>)$Q$1uf5z>r^Fs#=#%vVYPw%Q-hoEI7!YuG z@$AL_T3tBLSr+lB^|R|B^J7!(J!!V+I|!Bu$fw_pE|p=tQ}WK?n&Q0gf!yalhu%%g zIrH+4LOhIPO9akzx+Az3xSQq*s5@d3@2EyNgLqP#ZFNb^YI(tyS}YwK;)BenGxv}E z!B=dYDqoQ^U4U=YNUt@wuAHN`oJZG=@kV>(8XeT*#?pao>li6(^bV&rw$|zwdLv*U zhq&}=D>AYi?81hcUUE56U7U5j#lC1n?-LOJg#z;Wx1gV#)nc?-bo;qpYu|U#e?Ef{ z=OMu&!KQ+4d~WOI@pLwlznP%d7;##|tp*I3X zuC+$Ar~{vS&8hF3cz>>w9Aw2@H^Q^7Hh;*|kO0|(WoF$7kn5O`N51oUiioC-7w1|G zkmK{%*lP?N|3+sSxt|)*q7Hm$yFV-|=dvx%$jx!ix<n3H39~`$U9w( z$#^ob0h?nT)a11J?fTDt+rFB7-tig%BkLl@ZF%gZEADmj1^Lw8Q?+oMsJ&iw?x8bJ zlZ=@6@$`1O`(1lEj`&r32GVQrMxDOPu*qlQevUQu)~nytBY>{i0%EvGfUIFbtzNMe zerCs5&IT6?z5|6XnC)&GsHx7Yj;(;)$V43?QS@3W17(Tx6kTW?X<@Q{bxTh3jhJw`M7 z?`?HGnX^0xpRS}1Xr{j=@{IR$Cfe;BV!Q7b|4h}m?;HA_=Mn=us4?zI?wndo){0)M z{H*H4+olT}yV2Elenyw)CmIjl+5SaIC+Fmdp6nMi0>(sbNA7To+-`kpi^*i{ zYIL|;{oTa07oHL6uJv!M=QbXCoS2R%ro2P2UZpk9p#=ghN56yO{yIVkz0V%+q4*2^ zNYRlK>BGXuv+1tNLrhjHCghO29{i|;uSxjYgs)5ZGZOyHgdd&oe@*za68`LjKPTbO zP58eh{CNp~e!#oQD=~RNI0Jr6!jDb(3ln}^z&q*WzGb+ldVNo#k9f8;0`iHR8G=qa ztqZ?i6zl|lal(&J_)7xbNyi=G*WEh*`n}Qb9qW}_-ivt7wbe|o?|qizyOnpfyKCaM zpG~^YHg-?1R@`}>H3HuO)3qKE)Sh$jx7Ed<_S{Fcdu1Xrhl(A@#-3;^@5+t9c2h$W z(SgnQJXJPNL>})aFP*uef3ATxpE&dHEoVCQlI6m~n)sokwvIe;y)pQChMXXOYzO#> z34d9_|0Cfi1$-p<6m9QyjU6u!a>4&I;p-FrUjav7t(Uk1V=l(yLGLSqT<}*W{8b4* zIpMEP_-hh=O2S{8@Yf~$)P(l1!@!rzea|CjJLCj3naKO^C9PWW3A{?>%Q zE#YrZ_&XB*&V;`!;b$iN-3dP{;qOWK|0Mjq34dS0&rbOJ6Mjy@KalWq6MkO8&rkRV z6aJxuUy$$*C;TG`zcAq+P58$G-qu&E)fap|kH5F%-hwtqdwkB5sMeodAfxu2Ym+@F ze(vLsOKARXz~3pw?+a|7ZQ)m_HG&xe^S8wi{|gjQ%_3 zTSKoIn$W&jpxZi0X>I~0Refh(l0r<#S1~H@F?ISh;KEI9DoF{h99kchh*1Es!M_*Qm z#&Axs({~bgCNk(l;)Q(oNuxD`bJ&sXLdI;tG6CZT)g!gFSWxpL>fA~^=7{hi>>|4!Yrw@i%|1_Q(yf@OyE-Z#L1M?={wg zg4G4cNh4rT@9d+u5ilA7I6ANa*$jGt_-t%@(3S0R4UcCJXNmbr0e;51>Mwh3_k&7o z1K)(+DP@r_eC(zMqOZi1nDiPOzyG6?nxdCuO*vP@51vNAptj(39nsSa>S$BJMC)i{ z_(Xl#Cw#zmYCZeIo%Xlj5BHk=iGAzs44ilCw;DF z4|*8%5PZ27?LWQ)D+CODAr1_55Fb8&ZXzl0(I-0ymJ1reiv_0$-Y)pC;Bvta1vd+Z z1-y6NB4Ah^@x&g-oH)-HFq~)iGUsm`-D&p)TZjSn#Wg-{B0$y*0kW)1_m$;)hR$6PZK?U{+MbbQSoW($XW&n)JJ!fsCcu|fp=KS&Ms#Wkn=J1*tr=Nf z%{Fv2g6!{F(HL0<{z7w1U02v=d*^B02#9O6i&!&O3gAT!evl((!){tTPxf<#XwCs~ zB=-9V7|}-Rp=M*h=#~i&I5ra#>~$Qtf1=Giml)W{xv0zjE)yMDzxqr4`;$g{4C-sP z0QvTT&p?be`L+ul&SOJ7k6v(Qc-fEfrS?_`7~DJPWsLRI^wFBxc8pa0Jj!`&W8PKZ z7&T~cg zu*3Gn{w6N)aJCU(BYd^*sT?EA#!dhkoQZ#z!Ou_M8|cI~?Cj>e&vh$jPszPSj_j;%YSj9OJKz0Xsvy#X$O8YIaN_HGVV>61 zA~v2TU~TKsQBU5pEc8?F%;?*>qfw6M*kht zU8A@0V^@tI9r)3mo{C;J64=ftQH;EQVqAEpbCiF{<#$)3IzS>zWx zKi`9$=ouDpwq{?O9lYDr`0*PXF7Lqx{K1Acnb<(Qk?nWNn(nr|W6u|45Azp$u#4xO z`-s}?)JIoHZtSBgg}3$536jMa65t!P&U}dA=>l}Im-`6)-fQclb%lpm0mvp+ZFy{q zSzBFp+bds^|K0WqHn>;X^tRcLJ=9OF9^4OK?!gw~N-ehOYpYS${a1R>#hq_mldbQs zN-y>OwI1|yUoof={618$iEg(6&EvuRE_lY1(apZp+-e{EGX%tpI%xz9=+sZ_Rr-V+ z5|gVGlSVT%&%URTS3BqDEqB1YatwwdwhnR z^SwNIz~04z_*`t$aZQVk**f2*1N}7}#NDyS2mA3&=^zeI5o{?2*A#KTHtms%+g)p5ewmHm5wlFVwJxxa$Wu$i-{8-Qj~9)YMf}mi8GkFj*(YZFjJ{;ww$c8u zpzRraRN157u9LugU-|P{qkUw%&!}hWIO4JIYPI(*$#1K@Z>K$K?<4{FqP`i<4}Atu zdtTpBvrOoz_P7HXLjrmd-`tydRZ5(DuMlBA* zqIXl%-;oi$)U?Eo{tn9JnqLm0v6TRQpx?fmY~$GrpZkdZLN7X23mO5V8U1(6o*I3P_BqqmyS9O|*vB)C-lq15 zH3K@&FxRMUW3QWY_&zA`IsC}FklhFv0|IKDf&6ZC$h=V zb%oZ90m1aq)x^$?=O3|*K2cBD;&bQ*unVZ!9Akse#D@GW5Fl%oU^4Q!AKK(m4*-62 zV;j$MWKoy3{C6v7>m)~LSNfe__pRg7s~^-*^rKt-_{X`)>Yv@BzndJyo}fM$oa^Q+ z{Pw%ovoq4!BZZ$LBF~l`1-zpZS7u~0^VyX7z=D%6@bzWpJ9}{McxHNuncpK~<~w!f zGYXyl*i&oH^L$+`v!G!OW@U0Vmvwltz?fYrM zuTJ=95`Ly|?q~d?)?bnKUy$%s3IFGW4<&qg!siO-^DE!Qaett9^e#($*WNt#d*S{* zoSAoe_?4<@3$$O`L)MG`ykSh9p70^zTZoU^a(^Fu!7aD2jpd|y@`3Lz&ywPVMAM=C>)--g2+qUSCqYZWsg`QhrOjq&OL==pY6Z- zrZKrY1==frzo8FvwTI4K3lBa#MLf`m1#`c^Iv1Do@eH8h!l^sk`AFgMj@e6i?1!boW89`C{Hot> zxc|w7pDCPpJy^iJf6+}Wo>lg!ZQFCpZ^rn|M=xI>TD0K_!ioR)RAfAdekuU}e!_ns z9QqH-{G&4exXeE(^YvxELGwECU;W6jb3ZNgpOyLNW&VZcXwO;t4`m{LdcyxR;m0KW zsDvMu@Bg-2knr~>{LF;EIpL=z{N#k6lrzH`DCCwzy5ZRPfGal34eaVk52fJ34dzB4^8+%3EwB-4@~$@3167- z?GnCq!v8Vhvl7lPd&YeK;TId?zfSm16aM{#e>34-@DmgMqJ%#$;YTO@UlRVjUa&Ip?40nq3Ew>7fBM;mKK(G^S0((SgnuC6XC?ft2|qpIuSxic z34dn7pPKMP6Mj&__e=Q06TWA{mnOVF;rC1Uy%WB9!lx(vk3Zco-oH-x4GI5V!mmmA zmlJ+j!Y@wvg$X}5;qOWKn-c!&grAV`=Oz58gg+_a2MMR9uM0IjRA}D{vE3};h?bJfsCD8t> z&~^>9XBOJ>Kznqd?G|Wz7TWHCHm}f@iiSUXls!Ig-twa{+n1HSJ;UC&%O1XR?m=Pi z(z0iowx)fe&>md)puM}$@EI9f>xrCpW@V6)YjR`+hI6C$V zI-Xx>`v=-#g?2!oZC7Z~hfBV{p$}&#{0!mfdsL9Ks?Z)CXgd|!L4o!w{SgVyJ|@sU zC|b>Jg%8>(qD6m?OZd8kKPlmlO88z0U!3rJCj6FfZ>azG!twLSVB>2GZFQh6 zPv;gEo;88zhHs6@S{rEZ7cKgGdcyxR;m0I=IN^^Ij=jeP9s4Any%WBB!goseHVL1V z@ZVpzp%1?ljtwUU8-849FAKD*(z%Ngeon&Qknr^hKQ`gdN%&(E{;-7KH{sI~e$%xZ z`uW|2UzYF-68?^azcJybCj5Be#PO9OW?L58s{-v6-`voybqW7x;mCPSICIlA8=m=Y z!mkw0nb(CgFHJnhCVXu<^KUxC*?%wd=|u)VZ`!Z${v>bHg#YXt8`}JhgnuUC z=Op|s!m%sX;K_;Sc?o}7IrH8Shl2`jeW2}FXfG%}pHb#_mH7jOS6@d@`@_{^b{rFU zcvmF`-zf`_L4$7E6|=*Xr~0)!G-prKzn4NT@Yxy z6xykQwpF3MNi^d7{<4QZzxw)^ucrn6YYXk8f%cg~!yjaPJjghw?3t#mX=fDL`GxFW3XK}_XPI{t+Bu?Ok7I~E$CSM@1OMtmtHt%9W$z1te}19iC-Sc- zd&r+z_Ds{(v>U%R=1c64Zxz~Si;OP^8K2T#jPLmge_z7SD6-BgGSGQyp^;2S>ed}V3BumnXfK#xf|bJ zc=8@PU!3GUGvQB2`2GohP{QXXd{)AL^_4MuFD&+Hn)b~?`(~hBSZFr{+S^2nIX*Sv z&q?@W623>m=O%nh;l%ROLFXU8JVyILpnXHMXvgJ+=j(yzLy70C!t=hsb5fw8H{Ndt zhdtNg!;{SAh3BV1<~KUzGV*qvUg*de;s&EEIdA^t!ZmS zi*a~-!iUP4n~J>YDmXun1`_X<3IFqz8_NDk!mmvDrxSi&!rzqeR|+Q{n-`n#=eR<< zzW5F8utK9Y;lH`eJXFCqEAy5`4!@(dO*s?u@~11t^j%lZ^UExpcTC8`6@}+p+H=k? zD6~HZ+8YY(UcvT%FSK6WkLcQ}@N1g(h_bgu+1onoEiQYeN#wNc3hlQ+eqW(& zQ_jNo`!A09`C}pIbX?GRP1*a0qVs-1=f}$4KbF0J3VWxQy*~uq&nvY16#nf3|G{N% zM%gpZoPy6Syu35rzwpNR@=ImdzG>li9E480?h9jke+jl+SZLc8{{A8#{x_Gs`x&ott`{Z}|J`L{K0P4Neq3mK1=`mN4gc`vA!Sd~v`>^h)2NO26&ilQ|FFP+TG?~&!T$=; z;ywP{!b2U|)+ZF2`pwR9e&Td&~dl!3F277+=7?~Js|KLR(Kws_JmH`z3jPW(7S!1xgMbP722LfF0@}>I%e~O0`2NT z!&b-aqC$(ge0QM{3-i6Y&|(f>P-qVgd`~Mh=M!7@FEo6#yj=>d3AAksZAG9>E3|zA z?I)id^KCHDt}L{nK>Ki^IhWY-mO|S%@SRX-`vuw&h30&6_JBfj{-EtxXpabI?-}Hg z?|&|Pnx_5WGh?0Ja@n)p$Um*@#pl*b3+-7&2L7!QE#50nC_K*%JWb-+t?;ZXdY@l-HBGy3 z*)t6tfB5uk@vIaQt~;u;B}Z_UxkbMM38U>HNDA{>p^EAmPIae?-EUCVcCJ z|MB86dru7Zey`Au4YaR_7GwRH!t>(5b5x-nA80euxgULMLpfInCtm*^&OE!&P6)Jn zq;of3w4t1<6Mk{R&rJBM5`J{TA0r&QUKwn7P@%ml(6%YGlLPIipBy{;>Ogx}p}i*1 zjxDrP0`1X-_QXKjRkRrUrG@8=z%wuLY*l!k5O{w3i7~rQ547)z7G+;ncw!FEF0?m> zbFVA3H;6`@Y>Uuo$CW+P=%a%R?ae{P-i7v-K-;#^-Wq7X`}mmMZws`qh!*YsOyQyL zu;)#MSJSjrWzRJ1xnH408?X7;n4VVzJ*O2~tb->O8hJz4nL*c_vS%8)zVp%B>H+?< z0{>gfUaX4|(V}lpPWYqCnfC=d_b9Zp18wU->00pBAofv1!KNk8E99F7Jd1A z;rU|VIl9oItj*K8pMPjWIadiMzF!V<{v+``KjHsc&U`JL87Q=?0`2M#Zm8>{34e!h zbblk9*{9I13AEpyKgRb>(cu3<+0!)bnzDCo+52JGJ6C%#X75b+NICoMa)vs(Poe!d z&~83&O#e>;?b z7X-e|3+=;!_SI=8s+{3Y=GL!sRgXutfxn2-F2Y?gIJp{w`hfwpC#%?`BRzkfs7 zHzfQl;rO&gIP=;Ryn(kXfdB#CVWOY z!+k~UXO%b$o%Xf&jm2PYi2bKUi}L=b@XQE2Cl{J)ll$yBh31-sc4(n(tF!3-r!p@t zvNTN_C_MKqd-pH%K;Ze=d&lg&U)kI4|Fd@|V3uBGz39_jogN4>W@uDMS69!S83+a? z*`YfLAz>yV2@t^w&|z=@96*pMKxEPz6czP~3La+>apHQ_qvG+%aJgQ`s~((i9ubA( zl>7hf`rgXw<+rPLCC%{M=d36Htm&QKcdhT+ySloE{$NA%vja`>(f{^g?QR2|wXe%s z>)$H}nzsI)Ijo)4@I7i+yGOHj{;+mVv-a7;+PTfzreUql?fJu=9Q@7?toU}HhW>|! zwT})tdtgKVreW{wtcmG^n!T^gUhCVly7}X}`IX)L3o^<-vVEZ0 zI`CJX@&E4k9Z&ng%;{+L|Lm~#Sxub2v*UYfH-F>6bFV>X#hA|LbhI~h^Cu0wt-hlp zYY!UM?%CM2r;~NR%rB14k5im>O5k@m{T}`60>2~g@3P_Z_MxxeTdm(Y_B)>Ti_RGQ z-nahrq2D?5^*hS`J|O#au%Z6Woc4E4Kk~iD|IX>JXWstK=`Uv9{?6%-X5RkJ>33va zzvr)3-k3Q(b;o~o=4wGB7jOA7<}W+_eHxnIMZP)k`>21H9|Aow{oP`Wzt`aQG{65z z#*M)b24efDfWGBn{=oG0cR~2QcfVu$_mL(32Lrb64#aFR(EN_;-ayLG918fR@!h=f}4V4!E=Kz4PF?0Rq&GF<-sk%t-%|D zuMfT<_~zi-g0}^45570}!Qh?2yMvz!ekS<&;Fp453Em%kDERf@w}amc{vi01;Ln4< z4*ov)Sn%(`*5vt~!OmbYI24={JS3O|M}zw%hH`x*xGuOhP5@>9ePw`d*C9CXYSMMj8o?Gt^UKadE>geY5W%tz? zF9b`0b$ZJ->*c4~>Eqh^$sRHv6ws;8%D$49rRnp$d}S}6w0V3M!!rYSfSllAvwqfn zjjnusb;feew$dw>{G6BW8KE7MCl+jzuU>ZXpxG6S>3?R{$wfoPdNlUOXvB2A8gQ4) zs)4#M+IkjmK9SA7{=8WC9%m2Or3Q`$c#jOd@g&g5^KK{p@;Z+UviAq%x&O(-r{}Z3 z^J;VYii`KyRz5n2-LVqyhdcT}xtc}^_45%CVF%J98`>xJkJW$p1Pvv zrl8`mBjXzbbjJcR+1RdIMGl%(ddT~?#?tY(B z>NA~KsKY(Mu7D2=Dyt+{-( z{615+b7!obi)lL-pLQ;G?Y!=w()ajo{|VjP*>3qg@7lS~sqOsiZhlTTKewBo*UcZ( z%@23;v%2}VZoa*ntCQ9~cV#JHKVaU7>LYttUs_tw+PQ^=R6-iOUsp z@U&-lmY@B3@*L`IX`emEvhU2*9Y=>6yCl%uJ^lLwd*2j@yYsa#5SN3&p@3}~Tk7sA z`R)rf>0Wz7fW{b)@sVIL(9G2v`Rvksx5Hjwr~3K%;IR>KUGUuCg@NDKye05^Uw+rc z@6L#Y`-cv)+0@2jlDWoabZRwh)4BK6#bI7|uROOh`Qd)_+}Dlkpl`UrGCEL7Y ztB>VjzihGJ+PpV&bk5yB#u#@ueUm_Ya=`wUhYxhRm-#1`;%H57?B6uZeV##ceXuQ% z1Nlbdv%Y7};{rO51Z412UA!m|3+I;&6^mC4>+aFb!DRuy%1gzoVpwu(pD(}`cGR3K zbM;*EDu13K@;wQ}u zSWd{R+K8E}d3|-p=8J*Yd4G6+;Js4JYziQ#ddK5gOT_0(gEt007W{l*?Le>)&~ZgTmN?=!X9GX^Q!?2~|59LI z4(yRrcW9prbo}*f+7-}4zqL9??6h8W;Mv1p^E!X_oh$k)Zr0qLWO)wYv2U&}?eVW< zq?A@=pxGIqS&!!#4UIFgQ68U{=Hcn%a$Weu#kgy%dc_Cm+Qr5Ui#)ak8KUiYZpJ%vbejKj|6IrPipJZKyzR4rEGn5#%+CA zXE(iVJsiyZ(6G+m_XcReIo=u$Te_6(By+ff@i#G<_Hm%e*Iczx)u*%tmX1EZV!@xdu^KmeHE|rfrx&sgY>jgk%tm=J=f{yiEZkQ+0z$Y?F&%ulj1$2TlC644d56{RG^2`|hzwnt8gRe+l?n*vhAO0T<)S?_O3~>I{ zk9zgl(7pJKVXWS2jL)3_b=KUY+XJm??`X#A&Rh?ZKvU1^jNCCB)M(jI9MIsM7^Ic1mhP;q(|K7ymK^Yd4f?X-^o;q62I%%qDF2f{ zvreBo*gaA2b=F%O7cyrfUNYU)lRzu^WAyA~J05WmBX-ntnLM)V8L&O$#eg4B_ux{- z+JQigu(j?qI>?1K?`qvU#&Uqqy@>Wm(B|rl%r*BRI{+;^)Udgq3zD}x(0V#GT6BEa z7w}E%X=lk4(~?0y8Dz0}y-VO$b0`g$xJa1k7PS1US z=KNq1TopVx_;>_WjeRJLH)f3=?#Jui}ru6LCcPR zS;vl}p(#7Wgw5psYxwFOE*th_JTQ=sk`QO)|t=bS5P?Pd47n(J9A3MaW zVr(t{t;X;_LV#9o-1EDGNucpp%~TzgPO>I}X8+1S9q?5wZ;#B<*M2Ui$DAHHW=GWx zJGCnUyz24VV0*x)BLREb=P7>89v=Ib2X$WM#r#W}H8SaPzC0Jj&6rI`gD(#7T^y86 zrBmJ>70|_Bd>X%A9iSI$c5LKxpYukBKmSOk9I%rW1%C84 zi|;4fW_stf`KE!kwOM^=a;)7N+#aaUpi`9j9uM=pJATL{YE(p|oNP4>j_%-|UT9Y=zqb8d~rkxq2# zwU;Me*7YT$;wGoNf|CQyzSvdHt(85+`-H5W9=tr@7eDm$R_ys#HCg))&KiAsb)&y} z=noG4^AjxV?gKqL_420otkiqw(tEGbPXayL^-l}fAU=->E(|z1N%x7sd{gGnP5+Gn zJ#@?O?!Y>yD!%N##9Ep-*0|2ZJ+gK|-^TnPT+ngFBzl~wd>9Jlh_6#u>JN;=x z@7^=_y_nt^)8BvSoqKb2tKT#9>@Ytt^oNH2tf4<==+7Ja3x@t7L+?8ZwCvp(Z2Rc# zw=V^6{^#3oe{1lnPuza{ZGnGB^_JkDf`1FPhgQt!=0oN3kxlHXPSDs_PlvN_UMRnp zhBf}6b${RgUsh<<3VQaHo^9EqUvsAHS4`2F?;ZO6Ltn8eopOn;_$ya>pAqyLxjx&9 z)k1RZUEtq>>jQaVD_Qo`le!SkR|MAvrv%!o0{Jbuw`BZ;KwQXlUq;0AdpI(zsk`NX z4P@UC$h9#YM}pE#4qYz_=#>|AM+3A^n$A}~w|kbN)z{dZ9y;k3-?2HF_StHDL9jQV zU%M?h7>Kuhaas)c!B+RV)~<M3hKbdH)X??u-v|haSgocc< zc(t*rnCaX2sM7}rTjBsa-Q{SG1l}R)XMgg%CGf0eFWbbdl_f;wLx!t)_PdwbSe`G; z`pI+ZcE41t*3#{s5O1|mI`l)Hd8Jb?9(unUt*`eOHEgaH z&q^;Y+CS%6s6QN7`^`La#m_xpZ7M%&>>^VWPqx<@KJ@JxKF{iQP0Y&g;w94ar==4| z=c-*(m!417#7m=-yt>PsyZZ#}*V}hjs&h@v+Pf&&7A5Y9FON}mAFxlmB`{{AI`Vfj znX8TM;p4wEbFWP+`D3rx?iggEHNRWtbxzpqJ_h#i8`&<7_Y6^u;JeA-@>|DP4GS+mDaIo%c1Jj2z`Y_H82{hk1wG1<TS~_pQ$Fwb^60R{ATK=JHuO_?qi-`ezQuWYTdkaCUbG;&8f~Lld-d5zwQe;L3{e(Yt`{m*3|FbAX}?vgkKfYTQk9cerU#vfmZ8ntVk$pug&3SJvpQvxnwjXvDSd zmhy)Wa$N5X8BWg~9nR9BfF4aQtUWAP4Ah)6fd+l;Uz)Lf?_Ji^F;-ydHL)jnEft!K^9pY7vx{!=5b)!D|t7+QU5?d<5Vesv(fWlP=j-XB~Hb>_|) z=pU11acb{lcJr_GBh%Gfot80Op5c|345y7P=SD!~!}-wm2lCwBmg>4Ml)yj4$iZuo|FIjCByJ7pqeKykwFuhdys?A9O9G|HphEtVY}Q zn0C@@y6=fE>gIwj4aD;Fpw{IAy?Om?LrE9(We5{tP4!^imT&q9Pcg=b= z_4)s+rl!vi?@4#1rs`cbVoq31RlPe8Y?}nyfj~{wJHqCSL5(}(hXdumocENf{dWCV z^HN53-Jus}te(w%PTQH@yXE@>bzgMug580$ir;xFT`wDCnmdzUl6fnS9qz6A`3L)f zoV@{=?r{3gNIyouCF?Eya^~zS{tTzKI{Vi6M6SErnbqo?i3b`o+56<6;%N@}tQqs2 zZv4)@v79?!VloLd_E=vGCV_^&y(>=6+;fs`OM&+e%^m***<>63S$uTt3D~|pSPt+$ zY=gYst+a|s^(%MK!nB6mv7p(f=i=yL!`O33tlY(HW7mOUeA6&qNU!Y(4o^pUA5NXB z6{x$te6Ltc23mTn9=)gR3+U3y{_0yl$34@?1A53(CuMip+REFMY&$QoH1sw9 zbo4P{)$bL5w@l+vwV|))q`bIGw4*_t4fTjdY|y9+c`U!>5Y7Dpc~b+IWTA4TmlNl1 zcltd6`u@zZPyC#a)wvjJ+dYI|< zUl6!YYOQ~+imf&FZ4byqYcA&Idh;#Ad|{Zo>zoa_RTGzGu-@6Aqs|6?s5n&KuFl$e zSek=oJsI=tN6o5z*Jezw*5<@>PixoudOsukv+^V+i$Ue6=98>x2Lkz)1M!lR$^n^V zi~r?w#GjmsKi;yby_=q%^?4u`^U&QDny6Tf|B;N#P7x3T&kNA(i^CO(gIKoDmIq{x z?hzwd-VmidU@d9qfa{!YzkT#*3SyqYwzpw<@<+&N98lgsd?9YVIZE541w7r$ z%0N8CruN*Ay92TJvp4thdUQU6k-Hupd2%yGXT8-st%t0&_SJn}w#h{=Ye&`&2ih&k z8=CT|diAX~)QcXyyg#S;T*05Ep!Hwv$#>c0F0x-T7BVKod4!Vtk^Fp*%|Q3Qz?slI z2h7Z0(7-DD&|e$e9B8#x{R;m*r)QDPcLvTe+ugN~3$&77Jw4vVm(p(p&fZ4oH$uzq zl={?ee44wUVrCDG+UA=)Ed*mU&Hx&B9r`gE`A4HC=SV=8deGCQj-0{AMftJx1-WlO z@5nd%4hDw;e9HlP_ct4y(@CJUHBWDS*Xf)*K7#nx(oZtiiVqz=^-4b7&YSfo%)yVZ z-5ay`uU&)RIb^%o@byV+(8{6MsD-@&AD07nitqc}QRdEA zo7ehz_7z$89=a>Q+tc7b8Y~5qK&xkJ)rU29UKcwjCTWxD|5xg4Q#U?6b8(S>`s-QU z-h=)e6u;P1wIz3b9b6xsRacYjYX<^4+d4JBHlW*>ezD`j;0{v{1KXy(6jsAMJOf00$vX!6vgYAgY#KAMBY<|iH zZ5D&#ed?X$W&b4L@0i_}XPwRB`;ef1)`72bHOW{z5Xk9ifxOnd;%ZOc?TIC*Jvx>G zXYI-WAA9_KM*NFM?5kF-?GDO@8!|3^7iKJd z_LFfeVAmvAD{g!$+OpGGb>{i5zR*kpt!UW5hZ~dANqTKE{r|X4>?VuMBLRN)sY~bD zx!fICwlR)FA__TgjEK25L_Sp{B_61`+mks;usk4KgUio8>G5yx9IRmv$PuXYR zo_oo@`oMQ-pt0K-m}NIxX4##sX*|ePE9k_h>WgoDOsb~M9$IJkMA7zklTRH@T+< zEp65Owycx0ClGTs^)awd&WWt!v6|#tTa#yG&So*NUUk>|ZLg2@EPv7QgTGsX9YOE! zJhtr&->1X2s*&~T(SF4XkGf;8x)6i520xXxCbnWftJd5fn}a?l&K{ret5G!|?^ToS zomF+iS1~AG)e%^8HsoHf?#L6LibZ>t+B3J-S*p9B{A2H3@uO<&Q|*WN))|qfjrt*8 zVo`TtUyJ-|@4-)YUaC&+Y+lNrsw4hXowW6|J?m9heLaoU+*-ASzH)GK#%iFiC7(R?;$#;fZdhuWjyZFK;d103x zZ^hTXH8o_v>S&TNd&%W<9}j$V;PF|AOwT#6zAsphZ&zsM<=e=e#2>L?qg=UzTi=dl z4r6s9b`{qQr!}^H=;ytg)TP+(31*#X_K1&I@lB50w`^xa-EX}Qm3Qmyvjty!PVCiv zt4BZPTiwg{(N#`oJ=6Kq`o`|64Rr{7bB^jP@RNP~e3d7YVAvGQ!JSn-Rm6{}4dgBXZ8Iyqni z`TW`zjQN8OP3f=rOtPjO2*kYCCGK?5Nl)o)WtA`X$*(+#1>Ti=aNFwlJaQ_IZwS6C zcz3Wlpo}oEzK0o^WOUItz*qRx=`*M6TLb!cClD-Lap z+L(|hC*r~``ETQbk8XKIYoBcKFWJ^=+{;!g`vbPllFL^z)!-~S^zRG!I!g}w_`DJO zwuQdz>(AiI`Pn?x$47TS)hz$nOJ~KqY(J2-g#f*LqOE-5Aq!u{Qfwvxdc5+`+v1Fn zLmn9=j|@JOw~_mR{ELGx3%(`z#o!}>*!DUq|5c0SGr#2<*e32(lg?m$m&3-2O?zKd zt@sX(e|rMH^N$^Tl<&R<$)=0WlH2NNVU}0RJ&l^Yf zsDTp|uWgal$7@!-&wHmiM{=PC_6KY|7#s@REg&aiCMRv}$j?UZkxhxZI`nzsyx=jx z7X~i~-WdFF@V?;hgS$ns-=BSS@bus-gVzOb3zoCb&dL{?YFuYvOV-%UCwY*wHdb}d z@T+*+x^3lL9-4~HTDdQov+`YMxz*FwVXIS4_%JKq^Vm&>nqA9ww$5u$odb4>c^}g{ zNA&V_G2j!h*IAg??rou6%kI*puY0R>R-D^BRBq<=)p_V+e>7`t{m*N|ygK=@p3c@M z`qg$D?^@%p_}BYxpNDyEBEPq(Jx3LT)`ni!ygBFFoyobnS}QL0=k=GZy}$G1U93-} z9qO#Nqm6sj^SrU;e;eCYR-eO-oKyGzEV&!C(Oo!8)?KmDGiM&T^FA}TMBWtvn@a8{ z@0q#s=ZemcE_L{X;HANB!Fz+h3GR_+;<>?@Oj@!BrOHel( zscka%2jVwRyjz`Bi*4-NJ89mSAxGp}N1?81=gPcdw1cq`luO2K}>={yN`$KM^r{^}gox}J`)ee3q=wqN&( zHFZ-pYp$MZ-q)?~ulc(z;QPFBSFa~B|9)Q8$9*GbsO*__cI=Oxu@iBId_~?e`wn@<;u; z1g!Px&@0SN!a2 zt<8V&SG-DZ$y+N1-lf_YoG7{e>`p7UKO1GUzCL&K=k-LLA90_z-q^B{_?>wt{H)sH zUz?k@Ci+_4720`yXlrkt8W8t3S9kRsv~})$w0>3I%dXx}v7firJr6gMtEI-zgBc$R zHVsgpY*qjA;vSb9XR3bQYklQs)hmA&8~%p}zF&H7@HN5L2j3O^RPd|8?*$(XrvJ8E zlpPM}Z1s6|i;?#-`l>$I(|-QL!{3TsTRRm;Jm}<;++G(ST3vfHUkvaAemeTvY~`zu zR({{JtL*-6gHL2K)nzx-ZL&el2P zc&}Jb&bB$_jKyqLKKLmY>-p)~y`FvU(Dmfh&sf&7NByoRM~*k@r`ldmE}D(X<;!|< zo#*x9=k8fcj`~|qhO^kpa3`>@YPY=u+I#fQ+&5~+U9>-tv;J;%U(n5l_Wc+S-T3Q{ zwO{uL`toz--d*`Kc53jP;3Kyw>$(+20vdefm4Et(RRzSN_X&*=ld>`;*eU zCHs4VlLL7W3--2oD;aucy|tGewXQF@-FULeq=p4&dEG-#$qLARZndm z*tc~Kxof=(h&MUg=8#kO)LQn;^KRlSt{1O)-c7`Gqw!Kx>*YaAHYyj-T5{FjdOkbj zt&H{#V0U}2+Ph|>?*f%`dE6h6-QPbe_sYue45@E+T@W~rtzBfbcM~7My7OH%Gs##x z5I9q_D;V6HF#C~tnHuA3I{M0?lu3k?2Jgnc}VpH8SV|O!|{E|O) zQ*!CyBj50`mn=H)=-H2VXHfpvx}L1sU(DD&cOu@G%4T=Po&Ih}P@#gx5d&&mlJ{-8s{uX<*xJuz^XiF>b89h2SHMJsc@Gre^x z-}k}tbW?C^@YZ0h{HmdO^1ueRj^#j1<$KH*^(F82^?YsPWWQivjaHo%U(G9~Y@t&P ziz&L+$4`end~%*<*>p5}VxSf(7JOxUo#U#V+P7XYXk(_bRerw4qH6F#>&>F;7W z0kH-3D^`^wIjs9fj4OU)_phI)IwO@6y4Q*&Tj-**x?Y0acGiGRd;+_02J%K%{d~}z zPnE-C8AF|qHdbOOALVb+^yjqh>!Pc;h!q)PqVCz)+rILCw(|RK-hnp-c+ggz%B!4; zL)B;5&mVjB=b$DTYX^cY0eR%GnaqjRZFAV>hW&d2x#3?QgElwhiB}s-JZ(;T zpUb|A@hpBdKFdEm#Xn}B%8}=7fgG!gyi#k+a>QF5m4di8eP#6AM zqbr-;31ruro)3I0y|tz%r`>Z-mV#L|ReI~}^s?0fJ+t_aWe-~W>VC5(wymFKqrOmg z^Q`-CTWIA)%)}m@CV$Q-9pZ~d&t|AN(BH0?P1Y_AG&fc(#iaD3+1|`sd+^D_p5Wv_ zJX@ctw(ysZ#f37GE)mxiev}@J3b3%Vx-$yf_r|x!#jve#*injN)?gu*Uo9ipb`u2?T zx7O6Px%-tZeeIPT{B;KAtw*sgTdN++*8bd+Nk5*d?=~iVt&44)^Me^53Y;Zq-_Q7F z&AmwWSY41sznrgi9?(H+yO^`v`o+PPKsyk)1L!WF=|@*O@bMK5`h}qPg?xOKQ~csW zMm?wGXcB1Tu%VZ8ZPw(lw`VbH74NcPIcvt7gObBG5I_3aC1&hmpV*N#YkX<;G;+5E zC6^8$k8kAhhYs@E@g#GN3}>xmY|0qMVpTFG+1K!n#i!?;r5Epm1G&{dX6WnRnD+0v zT4$TS{;lb68|MBVTvQ5usJsM}yzUIBuxNK1~&-~ZpefZXYIez}) zVII;|y_cG#k;i8G*h$`7{^!cSXIJw_W?uef`=ouJSeYAFYg^tt0}|E0tJ zX<4&(#;_+Y4{zih8TQGp@y>x(o=+ZVeRe6?ANM<<1KkU<5&L3s(kHg z#)}yjJ>HV{=0V<4v-Ya2wYhu2Ky!9O^QeyI3kI5V8k*f%Q=bO{jm)zGIngfugWGRs zhxXC@BloS&j|_8r{kiol@qE$vr55>Cbmny~)yhvr)+y=hp0V~lS-UX(7pBl#zKYAY zboRWyn}78nv*@qQoX+x(kB|T3JN$c4_MOY3-#YNKsXfo?2c5p|0ngqK|Jm{J`LWE) zPxN(dR-fc}XYZr~h=N){3^CU1YIyA$VJ8TD!j@KGC7^*IsWwyXdyBZ~ZYZ zIP1o~?^P%0HRsrv9OtU;+Nuw+{mVaE@xT0&)9=b!&C&c#>Z`T=?cMy1ne(}F@)h0w zGl%`M7acvPW}R)t_u&uUe*0JreJJZ}W`D)D`tqq_)z95u^!l8l-#heU`L$ni-Ero- z12MI(iK(@Vf~TeCpP2r866AyF4+Y`{?i{gqp4cXy^;yZjxtPj}dud;wK6^Q*WUb^Z zX6(!YnRvDYJ&$_}4;$zy8|dQ)o%NZFE$zB7J!Pvr_51WX2fg01mHt__W@~z;*uYep{hL~A*{;jhcDyDpE z_v`Z*-)o&-ao7>`_S&nOxGS|aPn~#I;M1m{t%I_;t&g&KTWEWm=h5Y?o(Nr)i?MuG z9_6(1!8dcUuY9qCZ|!>dEPu6LKD&2XpO-T~5RlQX)1}7PCMIf)46&WZw#r9q8-Dh- zcJYI~YN)sEuG&y}`c&A^p0$cO-`KDiR1QzHEtLy-DIMZ=SI)r7_e(2(mO$P;ug?s~ zEq&_39v|(=-^sx&8t=^O(TGz^qh9*^gI{#E@n%P@>&X!dvbF|&UDy3jj(2JFo>j2c z^Qz_B720|EE)VT`=cvwf>sMPx{F-%ktoL=r_p$TD=Pdzy*tOAf&F3+Fvux|_U?;Fc zy;KdciH~gJw>w8n)PS7S^9COqK#uzyuwzqzzG6wAXB=90Pb;hLO8RS^PIlAV*N(l7 z*5tPE^mdZJbwobD$)`tboHunRHsZqnvYB7Cj-Kz@%K2USv#)$|KFqc&uf=h$zg69Qa z6KH)-)R=e6%0r!_$`9ZA`*laww2DQ=8;`w;Cz{Ixv1@%)V|~8GhpsyJ;@H#Fp0m^M zZOt0JRlj3?;$b7&F@MX3vAc=v@|!Pwsyw$b+ne=1W@Ea_-jaD|?B#1~*H}K*s_!-@ zcjdmSzvI{4CP#;YvxD=3hXs!gt`D9Qd{ywZ!CQmx48A}3(cnG7a&RCxInY{v>ho*e zZEMA=>O>7yeOH`X9qqW+hfl4L)#sC}wd|O6o=TR!?8$Joj@on7)0VzACcTa2D|^+j zy6eyGJaT67Y$WD&*2a8wcFGSnx3pttg+Fb)idVe)x@h;>__R4|Y3?e2>G;%~vz5OW zlrQH5=LeSu&ewB;R|RhlzB_nl@C(5Qg1-#@B{($)VllWRcx>?W;Pt_`1@8%dF?e6_ zyTRWE+czgS!Dk0&2NwpH1dj-=3zj4EKrnV*y_;_dD(*e4yXUUnq3&z)>kd7Vu{*KO zk=T^}3^)8NYR|D6ZQoDS_3j{H_)pKGvWqR+TIU8WISKdbJFI)h`eNW5>-#fVK5tZZ z#pFcs_c3p6?`^KTXUyiRm$hP1XSKDx&3CK2XxGwN_fEyyyzCJ3%5m$*M(vw**Y$ZX zy=^_WXTR#xi+TQ>(|^z>AHmfSiwZ5&(Q+p~0MZEMd^**(ifIjB6Atz)&r zzp{B&e%iR62pRNk3FKES`uBJCmalp>i>GR8(~SK#CS&}yzpw^BU)iPI8DGV{jn|3D zHJO#qS#?=@E7!B?vaQ3GraePzo%^Djr&e0|^{kfzwwjkL^UCd=IWr}vZ0gT!`<-mR z#~v}cvvF(vYGZq6Yp3$u*3eiSorzu_ANqT!r5TeWHZ4tCujI9Ps`y%K?~V0rUF-c$ zoa%md?tGS#6X(6Y@5ylZZfE81-txW9S%E)K_3+@Tz;`=O4W1pmAb3gewZU70?+E@& zp!Ip_<5fP^I{G#~=HkLeH0<0P$Xj2#+p?xr+*=+pp=ieBvSp)kmpZv)y5+CcJx1ft zqRd0HQTzPdc0IY?+t#Dm5}J+bR$m+CQRi#fB6jV*JknD!tvXUC#%tBr!R#LjHVqhi zHj>@eQJs;^%{m+C(c14s@j34o1njFbli_jpx{LW#&w(*t>SrHC)7~3(o}Cl%tGk_F z{r$T$YjRSbx%tu4)Ez~h*2lQLkI+_(`*l9KH?=z>gRQNMvABrwda+XnMbqb;T@^pM zUi&^=`8#_2oN6hkJMrR-uL>%^&&=4J`10V^Kr7qZT4ED?rrt^XZ0#HK0nJ9w_=&oc zymPK+-^q8vK6S7WpTwoLqp$V5awo0aCo4ZA^=EB%1!{Ox(AKWAs&?yK+iz>x8D-isdd z-}}nsBWS*O?=zCO^g6totauI-|&;& z*B@DOidR16itP3?PuV8swO+ciH2wVS?*#B25|HP;>rmk5^N$RC@AS;z%YqjNzH`!g zU)uXv+{&MRoj-D*Reg=!6Kx*x)bo-3{48Gb>u%bVaj%apy{uNhxEv1fep7y@kZhR6 zbE5UD@!tQ|-|`cUS{(DIjm^CBdOw`^Hjd_1&sB?b*BV-L^(xnWyx5_&_R9@fd?_E7 zGj?B&)p+}C^x0RAE)S~i=}`M}Sapr2)>^xJ`?iJ-ZP`a=-HZHU-*jx$-xn5Rb?;svS3G|t>*jS%N(P;`W{)j(R*GkN_}$}dP3uS8 z*;;h^;uA}AG`{nyGw#`MT(-#3zYV`?EmMQo;zuCn!?^E<}s z#hi|x=ziz;Zo@oVtGvBT{9;!!U*7$m@{bR{XIwHS25Ed0<2F9xD;}o=HT8$T|erLVtjLWYKPkP`W zPfqc)dk+})#GZcf|HFS=@w@IEa@~`)|MSEC*zX0uW!NL{NPxE;?`-5ed!Y3_XURUA zwbs6e4m6%wMRVVd=3^f{p653*r`P+Cn7PBv{cNCQyl0>xx9r@NF}mGDzb8F^?M z{t9qabmJIgb5ArMbKUl8mK#JKJu>vfkJvqx^U zvZMSskTo*ty*YZ#$yyGK#o}OaC?MaQyeo%s$!mN5J-hP(kG#;z5SL{|Wt4P%&g* z)h7AQ3I63k4AE<1;GID`5}>Jm<&IhT`Mo-w2hI^XHj4>gP8-JJCwAl?8^)9LT3;LD zt+BQ0sOm~>EDw8fukqvD>F5sokN4xwy^HWe{65wGli3|G&=4H@%6 zef2cAWlih-dO>G9znoq1d*R65sl(ovkL4uD#N{iqA%~OT%)t2>yNlF=eBt@3@bGsM;32E$aqdqG4hMMOn|D|CL#@3c zYxsb@eC8iMepf8mq=_&7+QY|xYif`lalA56b7ZmiMX~q7^yEzf?a4vuk=v4mhO9}T zwerZXyct8;qNn4<(Z!zjxx77dc6@cWcTLt_9>j&!=W)G*;$eTmIi$}W{enO%-SYX| z>B=2zwRfW4J=sAwXeGb;&(wEMXMxS_d6MIbbH%sfEzW8ekGmr&Tg{C)o1;OG#@Q(v z=b+-@*{%-8&ITSbHV4bWfq)%VTh`^ezZ2Yn8XaowB_s93H?r#8!Z}sjK3h9S;=n(R zjF(1+eY)-M9{PT5J$bDk5pi66zbNy9J@&IxJg*D1TC4s<)$KxL%hM##N`Cd9sdcNS z*zK;D&!a)b%%1wG+TM|Idl#vjy@7Rf_Lc*6W~}w~uO{f}=_*c@e=;@)?lbo2-NE|$ zyG_-SdH;8q`cBHa=h5Nx+V2lPLojFCmu1fGvxa%Plir-~z3tVS@lWLYb$i8kLHN{q zOY_H}VQaf~PJSK`bB|kla@HP_HTG$K{`yw|JIc;i3jk8nn?7__#1;f(!|O=Z{ng7aP9&*Qg# z%Fv%W^wyy0_-RgW^}a_GYt6p5JWL%1UFovyoQ*g9_S%x3Rk#)kqq z2KITcB;x_W?!db9AZ|wjFu=>qos_@F=Vse9Pwts9R6G|LmsY$L zb2hD28~d|gdRJ=Uj_;M!5Xeu-RWq&Z(l1tP>A_Qa$SN5N>+tRD`0l9LmA_wREGB5m zF7h=xd)vqCt@=}|W$*ZzS<%lA=+91;R&}=ZV14YFbXU$y)sXw7wfT-%t^AoiwJ=Xy z*x1KQ9Q$|`jk@uD^;f2!2TOC(%_D0TO;j8g=SNsbE1Ro-Qr6n<+SxV>&dRL46S?l$ zun@RIE8O3Uf%iZ;Ry&?i?s;{4Mc}!Jx9;Iqrdl=M-0inDXusy$2U>c^ zbQCT6v9lt+FU;OE1HD-3;rwRo`B*fM&-i%*igs3CJhS#|ojhZ0tuuIK_Qi&;TY|lT zxN2+heSY@wxkFl>Bbm#Se2JkpCa3b@oK;M%_4mh^JhrAZR^OxUIr1HWyOO-Rd&{Si zS2~{<8uz|dcD8$BvK-WNoNuLn%j{JY=Y^ zHZH9n*&03{Elkh0xUu!7Kz-1ym0cHP>})IqB?rw}LDA-)2AF;($0II_!F2)q$VVsc zWfNI+vD0?|FN@Lm?C%TgTYveC^;gVTf8~tzSItEZ`Q8RCIef5==linm3|TL`t$$2}pSz~*BXT&}_9u@GN{dCtF9oC@M=%cIVXJm}G z<~uW%+L}8v_}N`+?hCb3b9W9KYrZSv(phWHtTp!6+U|_yx#s&b*4)2ruh`P{rudKU zaA5wb%=xO3IWb7XYwkOu*TfO`-1Fk_!Ssg$c9yN`*uQlo2FB>gHr_Uj#kjt6v;N4? zDrn7(v{(=F5|nROU{67--UWcTsf?%m+T9J*Ct@r>G)6>ZcMKR`Gdcuy>$)RkgnQ+uk29U zAnxi`%O4+}-bK!Kp{*bBDE`VR8^wbEY!@GN>?2!FFALC%<6_`>;R|UwLuVb2=gHTG zkpHhsFRx^@F<8o+-PYK0ML=fdqH1f5Mm?yl<$!-B;}IFNU;ay9Tc;)K)!7$A`l<%m zUApCx9L>JkL|gA{Rg?4-A0Mt7=+dp$X4zJI?8dVYkS*?IgLu6@@sg`u0ekIV6NpE} z+jr06eJpr!AnswCwvxqO?La^u`wj)00Q5$o+q-j&hTh`4 zYT%;_tUGUL$kWuKINlJb31@}fy$tJP{I_Mjtsy>r-Qd&Lr$09E?T-?2#a%tPb59LQ zuKlvBd}!C)S9}nw|1EOaQh&~ISH@zi=B+ldEe{tx2R15X) zp;jk>=B%Sv1G_?0a@bfr`Y|3l#_Ea<_+hQuk}EZ&j>UuTVq14C_vPWX4A6-mmj;q@$q&4Le)jTF>%SH$4vx=wTzf*+qcY!?T+v`cj|_{^&ZilGtX=>`liTW z!@Otg#i11+{`B$Tn>Onll~3ZXM#NfQb8#?#%&>m-(D#29#Ai2j_3zxO4Re0zUp@5R z`OW#Q_w3Yr{_5Qyde2(D&xdmBOgg7>_NrBWd|UUu$=75q?)J53ck_!f zm-piT;e7Ye(my40@|}UAlevs(M?rL>je6P&99LR?{RuAN&<5Nq|w?}q*4rku_cK6Kb-5!)2 zV{$xGtf_5tbR}P3Q0K;_-x)M_-u2Fj=RR4Qdz0*og107S?$t|@l+)553HYae+z&NB zn6drcfp?Ixb$k$!)9*v&3E!bWJuL@pyK)$_uf`9^7+*WzI?VBk85*%+L%YUKYo`b7 zs(X$t^q1Y`*Uqfbqeox5XZcj`vUm;z{L(H9*mZR1jp-I2e(njJd-iGMtGQ!==Ud5Q zW5viB{niA6t^!y~Fp4INDlJ8v6jYdwxGL5;szal`3M%xh_o{mmB>34E& z>45tO#gC6pcJrXRx&kf?56YT;C=xc z*we4!MSEl5v!fWRqniR_wvpO$eTYh-v^9%2j19sjPs0nf>fi}x-bT13=T@dUK`h1JMIEs7e=Oe!> z{_L&X^NBqB?OOSn<*6M1R=kFe-`^eu?4hIeyZ2H2(8!f`MW8mwsk*9ssFSk-s@VVB z)c10Fc>(&w7Tw4E96WW}UjqY%u<)8bV z{(HmU5!n?Z{?I80CG%*;bRQXd<5_oC+09ou;~)Fq79H-PJ=w4Z@`=XT<+J=P2IA1_ zG(R;^6XY6i5AZDnm47it%T6(8XPrTJ6<%`D$n|%|rb&8r>Dh-~PSuW9_Or*DeDIAv=fJv{R&Sp@e1KO3bx+jVEm_mHtaPh)G?{EAzk0bi95DMEy1R3C z)=IA)zjz%8*dz{YZ(~I#U(pPqnEH|F^z)u|aw^y4fEog}u}8~aOK`iq%Ez8SeE6ts zL{9!nhEX|XL)j^prJqgtr_QJEQ2qL^Wu5Qe6@#2p=W1)5lH1n=+BZh1+Wqd(c&{6y z`L*z%d3$KQTaD42JkY!&G;+p&bk4E7|6xGJ_srP;iDCc0%-DbBu>ZX?_MbQGf8UJ# z>xTXBpRs>r*#ChU`{xY%KR9Fme#8C`&DhWKv_|F7*?3Y45|497ch&hMW9+rZMoWDt+;d$peJZ!rxbdx~C z^P_X{sLM&9;d$2#9(zAF?D2=MOTo3lV(`qMV&pCm$NJnJw&P-$R7~FsYTw;J{<}k1 zGI|<$MDybv&AzO;XAT5y&d~nE410HG?-@bq>g{DuoAX(={Ny^e;Cn?NM(zXiTLO*E zrv+oR=w55<@bnpU?!cBV)78J<`zJGY{(mYqj@=L6Fzo;IjQuYe_TMvOU(Cq=KW6Md zdf5M&8T$_(_W#cr`|?Nr&(7FCH0=M}jQuPhfBv&jXS4GDy3nXy_p==7H90XZy4Po1 zah5lB{e0v(_h`nR?d}8jiRYu*bqBpXJnh`?gSGP~bo0k#UN*P&sHP@?CQkn~bnP9q zUfrD$p0T=f=aip2GTu3Z&iQvnTH03UY1yl@&Hh%Gc==9A+`;@{fM@qGcbDO7mAw7J5UU%r*FT&8C~I>2i=i1iGanfCe`&`4PYwI; zow5Jj!~QSN*niWo|KDcpd+%i5ugus#I_&@V8T;oB`@cG4-@QZr`)2HC`M7$0Ws0Ek z{JiX`#rF@q?fFUQr!`Q|$l|$q;Q7D^Pqs#Ro;C1%a1I_dQ?>D=jODbqOU%@rb$5Vw zXid!)ZU1@h|B7yMZ;E3J>5HHLAIjb&y))A4n{`Kc2V|$(cDGb*AIrFGM>7dDI{xqI zXwUl?&#OZ>2{b&vHV4mFhi(#Rc>bR`c%BftNuc5R^*MN)^+}-N`Hhap`mO$#_Rc^} z{$^;#&g8ca`@c0~|24z@Z_n8OvSI&sX6!#@*#CcL>|ZhL|L%SzN1qg?Y&p$>zb^q<7)%o%@*IWjH|Y;%XkuKa`8W+u&u2FS##%> z%r6}1K0Mf4XT<%h(bu1I`pEu+4ec?1AS`Ho)`D zf#)N0@N5fho1@D!p9Gqi{Apx(pA=_zhIZ>pchbF6AL{APLZdFmo^#(hJPZFkG;%#g z^9xxg=Pw3(w-0pn`SOQ`{lA>C|INexU(MK;EAsz(#{L%%`+qZI|N3G7Z)fb+v+(a` z?ANpK?`Q1Sv+y5g>}UD7bNO?re=&k%L7gw}fRjLzyN`ykJzrxybWZ{e&p*z=k-=Nx*zGIWzb!}Bj4kM&#qFYT8DHT$oj8G9D}=&=89GxqB<*T2u$f91gcA2asr zGuQ1i_AeXweb5}U@4R7u(~NzeC;7K|#(vZuSM!@U-%;~b@6M$-E;KT{3%RHE1bJng zel8lTty{7;2{bacM8G>H?0uAr>j(3dbMWLGn8lD{;kM&#qFYT$r^XP5^&DitkU7=H(r-Wv#w(EIw z_Zj>3y!osd`}MrJ$Bcb-P5(V->>nNW?=@q;o;UZNv0u-d`^?zy&)!mEHWv36$Bs#$ ziTiycug&uq&#ur-0u9fpbMTxUx=EnnIc*M}b3!)>G(4xz!Sm&zn*ZOEO=Nzu)({Whs1-j@}NRNAm{ff*dfkxJW5Y*=n z_Itju-Sf>lx!_LQ9b6Y&8>sP~c9JzsEXZJoSkQAYddTrT%jWd^0`?sU*rn&|>6aAk~dk#jw zcOkKL&JV>QIq>|g&w0+Ay~Ew!HCYpjn*#X|!{uh2ludJZR`@E1Xw-w;o}KkcdNHK~ z&DeKjOIdH_md#{cAM6O&@zmf*;9QEicV%{|B{`+@oEf&9+t`A3mM#0UC#Ss)>@OR> zJ>zrMRaKX_!ntvUC3XT zOim5>bu^$4pV)}UMWL6QNuWJB;G26I?ajdj!Ja@2#iL}gP0r|hR`9UEeaL4&!|_hL zJ7A+6oF1?-Dvyg9J!IN@Xg2Zll@0iN`?9q9XI%L1PT~_eC3}*w#vc3n)((?e()9U^ayR!l|p%pvt!sWX?e!|OBo6G5s1!U{* z5mbKIS9KCG)3}o9&u7XPn<{VWf^NF%xqNlTtc| zUB5JNM!p~$WI9vz`+oB4dCeBOoSWsK=(a}*KVBC6TykdohTwj|EM74o>!yI5rv~p2 z$cTvPpTp)4yVT;N13!P@j~ubD^u9LZO9OSGk@1ek4mR*xL%S=mR(X-Hy(9B1o%E_e zUVD1Jwfz13^z3W&ofm8~NqbH3&_G?%D_`0z!Tvx#tkX9Z^U^5}WboDa)IdCqUmS>; zKj$k?ZLDv|T;9>CiOMNEUKFS){^CPNrlyWH`)Wr!63BJYvDeRF4h?H`XlwDPxrard zx|V~|SGHMO44x6x+T$`V+S1wjLlz!B6wjF>Yh!Xkw#sv77i2^y*Ase@E+MhWXV)@6XcO7h}DjP3y%9T#c`HkKDF`4rbKff>T_Rr4zSk^BIv`_X}&dQfty5I3R*3Hk#oIUR3 zM+EA5l4MNMe*o*ayV74A$dg9@QgBglY3j#4@RCzj@=?VtPM& zxgt0t*d56Kk)fAMd+r8%lR!HVhy&YN*<_K~^3`3F<*8h{*>FLCj=yC6ZO&-ff<|22 zO|6bhr+4D6^n5|b*3u`x?A#GtAE*s7=u;o17tIX;Kh%pe$4Bz&xqNcQbdZmZ9PPHi zy@uYqS#RHyvPLSo*WOabWZ`euizmy+{T(yvUb{TtEBo2)IRW%W93HjwzMRWG z24nQI^p%{quOX-PWlRqL`*ru~mSFGDFQ<1-+x+lZZK+$W)w5O{(2*rqW4TkC>VsS~ z=$#+FYJb=G$_8|J+}&e(`7x%aYJ{g~P7TCC&b7+xn2+KkPh9RqSq}Oda>lF1 zGMwtVJbl$xuaCT{4fJATjU2QK!CJm<%B}mH(7?TeuNv^h>D>)`g0lkiivsc=8=!UP z>z@&56_>I2m;G(7t)Z1i@o-n_waW3V{Z%rcZplV`ygr@8qJ2UL)dBk??S;DS)>M3N?{PZ%` zuCv`I{raYpPWr7tkM<$K!vdfE{zul}FM_9KuHL>Pczy6qf%WfA|Bvb6JsH0*_^n_` zpSAx8{wm{-4{O#>$=dyfy|dCkFqi}ye=BxvF01w`Uk?i1)?g|x{bj)^LDjiEt>pF3 zkCIol%x|(ZH9!`bbtj66nk)HosFi%{eN9?B9BdB0d5$xnuGl#y#~vHkI*XV1JkTbVsi>1gvd4}HlI@3GvkC8Ldd%fDW{#&p)&6|uwl-l#2fdLQ11|LDus zrHr-mV?B9QTYsPL1ZLf@Rp-u&cLzSUwav$S1Y!(ylIskxr|Nxc#u}Q6OU0{nl)dFo zTdVlm=P;T&Q|uu_&rbL4V$l2KKGwP zkM>!}=dB|nd+vk#2ClIu1~2O73(Y*kslRkS$t2abefs~Ey4#X*E9;p^(%6RQ+TaTV zjlbrle{;t4Ums|Aif={N%DZ%HhLSxx9anP_7tXIdYp%9FTjV&uI^ z&A5ZrlvpnW*5rL}fS!DD*4jNeSPs-LK8;-GrIm|LtG%jGYwSc{HjL4ZosBWN{(M&5 z7j5Zk*ZcPcXMinZI=5uKr{@zM{(3iM1ApkU?#$*Z$J;9&OPP!1WkI_y{;i$!yw~9O z4u`k3jeMv)cupP;)Ij?=&36s#A?KFBJ~^5*RdU>yW$VAh7qaaA#>g|34E0dH)OjaY zZK|=hM*GhR*`C(P*!t1z)w>~|7lN^T+;PvW{QEuZ|Nq!~^T4>S>VEv)H4Tge7(YGzm*4P?ppN%vPY3 zge5Fxrv*Y=+S1Z~DGhB(OG{{*`uF+V<;|PX$P2XmzJGk*^U=Ha+;h)8_uO;OUEY1; zO97pL0l)^p7631{pV1TR_(c*D<>$-G?vK05%EI{-M-egn&-EUXLlQCUy&qJAQP8UQbo$CP98 z_;pUdOFLqF^GRB!Q)cpETayp*%uoDY0BytuaO|lA(7rf^(6=uFFpc?2ZK?JbgTN7Z z8NLk&Q*O!-0GK&!8^SE_3jJi6rfv@+?5_v=2;Via50me10A-Pi1czHxwQr%F1OO&?|CauMdmyk;I_{L3(Kh7V~Nuk>%!8+A;61hY1!`~iT! zd_+C}N?OyeN^PP3uW$084fFv90s8^30=xzAF2LtC{4t(C0PrF|%12$Zj*S57!UhoM z0(h}Lv^QRUddeFD7#&civ*l-*rabaJA9~u>xzJM%%1K?(Ht5Hhk9d|%83?R1`^!22 z)7ge>7uJbk(lYDvlgV_OqXS&gm?57yHG zkcSK4W%4j==uLh6x@Q{m^W7Qs%8Tt}bjNlu;q?f!e3oOzWaeSGTD$n`%5?H+12E6I z+9&H=O&36W_R@ebdCo`c@4JNE<%tK#8I@aSTfHJVG zxpkR;JfnQ{>8u}RXPGR|0kAy3{49$X$1`4(&Da^!NN?;O<j0&S@oVA_gh|L=~)YW>YJC~qHtZMGe7Bj5<&9e@u5o&FE!QEmPNQ+q302bz^?Q`Osf=j`YUH%y{>_)*~Zfl!IaFigjX` zv<$ldUew(}8B)3&3xjBdetjvdgC^J1OYo}|4V zK!3`Mc%uvce^jjNO93=D%395?h^H=?*8q92p6s{e;R1O1ZIQI(M;qig{hQc_^K0h! z%iwQ&;weAQziGO~9gTv-;|k!6}TWB>NIzaP)MbpT$>LtRi0KhX9{TZjW_ zuK@rr(iyul^)YzrjOADM2a`Tu*{l!K{AE+FNnbFF+XK6^9kZuZ{k=^wZ2d(BlED%mAYcT;Kef77G_OC9O;Sk zmtp4El$CA8%j7k6FnG#X>1RmKwxZ`EJ%O^)W_XboW$>3te_?z@0AXH+j``aG?0Y}1 z()UOo2T=di0Wan?a{2Al;8-{2t86QybAOo}|NZ`q{8$dhJL#l0Hluq=4(IG=B6CKOvVoUZA3o2NO!jS`TG#%VLhlTQwPJ}-yY;&N!Jb>+k^i% zr(ZXf_DvdsnOiZ;@>n*(*jS}6APv_6!*xow8xc0|9NDLr0!Av*b^%9S?*vfhIKcEt z%1=4(M1$d<*PnPUpL1jvz-u3%(k3X&6oB%wO`8GaQH`$D_X5(MDGzbH3?IsG_@D}& zoTT;h+=KW+0PDhWm2Dda>;8F|BvHmRcG63@#+hIEKl##NI0$3LL@ggtMy8vD$tr{Q7OIch1 zFGI^Pq|PLLxu_0=w}E|mPOtR0PjILct{yo7G-!^ z|KB*&L8Yu007rhN9FzVsjb}e*`Xc?Lyo}TC{c?nLJfffM%S><6&rbbZj3?zKU#`7h zicR=yu*hl$YzI65_!;2pU!6WZ21o&32RMR-+Ft;cjtpQvJ;6?eFhji=E(dfT- zk~yyH0ha^({+@k``eU2z1yDz9H~JLzQ?`Zi_lz@*ez6BYz0#I=JqTdAq^UNx(PstV z5SX83Q6$b0lF-DXcviw=RdAIw^TiKU$$MuN+HpBt6H`)->QviQDZJstvTG}aXkx$wZ@x0an*v}1)w4;D(<;{od1$_j- zF@RS!TV-8Y7na5AE&#f_9B*EaF#9xt7t@e*`VDxpzf&fbZTbw$VLzpQ*gr|bD-EEJ zyA{B)n9ol~JsEv5FZJ0Cpgzfy{hBh+hp;?e*FcW11E?<2vndkVD zu1(*kETl1YAPuhv0j&V~RHhTyMx2+ChiMlC<=kW;o-CjJ-=9XG5(2Q^^ikwb9QjaY zKdpcM_j05$AIFhCz0?cLBWEMywZQ z@}Fx-Ax>TfN1AH@>;t4_8Ppy5`O9S71@O8Wz&7ENa}AEC3{%GrfNe&-)0QX`^BQ~d zmrFX9!SAHWkM>~VL0^0m!p7!|Zj78PgZZupupe?f+=M!C?nYj%0OF}b>K8?o)q^rH zKk=r%0ga<=P&R_clUz?5g?S_fQ%##1*CNtQ!h(Y6HOZrJN3c(P8EZ8L}{ z1N#td%>fv@_17C{Y1>A2BRAu$C;KnurtT@5NoScxF4C~=Y4_AUFY59h8B*m^ms=nc z{Uvq6_*TSCn^NX&KAAfZH}c+nL1D=+6D7ncZPh_8)cg( zUaT+W+I|Lpq~XPKcW65Ey9rIeQAXNH8-V2!Sgxrj%i08>JyfH=6nN6Jja&dP)BmVn zTVfQByuO42*l#G;^#JPsGJq-5MVObrjVKc@@-;lDSMo4@jZgBJ0#FvVFE56fk2<6* ze^Et;rq1^uofpTd1i<)5<|A+FaA$=MDMJ9@myLCzu0ZP5jkf3lc=_u_{j>geGXYlv zfMrwvE`XPxw_kVUZ)i>XP?k90T=N@Re}1+bbz*qC2=kgx4z`7%B_Ha<@O2U9HD6xV z!O&Kd!Ec*>Tl3qS%K~t*47NMvw*kD?0jP^%0P_s#C+&fC{3+~#Z8HKO9mC|q^Z?)y zZ7-GM59`P>Xm4iDLjOiR_+>j&y$vntn*eNE%5HoHWu{D&nf6WF_y7Kqi7x~`q|-Oy z$ub!yU*>lKyeR8h8B+ZGHc48)tTl)?08HOxx(ncC?3ZEse(H`-jx}ol%*%^)Vf#)3 zIDW8v(|-|^cH)=G$jkAP`lo)M^z~P!hXK@upW1IU*; zW!cmLZ6*#Ne};K6%=(xyD}eA{VV{HY6HGZ~z6_M)c|D%2vnk^qCg9?Jvca+3TLGl) z1ki`?LMHO%_}77_33DuAeJG!)4`pV%Qb(-+JG5N%twt`Or97-V>3F@yCw~j#4;|=Gp!Lon0zm=x7vS&a;?C-46j+7a9=l(!|M|I$&O=lb-TdOQ(EBC#F3q6LH)d zrVd!HS<_LE2LKLi%Gfk<>=V>4`xEoCP4)snS z&yr7hzctM^G03$o=%lx~MpR$v_6+oH802jcE zJXt>FVEgbgcH^fv?ZkRfXS{BZf7KZa6eBO{$I!%m;dYfQ&-xkrr~U)LvkeW7aks?2ojQ>j9SmSO)nKTmUcXir@lxx$>{-CoeWh7k{lM59f^rRN`nB;zyMd=1#Pgzl7&iP& zI~$)(-Yh2!;57^&J#{)CZ4=U1C)!#YfchbramDmi_AUIAHtZjV7+wZ2{)sZ0dQpGu zCmaJd0Vo@R>5n3jAs0_HoKfI_jBqHFYK(>*)1=Fz7(s@MD`g0G3M}$2X%( z^CS=BSDyCS7t3k@u)YMAOTAE+Mt_tUETznNl+}~XPk7e&j_RQZCYL08n?PE&Ou=(|-3NT>!|7vKk$cmU?D>UPcdw7x`Zc zU_K)^(}n<*x+EXN*Pjn)X&cpeus#q$&iRdgmLg7B$&2M21^D~sFyeiH8=-vapxV5f z^EuX?7in0}2%eOI?M;5PHC`;k&@dl)kDY;cBhty6ZBIG(0eEpN|2kj_a2tSSTmgs! zSeF|C{@-S0J~KDC58+n=C>!mVI_5?E0D$F@57VgU1iYnnmt&BfHP}(W;T?X*yBaZYzKs$if=XJj}K50F098+mel!x^(JSY##MpKlP zNuI33Y5>E-0P$3E0PY2B1~3on$9A|CK;G0d?dm4ouB+q_A{%DW;0jv*oIR6noR0_nD;skbPue{7O*`Xd?923j;?e*IKz?l7O#u2dw)ZXo zZJw8Dck(c{MSKT<@(^APJE9(qO^^rMkbTV90s8^NtLV%xdNXLo05WsRM|J4B6 zJ<}Oyx__O}hxj-e!04B<7&)01M;iJ0%OY>qi?UG8b^z<)pZ{ErIO$kE`v7U#){6j? zojmUb@S?8b0P=DHyl4X~gBSC$4y0i|7r?8Mo^8d8^oFOO-i$ewWl^7`^XtI)6q81s zxByI8SR<8jshqP>&Z6E1ITv>K)!5Szg~ZnHcXtM4U_YAr!N^RR{4%rt{&q$ctF|*~s0Y7HvSJ*XaY&Ik~_6~KDk37~%2 zXINL}w*l;5l>bKkWZy7x{#O4k#97W|6?pQZyu8+`hvZ2)$=8epEV~EL1fULiF>geM zRJ+rE3<0J9q^F;v9Ml!lNdGbbFVgh^rcgNbLAlNUDZsk%V%%T(PXIhT9PwWUj%`g@sY}D(_+!!#%-HZ+ z9jB~u0Lx&#IN!Yo&nSR$F%S7s9@c~PC64+?fq?Q>o6k1@p8!y&qX5(P^c`0K$VcWy zg~*R#o})G6A?t0{Hbw_7aJzEs7DvTi+c0tW8JCm%K)UMA7;Hd7pJW20Ze0^D(eCg$z9;`R}j!HLpaBa{zBbv()cDk z$%A}JZ~7&lv@Jea4xh}!C*Q~L$$bkxTQ#2hxs020;atly&hq%YS3h}Xl5xIE;*4w)wfhUf( zO&nBgJq#TAb?7*8A$|VY z1`JQ8Q|3uuI&rM~f8oF)={Q$4e0~QwmT?Qppk9pJ2wFeWa?>9%AAK$Ju@4L&ALU`1 z(V3~s6~K{>b@?*RN0W~GQ{=HwKMhazb>iu(`E>L%te+A6Y{rv3$?K~)dwl_(^wZ2k zx%s3&;gfP!@?u{4!6D=|vY7mhn!X87(ouiE#CdO)MLtFr(lMR&|AJ08^*8vB0nav} zEG)<1i@^Ksj_1oO_5CdLeGT%kOxah_XtayUK4IdNk74=}Ud+d~Z~&|W`B(B|+nfBf zP4*WPzd(o0yFT(`9UK7pu{={ZrWw66Oz`W8aidSR`G25pw6mPHGwOxc_ks888hSZ)`<(6Akt#;iUN#KkcD;Xb%I=ve=hM&$3zGk$LEk0&nU&TaoA1dGg$*^H2|_9azth&d>H@ znYYiA{|=qcw8MVrowAyIcg~aVF5r!1pqNnI4^o{%ych2b`C2Jn`pwdzCz-}V>Awv>K8?>b z?P|tMLq{3{=RbU2rk{)SlXHCH%@{l1xZSAfn)H+PWj@x0Pxep$)AYX{jbEal^kJl9 z9r@(ig3nd@xkf)-{T$TKVf|dEpBwaZqkeAE&n^17O+UBmC-uv6*gkyj*3Z5AxnDoI zo|pnq4*CIJoDZ@-wB>ieRyhA=`}o^x7vgLy)`xWO1lV~OPW?BrM~Gm+Ia!1=SJ)7kh~Vs?7^s7@~-=Aj##n9alsscc4P$mL>3$6_-x z$xOnJ8BeE-Sdt>1&BQ%HC1x^NMu6y8ERo3hnGolfR_4o>=RmWY4WK|8S_Fc(^HA?$H!ywgN0lyo*c^;Vujhfs>OJ! za3~osj1`i3tw*XHB)L>(Qj_El$7Z_wR3x5ErTtvvQ?X1YnTCbru}fz1vpLxU@q=UW*i0;*D(F6woS90FN#!SEg_vSe!W~Td z$>LK<CXdXNr5u@=?)D=lQt5PAyHBJtvGiCjIho2AlG-E`&PP3bVA#!_Z<+)^RET2xrwSJI$I+gM9 zy=6899&{ic3(t{(*q4AJOJfQR$Ml{!BmrIgpyuF9N@fnFa@ou@I$0?(c_f~k;Yd+( z6V(#S{78vlGMycVC6vsQqNsX~&&CgWYVxr0Try$C97)UikD+OdNPM39;R0b`=E(C`QZ9%p~+H@P(Yi|!drjkHM z%`mN^7)A0G66pkv9sZ1EeNEB8NBb$f?nb6%39?7|G3at-(OK;-6yHoz4`3=t9m#D{6Zcv zJrel7C1q{HsIP4ht==|FC~F%aD%%Dqf7>8hy=|CK-ZsGa+lEnJ+aT(18${={jl%h> z?O}R*JXI)MCdN^GE^S3SlDO24h*fDv4_n@j<>gW3 z$lvB;vHaLf7Fm6LbWZEdRVp#%N;#B0m>iRnLX2Hy6Y_NIR?OY9n8zPx;~tLXwAspp z=@{~rqZ1WlSGsHfNGJ1opA%%Xkn%uGyU~tDMya=Ezy~Q zms3lf#lt2u94^Lk7?xAh$uVd;gQ>Und?;cfJ!^&p6XS?bNSVnIu+q7E9F?m_IojL} zL1{|kVe;`9XQxK_-C1?vPVJcmIWs1-3 zS52yL{XQDw{!6IxA)pLjrE=v%L5bRP`%qt5!zatuN}1$gm`%AG&14Hcmzy2GSuT6C z6BFKyow#vq-RP+}qlsBPU1KDbuS}-t7Gio{MUwIex)!!)v_b1G?3;u7F&rYtXD24i z5LTJyZ&G*xtjYaD#7y>ZvTXT2og0&5ZG*1@JUoIhUNy9!k#H95en!PTP~Em72jHise!+_Wo>h6 zSXLFO*y=&FY~Le)3-(cbivg~}uso3p(F_!(w2ILrxujeSSJcZ(ERAZaHOl808t1by zjlo*T6w93$E=JAvQHjFz;}XV(jokLpQH8iEyElTkUu|ZKG zHZY#pv*Trra5RrWE|JncD9Z&B*)@MCl8xJvXo6HVnunRvLu~^OkVXoo`>0m$_q;#F$-jJ$KDJ2<`E3} zdd@;5m&38#q+Zw=3~D@)(#}KU;)nIPtK--LC`kwZ0|jEvmd)w89H~)9k0cRTc4^si|Dpb@jJ8qGeqZ zy&oGW6L59d@G!2`Lt+DH)?;KSVN!Dl(IZhSGp(7O!FC4xPHDgWa58pK?j0(jWK?bk z`s1=c`4C<=mE>%((gvVJu|wSRmiIns*<0{JDvfPV>jfF@8qHu#NF`_>s6IU5e@T4% zNG2f{EifqSKNab4>QE{#_kNC!-I~m0t^bht)-Bxaz)n`e`jtdK zp%|sjN99UrOyX6mEcPXipetW8cC&TYKjUo>E{0G0!Wu6m4gUu{Tnx*T8k&C9DVfz; z>f@Wpj$ye)N8z?^f@_FQ$7XukWGDsm?^!H^SYIaOMoLdtDK6(=J)Ihn<1p6KA!EwP z^b}oJ#nCM>y-uELPRkO~!us*GDqk*n2%CH}Jq?+{REx}uK)8?&PbJ*&{{7+o&Efsy z;r)g1{!Dm(u4M??jK-&OZm?sAoPtMla8-pEw#DRLnX}j##K@noKnL42b#>x0Y_Q32 zmd#bcwuB2dYPu52E4_qTtBLr!z)SYMxM@@360=;Ba*Ny}Wu#9hz&brV!mi`E?7`7N znD)V@CDE?lXqVfw8B;JUkfU8?C!y>-f#l z{vQnoI|jJ$m*&>*$dtS@J)18$Q?Wxyr!bXt z^6>DET4Dt|6}2?Uvy-|sZ(3_k0)u66pe z&VY+9pFfHodBl+eOLQB|k@@%Rp^xb`Q9dyl;n)KYJWw2zj&{U#dv+uXQ9WPBfIOB= z7fyjGT*;{>40E&|aqsqKQsH&Md{1_RnJR2fHNn|P9+zwc%VtuM%{))He+cj0;kuJK z?6z;hPFvI)XWUb*s_tNC-8I@XD3?f4zOdBWE5VQt=XIsUq(Dq|%{3*8YHDrM$?%Eo zIw);ghrtD{9uG(I;Yg|>k_Kb|n^NJ(L^v`Sj@%ZG+!2nngd?rtNGu#Fgd=Oikz7M$ zEO%-tPZXG%t&^L=)JtIV4X0{s5oq0YswN-;ZFtm(KqnrxA`r!+P6WDloT^zM0zG&v z6oIAJpQ;IpKp!6UBG7;1shSH!U?m-on;zahHs(G2HTQYg7=2B62?bxZB%S7F# zv3bcsut?PX*M_irTiD&_|64o}Y$05-)d2dQ)-H4Y6RK);2#SP=N+*)4A;rbPLJd9GUD>`4n647h*FVB1 zlgCbuyTM_TrtSJn;u}&wn@9v+q@lSTjl|n&Mnm4DRfTZ-O`fWdN~*EuV<#=RHaNe6poB=(Vj_uX)f%<+gS?QOG@WZD ztEAr=!}eksX@F@SUXh}@!Tu_O8Ws^~VBYLlZ6s2Yslut6heiF*uB|FgFx2m0SC3m4 z3C`R)l`(WUc;ADSIgm7$6Mf-%-Gdw4QboYC@RYVwm1QK+S@J^7tXf)(dQa6#pUK&UJDhj9CzesIsf^q@FQoALz&V^MOu@uY zbTtF-)0Fi0yQ^rRnmeU4jDT@f-jR4EYYq$N>ED$2U0(BbIGE=r=&;wGpNyvcHG{~| zd5hA}L4CC~OVx4x`Yw!&)r@&QO*K;^)H^dr^1+@=Hq*&%0w5EGsXP_{Nf>W_c4j7< zqp8Anok-j_7sxN4&6tWf*oNa0S{e9x*G4MV4R)TF7Kfj3lY&~%`aT7J*sJ2bqS!|(a+TfP8%k>4DW0*_ey|Z~bA;)Rq zAeF_Wv^|rBeX1R>hL*LhO`V-n$@EM_{zY*odgyo$X0nGfPF5a(a+-l{XpYvqDvg4dazhyrs=f z23xP_dKs^H@@^n+Lq|4Ms3?25--y$~94zFRQpqu`AW-QBIl0jV+j^C}+8IveXVS5w z7#`t1xh2HTtcuJl8qML%q?$;VT09YUAkoR202|#Fhu#@whVBU69=gq!D3jZCG6NL^m!^Tc5TZfI4v|8i#L(}@?8wJ?t z_Ro`u(y%yK>PzJS#5ZxXIE>`uqK|dWVH{lkYvq;Y{<;#El?lsGyO(Mo`OM-Mr83y? z!IdrBa@k27j+0Y9p6rE>m*a5fWQW;Lz&YPc!NCrC{2&&B`V4d{JBqd+DDO96r3bKz!twY()}e-|hJ#yf2nAxV^}3 z9F##8Pb}Fr$MD#tq3dPUQlt@`e;&SgVE0xAqc-{-v(dk78(t7$Z^e-daI7I6?&>EK zU22b?`csI~_C6*-dVAkd+xx|nQ|y{2Q*IL+Q6%5$I1&X!BM_}csX~lPMU2zo$d1rh z@kGJoZN@$CWM{-V{fUA||FqHpyrF`Jq`WN%Mfi6V3a zZ&Q9~+5LaBz1_a*jq8@!mwxO&zHKl1@WyZ2mpuROr|p#s)9dZazB~DS`{JvPf7$N2 z>gR`Tap-do+1LEC{pa@8uRR{LFIac&BD?**Pu*@WJpN}J?7&M4aeLw3FFtNx`u%Gb z+bh5MCwuJH&wZ}P?!WI)#_pSb!+rKO`^Lles=xmDV|MhZBY$l-f8!PR*^viUf5Be< z=&Rmr+kgA?CVSD-Ywxfx%Iw%`Uwy~F?y+kRTyUp-@!xN`)4nA3@ZZ`mJ{cXTKb^FWMgMv1?bn>4$b` zxVXu#e{R)hZ1I8hSJ+EGwd(tJ+pc$@jO;U0cGKV7)n_ltF8YGK_^G$vioK1_twRHw zH*MdwW!u2^fz2KMh~vK79STK5Yr?A*ht`Bvh3b3sJY{5hrf_uZmf7TN@|fcuv-Tac zZtK(YSGgG_J)(R=*3UCub2q`bbvJKPA$+PuX5;2v?a9r-&iRY#qZbt3Ce{!(vEFgqE2G0SvpVxKs&LnMxGNj( znhkdyIaRY>*zKdfm#)PV-K7@ zYw)Tf+ES05d@YCFq|`(TGaB`7&N&>*qgGibKZUhBd$g*f8yuQPsPo}cJh1}roRX95 zR$zzy`jX)scUR7vhMnoouGx${9_E-6)7V2$h!PLHxI`laF+Wl%rB~xo8|= zIbrGQI}*t+Ggno3~+%(o{q8>`~(`oHB~s!1F|>+9!+^X3~XDKez+w(XOg@Zd@YesztNfAk6OI;P)B7+j!f)_KoMNWiURq|qk0|jMkmLvY` zObgca>Exj#jITYPoz2DhW?Rb>^&wPo`1tdnE=~r4J=HZ^NTu_OalQ<4=J^izdc3T( ztsAy_8+&+lYHhg=Z%*$R#CucA9du81s$AH&iX+Qy8__4XZ+04SKy2K>`!noH$XDXn zhl@As?+ZdJL(}0`>XD(Pp}x>EtafC-9K?3nTBni24`x;hH*}(R z1E&4`*l&$HkEHCXZl&iS;a|W`lAMOwQ&!T)w_p zzx-W}rphGnH4DGV&GBeH4tT|8(}k|egc3p@+--}qTaEGUZZBW6%b5B?6Rn(E;=?K4 zsbs!eo#Y-Xk@a{OkI0~C1^gJ}U^3SPe}Z%r3C(0_MIEtRdTRw&<$5nv3bw&fE!W$^-ZHHd zj2KuJ%g-6*hYGzcaEk8>O64?8;q+(|X1q8+*sS|SH}l~D)+A0LtM|lR@#$10B3p@w zRU(d*A-dz!N6JZ-#&Cc(H9f72-9J2@qY7dmnB5eM@y zLF=42oQusIayoB-Q*%0p$JUK*8X4QVZrzTNonwQeJ9n(^TSD~qk&!Jsw-0RD=>!`) z)7+&<=AF*;jA{sH&K2D9KV0mxbi(P(Ih`~>=g9IteB$CbomofQXgHQ@=$x5UqkUAW zX>8r5k=>g{w_MxnL?R{(=)2}23)k@AjX(v10NCrqdyjV+Jv zfH=_V1SVdo&A?0K^K)tpMCT3Zj?PS$Cv}mnfXxsbW=`}=&Q+8C7fbzLWc~k7g*y16 zqP0S5KE0+3HUj=<4qAQucIp_xU4By~y6K?y|@dFJ*IA_X;nvrK@|n zjP!JMEgSCYQmlJW#!es_G2o>lvFSwLl4k9-a2N}}3~^*BCQs~UezWb2hojkWG#`$} z8ZaQQP}bau-yKOOJ25K2Xu6k1(f8+1X__;`jl`nZzHXu0fUlnHFaaE8OuEI#usax2 z1E)II@R-}^IvRD!@#2YwRo!b`{yAyg#=#Rf*Lh41qd3Pj;L4DD(z-(h+-`Rth;MWE zMPk?uJaC75p!nFyoA4$ihP{pkr^Rvkr-+TpP^&Jtrg6YMIc1pFyxeeaA8=KW`FPY)FbhRnOI=16afueQ1zXMiW3umD$I zqH^NLw_tcx@8K}rlkW_BAbPxnmG1-rH4Hwxx|;dYuMh1VaIWr-w#BCAw$586%y%f3?IpQNn)1l4!br*`mNJ{c(W69krA*>kni>6~qLdbFFnbStSCz-F=uDX%3K*o?R)_{$BnS0w z6I&QYQnRgy8ejp+qJoPhrAKfW+~v+3NGOYg_e<25(MvSgr-Z}yQx-(?_*IM>LB^!bql^L z>aS;pX3kWb9k^>A%%Uo|FwN(q!M&1JD+#j(9H->W2_$UiGlP@q359fDV;|TuEDVpxo?!9 zsdZ*2#{KwR2XLA^MR z!PHSRyX|-I^dgLBv0-u1& zb8<>?FkZD2AYZ*k9cRZZrqv}@_*?;J7|fm#ED9Y3W1ba#$M{h$zjeh*5_@&Qo969VhNym&8bP<>wlSK#)Y}{>gU{krXUB0} zm>Cp7hu{Qz9DJb*OTwOt*YRPvKDTRZ*YiCXXqwZp@nkyh1iR(_@A>3zl3ATo-D+?* zqZfvDAtHMk`s=||`X~9L7Ho6%`#nl}zB|sPP=$OlnzC@eB)u27dLrP z{z&~!5X=GIV~_(rssW>>?uVWQG$g`#~r6|b8*@%nBC_2tKvq38;o5Q7ckZFkPI zLnpXRs#s2wWJz#=GPcQhuE~1a~9nL^U>B0KSgl; z+1QU3Ffpdj1#k3nb<&m77@C5#J*Gy>xQ3#=xxz1$<&xYK4`W7@h2pcI!=` z>$yyjFH|_KRr4j;3gg@uhE?mMQPJgcB=bmlUP}*=%cFFcN7XPZz3Vx$gqK;(TF5U{ zF^`ZFZaE^*PuHKVCjHJ5X^7f=a~!7moT}LBS2LFvRNQaPTW#3?emW+Q&o*(QH6 z0&nT@9VLFdV3xj3Rv#+FKY4rs4;$*<>z%@QlxM%Sih7(7rRiKPp{ z+CZ< zsxmq^v7|?zR}{4}Jwv@v`26LsHcMCE?>LtHBvjDg@F*aTfSi#K1*j7?YYo{<>?jU7 zsN?%stmRVUv#>gI8k!uN&O(Z#8qs=rz|INbv`VnmjJi&eU()cM3|8`JdDGzD5=#w& zZZLYzIi!wI#$p`ZP{&{J@`XX$z7#9)eM;jt3u z+=>de&7#UU5{p-&I9?K$yIgwBqxMvs7A$S>X< zhXRkP1~}zVVfb`faKuojoGR=%*9^WwmiY3h9?MA${GR+a3cnAH9;|l&FdFJj8hlqW zr@(X0j88#^RBclH`QW59;_eC*<{BMsrO9cl3Bs*@K!`7HgF$o*NRLTPVtS#+d#{6V z#Ne7#?oh0(hcyJ3%eA0d$R<(~_^l-F$e6`H8ogylk}LcSSMK`PN1f%-rEn?}=TjCe zmW$3`qaf5uS>2IyGw>ij73K5~KkW&dfD@eHOCEL$8VldvU`A-paA#*?IN|69_e;Az zml7iQy6-&MhoWXP#%r;aqv^E#%ng#5?+DCt@>I=J!us?mzb$u*LvC@{E#f`&O~qJo zycjPgipk&Q2#)4#aEmzZve7MGTioOpH@n3x#jV9{#p{aOi#v)ti@S=~7jG!; zF5c)C_qxS>Zm_LA*14p!uX9=Fiq4*8ojof$dwZhM-W8oox}(u0J)KLIbS_!ixnz0g z(ymBnti88;@eO*9Hafy@-t)!cK(KYkEDlq|xxV5QR-R46AeAd{mrC!LqN#HSqs8K2 zu(=Ag-qEU{9qJwS_8FWB{L(gee~QK7;6v-wzJgf?Dm%hTuHOr>Z>s+FF%y`a9I0Y|+SM30d33duw-g(25SaL+cisml*|x$S_~ zG+Pb)1j4umY-ixxM$8NHI0Ya#Hw~5KD5pl!reLwkC4&39VACeXDwRlQN(3O7oz)dH14x>(Q-xIt>gAL{tg`V|+j$2mTO*I)nw=sCn zNU4I-9b)!^U##uqVR46>UmWaWa2n`gbeXb&64_)v(`VpZS^jm{L0IX-Z?V~5L_p}I8ZD5ibXwAxA$)0PO(|jOS1-gNB>Sv&&_v^UOLzJ z#p2EtyVL@=WPW9wIZuoWpdXB|H{xl`OC=tbWu0^6U#fFp7yw ze3qkhMd|a4!|tF~rxZu^8YvQ{P)_(am1%!)^$owl%L>%$KyWQA^EY^50UkF7_wPKM zH481&tIS1n5ebhhe_V%qOPHl3{hLOG!&#{o?2luz0+$S*rG8IKd2bXj7VH`@)&UnI z4?@A?9LBHFn+3UKUpkb8Og9Vf zeAB_DTe+j=c^JHgQp;iVx>%ZL#*UWk!CM$3=X7xGx#v_Olp7y-WY);}56z_7+7lGn ze&hE`OBB7VMCweieN=D5o^?TpjmzRK_~oeaJSXF&^%h^unEBT1j4@<++zUB!!4P_& zdBs@(9Gz#hT;1pz6`{`iT^Tz6C~HX8{`RmmXADz6=wb=+nocg9$t|+8*Cmp zwB)uvg)%fnTo|*d0JGy8pByXxgIGNZ(BQ1_Lh!1 zEqh0YE?%q-&g~Pyb$Wtazezl@?=- zTME8QRc+wpO^U&=yTrZCBaGzTJ8+=Ijh1Wjv6HvTBRP>stUr<}o=mILAf25O+uRXJ zb#?+TRgHq1SIINWYg`lX3cVFam2T6iEUUk~9K#^83dfz-xay(g9MC+5-NoR*WQchO zcvOgbqMe^v$lp1_7qd9Da&lS<+2un+Tu7@JQc>l_;cE;YKUxglrXZYrCOz>w6-UP- zDT$VrGJvzzcYp$imS76iML2n@HmcrAQTp-Y2IkcEFpuEim>J$KOMT+=3jX$iHQ@pISBHzP+bZ7&M&StCR7h?MVW(w>?`Pid+dkL^@qVcwnQ&KDB$s}WAepF| zdA0e$f+Rj{<_u*D|3gQb|4RpY61gvF#>$J|$@4@^Mz0_7+ec?8s0t&>F_#VAaP8!- z^8DqjQt9($kCsb8WpL#x&l5!5{_<4p;&^HJ!lgVBS)+2*=8?E-$|;bY(^xMZ-Y8X0 zAxD0mnZhqAa`O@s05$8Q({|Ri>~4*6cS^k}_70+};{sH@nl3mvr^^$Uom{YRiNN3A zbAO9v6;G@k)fqZ|_rb%D7xksIM~c8S^oG&K2HwfY2mm%Z1uPV-46#YEtvd z<2a8RYN-Y!YQRyN(3nhZlbP_D0?gcy`%&%T_Gq|$b*MAk8ATb9&}w`cy(XN^g>Sz- z)D&)N3iq#WfNmo4hdCM2zrE^X(&3%{!YYu391FL!GCeYm|1&JZ7_klbs6nwYG0iG; zAhZv^0dkvx@a+e}`)+@y`%YJdm`+tlx=?t{9pT$n(E~1$9&nMXFs62GrPn+7**kd} zjY(dZ1%ctihPl>bBiqkUc*@1krVZfh7&eBBADF=;Osy&W;oo)LPk`_kKA#x~b>arQ z7Oar)$yzqou2%Ipm_L&Xg+kP|QFIkGvl$|&Ce#(~@ArL0t4yJ#^_apPlfPa3ko(X; zabN(&;-e&t0r;nQvy=ub+Obk@!l4`d4zp^8h&+SSrq(k!gj5J8vW*FhT}^n=mMLT# zaa1VDR%`Ws^Pq*xEdH#fD!2h1w*ii(#q5qW%K&U8H4#o_nsIz0J)214iBmJFLOXvg z2}ir|6mfd6=*N$I&sS!_5v(a7Z{?6FzDe{Vo5 z(7ts?;Ms~y7}E1Mo*N3eqp}?vuz+pW=R6vD!YYEdh3RA?Hxxoqs45thzeOldORCv& z!NKTOQjXdu_55zI5#10gaZDUZlN(-oW4d6n}_EK#0%o435YO=xrm)A1FR|o*zKI?#d%5iI zy-o7bqaNK%XjzYsVEMDaCIfmkd$uB}%zy+h!?BjZ)TGSXtjju8bGfkIwEY;&ouE3% zoyv^ySZIldEx`*lN3Cmws1>442pkk!C`3?*dLb?l;zdHdScr>+xLAmn2yuxJFBJl3 zh%Oc4G9fM(Vv!J62=Q`Ph*t=4r4UyMakUVR5FsJLLNo}`h+}O+GzrlxM2iruLM#@d zONd?}mI$#_h&~~f39(#=6+-k2u~LXtLaY{IjSyfvAjF^$LqZJWu}g>>gxD>_9wG2feV-8fg*YI@jY5nGagz|^ zLd1ng3NazXq!3d=q=dLxh=W2*3y~2bE5wWtw+N9FVwMhZgC)d;LR=$6n-J|nbO_NY zL=GalH^RAreC1JYQajf?ID{wf}Vbw6JU|An$tof5R`vU4vgIzZn1D zwg0ZQ>hM1wzYO=KxG%@O=p65b)cRhJT#Y#p@Pai^_m>q2>N zw94{`#ycY#u~%@TJLr&$9kjnChLCOH_H2v zb;vp<@57e5k61^nSK)q8-Va$1S@+<63+`9r-sjzKw%&~Y0s2gL-pX5VIFI|S7Vk%K zKcerqS#Pu6jyr6<19u4j<9LJhPU|u2-MHUX<$m1a{a)*RxSzoNd-6VEyFUS^%r_lK$vr~bGomzp2qz}++V=`W!zuE{UzKn+*@&f1o!9l{Z;Fa ztUcB%_5C}Rxd*L5>vi7!HS2ut4_T%AF6%DqsCVCK-Dy3H`wHAo$-CF;wZ?I8!+k;7 zeJlQt?+2_R?%Qx5z`Ymu2<|EGUTv+mW^vz*`*z%S;Qsn=<^G2C4eKiFTUOM15$>1c zUM%mc@xQfy)4R>DP^qVM`8FKBy6O4_QutS32w=QM4h4pS&sv$PXljsND{1(wm9(`O z7=nO0+_jPyIgzW%L*8?5rqzIgz!Gekn>cdjfTaF1Eb$kG*GrFn9(r9^cY$OGV~hV`@mRjsV*qo_@7O}i-# zC@oMz)%vW7x|z<9%12!g)ZaQOm*UHsmD-mrr0PxCSr#SXZNdv=EtGvQr)o20F{(_q zpRyrU0&^Oin%I3r!dGIBYhhNt7Jn^_?3`ia(GX4f^Nc zd;l{POU|T;y%{iuS#}H~xP^JOh57LpVUm{hFIozAt``CRRmbb$uB%;l+KcR8fTq>H z7=N#@FVyt^rk^IyRxkdL_;(q8zj(Eja)W(bJXj|07JIY(CeZX_J$gl1is9yeWWPjEEn*DYA8}>KtZ`t3rzhnQg{U`Q!?eE#&x1X_3 z*gvrU)c!O3&+Q-TQk6X0?MZtAm?U7zj@fa0mwml`gT33{V~=afgnhFNrSNyw-fQ2a z@ueC)4$KO%#6y%6u++nyd*Ed<`#${rG~ilfycO_OtmUd*8?pFS_#n0n48>jqY^=8S z;h6_~3Bc~dVd%vO^Li=Z62PsHJ}T?B~+x2(1LNqWn=+`bp_tL>LrFDk>o z+`d$%A1TAW6VmLHm@)bHfV~sXjrOR$$-dTp*pu}#>lniKiPw0TpJ+Z;Nz9{&WhG|D zKB!Y+Ee_ znq{q&x!x){Kj`7Rtsi?~%euqP`C>jHss_I$u|KYwW?9>@oiT_qw_=-RF3Am8J-(`} ztT))NvtMh!5xD#9mmtH%SXp->)(+^hLmusw_G&Mz_^w3!Hv2A(y~ch3<-JLl`KWlL ztn|kbD~fx>-QtZ1y$*0froRP$|K9#P&BMVq)RhvC{|OMdX^pq68xh(sW8X*NKLGrx z^(WR};`trG_W~?;*faY-TOSR?uJCKa;$FYX5^* zqRMMo*NDHKgF`>Su9~6vfp`YtuX%Cw1%#IYdL%CFOEG!oKGWFcsCHchWZ3T3GBnwZ zI#lnI>J>74pZxnu`y%_OPWv!Qe!F;^cuc%Q%J94R`&Yhvmi1@AWXdp>^>>oCnk-Y; zX*2jMWuO^h*3bPO9oi1NdI~-4!@@IQmHBccY`~6?g*^!W^-ipG4_eOx^-V9& zcf>bj_(ygpHt`0qbEk4NVB7M5M};v8o0jlN9_D)NL;0`&M#`&wb)M0Q9d<9U4faxB znq{@v4&ti-@3Buwp6?Ow7VpBYXcKlxne|nG@5vBj56j&DpyNNr^Ud}{!0q%XNcCO* zu_m#RiP2i7yh38Gv98AcM+o8PB%j?f?I!$<$&h8O)6XN=m#cQYLn6NpDx4*^zAb)V z{M=fO?b=@KcM`XGPNr?xb1>JRNba{_53O`9wwvuf`vQA`lt|(KT>Pn|EKxC}|F1@g ze4S2uJ$47~LinfRXX5{eztOq=9+*G3{@D69o+*!0ROV^Ho=v0mx7Odu7-ldseMJ6! zv&Ql9DBuz6Tfl$OlX-s+QBrOf?%S`;L57Jrx6gUInd@m}P<+y2;GV(X(7 zxYx?~C&j0b;~@5=I}q>mX!eL-U?14R4j1~Nhb<5MrIhp!Wl8>Boo@2}QalgL>&5-zYX*hqCw2IP@_8@*9tRxLSUy^@f68mTf}ccMUy<0q z!rv!#`g7vn#J^+n{_B>oYwf2*2891CekHzQ-D7`9X8H*B)G!N^;k&WtXkqv94fy*n z5_7$H4EssydY^t;){i9jFX=KY>pu|s0CwU^*HhSq)><<u>H$G2HkKgHnDSxpN!0wH z<~pmT=0kyJYJXC5D)7d@yK8>OdQVNFHd*_4?bmAmv-X#@_tze_-XOMH)8bfQS`&GlfXnN%!+~_o&uad@rnROa@a;fj z;Cq34Ywiq$Ykpeu4>ix$e8;{!a8IDEroCowV5D|W?Yi3awHs6CjruNVTpMaIP>Y} zVWFZgoIYJ&YrSOy)2^1*^dN({J|t~#x&3xvUy$Vzdl1mK{upH1T0b~2I6$1blzcx4 zJbDpJKO7)d@p`+>{Eu=HEYe2n6;RX*;NmCM*K5l!It%i61@j<(wm4S#3YvbL?X0|#o<{OdOB zKP2t_Bh)Id-r6O#)Y(YwR_LDBWy{s`(Y4Q<{%OrcftJAiBaaO|85kVsts%|ZYFCIa z*1iss?uDK$>#^Fq1NS4ed-MVPCHyw7FVzmO8D7J7{e&)&vb}nq(jU|MqGYC?Z##YG z>EShl1J9gpKm7~wG2~SCGB|Luwgt6C3-q6^e?eMXW8K5GZ0B>oEo%fh__rLeH!v_6 zpxr!E`;XB1GqpR`tJ%TeKn$-jDIvA~Y+wPxCv|-cmj{&@lgP7=#}R)1#n_L4g?_8H zxlYB1!F;Ih(z+a;kF-5=dZc!V_*HE;(lNi4e=*nX2n2psE9xF;QxyeaKjG8z5<9l~ovZ(RHM!PGuJ@1JXAiGY630X{a(oNU z!LpVkby3|vk`P{h&xWbG_L@(xdvfJ_?N`6LnPA;N@{+od+IoAW_J_5!)tJZx zx7#m$@lo`O1CsxCTlKepgcO4V-#dK~?6+ql?fIHIr|#l9w&MLGYeCy9rEQV9B6V$b zPl)!qNoeW*kvin>K54kIV48p^X%3J~;5Ex?!a4K&i?<(HFe&^b4m?g2VE< z<#iw5&{gwir~m5o;J^p!igkxiKVJ9fMb8G*O5h`bA3?)Cb-#dTes|z+L45)Es=oC| z+uhc`qGt5o!)Q}#<86U=qL%DSx7U3_YT;o?!CKxw@-Bosbc<7C_apB|VXgnQ;V@<= ze^htu^anxl6X@&E?e-`y1%ZY-Z7%M z93!uU?yeGSjb~B9B1rSO(~q>#672<((i06`FgWn&s`TK+G$qJ-Wb}Qqr#y?gy>R+~ zIH=p@8l6s=Yb4b8Mn1OlW^ws~AEGyr&%e}OE$JDy@b2^3TGi{YLR|2|>3^^L?>ZsV z1Ngge!S2!J3kD$@d0$iew!q)iJzqPj^FJGSTi}z}g&RWr1!(;WiC6m|8A$p_+Y{pX zI%U_7v>8oq1||8KYs~_-KV=i4eBBGDsm*_^tpTqu)VUoTUwjdr%drlt&<%HiUR`Wo_6b`12f&@W9~^jEjuS6m@V&aXNhx}3o(+5hdZ+In zfz1-IzC{1Qp2vF2x=5B_cyf1<;hzldS)lrx2+^jAn_BQ1Sn}7w^#gUcPT%^X^n#IE{NJc3WfGyacrL^=?2)#-w4&G5j9|1;IbZ2X z@+)ZRcEni2|Bt=v0MMd1+cUGfcL&HJpdg@t5o`0Ra_IumOSyiH)Ly8hfw5 zT_eO6QBfl*Mnyr5QNTo#s4+!sG3t526tTsQ`u)!{@4ny6es>_TCvo;}%G+n=o!Qwk z`!O)RX@?!^_8v@+_?dm)+bFo>p}hxacc}Xl{B2_T5-3KdAD7tD8zFz9x4jjtUeIjf zPET%#H9|VB`Vz0}5<3}fakg2SOoqR`p6xxD$H%2Bl8Nc7*{j(}Xw`G8Pw}+>OoyRl z*QVCN$g%eszm+BF1LlOZ@5cL9kE*`3dK!AcuKnla&;5RjD}lKg%OeKL+{nISSPlRE zVfUnT5`2MyvRa{5J*!()FU_{9UR1R-*_;~W#Rk4>Y+lV@-WiCpzNe+53Ef@U~kNNJH?_L4Fx~Y1; z<@twRF$G>H*vmG0Jv%6U(py7bWA1_`jts%Gwcg4`S09NU_Os_87bd$$(-d8bOYs36`qvJa zUYDS9f+v(==K;^H%5=JKoR`zq={f1yXg~&OujzFc)v%OS3C&$S>deB{Q#T;&XInD< zwU1FLpSJ6j73lQdL-!4@zr@I=_K-k|spX=GPCl>Dn_%IBm zgYh4S(^2P8@A+HxxCeEFSPg1JmFbBej2Wn0XD7l1j<#uZ;EohjMA@qo>qNY z^~u#|Cv~}Ha?_)+u7TTJxea{;w{y1Hu@~GnA~_AM(ArONcfszH^EPS7Q+i9A>YWFu zPehC>%pTK~=o7qM%^>Rx{PPi+JSMATJ*fS9s|)OxYxL^CTxfN*L?s+hXx-o+-{P36b!KhwW1J9pG0sybr=#&6QD)z6{98)vvFlfYYk!Pt!J;$xYSQtkL9KI=+lk!I$aUT)?QSu6{man-lrc_hRfE;x=re~ zv}=b||JZH(+Kbm7{GDHXXW?4YJ2vmM#X3DY&+go7-QzoT?s8F=s;;os-!J9^l10g) zq-H&lwMU!FS8tim4}Wb#*fs0kU42v!)(;PWn+O&p+56KSSIOsRGU&W~dN!p;y5p(7 zM@@7p=K; z^Gc%GTd&dVA9YLIb?Nk|CrEW|nO57rk{2U)3rfXBsJ|@Tel;vkRy!mg8F=7_HhvHF zJ3qOh1kFmI z!ZT|Qj{Fh5jP`2jrdO|>u;qrXMW1|3&>Grg6A*OKFuq=PkV?PZzKEOnJP;^pfWTkBzpF zJnJ~U`nQN5_F9zsndEqf@CO5x1 z@ARpqYpd&8R#i7M`SXqgy_%@+Vf*Ih$KL6&MNoRbO7Zx{90R zaVNst^?3E#r9-kmE<0w~Y9FnKHaZ0Vc*}>8Ic(W3rCG}^th&y3Wp7WvPkK2hI;PK} zboIyQwzvR#eo=jX>Eln%%{6*fMBABd06{0sxZ_@I6uHCRi_IeU`lE$=Fwe0(#odd? zj&Ith%unnBydH5c9z{=b`vY@;xfLZITjM5k7k40DiTVp}vk-DHUIk)05ikGuF{6_{ zhz~W>lhf>d_W0ylJ0fl8uC(pl$YgHXJ?(DJvj3MpX@8fThz%Rtrf;Mzvv|V1sKK9(lY?~d2ms2L0ZL&_;WOI8u-QH?`YzN!*oy#so zy*6@NCzH(}yKQnbo_EzIt+F?gN8BfNf4tCf0G`Wj;C`Lf;pSM!?0QT4_s1(e2jKj0 zFkbYVYhO$zn!Xv~AGj^DL(Sp#V7$yF^;*~6VlQ;(*^Atv<|NZ49hyC7XQj8;z0#{~ zGqbye=z4 z>3!MjZoYXeeaJp!e+RCO+%(+o?TywR0^4>?I;PLtzu3dwiP;{>_Q?&Peb7AMcCu$= zH@m^M=wqHqjzJ&SWY@amk=|OxLI}_EPNFk>u$A|q$BZq-W*$N_DW8+i_Kx_ zop!TycQ*q5d`xz4G6mi;9~;?LHB0Srb}{_pUfg_p3h8t9knAyT41LisS$29ym`2Q|uhO5Re=l&$2&12m<7{zZVYrwkevh}gn{U~wC)yY0?BQq;~ z9X0t~_69t#!QO@cH_?la!kYQ!ID0a-wHya4Hcw|HvtaXFJKCL$@xFzbnx1TXpl7;e zySuyWQEoo0JT#kRUNHM%wB3@;atq+|^q!+IT4v#C`{Zn@9iL1{hPhepdiUcb%Z_qK zr2Cuwk^{^(?kT()G#@XU{@gu*tuF_enaMJHzZ;9u)-Su#4oD}WMjI#JOU7i6VN~to zE zyb7D2vhTR}+)?gWHw?$qc(rCs`ixDJ2G^hc?zVAB(kwXz4o+)a zKUeSmls;$ILth{0dv7o#9OYg|+$?#+{=v%{o!pHvdW3yErQ`#X^-|xvZuN9z@_4co zWBL7b)pS412ousDfaV6Y+0&5F;L>zBBwqkqpK$x5#&0?c{L${`(BIkAqAhx%S2!cw zV=l=q%P!51c5{*!&Cz&?axUy?Kzr<)%uSxN&ja>kdL<;Rk}kvc(8t|mc*Z|L&Z(hKiN^l~ra+TvjQf9Rj?n7fz2=E>%HywG*D`#ySL7+x^8 z?s#yX;OzJYD z;jXz6v(wht!{*p`5w4$7J4T%?1OH{Ip-bo(RxPqNd~ndWrl9&~NY0@p4fRReVV z#@4%efY+nmZ=yEy@v7QucZTeH# z^=I_;AlUJYZRfSryRONA-U=ZemvB{+|6KyBsq&IWJGYkKW}R_Y-@yy9)E~ zGCK=1$gi?XU7hdWhtR)!yN@wm`X{4Z7rgG*8o6cID3Dg2jb6XpJ`5cXnZ@RujAQL$ zb9V9&G+$}!P^ztJm+j~7OUJ{8W$poZ(Lu?KtaCO4FMdsMZ5%f)j>EaG!CeK9o0M#d z8cxg}L2u2q7h^*-d?9<&Q#By|C+PkNd)cN}+o#ew$wsK@o3Q5(XoEU;da}?g!5WEP z@h9~3Eol8SKrtWEZpeP0P6y`qNgb%TWppvDo^Sfwh0wASTJBBEN#RWQM%CVkQ|DdAL_PpoilE<{GKCiy&H#F z>ENtodX)Vj*~-hA3wfFMjn2^C*{?(BA17st?cb79v$^Q~sqVYkRJ2%kyt4MR#f*jC zzXEa_Tnnrp=Gj})cG+UL$Xx9`*0hHs?qqFhQz6i6@1bb`tC%_h&qp%&RJH|6*9h*7V11&Y*%tpU00sPn5 zxq$x$GM2!uMds|RGwQ^#J|Ded@#6Pdz|F@4yG8Jz27AA!T!NO6y^PjVZ6e zUYKr`{UlrBu7zbwumNL<9}Tx)Cga)d#^l|snL84C7uyeE$I;0#I4jO{_xRB<*FKoE zta=zc?LaltZJi}p;Y>H@-~n4R@Sp5{j?xl0-JIf@SGB0(+<9q22xKR-T*ssqbfl#2 z>9D%w{tS+pZbL|*UtI5Y#3ruAklqX*RECwm7>UR&I)VzLve7Jq6rPvlr}vX*0KH_7ukDi}vRU zd6&4E*)>RaNIpUP+-9n>f7lFddw+u0q>`JmDYi{Uzptsf2CaUFI}=hn!0WCtYi6rd zJ%w5<2L3klSaK)M{%xyPt9k}Le^_!gr2HAacqS;XG3}D+c4~4l>N_3Sk$CJm9q{S) zE;A&(&`!reD#kOw(*UoW=4NAdo{sT6+n#Gb#CnhEY}EQLyd%i`G+4>B0WSpKX0}iJ zq^l!8+qT00s;-@&``wO-tvQ)!`@8@zR#xOl~)Gho`e4 zzXvF3*SV-EV^Em0;7N6`au%*5y1)l&!AE&rk)H*5^?13v*3H8UBJ&KfwK&_*!~5fr z^^3ktSaWEa0C}Cw`6w+$ue8W6K<;8lChhEuRHvnvK>BUwC-9A~$>orE8K6sW)Vh1J z3^9+jq4^4TPr3j+i|x#4uED(Yw7t>&)Xhk5@$|RlcGbGyrjMq# zVw=;En2~-BsZXSJp!h93qt-o%jSKH1#jr@K;rGv`Et6G~7qgeLGl6dfFRagA&Kk16 z!Y`M&i_x1G*)x&;ExX9x2=87uX`5VZkMvu#S|=C57mjo@>|5Yo5AZWx=j063?WgIP zi1)&E*%G%Ut~UnSpV^x*PhV=zbiJWtiS3gNO@>4Nj>#^`>~x>x2k`ZK>_pI>=`O{q zj2EMCF0#{-Yr%6k&dO)H6O)sGT?Z|BlkIBGO`eArT$ZehtB`h}x+9sF@UsM6aa?Pj zPP&?xlh=|>vSrCzfZt|ZN(_%9A-_2&Tfv@dakNfX^SJ4lcRAkHPCKX9qURb=%k|Mi zM>}f@?R|f`FkK4#FHo}uIlLZTKs+hl@~}UqAEas4I=d#l8ML>V)iUB%M~ph-9p3g? zKb)C(+{Ri0z7D*4<7}gB`)m$Mq~^Kq#dJirJ7%N_*$n%`Z2#;4q$gx2XBQ!@hfiFU z{V2N`d6sTN`p4`E_%^MXj?XRp9+01Bk7j?$p2?oY>vz=ts+V4uy_x+1uL*vX{m!_m zs;XvHx1qIKRXvxjT6GQTo#C8UkJ-N-=}7E1?hb#LftS$OJ`I3P#|*`E6U-ero1hkp z?JBU7n3FKGO*e0#M7tzj3e7jCuVGzO@6NI_+_UCmtdh7ko$jW)A7c#8uuJWgC|_i+ z!aCt~Txr~9mZ2@L&t@k_qDD8_F4bPNhRFsNmH@J^W^@)C5avhSc9cJO^z+D%``w z|8yVkfluA+g)i+$Di|Ph3g*5C$qf22m-%KSKE*=_Q%dANCGLZ5H)HW#9!&xAI6Omv z<)qmUZA!}hU@zrib6>g-dYgI9L;xTVz63qGz?TldeB?78PCDVlZ9-sfw?ah<@-0Bj zw)i3BOSlH_OFIG zk0ugJ&H<&3bJ8#CXzk zweU80_#A8=?hAhPv{St-kwh8fWxN2b$JP{GxFu^Yv*)<)WU5tdpe5q3d_hU%h=g-; z9cv{4x_Nev>yA0(9LGJ~+@2~QUpfmUXJh+GXQb!ge+OJOoriRnYzS&3VOX{nGIQ`@ z5DEMo44x7C!df1BA>!Y{24eQjE-GV)WeZBU*j$q5gzI*r8&Cp`(lQl&j7cv%f|oou zUC%M+!@5=cW^DKdW(2(SpIa`R!i`(#S!-;;y}VqjSU#m{?bh)9+Yui?TGPW8__mQ= zzX2b2`B_;4bxE)AF+`|?_R1#M3(|DB!)%I;Qh4GgYtqk0V9AteAPdNs%DQltED|96~NgisER#y>zDrS>Y z9VLhyro4AK2OkF_yp5;Q`m_f&^fYPNW>;9|G<5Nqfo0e_=535m@w4?kZVpP^(8Q1Y z@MTv9ncaOB5i#F`Y)b#gigzwVj^!;pcl=V=9Y(h{EyO3F;xRz_bFmpqg2>4WUW)X| z`3lO@3(Ve0OnZ@sk1%|m9C~6HR;w}w)H5`li?+l24fy8=!FVt%ghs*mA|j=iGUqhf z%YI|{mnAi68Z6^EUXqlFr(A8d)D>k(d-5DhxctWyDLT{0_*Ac;51uwi4ZMP8r5;GjQBX%ukj&=-{P}bcz?h{B%0$jGT+nNx-~w<$d`@T z|BRXTv3m2`n`&AHejD;rg1mZGjJFmp&x*QDGw zcS+<&u}sbLZGyjhPp5a>na^?T3zmXs2>r)ad`nvfFR=U7k9Zbo?)2*}rbm0s(Ju6J z@FT3G{Mszc&pN*8&kcEN-vKG-qr8KY4TY31H5VG{lA3d!M+x0LC-X8t&&_3h1iLo| zl=WF)y5q@&>JUz;Cu^mnOz?c}Lapro)f^9&n7<(vp4FUeD2uU5Bd{>uM2=WNNjk5H z+|Z`vCr-4jhS7d!uKj3l!AF*5(ZX2s4`M|lTfXVTB2{bT59U`*p(iJzC+P(;BQPiRV{T%(?7zILTC*ZUF6R;B7qiZ z&@(MJ%s&SpTZUR{62>P$4i8fEgF8q2e66=q;k#zLmDhTtyTVRHo8Ex&p%jG1LF6&M zAw9vK2#sUQXtu@NXimHn>+OB9YKncC#L{Nt%Ds#?@A4X|DD`Eonm)$3y$C$RTrFOQ z31L5EwFNdpp6fIAhe&4~B;1M5NsLD}K-d<7o8S|!n!@@__*E0zbbZ7AN4p}XCdny` z=?!TOHj>x)gKeNWrk(-oGlm{zNi}{p5}Z(-DTOFj4Yd4P_#n#)Q@L!-kSDYBFez)` zp^Sx71=rXY649=*h@t#z9S`OOBI#Vy&-Hf$+>UOb8-&m8?BsUFCwGRpp?Ge&tJ}>D zcO%^H`G=0K#TF~oqjFfzdpyTc%e07&?<%h-2sfXT@*t(=m!CGKQ4J!4{?ybF_=28( z1x`G~|3)G=(4EukWJJY9XYgg|*gh?BG2)u-kd^@lt949ASjoevS zjhvaUM#xc=D>4MGG3O9cU5I}PO!fS!upCt$d18Ucr;S^|jyMQkCHI}!YOe=gOe^P` z&QV?^Ms)PUGY9dcO1zWNGOYSV%g;tEh0FHuLo|3 z@5vY%@?EVQ7(t2Vm!BF_i8Fa1oLQ!gkELbVAjxSo73#ReJn3RsS1(mC%*Qy%2S_MW z21|@L$YnCW@}VEzFO#Exs=4K*lv;^XO@udv7y7^#XaY=lgJfbzcSI6kLC$*K-k5uc zBUWPO1jkrBLsQD+I)Pyb=3gFCs=N*%Je+gGibU>z2@W6F^KvLtWXU;qQOXi=GV(D2F(0HVr)VICxi!jGtHdBdagiUZpB(Q)+>}TDF{U#fjWd7D*j!y^%vDhmvAKN}5orR~DZV z&Jg1z@4*$3P{$lGXCNj;kf?A%mX_g!s-!rlc}-t3a;TJ0QcOrm6G|^Bi%$t>i1Cv5 z;EG77V~&_J5R)QER5&58<#2(iBvLcPv6NmlatJ+kruu^=#k^Y17omiQKx&4-rMW;8 zazY(*#GEl*Q*d&xYGe5-iPQ{n%+k{QP{~qeNiiXT+N7CA`K7*5ENGF-H3tTMHnr`E{9B10%C zCZqu$s6127*BDQ_rh>o)r?Mn1a*(1i9FV^UxM50(@Y(n_fEC|uK`jF?LEq@V@{r7r66s4|t(DD-2q zEawv$3J)>~QJkcozyo+_2qndYlr*6fcoeQ_Q3j!vffSU*pwvOK2j@7UQX0Xq^ij?i zTM^47rQ(==m>(iR%Pc7-q?J(RQMjhUp{1Bg^Q52#2Bj|Q@u)JD(kS#p{IH$U3yg6r zQ_GSrg9q@?5K4*(DQQ9}@F-l0dctY(*@Sl!}w| zBX|H04WXo%kdh{p0*}HqEy^IYGLV9@7?e6l_TU^RR7xWlmaJ9!#?(Qw(&NW6@5K01-auKR9 zModbTGBdp} z&kO7#^uGiZBqct7V-CyZD3B&9%9=T6Bs}1AU@k*TAr)%j5SfgXKc-W7fC>G(WlI7^ z>=h{?772-!L#acFIqXHq@ltABj`^4m{900qI91sKi%Y6UF_ai{GEW*;wku%8UZDsv z>ED3|@X!!S0+n(RsxakYD%6q|rNva57iy)8ODabw-!av&ureq;(-_OVl;c=o?;1H& zS|~AxH`StpG?nF;FW@VoTGmu$OF5LPtmFe7HC6_tXBuP0UQ!EGaZK?+2Y;xnP+~6N zrPR0_^D!UzwWJgw&2o*D&!Cz@-h(}cSS@L)^hI5ytoAlbEamDltQvAy(u2|@FR4nG zl+=}QQWvRMnw&!wCsa-IQ(~nArB_=NPfC?i<@1aMR%LmxB&n2(P~w$}loDdD023(7 zsh3)$)sjeLsVFzVg|bK=tWr2OQ9_Hvl$DiBS)OMq2YEEdRAgu@a%pm&XDSEfX^v@-FBruKcudtQq8DD3AXExdXpkA? zNlxjR7O7KTmYBBE9~36}6fij`OLI(%TBKZr$E6k#z0!&Vp;A~ZH_iubO3yT=NbMwF zmYBBE9~36}Nr1^gd75JywQpOIH945ZOxCQ96 zBsnby9RVN11WHKDs5VL~lq!*>qTIkOltp^d#uP2=>)^*v8Tpv9=no1L-w?>_fHE*u zhzFFTfG>k`S}Cs*)kbLrqY_zCJ&KXE7%M$fk)+hM-hPQGi~gW6@eP60S}jRV%Rx`T z$1s5s@>l?SEz~0*mB><2u2Mv-Wg1deQn&P0N=#Yw2Zf1m2&ARQ5GOe;2R%wHslXdk zDV%9beE&>R(Gl{@F~qV2B2b}MTNKmMt^(`o9b=)RKS*g6;0O~)C`nGsDoN-V#~xKI zHKu*TgH$35MUGfj%pGisDORzMd21!6Ec%1O#5V-;SnerI6%yn#r__=PPPvMdfi|X! z`DG`g(lzE53y3djQx26y&STtT_~#*VGz~j;W319N1rr?k>b)$+L9Sp0L-^`ttjMZ| z1^h}zkwdH@T%|J=8sQTP#-w>8kBOr!`okOEqBoE-kb-$F5yF4rB!y^Gyrcq;sR(J8 zTcxywi7b(-d4VfTOPY!;j3pP~%26qw{l68ySEYWSDWSq0V`GTmU-WlJgnDbwp?stb za#?!Sk6D4ou}}$L%u%0i741GG$GPTZ=u>*8AttXO8i;i4?8Fck@vtws`AaY?OCt>+AIdRJVcTnPfzSg1ltsm=m_Q*}^!mA*B!Z0!%J1Iv^_ zDC-cgp$v%{%w9RF-0fhSomaRXIv8o}-dODddEb6qP|}G#2^F$5eJr4DnVKd5IxCadMpK?TvSaG|KvME_(Q=08{(M8J40~y5-=XR8l1{Mk+GPk|S9j27O2+sBS>yh~UJL7oakIj?Qg% z?kEq4XoRvL%S%?qCS>I()e~74n2=M+0?hYubGJ5ka?5UR%?G})+Z+9dFJvi&@&rEF zS+1NhzA~>eG!=YYl00RJ{GtS7?;i5Y{gFL&u!}&yIPtKS_^CA&Q z1d%IrLH=CND=~3GMLv2)k)Ki+=H`c#NF)D3UFlJ$_^NvAnVV2qi?=P8eYunqC0 z1_`?%(fnynjvVFT#Le{*PIHtK2Z1X$F_g{zKi0isRhIa}v5>8v@gQ)T7kMnbV#y;i zPQw@IiIF(a3S4R>oEi&_#+0R)-d-2`-{AY-3YW6L7{6k7%<)3e8~Xo-U$6fgJZHGa z3l(DqVkGs&C>jnN4+hmLd6D&CZb`6UU{2>*5D711(ohyT1uHns$MPFI1!K|-hd-zl zf-zUg+?hwR*Yl+8?&RgLE&Un*DlbQlRP`(U?|ED zaF2{4rF+=hOx}TB!azt+St4ymU?dO|>m?8Wg_9Bkr@(W@+%~Dz0^fcM>})SfWHWvc zzg0t749tskUxd#L#J_L~UR#j#LMt)^D_o2TUF5kJ+2cJWp_Ii`Jfm@5FpDD35gO%O zWZD1pf)kh^2%hmm+u&yn%3fHOKw0Ej=;Pp#Y6CGMNn@o6Ry^c+B_wMH#mBR1k$MvauRc-=Ttmp)S*DCBA-|y_j@%Knjhwr_SpZza39O$`; z6W`koaLI`k>XCi_s#M3j@%3q6C*hfjPiBJ*Ws7| zL|>1Tn4FZzl$;7hHqR4!fahlKkg_lSO>PCe4((AF^*n80=<6}k`|MS6GSCY0$oX9Q zRp1&E8wc%sg|SQ;rjjqpYQP+*v`WV^tq>l3+dJ10@Pg6)7reymf4o)UW6`KFG4=Sh z9by@)-UIR7GJLPyf4xlkg#AEIBYXm3Oqv7zKk<}BZVAFqiNOZNQJ=tf#upb3^m2rY z{FF%iPl?N_Z?SmM(Cm444(c1*h7c$9*@cA;tspa$b=<M zPh28IIh2bKrI9qIkUZf^Uxa8WNEX__p_l*{jR79#g1j~GeT9yGwDKNTC*;<|zkacL zE!)}SC^ZgUJT$(?)zw4Vd7`!LckDX0n_bt#n!0Z!-+7o*y4R75;aBg#DpRCttQg@? zT0(`3xey2|QYw`|g;J^FQY=I80b@mwy+4&=33`Hs+RLPt?cQsfT^j zen*Ro=H;ZEPs=&JQQRJuRpBl3_W1T`Gus?*9`YS3zQNWCUxeUS5=g;+(D|4pDHEol zF@%_=Cv=6Vm>WGrqTkrx0{W=O1TfF1kJ-m@KK)$*Bj?lErt$fdyxq;s z_Sv|YUUk2(#0!o za`@f=j+#>!&rSFRgj_S}f@aQ&jl+sHlRnnWa;&*HD-s*(EG5>t=@4r!Qn1bpO=;G5 z1BjP*13LItWVvzpy53{x=xtJ4zX!v(BchgIbDTE-PP+#;srZ&V`&|8owP< z*#k{qjgqSJYE<41Att^WWx4Y0kY~&9hu{u^x3*}hT-A^>+=Gm-odqM;&XU*oi?%kj zYPiNPdbM7Iy@J_^)_&9Nl$QFs?4EYt5 zUr+z@xBiyovuMZ_EtOFvR6UJw1X_HNsEJvaup*^W2~;YsRB%DxGAR)j+C(P&;%-ft;V62ef_7_>GAMrCoF-0bgK zH80=q@ytHD1^2z=?4vSO3S|qOrfZmYFt1i#y9vz==2kC>t3uo@5TGBU&AgQ6?ma&z zhgHh^Hs~gKah37`sN=Qd%IL0Ko9Po5d>5&aZfc}AOIVTa6>EMuZzHWW+lno|PQG8H zvF2_bqqonH=Ww$sjkkD8+;ackz_x8%vI`s9dOwI(k z;xDnU-}PP;G*?~$eA#uDd057l&dDokZJEDGu_7RC?rRUK&kXGRmeAoJk?a$;sGNR*ML@fTQQodEvjo}dRutEjuyYx*I4vR zUR$7XixYpXQ!1^mrg6OkrP3=`kZ^(5EO5yeH3ts-#vf=ea7v{ZO(~PS)D>y>JkQ{YUlFlhQ)>W#mW@PpjY^8^hw$hsA%_o7DlIdZ~Um3}H z`rq*|N>lIs^f4{{uJo}tXr6mjB(K*^)SzLBJJg@qv>ay9CAiG zueeu5+l#;E+*H`W1Iann2F^`z$7Nb>gK{2jkMNL9v7&5Yj zRiE0hsc*w0LA{yJbytGi1}4D<-u2Noe0;gqb02VM1EJp}hZyrx;dkD-4_L4ImiXVI z=2c%DM3O@4Av^3pB~JDMt3IV;`pcAW^~kBHNo$`+P$qj5z@DM_|!z->IqzY3t_YkZ}s5*R9Vj>X?P;E zUl|&BCAXfH`UUt9`v=D-LVrZNuztp{e)5LJpPW1q+AWeN{KKu>p~ikc8|oMH2Mu^5 z9QD)ke4k4`GN`3{UvUanfeY7@;`?T8B!IwT? zZ8|~1-etSBHbbnoMzI${ZKzkRG$yv2wP|ekp3qYapU-Z}+S~sY1aoTltL0wguRqAI zK@cC?9iVErK*VnSb%|HYzx_l0IP3xCJ2G&2rn zt%A7LZ;$*vPDpaIz8yAjo@6_iU*o5-JHfc?@ZS|Dl^yFPBfZ)hwi+5zUw zTILkX+y4$5347ocwSx+4E_R7Yk^ie3Z>}=GcK>JQB!7mizX0>y^ju5~Q_LsHY||wn z-H(zZ)63H1)5+;-mJdVtv+>sLVfMr;oBNt^WKmv zdg-aA+MI5BneO)7G=tP0c0V@-~_O0|*+!mq48ocPR z4bs+j+w4TMgFV^YYfc6I>E0ENO6%->=DGAC{NTjaS^IR5tpn|ez@Lo&Q_UdIjm9f_ zkC{i@$#%3|JzMC;+BDlP83Q_F*UA_hI|j$erWZ<`@FV1hViIniwa@tTNmY zSiGP!$_~b2WJEF+dghyZAbSif91Hy3*}8ZQ@c8tMtS@lGQa%h=Uz z2ih_AcKp!wB-@M2_*-QUj24z#1(!JvhG_T6N4w9=*7UBF(I9d3V> zKAdtXHpXt_j<5sl5A7x3y%hg5FoXu!ecT6GYR|U)?KzOPW%_yorvbJ-UR0^E7q~XI zOL`FctHxeoTW2q4iG3aZQ)}C2k7j$KHpiiLZ-nmI_GVbj{uzyzNVY@1MauR!_~;SS zKKLKS9|c3JjkOzRt0l%hgmzrhu4Q|oHB;F2DD0|%T~9!MU$ki_ep<}lo3%mQ22w`Z z=j~rWHx_jDplh(bJ$!pFo9)&QxH{B-|LlNluzlMOOgcDxdJ2n)L$ZVHY3QR#C}9{{ zegL2j^2fl2QFdQD&bRo1c954v-x_7xx{1&_)=oiRF90uIKZTuL+!))zbpob?J0iQ^ z-r}zE-ct)ae+Y$kUgj=$?T|C@$_wC6FTjo;yAEj0?Ob#FlzrMhW4A@Q17!Wxy#Q?; z@S@NK?rPArvD>>ou#m7Z_&DaHSvyGF81395sk3WfB-Fs}L1@P@c3#rgeu6d_1>K{t z9BYvbg1v{jZQL2y;G5bbTxY=X3X*FMzDcO%e&B5f>NXaST;X}6@iAFyTH8Gi3!ZR2 z;VYxjXHRBzc4O%KUeXqQu^B9BV|T!bydz!`XP;5hEa$S3Xg_0@CAGkhL7xpm?7Y8> zfuvR8V`I|!&~&d$?9bi(u&Xz;A7r8?p_G7=Q4!UNl&W_|6g z?lrtd*8$M+==;9OB+%8OMSqao>DEN)HN>2;6I*3YKu=Gwo8l+1_eU!nh%t09X0b`A z(>W>U7mk7Lp|dBjW9+kNktfkV-!XlYKIo;ss7o*O-UhyHheG$+;5Y}Awe(T6)RuNk z($nsn0GCX~e+_K80`o>+=r}m(i(@Z4CE@7oi@9z9N_~?fll9Uc*h4TTsiiM)7y)Jq zxHh$$0ls%~CMY`E|3eGZqBYJ>dPC1au(1x5>n2;`$8U#X-spoD*!seLat&om*y|v# z2J>%ocu?!KH@I72RCd9r>jy&JD-%vm+q%v5Co!b}{rh;7nocM7zjroDK%& z5I|YS-pXm?S!vokFuj-4d>I35?V9Zo}T_OxeV=@VqU1ixUNAj(Xxr~EY_ke zINI2@>8xa5+YW8h3BEQQv+iU_ud#P0y+CSEdV- zE7Q*QMf^XG7ESFc>7j0Oa8Gk=n>w`3YiTPxAl(a^#$(prDeZ$6I|To0W0bK+S(82B zHx9GQmFcLor|kw?53&2E>)QR&wsrzIet^k(2U~6W*bdng`^W50IQzBtoLzw3$sU1` zSf5V9KPkFl-rW>^JIVhWq~p*Q#-5daA2TWY>b!L0Y@B@`vwT042iQxYr;qKI9fCHQ zWPk5E+MlG9*U>hsx-Q+)_JCD4rfuCe>1=4&E4vjj?OxZn#W*`B-4vs868fr>y)T^z z8++Raz~33^so6s*+oCV@j6ymR>BOuh+Gt#QQnnpt=Rc)SLf%uL@5z2fO0SrV*1HK5 z9Mg4nNjf>}WY01iLhm40c^+0|BQg5x;Da5J8v9=QK2{ig;Df!!1faWwf>iR`P7YSqY;y>5@%C4?cp` z-*>Z#_EFOdI(tF;7JePVw&;oTtFhZ;y|Wru5n1E1r$bda~FH7MF*oc6_hU26}7JbEcxr!Q#x!hfe`(*Ui5 zEf`%HTjyA`7-zW?vJd?9!Fr~nZ=JfV7iK+<^*Z!xU-b6|u)hwY za*BN*dk}S;>OJI_*{`yPvqzwvKC-!e46WANK9NB4F>r`|FPn^Y)M9vVC;LhE zeONscZGJ8KJFUv9CfS;*26q#DY?Z1l6RucrQwJltZPjX3eeGSWC3@-}$XOS*-EV(E z3arEK^!|{-HUn)npxZCKKbw%QgHg%z^SbC!&iQvIa=z~f7|(phz5vTR`q8>B`ezKz z+s|arX6q%KU)x~5m;zY6AIW2|`g_+?8~Y*JY-zR=&i9w5hggg8!8XH9HoFTx?awp( zN2o7XLB{+5qcR0%c3M?c1G;8a9URa1oZVVgtyjl}}fO*pKoUtKn zdlo&mgPn#Mcr);I!#e6^Hw3G{9f6wydpQI5#q4xi_PVF+2l)d~!!6SDu$E12&-8u! z0b~ucy)hH+2;b-DgxmR68S87+0xdY!kH1~gAt_hmtKn*(C;Do4aBwZ#5}InUI^p=^ zH3`q~<8h7|?MEf&53WIURMMUlHB4bY)`pnB*2YZ06+|nnvRk1Irs97RR@uh9koCs( zODEVr6`xbt6w%nS`!CH^A&>he+H`xi}cV0dl4geHCz~HtA$7s9I zL+N`hA(wL`+qNyn?--+u3!p?Y!k}QOE7T zA>*MVT9W51_VxCF?txXdT;Xsw?1WYJV0g&)(etdsF!)0YtPcj+yeMj2ag=juzEi}Js~|2YZjapaP^9L$Lxzb za`tVGRrbE9M=h?n2Ep&z0NM?$*9YhOk@hlZ?SyqyA5dSN{u$>Mj{YIAmG=RDihCy< zukbFM^~cy(vn|0#A7k1Fqkk0Q8r-8`X}hE)t_M%!n97lKSkVY`^S0yH@f{N_`u8eIx9P?!u%#eK~EQWyz748(+lr;6+%CY=PC{>*=BB z@wd`j@_Aq$G)=ZIC#S>5uJhX}?y@(UVYqHevz-!`4alBwXQs_Fu3303UP5S{vByiL z)w5Q(Rxg!0ASHY)tWrv)u2_k2%|ghdJ~n0}P;HEV1N>%K0ixu$HR|@pQmLhv0NF_E zKv^oCoiHwybY#`RR|k43rXxVJ2mUt%1lM1FOR=Wpn&4&dTD?^2&GC=b2cWoC=b5Hd znxEX09FcKkaqb{TsWc4fj`k#YAxpnbcFEza^%&@oT9- zxm4mAUh}2Wx_CrVkGm=(&uUghPcD`4kjS6mMc%!hifa~@TjENAR(?NiVfObLsfmI1(rYLAaz}WCtXYU_ z39l`cUdSm4DV3I>w23(jGRTD*V0`Mix>VwtrJv{e(D&S6tXar~+oSMW<``<6)^dA0 z0(TdAce5Y*4>iI+*UIzLj-X)}hMBQcTHDdyZaGYB6+C-=GY{{cV+ns6v)i-jw&3C| zA6}(rrV4jQ*`iy+J9;7A7XPneR-k{qk-k~(hj%f@luDy;E*A~FQYe*f^kao*m{MsZ z&M@>kj=Gk(Y9gJEgZn%kA;G_RhAEYF)Rjt)m1#()LHeEJK-Lx<2NF0A*f!Nzvkbs0 zoLkC>xy9XzIuFggOU6N|B;#OY*4cKk`$V3{b}W^&-*p^pZhr?Ep$Byl#!YRNwCOZ&J9}D39XU#+69GRfw^|^fr=`s6936G+ z=~C&kgrjblze-i#E4D6uZ(qM=kx@sk`^<+}vv9`asMDS%CicDJ7NM;?wk z#xH%f-FSaJ`t|8tM_dKMJYdjzOST*mEhWSS%>dYs7tm8(tQS&KSv#=J|qej}A z^f-<>`W`hOfq(j*Y9{|t;F5l1>BLC$>A*S8Zm1W+qD4`kC)# z%waO>ID)8$@l9nprP5C2IucX#J+0${GQEyEdXu)U`X2ciUcg-t$>|7U>lW+CGV910 zpZQ_9N@ZFq(f2|Kbrc^77|DfMiN3dbKK?pn;(KeA$D`J3B0LPM6wu0=MMfP<^r>x~ z%+nloi_2q5e5wjp-{KdfMh|)!l4m^1UFK!WSkZcwN{#EqD+TyPR_!Kx`=&dNy5hK^ zL>X5d-ASO*(aU;W;5h0^rE|-*V~Jrid`3lb5|8t~r;u5or|&hx^Qg&o74)Dyvm`z| zv&4!o8bQCvM&h1-RTS$LMhv|PccGJTrXGm)Vr$Zy z#^7JqdgRn_6kdu6-b5&8Db|b6ELm0$eA(@qa7@vs_JCxzCP&@!1IOM&hQ23bWsaw& z@4aAO#Iu(o=ZVSH9uh_!uUf-cp-+h?eq!h1ilS7Shr7}$BluBAyRE;54D&PE$@?D1 zijLm9leHb^=b_2!h$TqPW%O=_D>|vU%#DvH!pZiQ`FUa@b7O~WS+W(NtXG$8TU=)r zM=#H0GV0W)w7uK=_Fx@(_k=#hfV=Cd)T^a!<|*XviC`tx`CsZKux_58V~UoF@2O8s zEQ}fYp8C||iTc#olsrA1PSnJ5rIq6jI<>4$}S*Q583 zN>kLNsnJG`&@%0_z0BTz?jW3jV`T=O5$Jk*8lHi3)fD?O>BOft#4`$(7(2 zt4+Mltjbq8GIPq+fzYiNtu+YYbtVJ7d`sNN30^Mn{qfB5KwNzXn+WHV;4t?RqP=!f z#+SZ^;J(^0yQ|#|cW}ciNbD!-(N_aU;w~|HCCCiKJXc5PfgHzPi)(vq#6!BuAY;W? z+y=)?LoBb0@SGdh>bx%Ec#;oo@IEd3fa6K}K<)wZx=5w+Q&1c$>;ry&LhgI84>q@3 z028i@N~K;{?`?~_bb1vov*`eT-$VLf=Ui@O+t7zAXBxK61l+?bmG-v>;EC};$Z@?a zD@~43-UHN`l=ez1v3@dER>j#_>an^%!|QxOtJ#MeXK^3$IZ)r6UeC_j3Yw~q;S7!U z5LiDxnG-DM3++RhFO*BqBC?*b zl~%qt!#$OzdvhUb@cDa_Hp`XjKPp;;7!B_O7moymYpSh;c_#U^R{C_GUtTNqP8$3C zr?nC-{32UvMXjK%(KyxiN$pji+CJoN+KX_P=?nKFuC|+MA7hHE4?b1noRHu-P34>* z*RfM^=SgeMK4#Drl$0v3L%2=|BR`yv<^Gr8dSfn^Rk_}Il5=hy?rsnEI2rje?)7|3 zeVo0=Vb0$Z=a%9+Azb?#+$AAxdiNG>OZKVO^z)s^zML6oMKiSeE$gtNRSB`N-~M;k^M9o`gWs}$8Durh z+^4UmNu^==XUq=#U0@Mj>9*vp0axUv>siVTIw}D+wDKKH^24Urp_z>xjp)=-+mGOsrUEk z2gUH!pIN@l9{uLj^M9k3^riomnpV~mPl|C@oGs9J9Z%>t?F{$hxyFMpjtE%E(6mf|-U9%OSq@d^Q)KRrvfZewH>4PYuKKGD?v%3!lxgKR;_tDT!fa&Y!YR zLEq(Tsy{_mh>JB1@VKUg#x-rao}~J3s^>Somi!15+dK~J&Ei{hf?ZK>e%dc|?(W3_M#fSCnXB(eQ_o%_!N__uK@5sw+!{>r48in!uZ`#7){Wpay zZ?<7=NF(o|f04Bb&le0dOv&FVV{MA-^W}NtXQ@~Ge#@6tug1N^w-mpOUiz%H34N}) z<({G(?-y@eN*|aqO{&;_cYl9TluW*tDFVm{{OZ%@tpQ;-vr-?SMA?~ zS>TK7n^4EF_d{x^@9>hM@menCll+Qj0fXJDVU1Hfd;aIurnqAJDr+Nc-MDYmD_1;2 z7vCx^UI|mOTpt>&Y>GRNL@U>%l3V`HBc){8EvNRo*?gXR4C1jwDwWCaCdnJ4dPk!p z-k0azlcu~+c7c;$LSyga9SyDrWj8Cmk6)^q;`fSip5ty-UeD9}hUL2(SXu)xT_5l| zj6wG7G+rM}^xxUgt7=keKm0o@QSuc-cKJ_F3mL zCa$IK*_AyGai8@>`^LK`^gc~xE#o@yK21$|#%PJpO^-yM1;3N0Tk-qa2YIV_pJrw1 zpfwA#9wDEv4zizVLV4```*jejzTP@;#C&t>Aa^uF?`dvDzC@bXm+0ZKFR6^mcmD~G z=P;#fJclV}`QyQua5viZAHMJ`EBYUy9BP{G#Rt=5c(KY^?3W@)kLzvr0&+i}7AE}c;HS)W(vae6z zJpaXeQDXlgg|6s?8oPNxA8HxvjB6>>s14lT;MM(v?SW;x%2h4*OLn#T!w#fgADFmZd9LMt$?oMZ0g0FC z9Z2yqt^oUEeI(zB8jSBV%3e~|lH*LCu=6`Id--!GeR?0jb3W?j5qy8}br}(eJKgR>#l+yjfoM+mg90wis?1{J@LKBY%LUcTE zKOVoSP}vi@Zll*UzFO7sKt2Zkh(qOifpDpvj0f32JlQ`RJk)DsEg2fu5?>C%F6pLf z$uF9bhqYuX=VZw>j&+xGTuY_msISXqXf4Ge-Pat~l2<9q~FSv$*Eh=Mgg7w)N)}W2D{nIxSuwgwY!JC1p0AZHworiGDx+6u(!R zXARB(8gvGT*Zss*%8Ydqk8l2>hT%GmwUqM|&)Q9$r^qF}r8?DP1yiYWL#&wjN?gXbyMm4V-O({qPF^xRQdOVJqW+E}CTfBG3xdtK|QSA%+W&iy3Z z6QSR(pyrP76?ziaG{rL{xx^}6U#K0$eq(#+Qz&T<{pwA8-j2U@NBY3U_TYI?t*Z2u z*eb1|_FGMvE3`Xn7}q7PAvMS0v)53i;M*5yQwiGcEXAXtSi^WU&{FxDAN^WAL_C&U zE5B+J3qq^1EccfLBdx0K7h5XtleF~ppiYL+7wqeBCqM2B(pBESA&f!wNZZgVy?@iP z{KYxxr!ZnVVjWLU6bXz~Gp(X0##Y6e)v8#J!I$9smDeP!eb6i;b8uOcYHnQnqGr_- zEF=WK0Rue=+OPN|R!5!ak-0$IU2CS2ikidxt-cjBOFzZ)H)XJ{L1w5~)AKhuiW&)t zJ(lB#GG(q+kCoXY$P7J1{>CyxJp>5N2J!B;s&jVrhpdZAcaXmz)`deHN@&$j3 z>md^L+|ZQFcy%A@q5VUC`n;ZvM4pa6nVUkdgxZ8Y6Ao&YG0$>nKh>lDR%}0=eZ|9r z%%D*{Jg!C1$TpR+C3<@MHWqKz_9KjKDl(;J^k#BYwrSjcYE29a=W%M55ZY8)Qm)L1 zQ_akWG0ak|In+=v!8fV7vW9Uxs5R81Ey-MQ_6W17jA3a9ndbx&*HHSW2+K}g*8Qf3X=x@>ROP}h-SZ>2TGnN>9hYvR?8&KWUG zN0ij2XboXaojXFmR@Nr&SE-HGP%Vq+4C15@rC&o0g;zX|HRSu6{7n*p7d?*OyQdVk zZLn-2?sCP~1GKDL?g^9Gbv*(9dmJAga#{i&&O72e3z=W{A8u+D~)h}WF0SMW$sc@Z}I*J z+ogDyiuZE(#WUKi*QbU;5!)IEHaZ8`n>+$Mr6pyz5A6y~ouIT)b~Y7{AQMv@&$^ z(9nna6hrD5e4Bht-8Yi28HM|CrBZ)LYTG~s+I-^S!_XJS_IUt5*)X}DKDA=l0)qB73(i=wezO`lJT_wcv% zl5{Q=Tf+HN$`Y^me5&7Oisvr!aV}kc-9+;8&Zk;8q0+U2l)nDD$-Mk+-L!W!4L+%m zZ!6$RzgpduElvw0eAz7?G!M$}_J8%7E3W{)x;lTWxv7!W_)3pH zA@f>sKG7?^6<=@B$2g|tU0wArO~Y(L$eMUUs`E*4CL^{ulQn&POFF&QqvjesEhUU2 zx-!JNS5#~A1>GxCYiic{`>WMVy;XUgnXl9y*O~Y=@xH#a_=?**JcU?MZ-0ID{#G-4 zvl!yO{`&lzHtCqITq6)y99jBHSn-`BQpIC>Wk(kIzBtWtFJER8eP%`t8b*}&a4AG} zkMsL?WDXV1P-oe7Q2Dzy%Bi(hiJEd-^;&`Pn>efy+!Kg9-;%VqCLnz zo1B!dBuOh*2(p@!GGnztIoVUReo|p3-RBWtB?p%g=*Z>I|r^s%br8 zMH}?_D>0m%^!E$-h5fzNg=C!l{VSi)6K_%Ek4Z< znCg*IHJ*A?4}-kbvnopRq(-0;^Qs~|sUa-r858~XojyT|c_qKCfBPYZH!JVu(lXW^fk$kBpB;)D7)#{Qn43H)6zq;k%n1 z>iX@x+aAMqAAsD@fry6lKTn45FdXOspc*i6@KDol7ciNA!*&^lJmV-kV7EQ$b`j{n z;REV+A21w+Aw%jA4;``l@Vdc6cQ^fq;cw^wM9l9l$zDTuA7%#ZGGc%k0OJM>`~UX7 z1h9?b-h1pgheCiHEmt|#hkPWFt=!-otYSOF!HJFST!hq-rL`?0YlV(Drlov9fv-S{ zxLcs0hNDminnEe%>H(A#T8{L5J)rNEQp$stuLn@heZT+Aj&>!jBiZ45eEnWE*35tY z*Zk){v$M0aW6dfiRJCksYU${1MNuuApluzruksPws`gH{YW+I;HgP%!fRyE$DL1}F zVl!1~UByt9)^$y7>ziAUu5RgU?MB+#-Rf&=Jsozp`A*-=+NkO+X42MzdUFgpLjvR^ z31@LgLnIN6(A0wZ=j1bJt{u_Z)^+Pq4i(Yi>ugz<5%5{EzV4h1vTJ?aO{>}3mhRQ< z%}glaF*%q6(xA2N&FkA**xL2ozLiMVwQOYT+ShfqG_m%TYg(GR8NA=#fr8;pX*#FVfF@?At#9e#O(1%Z>G6!KNpYvBNmt9-Rz{HkR{J_TSXb*Qtg9PN zME_Wi!n;?a>S{LSr6CP6KqT|WEDit^=q=SBUocqr1}5Y~2T zvHHPqxTNHR4kvW!v`$B~;*4I=ksevzm54#N5)LJ_m_MvU^n?OvFck48w4i!ma(ZMz zYdEa+LoP7jkNE?TRBCstdqV1B2ZB3ZmmYD=layY6V0%35j}ItXJm8ONN+_blg*AFC zPoZn!nB{nRi<|VpK`oNVt=TAe7`U)|AQV>urdU9aB>bUBT=7SgWW;ifG}Uz66vn2^ zXuf%*F~^_1T0aR7XfaK7b&f}~TJQFct~9-eZQHGmxEg8{80}ZKYr{i&EI3yQC6s_a zLe1H$Dap7NRQz!z?C;gk#{NMVGk=>qK1QMRh_^Me!ygU>GyP?^s?N{Fx#Q)tQ?9Dk zu69qGKM{(|vl=r_jT{Q1JwkmUEf$~C#`|1uyGuEi3~ z>9m_WaSea~x=Z}jbb2;g1ziR0k~j_gLA^7bt_tcAtqXENeJGO9HvprB2#g8GoVEiAw9Asovzh(qAer-@EK6s=Lh3fF!t%OPg0VM^ne9PfY`UC(={B{V}6tt z>eDEW^Z^};1j5On*3UsSawsv7PR|KNLWvOEbT$w$BkVtW_)Mq`Yl$RE8}ugv182j~ zK`k+$2R}uS9!!R{bD?E0neg|9HKu|;q75-0s1ZF9(*g{hsn&bX)B*_x_f+V848Ez- zqgsTuP(H?1K|wSY+JQ@#!Aq4S)qyk~>SyaA4VNV$4VP3U1|SBfR3vnEI^|K1eZ2JL(#_0Z6DPc8Y@Tozc24du z`|`xICUs2SGx^g~&S4)IC2S)8iD?p>%(l3OU9D5!G2S+gKID}{-ZI`a9+-CMq5ebf zJJfa9*2BJj*u=v(AAT2R?WeQ#)9;-A{`Avk+%_Y^zGu8@yj03&ZexCS2>Vat7325D zj?$g%(`=Ca(YT03*vs5ro&CXRD?5w5Wc-r-yYT}1t?@czGhZ-jW;RWHx%7Es8aoP) z_VJQyOP)6lW$R~tdgjeDzdv)o@wD-b@vQMfF(ai8&R`y{N0$r-oTOKk4${u_$zx0HT%GL4@cAAIqN<6Y$kixp!z*L z=^v$KCI2u=Crm7P%TT6FDR~qBh_VmyTgE@|`0&?R2DtW3sV)hWy^rH0>1RO(%ic3? zDt&vxyT;?Lcd)tOzLNKh1(QF(eDS=J^Gn`0E}wjKNhSVqY#g?RW$~?rL@tNWkuNRv%hX<$6D;^TO`CYJ z8T+!eTRDQPT*S;pn2u}mEU2)`5&A?Kgq8a3spP(#BZ=orHvN{YU0%T1@z;b>$lhma zvgj5hZGQqh!XAre7|*ev083w@p~>q0U~07`HMolCI;z9fH3y*N*StRACS; zA4fP8*ZMTbR!#>4!vR-yJ8%AC5aDmw85H_;Y*(cd~7_9#n zyO5pBE&$&t4q*!uVH3u!+_0JD2ZfC#oS(y8!NwLoo5x>@HVUvHVhS4TLpu}H&f^If zF|z}4OkiI$sl@pO^o!j{2hpvBmM^p0*`1tYkIA={WrqjZvnEAIOkmHUPkkLNdKY^f zF@>M9pP^S0^dOHXvhSE7j8Txvo51N4Oe%3Q@IHvX_%MPP)2L&g#o_%n%-2~IRzIH6 zG6}MRpJK+IL`bq9A|!c;0;hB6$B1{~D?UHQ6+t$}dD%(GCfQ}2PjXzs882ZJ#795^ z^CU+-#bYX$zL!A$5_Tz>v_8LhJ!7V6ah!8p@ zM(|O&^!;2`Im9CeIbo}`;9f44t7#JZ-;mhHX&2>b;%H#$W0igrhi_)*nEax=i#ZQx zHF<@EtUGx-ZS%WfP`fdFckndZYLXIdm1IMJWLsIbBzRFYy(63`OAMMsxY5KCh4jeK z!}0@H#G@Y|w$sT5@g+Utv)4>1+0MS36LRGRv#@YG3n3dagP>53@D$E;2zCjAsZ6@2 z@T3%}sZ~Ol>rmOJLdU7&2#l?PG|7%nehHT+ zYv^+lzWMj7<2lWWmSFx#f##u&MFuHNy2c~FL@MBEv34#U)y`#kb}#1`S&XoA?D7ix zUQTejzsXWW>cmk9Cp9Pl3h_G8x3T;nb&AwZe}v_SZ?pVh*I<{o<8xsr>qf`1an;t+ zSDq*DH2=!B(TSrFPHHFzP>9!wPWNZ}4Dz^8B<|0WE5(5;WEQE@xMh*A$$(d}>i}Py z$rE7tt{7;n{JA)Z7mN}=9TC4^pU9=2b?$x;iQI20EKv+=wD^|LFyE#ot{l8E?2C)<-1~_gKeLD z`FdWRdPYHf1Z2l#*O>SORd7Cy{L|wI^=u*g5x!#&vV1Eg3;+A<_QG!OI0D%yzGN@M z8r|4JzQhR24??$$?R1G7OX?)wfVIW3gvvZ_r)x6XDkqLYIH_U0qr#&sKS-S-wbQdH z#pQ~XFJ>&Tc=E4mi&hMjFMsf(g78N}o?D#y&3qeIeO_O2lE}pg1tdE@`Nvp(uo(r= zPS2(kmn&92w`K>qM9GAAM^1t{CWG+lSub zWCy1^#^NluIB^uhNd*f46ykNFOZksJb+T@B-1us1>06lREvMPcqAa&KaTLNy1q%Tb z;&q}+`Hw!ed{+!~ur1gGD7sT1M-EO+^N&fmZUyBcHt*m1$x96%o}Jhdnia^3>`yUvjBQ>-D7>|5@yN~UD&89(c+{*F;>2dx@ z@5+)T*Ml5*NM?~znetM%Vw0zcufQhHpD~L6xj)mfA$$h5q#lEK z1~zZ5#YV>(Or`U~25i&Z3hr(Aeg@xj!MEBW;D5$=$i2N$K6mRU<;V6pbZqQ-+!y3w zXq!|og4nDT#HP%#EvZ1M3!S^rWqx*P8q!bscsHx{Dp7>7%9&~P_4tb)NfkOtv zc!+QE6fxa4sBi21Hu9W#Ga=05*yS-8HVUy=%CgRC}qTq=loy_+0 zcrw>ZyQa?qG!ZfV-^XN>Ks+K)Ir!-r&N&4eq6I`4f&}LKoGN0nmA+FTFQ|g^Zs4Xe z5l_YTXrWg?6ibZ2PX;GhHx)VrHJjrQE`JENIurB>d<7&iLW{7Fv`poEf=V&%d>5a? zI7I&jaTvEw{DXyv1x=JMYDcn!75o$nEr;`z{=Gs#S8+(hgwZ*jY!#N{U*#by_@xYf z-W&9*u(_N9>3z|oa;zzSr^cL6A~EF)})23BRfc97UvNh zU6@Gb2D4Zsu zrO*!sTRlmV z>^&Cp$BrW$4;iYl_#6+|X{)ECOD-p#1LLHI(MmY5^zrzY38{fn%AEjQZm{z>bL2|o z=B0+wO33BU%`5D?IU#p58|7swB6Z>@gp(RbS0P>}x_#5Ngr!cAN-U*LliB>upO0kK z%Pya-IXmZM-RQXS)z;Ei+*Z$Q3!S!N7Q#slLMM(wI9dA&)VC0?6a8w)UCqWG zNJ^G1(;Lv%^!xAoG=S_?P6+FJ6(ZS|Bj6KSChTuyYUp%UJ5q8Gy5!t#UE zDN;K9+Rrt3;0nxt&6J*C^*Vv*8&VAtChkscbYar=; zyj)RM@iAHF=2p6qx_J!@LqK*+w%x=hsDkrpdF^j}({U2(Fy1fMd%Sx7E{|Rb!{En1yiCN2I9` zuM=I$fAp!7b))0PS6fTpg1n8f&KuHk+)0ryeKl;?!zR|GbtF5K2 zxUHTGv#uYft(b*y(yyec5U&$m%765!lXaux##dWQ-;%tIvGy1C63+ID#EvDE8kV4a z#v&(qPc(Z7r2;+?|0u}l z53&@I=FmOOvvZuO+REJdVF9EEUF1L-Qn>qK9bV*`Gi8~=Kc8)PXW z&7~HTml~+NV)%1;PRX;=X{)C!MWjv~g>X^>l~;(@iQb0Inr)C3TRjO9u!X@-7w3fj z3_nRp3q%@1UT)l!7z=0diZUr5f_5oEoYsfRr5wfdP4G0qC0l89^Q5x`y!c zRRS^$0ogHPb0_grc|-7!pjtBLa4qNH$F>Ay7y`0mNLJcQ^dZh|=eU?_xtLK9)(Oat zv8*P0FNO|5wPY^gvSQn%;3n8G>==P3Tj_fVbXeOo1?^I<27nt%*LKz5AaBwOiA zKeQ&Omds^b%Vqc}Hvt)jfb1A)BiTXpOF6flV;9%53qKbpAj1%lg}D(N^d(y_#m|cE zf(}6yoHqiO8$`KIG1)5YmE{Spdx19$5ep2JDL;0YxOOr63cE-~+DQC2f|ehorh`fC z*4bgZPAZx56iXhN+WGz`!}nqr7yr3qhuwewJ&}n8JN|AozBdOIU^t%7 z|F=yx9%uY_%G8Xzu>S!~Hf!9@`F~RoO;)-l-!!_2=^Zr1g+JnwFTu|aXMZL$K@q#6 z3&*)bN47SGfh0fV^873RQF?%Pr~IkLQTUzUd)Y&XALf&ld=5M2DDdd0g|%r}P|w8H zTY|E;@QR$%1~0|>3bg>dco!iim(4%2(hZb&V7(Js_4aRo_>KekK-l#t@&{*MVOYc^3 z#LhPBt9smVcU+NwAGa8kP1Y7^m#O!8$m$Mi~sn`B^gxj#C=+hjF;gpccddJkg|sqI}gA zjg1vsw$=o6eS1iYr$Pt`>284?n@?;Eik`^}V_tR-}o(@tJ7TAsqQ3 z*%l7P69;RXO~;31Rn#Af9jsM09aZaamQz)iKByhMeZ1T0{M@IEh2!jYSz6?U;SOrO z$^JRGx_Y8G(G26kT=P_@o?s{zuM6w`ASj7}xpY)hk2vZnUY9^0>!Fjl#!$l(b1y7h zPv(WRXiU9S$~oAcWu#?$R+Tcg=MNgvE4=YUGt$vg;u>v`SM-oS7Qv}=)jc@cO6yTo zoVqqgo+2h{q`;p_JlX5vV~wKsDRf|0gpX@A7)&Z^>Qz_67-VqRS-qPp%O1i{S`SMw zu0>-S4!m|SO2m)p)&iM0~_bEO|q1{bV+*RpQ=orMXCT}A0 z%t9P|2V-$AnikxkiUp@+~>e)X=3Zk&&%1T~yU7vnrQF)(x7o;Daw4A(De(-I0D ziw1F}HxvoN_;|gmnioJ??IlP)OdgVSTw%SdraOu0VO$wZV!$8p@6Z%~LJ4br{1i7OmW)sv@JoQ-=Fu6W zF+HHg<9dwW+?z-0=`=;0+lKT1B7EK>@TzNh(VEm89qzb_tH`yW#XOKtu@|cZb<~O6 z4@-i{0GyzRNe4}-3K@0EICMIh=Q`OO`8~-<+}~%Or^uVkpKUG%ktFZQu+tpK5;09n zlch7SNUO?7-A2*XY0}8;7jd&XPu-Fs!6#eQ`jqOLCuVfy@hrFS{(vzV-2lB02L{SX zUwp4Oh!X&{SVNSq1dVt4^P2aTm9j0(N)6pWFfmJ8^MAD#Q!4S7AuBcfI*mq6z7ccE zJzMb6ynAkkP|urviJ56nCW172^_VkIbp_YcLuR76Vm*AM#S9YTM$A7*bIK+i)8zi7 zxP~xLp(cE!kltxlmygOKdd|Eiaoy34ODHfM+pI3iBauk?Y-)~aA5&clUwmjbCg3Q$ zi}9VDyBL9rH!4}o5IF$za+tkmo9e1`Z}ECg@_Wwqc~0-CpS=}Y+*{17XRETD96r0f z$+wn{>GiF(fpyz8E$RvCfjI7@Xxu=eA`mEVt!STL(Y~OzogaW13Y2%%_|GBD`JSI2i}6~2CV01tb7R5;#dy=!@|KS&p7QsX!93eHtASHW?cVt`gE{K)LX9~GZj}Jm0rUNQY7xdQ(}314$U<@IJ6g?dQN-*{oO;) zk(ja5soC{Jz$Hi1Wq%^xU}obQd>;vD)roWlPB};hgzF=B0NO!u1V9RThx&TI)mC8!D(6Uq~e6#T{)ue@^Wway!1#t4YSs5 z4+F0^8%Ah{GnG}HY(X2udof<>5-+xNwcbcC~#7> z;s6Z)7nP02E#*B+u&{uY%E+)%(^I3wHL4KqzVQaEWYVLbQnMT_08aybtNz}$4m>4L%8?Hh81xe)MLYq%7P}$-?Ye%`Yygi!zaq>qRh$w zCdG7wInLwOV@t(ju_G;i%|fN=>y#OLD^$g&5{L(j5%;oz9rIVHA{nU>t4x>yj8tRp ziSxg27BaQ!(q;1$&-@iW_Q439i_X!i>Z(x{bqm*FieiS!1>Jrr0&aDyS$5fxKGj}I zCFZo$>s7@Pr&(?~GZ(KCv-SDBs<{7KUd*s8&Zlu9{#v3E+FS~3;t$v8B~dZi$Mg~1 z1Z~bA8@PGokIH2`R;U!=f;tP#zR%TXeu5zt1i{{xHx82+|)g5u2(Ck zy35n5T2&ty3{j+4)a#V)%tRsSQnjpZWOi#qySe($?butE^r>e1Nk1%9w^&>%T8$T$ z@xh|(cBq9bx&OuSG2~Wd%Xn2(VM%dkx)RUkYPt$>NUc%Mm`bm*${TCtMc`Uw zzAKUlWs4ZA=;cyePsXqqLeI!>ULc5$F#;3N(bf(iOd)kNe=en-asn|+RjkI z?b!j$k{l*Ut@W5s?yfmX7kZs2K=I?5Fhr#DgRTJn*w3dn)gF#^En5~C46aa=ju2Ma z@TiM>en7tVP-sOZ4m&X6>L18n7vW-69?aZa^>!7)Uk4JZgph0AGBJFi1IF=;{Fv04=b3+Ds-ue#;L3E2o9HQd2JaOgLKoGA8&6zrnm+Zd7?q2w0@GkLj9TIT4zqkgSj9nc zJ&4g7{n~s>l9>izM6d9)y5=j*$-yY^OhGNj^kH!;Ln~5@q| zKPNuwUbWH}>-UwEq*UKtbvEFh0WFM+&sS3V`{zJ*`(iQwu#at1eJhCpZ_6dagx@|# z9QA~=mXCZT6E7lNb2%ClbDDwz=_g(;4=3^hCX&vky=wJJ+=i$`b~{%%e`Vgg2grYh zl)6_A<4uH*wUV;=^tPTR@3h*!ia*AoA^|9E-m9LNPh5$o;6U8h#tZS<>23bAhf(}Z zyuwYiN`?X#@)}n)4fta|rgEX0rZ5)A`r~kpLFUw$b5vi+Bp=CEi?vpeIeT?8AB;d< zMKx`10Y`HP4U~YL-{dVoK551?K7UAs-U-i=-r7~@D%7~pRKpc#s`nhXs%ACr35nh? z^gO|fn%jyQP$JY9qMin+-*9iWMiL9=``C7s-0Vhf@j@Tlfr3%2yN&uS>N$Z}tC7Qn z4<}rxqMfVS@S5DWlQY(~;SNgu8P+{cymf7Qq#r|D1l5@E1JYHw)(?-d8+k3^mbI8s z4*0`9)-B4aT8kA`SQX>q>-dO_hJ(m?Bwn+Q-(<A!^BgKt_Bz)^Sy7WqR3Ci43LfsrEP?n!((Tn^(H&~8C#ALgwy*7k znI-p-qH2!lLpI25s_w)fst+RnJ>kDDEER)XI*G(9yELlKRl;LkiC_=S7GUvBM6K@P z?dxN0q`6K!(cqee|IkqA8Khts{kq+(a<>-4vO}K^21W{My2UaCid#b}YRzdd^_c6( zywf~u{fWRpPoF;&#*#wQDd6h#;HKK6_w@{7#U(b}qypFFHQ%GsHXHt?tf`4CXxZCc zv&xiR$&FZFw@y#=@CU;tbl<%jV0OHR4>V0aIDX?COtncn-36MOsp6Zw&7mD3ddJ+; zJKS@&7So$rAi237&v}9EJy`XL;h}w~X*DsQjt9GVPcIg@w&RUQNN;Kd>lO?qaV>^& zO8`)-A!7=CVUD&}~eoGk!{W zAFGIDsoABFaPz`>-2jzvvVF!-2Hn9$`(j@C*NW0 z{QjxOJh}UV=?!PUcf`-rX=uuc0etw;t=E5W#j6$TZ+PAJ%Aae~X*chHDR22P4{g2g&g)&rO_AFbX-|{$&kXJy; zyRfVJtyku}{*&OVUu7@PI;x4}_+9}x+IDrNykESb z_Qm@H7oYWm&%FA^9rHiA5?(eh$dtD(acHvSo99%_nRMIKuCG452M*)cF3m?%-X$m8 zbxiO5|9GRWWX-YR|9J1uR3=^Lv6MG{uMu8)dGnP|46S@{?e04oPe?UF&s;wBNZ4o&Kq>FCYvx{a^$Yv{_;jSP?2FI8@CIzm3|A@dYyanSzv#O8*|&F8 ze!Kd$SN{T6^N}s(ef{PS8ZXz|Z~uE&m&bGbBgaFfIR>V@FSq?}f2z6Z_0xX&gL^AS zzV$_zf#EXc{p-nxxu^eS*Qqn^(udCSpMN!q$_%V2@3d!+Jn_`(S?`^B#fvSk)@c`@ zW^x=(c|%8jVd#e6`!>~`z2*EjUwGx?u!9Edly^_hwrhSgwL9RwEB#y7MYmoDCyIeR z+dgNRE552JS!h1Gd4kz+EK+2np-@4p*BT@Hnb8fuz>Dq73B5k-Kro8vO zq}}%PBa4pv-j*jP9p`;~6GZquB<0=p>aJ~nty|Zy{E6$1Keztf-GZ`Ue#-mY3rpW` zKJDZ;-;e(A?>k<3XMH-Ib!$p_dzS8f@tkKqc7^xM^FFoay0U$6m3cEudCOAO|EQX_ z)c?p8Zymk&jZH%^U)=ao-ffS*+_(H^=ghkAO4qzZ{jt;G4|$VJdDou&tE+B(`QBt%rEJ-o5M=?evE(a&LVVYQ=3h<*j`GJNuNcOfPL}S3kYv zIrSDI@tbzad;8=K#~k_bmwx|^8Sj)|IC9LXAc@<1%6n_f=(u8J|G+t_@8a{HdZiw9 zFlPcO@5rU^|8~-?fBW?3-rfJeTkgtV6HUw-Qr?wU9`UTP?ah~d{Y3pY&OdjpAD*V^ zMasM8v~y;59P-%C)K$|@*8hCMx4M}BnM=y6 zyTAJ5rv|<>zvS4Jmw&6ebY40=>hve&y>{h`e>!5tsv*~fPxW1V;-7lbX@`ka%KQF< zZSOoEo%{Le-`4fx?|5ezCh^Hv$~*YP72auoy6(F#9{s}~O+Bll84B`eY$@*rt-B7} zz9;&hQ@-}xm!4lU=Xv-~O!QLTrTf2DwsG0-es%6+zbR8!TnPWwVz$U%52U<5TsP@~ z$v^(XGkcSNfAFG33W&B@W6IlkMA`1Lci&#LXwz+Pw7vJ@>*!$inP$psJaPN;AAe}| zjb}d7bn?e;-1Q&nbj}PFBk-|TJ^IQGHP8O#$#;*q;ZwIgV-_JMwkhwd$L{Sf``zuo zxaG1PuU+z!cW+14`7Ai)U9n;Bgz(mzv?YPRwUjR2a3~38rpzht)tA>q?$mmp|H8wa zubiiU5}luB*D3FLH@3a@(*=(&eDuh~{2zUG_X4%4y}5-=@hog^>)_|JG`F>N(aZCW v&epYz9aYin>-MqIb!}an*RI6f?3Jd@CeSC{4VK9?ah-S4NhfXc&YSmNHH?fU literal 557017 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 z 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

  • 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 Kw2Uw?Gz0*7FQlCS diff --git a/boot/ocamllex b/boot/ocamllex index 8a2e0d8ba6b0d91680064ec7cb14b9ed3bc1c893..78a36bd7f3a9da33997af3a604e3f3470a6bbc47 100755 GIT binary patch delta 53100 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 knd&L8U0PX%_oSqj83)df4~2)KY8hXRj;aE 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 diff --git a/bytecomp/.ignore b/bytecomp/.ignore deleted file mode 100644 index d2f18a85..00000000 --- a/bytecomp/.ignore +++ /dev/null @@ -1,2 +0,0 @@ -runtimedef.ml -opcodes.ml diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml index 10e70c0b..806c22cb 100644 --- a/bytecomp/bytegen.ml +++ b/bytecomp/bytegen.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* bytegen.ml : translation of lambda terms to lists of instructions. *) @@ -140,22 +143,28 @@ let rec check_recordwith_updates id e = ;; let rec size_of_lambda = function - | Lfunction(kind, params, body) as funct -> - RHS_function (1 + IdentSet.cardinal(free_variables funct), List.length params) + | Lfunction{kind; params; body} as funct -> + RHS_function (1 + IdentSet.cardinal(free_variables funct), + List.length params) | Llet (Strict, id, Lprim (Pduprecord (kind, size), _), body) when check_recordwith_updates id body -> begin match kind with - | Record_regular -> RHS_block size + | Record_regular | Record_inlined _ -> RHS_block size | Record_float -> RHS_floatblock size + | Record_extension -> RHS_block (size + 1) end | Llet(str, id, arg, body) -> size_of_lambda body | Lletrec(bindings, body) -> size_of_lambda body | Lprim(Pmakeblock(tag, mut), args) -> RHS_block (List.length args) - | Lprim (Pmakearray (Paddrarray|Pintarray), args) -> + | Lprim (Pmakearray ((Paddrarray|Pintarray), _), args) -> RHS_block (List.length args) - | Lprim (Pmakearray Pfloatarray, args) -> RHS_floatblock (List.length args) - | Lprim (Pmakearray Pgenarray, args) -> assert false - | Lprim (Pduprecord (Record_regular, size), args) -> RHS_block size + | Lprim (Pmakearray (Pfloatarray, _), args) -> + RHS_floatblock (List.length args) + | Lprim (Pmakearray (Pgenarray, _), args) -> assert false + | Lprim (Pduprecord ((Record_regular | Record_inlined _), size), args) -> + RHS_block size + | Lprim (Pduprecord (Record_extension, size), args) -> + RHS_block (size + 1) | Lprim (Pduprecord (Record_float, size), args) -> RHS_floatblock size | Levent (lam, _) -> size_of_lambda lam | Lsequence (lam, lam') -> size_of_lambda lam' @@ -303,9 +312,9 @@ let comp_primitive p args = | Pintcomp cmp -> Kintcomp cmp | Pmakeblock(tag, mut) -> Kmakeblock(List.length args, tag) | Pfield n -> Kgetfield n - | Psetfield(n, ptr) -> Ksetfield n + | Psetfield(n, ptr, _init) -> Ksetfield n | Pfloatfield n -> Kgetfloatfield n - | Psetfloatfield n -> Ksetfloatfield n + | Psetfloatfield (n, _init) -> Ksetfloatfield n | Pduprecord _ -> Kccall("caml_obj_dup", 1) | Pccall p -> Kccall(p.prim_name, p.prim_arity) | Pnegint -> Knegint @@ -364,6 +373,8 @@ let comp_primitive p args = let const_name = match c with | Big_endian -> "big_endian" | Word_size -> "word_size" + | Int_size -> "int_size" + | Max_wosize -> "max_wosize" | Ostype_unix -> "ostype_unix" | Ostype_win32 -> "ostype_win32" | Ostype_cygwin -> "ostype_cygwin" in @@ -446,7 +457,7 @@ let rec comp_expr env exp sz cont = end | Lconst cst -> Kconst cst :: cont - | Lapply(func, args, loc) -> + | Lapply{ap_func = func; ap_args = args} -> let nargs = List.length args in if is_tailcall cont then begin comp_args env args sz @@ -486,7 +497,7 @@ let rec comp_expr env exp sz cont = comp_args env args' (sz + 3) (getmethod :: Kapply nargs :: cont1) end - | Lfunction(kind, params, body) -> (* assume kind = Curried *) + | Lfunction{kind; params; body} -> (* assume kind = Curried *) let lbl = new_label() in let fv = IdentSet.elements(free_variables exp) in let to_compile = @@ -501,7 +512,7 @@ let rec comp_expr env exp sz cont = (add_pop 1 cont)) | Lletrec(decl, body) -> let ndecl = List.length decl in - if List.for_all (function (_, Lfunction(_,_,_)) -> true | _ -> false) + if List.for_all (function (_, Lfunction _) -> true | _ -> false) decl then begin (* let rec of functions *) let fv = @@ -509,7 +520,7 @@ let rec comp_expr env exp sz cont = let rec_idents = List.map (fun (id, lam) -> id) decl in let rec comp_fun pos = function [] -> [] - | (id, Lfunction(kind, params, body)) :: rem -> + | (id, Lfunction{kind; params; body}) :: rem -> let lbl = new_label() in let to_compile = { params = params; body = body; label = lbl; free_vars = fv; @@ -546,14 +557,16 @@ let rec comp_expr env exp sz cont = comp_init (add_var id (sz+1) new_env) (sz+1) rem and comp_nonrec new_env sz i = function | [] -> comp_rec new_env sz ndecl decl_size - | (id, exp, (RHS_block _ | RHS_floatblock _ | RHS_function _)) :: rem -> + | (id, exp, (RHS_block _ | RHS_floatblock _ | RHS_function _)) + :: rem -> comp_nonrec new_env sz (i-1) rem | (id, exp, RHS_nonrec) :: rem -> comp_expr new_env exp sz (Kassign (i-1) :: comp_nonrec new_env sz (i-1) rem) and comp_rec new_env sz i = function | [] -> comp_expr new_env body sz (add_pop ndecl cont) - | (id, exp, (RHS_block _ | RHS_floatblock _ | RHS_function _)) :: rem -> + | (id, exp, (RHS_block _ | RHS_floatblock _ | RHS_function _)) + :: rem -> comp_expr new_env exp sz (Kpush :: Kacc i :: Kccall("caml_update_dummy", 2) :: comp_rec new_env sz (i-1) rem) @@ -562,13 +575,18 @@ let rec comp_expr env exp sz cont = in comp_init env sz decl_size end - | Lprim(Pidentity, [arg]) -> + | Lprim((Pidentity | Popaque), [arg]) -> comp_expr env arg sz cont | Lprim(Pignore, [arg]) -> comp_expr env arg sz (add_const_unit cont) | Lprim(Pdirapply loc, [func;arg]) | Lprim(Prevapply loc, [arg;func]) -> - let exp = Lapply(func, [arg], loc) in + let exp = Lapply{ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=func; + ap_args=[arg]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} in comp_expr env exp sz cont | Lprim(Pnot, [arg]) -> let newcont = @@ -619,7 +637,7 @@ let rec comp_expr env exp sz cont = (Kpush:: Kconst (Const_base (Const_int n)):: Kaddint::cont) - | Lprim(Pmakearray kind, args) -> + | Lprim(Pmakearray (kind, _), args) -> begin match kind with Pintarray | Paddrarray -> comp_args env args sz (Kmakeblock(List.length args, 0) :: cont) @@ -632,6 +650,16 @@ let rec comp_expr env exp sz cont = (Kmakeblock(List.length args, 0) :: Kccall("caml_make_array", 1) :: cont) end + | Lprim (Pduparray (kind, mutability), [Lprim (Pmakearray (kind',_),args)]) -> + assert (kind = kind'); + comp_expr env (Lprim (Pmakearray (kind, mutability), args)) sz cont + | Lprim (Pduparray _, [arg]) -> + let prim_obj_dup = + Primitive.simple ~name:"caml_obj_dup" ~arity:1 ~alloc:true + in + comp_expr env (Lprim (Pccall prim_obj_dup, [arg])) sz cont + | Lprim (Pduparray _, _) -> + Misc.fatal_error "Bytegen.comp_expr: Pduparray takes exactly one arg" (* Integer first for enabling futher optimization (cf. emitcode.ml) *) | Lprim (Pintcomp c, [arg ; (Lconst _ as k)]) -> let p = Pintcomp (commute_comparison c) @@ -806,12 +834,16 @@ let rec comp_expr env exp sz cont = let c = comp_expr env lam sz cont in let ev = event Event_pseudo Event_function in add_event ev c + | Lev_pseudo -> + let c = comp_expr env lam sz cont in + let ev = event Event_pseudo Event_other in + add_event ev c | Lev_after _ when is_tailcall cont -> (* don't destroy tail call opt *) comp_expr env lam sz cont | Lev_after ty -> let info = match lam with - Lapply(_, args, _) -> Event_return (List.length args) + Lapply{ap_args = args} -> Event_return (List.length args) | Lsend(_, _, _, args, _) -> Event_return (List.length args + 1) | _ -> Event_other in @@ -869,18 +901,14 @@ and comp_binary_test env cond ifso ifnot sz cont = comp_expr env cond sz cont_cond -(* Compile string switch *) - -and comp_string_switch env arg cases default sz cont = () - (**** Compilation of a code block (with tracking of stack usage) ****) let comp_block env exp sz cont = max_stack_used := 0; let code = comp_expr env exp sz cont in - (* +1 because comp_expr may have pushed one more word *) - if !max_stack_used + 1 > Config.stack_threshold then - Kconst(Const_base(Const_int(!max_stack_used + 1))) :: + let used_safe = !max_stack_used + Config.stack_safety_margin in + if used_safe > Config.stack_threshold then + Kconst(Const_base(Const_int used_safe)) :: Kccall("caml_ensure_stack_capacity", 1) :: code else diff --git a/bytecomp/bytegen.mli b/bytecomp/bytegen.mli index 24f1d64f..b23a1dc6 100644 --- a/bytecomp/bytegen.mli +++ b/bytecomp/bytegen.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Generation of bytecode from lambda terms *) diff --git a/bytecomp/bytelibrarian.ml b/bytecomp/bytelibrarian.ml index 7c96dfd0..e89676a9 100644 --- a/bytecomp/bytelibrarian.ml +++ b/bytecomp/bytelibrarian.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Build libraries of .cmo files *) diff --git a/bytecomp/bytelibrarian.mli b/bytecomp/bytelibrarian.mli index b9a4ced8..04a0316a 100644 --- a/bytecomp/bytelibrarian.mli +++ b/bytecomp/bytelibrarian.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Build libraries of .cmo files *) diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml index 2f5c0ec4..e77920b6 100644 --- a/bytecomp/bytelink.ml +++ b/bytecomp/bytelink.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Link a set of .cmo files and produce a bytecode executable. *) @@ -50,7 +53,9 @@ let add_ccobjs origin l = then begin if l.lib_custom then Clflags.custom_runtime := true; lib_ccobjs := l.lib_ccobjs @ !lib_ccobjs; - let replace_origin = Misc.replace_substring ~before:"$CAMLORIGIN" ~after:origin in + let replace_origin = + Misc.replace_substring ~before:"$CAMLORIGIN" ~after:origin + in lib_ccopts := List.map replace_origin l.lib_ccopts @ !lib_ccopts; end; lib_dllibs := l.lib_dllibs @ !lib_dllibs @@ -80,11 +85,7 @@ let add_ccobjs origin l = (* First pass: determine which units are needed *) -module IdentSet = - Set.Make(struct - type t = Ident.t - let compare = compare - end) +module IdentSet = Lambda.IdentSet let missing_globals = ref IdentSet.empty @@ -595,7 +596,8 @@ let link ppf objfiles output_name = link_bytecode_as_c ppf tolink c_file; if not (Filename.check_suffix output_name ".c") then begin temps := c_file :: !temps; - if Ccomp.compile_file c_file <> 0 then raise(Error Custom_runtime); + if Ccomp.compile_file c_file <> 0 then + raise(Error Custom_runtime); if not (Filename.check_suffix output_name Config.ext_obj) || !Clflags.output_complete_object then begin temps := obj_file :: !temps; diff --git a/bytecomp/bytelink.mli b/bytecomp/bytelink.mli index 37dad2b5..113207fe 100644 --- a/bytecomp/bytelink.mli +++ b/bytecomp/bytelink.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Link .cmo files and produce a bytecode executable. *) diff --git a/bytecomp/bytepackager.ml b/bytecomp/bytepackager.ml index 05ebac9a..869cab79 100644 --- a/bytecomp/bytepackager.ml +++ b/bytecomp/bytepackager.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* "Package" a set of .cmo files into one .cmo file having the original compilation units as sub-modules. *) @@ -96,7 +99,7 @@ type pack_member = let read_member_info file = ( let name = - String.capitalize(Filename.basename(chop_extensions file)) in + 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 @@ -261,12 +264,11 @@ let package_files ppf initial_env files targetfile = files in let prefix = chop_extensions targetfile in let targetcmi = prefix ^ ".cmi" in - let targetname = String.capitalize(Filename.basename prefix) in + let targetname = String.capitalize_ascii(Filename.basename prefix) in try let coercion = Typemod.package_units initial_env files targetcmi targetname in - let ret = package_object_files ppf files targetfile targetname coercion in - ret + package_object_files ppf files targetfile targetname coercion with x -> remove_file targetfile; raise x diff --git a/bytecomp/bytepackager.mli b/bytecomp/bytepackager.mli index 69e3c77a..c856b632 100644 --- a/bytecomp/bytepackager.mli +++ b/bytecomp/bytepackager.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* "Package" a set of .cmo files into one .cmo file having the original compilation units as sub-modules. *) diff --git a/bytecomp/bytesections.ml b/bytecomp/bytesections.ml index 759bde3b..061e0923 100644 --- a/bytecomp/bytesections.ml +++ b/bytecomp/bytesections.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* Handling of sections in bytecode executable files *) diff --git a/bytecomp/bytesections.mli b/bytecomp/bytesections.mli index 12e679d7..22e1a3bb 100644 --- a/bytecomp/bytesections.mli +++ b/bytecomp/bytesections.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* Handling of sections in bytecode executable files *) diff --git a/bytecomp/cmo_format.mli b/bytecomp/cmo_format.mli index 0c0f08f0..fe14af0b 100644 --- a/bytecomp/cmo_format.mli +++ b/bytecomp/cmo_format.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2006 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2006 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. *) +(* *) +(**************************************************************************) (* Symbol table information for .cmo and .cma files *) diff --git a/bytecomp/debuginfo.ml b/bytecomp/debuginfo.ml new file mode 100644 index 00000000..1ef4de27 --- /dev/null +++ b/bytecomp/debuginfo.ml @@ -0,0 +1,81 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2006 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. *) +(* *) +(**************************************************************************) + +open Lexing +open Location + +type kind = Dinfo_call | Dinfo_raise + +type t = { + dinfo_kind: kind; + dinfo_file: string; + dinfo_line: int; + dinfo_char_start: int; + dinfo_char_end: int +} + +let none = { + dinfo_kind = Dinfo_call; + dinfo_file = ""; + dinfo_line = 0; + dinfo_char_start = 0; + dinfo_char_end = 0 +} + +(* PR#5643: cannot use (==) because Debuginfo values are marshalled *) +let is_none t = + t = none + +let to_string d = + if d = none + then "" + else Printf.sprintf "{%s:%d,%d-%d}" + d.dinfo_file d.dinfo_line d.dinfo_char_start d.dinfo_char_end + +let from_filename kind filename = { + dinfo_kind = kind; + dinfo_file = filename; + dinfo_line = 0; + dinfo_char_start = 0; + dinfo_char_end = 0 +} + +let from_location kind loc = + if loc == Location.none then none else + { dinfo_kind = kind; + dinfo_file = loc.loc_start.pos_fname; + dinfo_line = loc.loc_start.pos_lnum; + dinfo_char_start = loc.loc_start.pos_cnum - loc.loc_start.pos_bol; + dinfo_char_end = + if loc.loc_end.pos_fname = loc.loc_start.pos_fname + then loc.loc_end.pos_cnum - loc.loc_start.pos_bol + else loc.loc_start.pos_cnum - loc.loc_start.pos_bol } + +let from_call ev = from_location Dinfo_call ev.Lambda.lev_loc +let from_raise ev = from_location Dinfo_raise ev.Lambda.lev_loc + +let to_location d = + if is_none d then Location.none + else + let loc_start = + { Lexing. + pos_fname = d.dinfo_file; + pos_lnum = d.dinfo_line; + pos_bol = 0; + pos_cnum = d.dinfo_char_start; + } + in + let loc_end = { loc_start with pos_cnum = d.dinfo_char_end; } in + { Location. loc_ghost = false; loc_start; loc_end; } diff --git a/bytecomp/debuginfo.mli b/bytecomp/debuginfo.mli new file mode 100644 index 00000000..b80fe99c --- /dev/null +++ b/bytecomp/debuginfo.mli @@ -0,0 +1,38 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2006 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 kind = Dinfo_call | Dinfo_raise + +type t = private { + dinfo_kind: kind; + dinfo_file: string; + dinfo_line: int; + dinfo_char_start: int; + dinfo_char_end: int +} + +val none: t + +val is_none: t -> bool + +val to_string: t -> string + +val from_location: kind -> Location.t -> t +val from_filename: kind -> string -> t + +val from_call: Lambda.lambda_event -> t +val from_raise: Lambda.lambda_event -> t + +val to_location: t -> Location.t diff --git a/bytecomp/dll.ml b/bytecomp/dll.ml index 21688e08..c64f43cf 100644 --- a/bytecomp/dll.ml +++ b/bytecomp/dll.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (* Handling of dynamically-linked libraries *) diff --git a/bytecomp/dll.mli b/bytecomp/dll.mli index 878ffb91..485035ea 100644 --- a/bytecomp/dll.mli +++ b/bytecomp/dll.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (* Handling of dynamically-linked libraries *) diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml index e9a97765..0b09b87b 100644 --- a/bytecomp/emitcode.ml +++ b/bytecomp/emitcode.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Generation of bytecode + relocation information *) @@ -143,7 +146,8 @@ let record_event ev = let path = ev.ev_loc.Location.loc_start.Lexing.pos_fname in let abspath = Location.absolute_path path in debug_dirs := StringSet.add (Filename.dirname abspath) !debug_dirs; - if Filename.is_relative path then debug_dirs := StringSet.add (Sys.getcwd ()) !debug_dirs; + if Filename.is_relative path then + debug_dirs := StringSet.add (Sys.getcwd ()) !debug_dirs; ev.ev_pos <- !out_position; events := ev :: !events @@ -409,8 +413,9 @@ let to_memory init_code fun_code = LongString.unsafe_blit_to_bytes !out_buffer 0 code 0 !out_position; let reloc = List.rev !reloc_info and code_size = !out_position in + let events = !events in init(); - (code, code_size, reloc) + (code, code_size, reloc, events) (* Emission to a file for a packed library *) diff --git a/bytecomp/emitcode.mli b/bytecomp/emitcode.mli index e2fdb815..f4716e03 100644 --- a/bytecomp/emitcode.mli +++ b/bytecomp/emitcode.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Generation of bytecode for .cmo files *) @@ -22,14 +25,15 @@ val to_file: out_channel -> string -> string -> instruction list -> unit path of cmo file being written list of instructions to emit *) val to_memory: instruction list -> instruction list -> - bytes * int * (reloc_info * int) list + bytes * int * (reloc_info * int) list * debug_event list (* Arguments: initialization code (terminated by STOP) function code Results: block of relocatable bytecode size of this block - relocation information *) + relocation information + debug events *) val to_packed_file: out_channel -> instruction list -> (reloc_info * int) list (* Arguments: diff --git a/bytecomp/instruct.ml b/bytecomp/instruct.ml index 70d62229..0360a6d3 100644 --- a/bytecomp/instruct.ml +++ b/bytecomp/instruct.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Lambda diff --git a/bytecomp/instruct.mli b/bytecomp/instruct.mli index 024dba13..d56bbb7b 100644 --- a/bytecomp/instruct.mli +++ b/bytecomp/instruct.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The type of the instructions of the abstract machine *) diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml index d32ac4fb..b3011291 100644 --- a/bytecomp/lambda.ml +++ b/bytecomp/lambda.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Misc open Path @@ -17,6 +20,8 @@ open Asttypes type compile_time_constant = | Big_endian | Word_size + | Int_size + | Max_wosize | Ostype_unix | Ostype_win32 | Ostype_cygwin @@ -28,6 +33,14 @@ type loc_kind = | Loc_LOC | Loc_POS +type immediate_or_pointer = + | Immediate + | Pointer + +type initialization_or_assignment = + | Initialization + | Assignment + type primitive = Pidentity | Pignore @@ -40,9 +53,9 @@ type primitive = (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag | Pfield of int - | Psetfield of int * bool + | Psetfield of int * immediate_or_pointer * initialization_or_assignment | Pfloatfield of int - | Psetfloatfield of int + | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int (* Force lazy values *) | Plazyforce @@ -67,7 +80,8 @@ type primitive = (* String operations *) | Pstringlength | Pstringrefu | Pstringsetu | Pstringrefs | Pstringsets (* Array operations *) - | Pmakearray of array_kind + | Pmakearray of array_kind * mutable_flag + | Pduparray of array_kind * mutable_flag | Parraylength of array_kind | Parrayrefu of array_kind | Parraysetu of array_kind @@ -123,6 +137,8 @@ type primitive = | Pbbswap of boxed_integer (* Integer to external pointer *) | Pint_as_pointer + (* Inhibition of optimisation *) + | Popaque and comparison = Ceq | Cneq | Clt | Cgt | Cle | Cge @@ -130,7 +146,7 @@ and comparison = and array_kind = Pgenarray | Paddrarray | Pintarray | Pfloatarray -and boxed_integer = +and boxed_integer = Primitive.boxed_integer = Pnativeint | Pint32 | Pint64 and bigarray_kind = @@ -159,6 +175,17 @@ type structured_constant = | Const_float_array of string list | Const_immstring of string +type inline_attribute = + | Always_inline (* [@inline] or [@inline always] *) + | Never_inline (* [@inline never] *) + | Unroll of int (* [@unroll x] *) + | Default_inline (* no [@inline] attribute *) + +type specialise_attribute = + | Always_specialise (* [@specialise] or [@specialise always] *) + | Never_specialise (* [@specialise never] *) + | Default_specialise (* no [@specialise] attribute *) + type function_kind = Curried | Tupled type let_kind = Strict | Alias | StrictOpt | Variable @@ -167,11 +194,17 @@ type meth_kind = Self | Public | Cached type shared_code = (int * int) list +type function_attribute = { + inline : inline_attribute; + specialise : specialise_attribute; + is_a_functor: bool; +} + type lambda = Lvar of Ident.t | Lconst of structured_constant - | Lapply of lambda * lambda list * Location.t - | Lfunction of function_kind * Ident.t list * lambda + | Lapply of lambda_apply + | Lfunction of lfunction | Llet of let_kind * Ident.t * lambda * lambda | Lletrec of (Ident.t * lambda) list * lambda | Lprim of primitive * lambda list @@ -189,6 +222,20 @@ type lambda = | Levent of lambda * lambda_event | Lifused of Ident.t * lambda +and lfunction = + { kind: function_kind; + params: Ident.t list; + body: lambda; + attr: function_attribute; } (* specified with [@inline] attribute *) + +and lambda_apply = + { ap_func : lambda; + ap_args : lambda list; + ap_loc : Location.t; + ap_should_be_tailcall : bool; + ap_inlined : inline_attribute; + ap_specialised : specialise_attribute; } + and lambda_switch = { sw_numconsts: int; sw_consts: (int * lambda) list; @@ -206,11 +253,22 @@ and lambda_event_kind = Lev_before | Lev_after of Types.type_expr | Lev_function + | Lev_pseudo + +type program = + { code : lambda; + main_module_block_size : int; } let const_unit = Const_pointer 0 let lambda_unit = Lconst const_unit +let default_function_attribute = { + inline = Default_inline; + specialise = Default_specialise; + is_a_functor = false; +} + (* Build sharing keys *) (* Those keys are later compared with Pervasives.compare. @@ -234,12 +292,14 @@ let make_key e = try Ident.find_same id env with Not_found -> e end - | Lconst (Const_base (Const_string _)|Const_float_array _) -> + | Lconst (Const_base (Const_string _)) -> (* Mutable constants are not shared *) raise Not_simple | Lconst _ -> e - | Lapply (e,es,loc) -> - Lapply (tr_rec env e,tr_recs env es,Location.none) + | Lapply ap -> + Lapply {ap with ap_func = tr_rec env ap.ap_func; + ap_args = tr_recs env ap.ap_args; + ap_loc = Location.none} | Llet (Alias,x,ex,e) -> (* Ignore aliases -> substitute *) let ex = tr_rec env ex in tr_rec (Ident.add x ex env) e @@ -320,9 +380,9 @@ let iter_opt f = function let iter f = function Lvar _ | Lconst _ -> () - | Lapply(fn, args, _) -> + | Lapply{ap_func = fn; ap_args = args} -> f fn; List.iter f args - | Lfunction(kind, params, body) -> + | Lfunction{kind; params; body} -> f body | Llet(str, id, arg, body) -> f arg; f body @@ -376,7 +436,7 @@ let free_ids get l = iter free l; fv := List.fold_right IdentSet.add (get l) !fv; match l with - Lfunction(kind, params, body) -> + Lfunction{kind; params; body} -> List.iter (fun param -> fv := IdentSet.remove param !fv) params | Llet(str, id, arg, body) -> fv := IdentSet.remove id !fv @@ -467,8 +527,11 @@ let subst_lambda s lam = Lvar id as l -> begin try Ident.find_same id s with Not_found -> l end | Lconst sc as l -> l - | Lapply(fn, args, loc) -> Lapply(subst fn, List.map subst args, loc) - | Lfunction(kind, params, body) -> Lfunction(kind, params, subst body) + | Lapply ap -> + Lapply{ap with ap_func = subst ap.ap_func; + ap_args = List.map subst ap.ap_args} + | Lfunction{kind; params; body; attr} -> + Lfunction{kind; params; body = subst body; attr} | Llet(str, id, arg, body) -> Llet(str, id, subst arg, subst body) | Lletrec(decl, body) -> Lletrec(List.map subst_decl decl, subst body) | Lprim(p, args) -> Lprim(p, List.map subst args) @@ -500,6 +563,66 @@ let subst_lambda s lam = | Some e -> Some (subst e) in subst lam +let rec map f lam = + let lam = + match lam with + | Lvar v -> lam + | Lconst cst -> lam + | Lapply { ap_func; ap_args; ap_loc; ap_should_be_tailcall; + ap_inlined; ap_specialised } -> + Lapply { + ap_func = map f ap_func; + ap_args = List.map (map f) ap_args; + ap_loc; + ap_should_be_tailcall; + ap_inlined; + ap_specialised; + } + | Lfunction { kind; params; body; attr; } -> + Lfunction { kind; params; body = map f body; attr; } + | Llet (str, v, e1, e2) -> + Llet (str, v, map f e1, map f e2) + | Lletrec (idel, e2) -> + Lletrec (List.map (fun (v, e) -> (v, map f e)) idel, map f e2) + | Lprim (p, el) -> + Lprim (p, List.map (map f) el) + | Lswitch (e, sw) -> + Lswitch (map f e, + { sw_numconsts = sw.sw_numconsts; + sw_consts = List.map (fun (n, e) -> (n, map f e)) sw.sw_consts; + sw_numblocks = sw.sw_numblocks; + sw_blocks = List.map (fun (n, e) -> (n, map f e)) sw.sw_blocks; + sw_failaction = Misc.may_map (map f) sw.sw_failaction; + }) + | Lstringswitch (e, sw, default) -> + Lstringswitch ( + map f e, + List.map (fun (s, e) -> (s, map f e)) sw, + Misc.may_map (map f) default) + | Lstaticraise (i, args) -> + Lstaticraise (i, List.map (map f) args) + | Lstaticcatch (body, id, handler) -> + Lstaticcatch (map f body, id, map f handler) + | Ltrywith (e1, v, e2) -> + Ltrywith (map f e1, v, map f e2) + | Lifthenelse (e1, e2, e3) -> + Lifthenelse (map f e1, map f e2, map f e3) + | Lsequence (e1, e2) -> + Lsequence (map f e1, map f e2) + | Lwhile (e1, e2) -> + Lwhile (map f e1, map f e2) + | Lfor (v, e1, e2, dir, e3) -> + Lfor (v, map f e1, map f e2, dir, map f e3) + | Lassign (v, e) -> + Lassign (v, map f e) + | Lsend (k, m, o, el, loc) -> + Lsend (k, map f m, map f o, List.map (map f) el, loc) + | Levent (l, ev) -> + Levent (map f l, ev) + | Lifused (v, e) -> + Lifused (v, map f e) + in + f lam (* To let-bind expressions to variables *) diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli index 0e038d93..def712af 100644 --- a/bytecomp/lambda.mli +++ b/bytecomp/lambda.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The "lambda" intermediate code *) @@ -17,6 +20,8 @@ open Asttypes type compile_time_constant = | Big_endian | Word_size + | Int_size + | Max_wosize | Ostype_unix | Ostype_win32 | Ostype_cygwin @@ -28,6 +33,17 @@ type loc_kind = | Loc_LOC | Loc_POS +type immediate_or_pointer = + | Immediate + | 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 + type primitive = Pidentity | Pignore @@ -40,9 +56,9 @@ type primitive = (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag | Pfield of int - | Psetfield of int * bool + | Psetfield of int * immediate_or_pointer * initialization_or_assignment | Pfloatfield of int - | Psetfloatfield of int + | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int (* Force lazy values *) | Plazyforce @@ -67,7 +83,11 @@ type primitive = (* String operations *) | Pstringlength | Pstringrefu | Pstringsetu | Pstringrefs | Pstringsets (* Array operations *) - | Pmakearray of array_kind + | Pmakearray of array_kind * mutable_flag + | Pduparray of array_kind * mutable_flag + (** For [Pduparray], the argument must be an immutable array. + The arguments of [Pduparray] give the kind and mutability of the + array being *produced* by the duplication. *) | Parraylength of array_kind | Parrayrefu of array_kind | Parraysetu of array_kind @@ -123,6 +143,8 @@ type primitive = | Pbbswap of boxed_integer (* Integer to external pointer *) | Pint_as_pointer + (* Inhibition of optimisation *) + | Popaque and comparison = Ceq | Cneq | Clt | Cgt | Cle | Cge @@ -130,7 +152,7 @@ and comparison = and array_kind = Pgenarray | Paddrarray | Pintarray | Pfloatarray -and boxed_integer = +and boxed_integer = Primitive.boxed_integer = Pnativeint | Pint32 | Pint64 and bigarray_kind = @@ -159,6 +181,17 @@ type structured_constant = | Const_float_array of string list | Const_immstring of string +type inline_attribute = + | Always_inline (* [@inline] or [@inline always] *) + | Never_inline (* [@inline never] *) + | Unroll of int (* [@unroll x] *) + | Default_inline (* no [@inline] attribute *) + +type specialise_attribute = + | Always_specialise (* [@specialise] or [@specialise always] *) + | Never_specialise (* [@specialise never] *) + | Default_specialise (* no [@specialise] attribute *) + type function_kind = Curried | Tupled type let_kind = Strict | Alias | StrictOpt | Variable @@ -176,11 +209,17 @@ type meth_kind = Self | Public | Cached type shared_code = (int * int) list (* stack size -> code label *) +type function_attribute = { + inline : inline_attribute; + specialise : specialise_attribute; + is_a_functor: bool; +} + type lambda = Lvar of Ident.t | Lconst of structured_constant - | Lapply of lambda * lambda list * Location.t - | Lfunction of function_kind * Ident.t list * lambda + | Lapply of lambda_apply + | Lfunction of lfunction | Llet of let_kind * Ident.t * lambda * lambda | Lletrec of (Ident.t * lambda) list * lambda | Lprim of primitive * lambda list @@ -200,6 +239,20 @@ type lambda = | Levent of lambda * lambda_event | Lifused of Ident.t * lambda +and lfunction = + { kind: function_kind; + params: Ident.t list; + body: lambda; + attr: function_attribute; } (* specified with [@inline] attribute *) + +and lambda_apply = + { ap_func : lambda; + ap_args : lambda list; + ap_loc : Location.t; + ap_should_be_tailcall : bool; (* true if [@tailcall] was specified *) + ap_inlined : inline_attribute; (* specified with the [@inlined] attribute *) + ap_specialised : specialise_attribute; } + and lambda_switch = { sw_numconsts: int; (* Number of integer cases *) sw_consts: (int * lambda) list; (* Integer cases *) @@ -216,6 +269,13 @@ and lambda_event_kind = Lev_before | Lev_after of Types.type_expr | Lev_function + | Lev_pseudo + +type program = + { code : lambda; + main_module_block_size : int; } +(* Lambda code for the Closure middle-end. The main module block size + is required for preallocating the block *) (* Sharing key *) val make_key: lambda -> lambda option @@ -235,11 +295,14 @@ val transl_path: ?loc:Location.t -> Env.t -> Path.t -> lambda val make_sequence: ('a -> lambda) -> 'a list -> lambda val subst_lambda: lambda Ident.tbl -> lambda -> lambda +val map : (lambda -> lambda) -> lambda -> lambda val bind : let_kind -> Ident.t -> lambda -> lambda -> lambda val commute_comparison : comparison -> comparison val negate_comparison : comparison -> comparison +val default_function_attribute : function_attribute + (***********************) (* For static failures *) (***********************) diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml index 8ab6cec8..7d541606 100644 --- a/bytecomp/matching.ml +++ b/bytecomp/matching.ml @@ -1,20 +1,22 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compilation of pattern matching *) open Misc open Asttypes -open Primitive open Types open Typedtree open Lambda @@ -27,7 +29,7 @@ let dbg = false (* See Peyton-Jones, ``The Implementation of functional programming languages'', chapter 5. *) (* - Bon, au commencement du monde c'etait vrai. + Well, it was true at the beginning of the world. Now, see Lefessant-Maranget ``Optimizing Pattern-Matching'' ICFP'2001 *) @@ -1348,7 +1350,9 @@ let make_constr_matching p def ctx = function | ((arg, mut) :: argl) -> let cstr = pat_as_constr p in let newargs = - match cstr.cstr_tag with + if cstr.cstr_inlined <> None then + (arg, Alias) :: argl + else match cstr.cstr_tag with Cstr_constant _ | Cstr_block _ -> make_field_args Alias arg 0 (cstr.cstr_arity - 1) argl | Cstr_extension _ -> @@ -1408,11 +1412,6 @@ let make_variant_matching_nonconst p lab def ctx = function ctx=ctx ; pat = normalize_pat p} -let get_key_variant p = match p.pat_desc with -| Tpat_variant(lab, Some _ , _) -> Cstr_block (Btype.hash_variant lab) -| Tpat_variant(lab, None , _) -> Cstr_constant (Btype.hash_variant lab) -| _ -> assert false - let divide_variant row ctx {cases = cl; args = al; default=def} = let row = Btype.row_repr row in let rec divide = function @@ -1473,10 +1472,7 @@ let matcher_lazy p rem = match p.pat_desc with *) let prim_obj_tag = - {prim_name = "caml_obj_tag"; - prim_arity = 1; prim_alloc = false; - prim_native_name = ""; - prim_native_float = false} + Primitive.simple ~name:"caml_obj_tag" ~arity:1 ~alloc:false let get_mod_field modname field = lazy ( @@ -1524,7 +1520,12 @@ let inline_lazy_force_cond arg loc = (* ... if (tag == Obj.lazy_tag) then Lazy.force varg else ... *) Lprim(Pintcomp Ceq, [Lvar tag; Lconst(Const_base(Const_int Obj.lazy_tag))]), - Lapply(force_fun, [varg], loc), + Lapply{ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=force_fun; + ap_args=[varg]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise}, (* ... arg *) varg)))) @@ -1542,7 +1543,12 @@ let inline_lazy_force_switch arg loc = sw_blocks = [ (Obj.forward_tag, Lprim(Pfield 0, [varg])); (Obj.lazy_tag, - Lapply(force_fun, [varg], loc)) ]; + Lapply{ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=force_fun; + ap_args=[varg]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise}) ]; sw_failaction = Some varg } )))) let inline_lazy_force arg loc = @@ -1628,8 +1634,10 @@ let make_record_matching all_labels def = function let lbl = all_labels.(pos) in let access = match lbl.lbl_repres with - Record_regular -> Pfield lbl.lbl_pos - | Record_float -> Pfloatfield lbl.lbl_pos in + Record_regular | Record_inlined _ -> Pfield lbl.lbl_pos + | Record_float -> Pfloatfield lbl.lbl_pos + | Record_extension -> Pfield (lbl.lbl_pos + 1) + in let str = match lbl.lbl_mut with Immutable -> Alias @@ -1703,14 +1711,16 @@ let divide_array kind ctx pm = let strings_test_threshold = 8 let prim_string_notequal = - Pccall{prim_name = "caml_string_notequal"; - prim_arity = 2; prim_alloc = false; - prim_native_name = ""; prim_native_float = false} + Pccall(Primitive.simple + ~name:"caml_string_notequal" + ~arity:2 + ~alloc:false) let prim_string_compare = - Pccall{prim_name = "caml_string_compare"; - prim_arity = 2; prim_alloc = false; - prim_native_name = ""; prim_native_float = false} + Pccall(Primitive.simple + ~name:"caml_string_compare" + ~arity:2 + ~alloc:false) let bind_sw arg k = match arg with | Lvar _ -> k arg @@ -1815,7 +1825,7 @@ let share_actions_tree sw d = let sw = List.map (fun (cst,act) -> cst,store.Switch.act_store act) sw in -(* Retrieve all actions, includint potentiel default *) +(* Retrieve all actions, including potentiel default *) let acts = store.Switch.act_get_shared () in (* Array of actual actions *) @@ -1885,46 +1895,6 @@ let make_test_sequence fail tst lt_tst arg const_lambda_list = hs (make_test_sequence const_lambda_list) -let rec explode_inter offset i j act k = - if i <= j then - explode_inter offset i (j-1) act ((j-offset,act)::k) - else - k - -let max_vals cases acts = - let vals = Array.make (Array.length acts) 0 in - for i=Array.length cases-1 downto 0 do - let l,h,act = cases.(i) in - vals.(act) <- h - l + 1 + vals.(act) - done ; - let max = ref 0 in - for i = Array.length vals-1 downto 0 do - if vals.(i) >= vals.(!max) then - max := i - done ; - if vals.(!max) > 1 then - !max - else - -1 - -let as_int_list cases acts = - let default = max_vals cases acts in - let min_key,_,_ = cases.(0) - and _,max_key,_ = cases.(Array.length cases-1) in - - let rec do_rec i k = - if i >= 0 then - let low, high, act = cases.(i) in - if act = default then - do_rec (i-1) k - else - do_rec (i-1) (explode_inter min_key low high acts.(act) k) - else - k in - min_key, max_key,do_rec (Array.length cases-1) [], - (if default >= 0 then Some acts.(default) else None) - - module SArg = struct type primitive = Lambda.primitive @@ -2035,8 +2005,6 @@ let reintroduce_fail sw = match sw.sw_failaction with module Switcher = Switch.Make(SArg) open Switch -let lambda_of_int i = Lconst (Const_base (Const_int i)) - let rec last def = function | [] -> def | [x,_] -> x @@ -2051,10 +2019,10 @@ let as_interval_canfail fail low high l = let store = StoreExp.mk_store () in let do_store tag act = + let i = store.act_store act in (* - Printlambda.lambda Format.str_formatter act ; - eprintf "STORE [%s] %i %s\n" tag i (Format.flush_str_formatter ()) ; + eprintf "STORE [%s] %i %s\n" tag i (string_of_lam act) ; *) i in @@ -2091,7 +2059,7 @@ let as_interval_canfail fail low high l = nofail_rec i i index rem in let init_rec = function - | [] -> [] + | [] -> [low,high,0] | (i,act_i)::rem -> let index = do_store "INIT" act_i in if index=0 then @@ -2108,7 +2076,10 @@ let as_interval_canfail fail low high l = let as_interval_nofail l = let store = StoreExp.mk_store () in - + let rec some_hole = function + | []|[_] -> false + | (i,_)::((j,_)::_ as rem) -> + j > i+1 || some_hole rem in let rec i_rec cur_low cur_high cur_act = function | [] -> [cur_low, cur_high, cur_act] @@ -2121,7 +2092,16 @@ let as_interval_nofail l = i_rec i i act_index rem in let inters = match l with | (i,act)::rem -> - let act_index = store.act_store act in + let act_index = + (* In case there is some hole and that a switch is emited, + action 0 will be used as the action of unreacheable + cases (cf. switch.ml, make_switch). + Hence, this action will be shared *) + if some_hole rem then + store.act_store_shared act + else + store.act_store act in + assert (act_index = 0) ; i_rec i i act_index rem | _ -> assert false in @@ -2149,13 +2129,6 @@ let call_switcher fail arg low high int_lambda_list = Switcher.zyva edges arg cases actions -let exists_ctx ok ctx = - List.exists - (function - | {right=p::_} -> ok p - | _ -> assert false) - ctx - let rec list_as_pat = function | [] -> fatal_error "Matching.list_as_pat" | [pat] -> pat @@ -2163,41 +2136,6 @@ let rec list_as_pat = function {pat with pat_desc = Tpat_or (pat,list_as_pat rem,None)} -let rec pat_as_list k = function - | {pat_desc=Tpat_or (p1,p2,_)} -> - pat_as_list (pat_as_list k p2) p1 - | p -> p::k - -(* Extracting interesting patterns *) -exception All - -let rec extract_pat seen k p = match p.pat_desc with -| Tpat_or (p1,p2,_) -> - let k1,seen1 = extract_pat seen k p1 in - extract_pat seen1 k1 p2 -| Tpat_alias (p,_,_) -> - extract_pat seen k p -| Tpat_var _|Tpat_any -> - raise All -| _ -> - let q = normalize_pat p in - if List.exists (compat q) seen then - k, seen - else - q::k, q::seen - -let extract_mat seen pss = - let r,_ = - List.fold_left - (fun (k,seen) ps -> match ps with - | p::_ -> extract_pat seen k p - | _ -> assert false) - ([],seen) - pss in - r - - - let complete_pats_constrs = function | p::_ as pats -> List.map @@ -2206,33 +2144,6 @@ let complete_pats_constrs = function | _ -> assert false -let mk_res get_key env last_choice idef cant_fail ctx = - - let env,fail,jumps_fail = match last_choice with - | [] -> - env, None, jumps_empty - | [p] when group_var p -> - env, - Some (Lstaticraise (idef,[])), - jumps_singleton idef ctx - | _ -> - (idef,cant_fail,last_choice)::env, - None, jumps_empty in - let klist,jumps = - List.fold_right - (fun (i,cant_fail,pats) (klist,jumps) -> - let act = Lstaticraise (i,[]) - and pat = list_as_pat pats in - let klist = - List.fold_right - (fun pat klist -> (get_key pat,act)::klist) - pats klist - and ctx = if cant_fail then ctx else ctx_lub pat ctx in - klist,jumps_add i ctx jumps) - env ([],jumps_fail) in - fail, klist, jumps - - (* Following two ``failaction'' function compute n, the trap handler to jump to in case of failure of elementary tests @@ -2242,20 +2153,20 @@ let mk_failaction_neg partial ctx def = match partial with | Partial -> begin match def with | (_,idef)::_ -> - Some (Lstaticraise (idef,[])),[],jumps_singleton idef ctx - | _ -> + Some (Lstaticraise (idef,[])),jumps_singleton idef ctx + | [] -> (* Act as Total, this means If no appropriate default matrix exists, then this switch cannot fail *) - None, [], jumps_empty + None, jumps_empty end | Total -> - None, [], jumps_empty + None, jumps_empty -(* Conforme a l'article et plus simple qu'avant *) -and mk_failaction_pos partial seen ctx defs = +(* In line with the article and simpler than before *) +let mk_failaction_pos partial seen ctx defs = if dbg then begin prerr_endline "**POS**" ; pretty_def defs ; @@ -2282,19 +2193,35 @@ and mk_failaction_pos partial seen ctx defs = | [] -> scan_def env to_test rem | _ -> scan_def ((List.map fst now,idef)::env) later rem in - scan_def - [] - (List.map - (fun pat -> pat, ctx_lub pat ctx) - (complete_pats_constrs seen)) - defs - + let fail_pats = complete_pats_constrs seen in + if List.length fail_pats < 32 then begin + let fail,jmps = + scan_def + [] + (List.map + (fun pat -> pat, ctx_lub pat ctx) + fail_pats) + defs in + if dbg then begin + eprintf "POSITIVE JUMPS [%i]:\n" (List.length fail_pats); + pretty_jumps jmps + end ; + None,fail,jmps + end else begin (* Two 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 + eprintf "FAIL: %s\n" + (match fail with + | None -> "" + | Some lam -> string_of_lam lam) ; + fail,[],jumps + end let combine_constant arg cst partial ctx def (const_lambda_list, total, pats) = - let fail, to_add, local_jumps = + let fail, local_jumps = mk_failaction_neg partial ctx def in - let const_lambda_list = to_add@const_lambda_list in let lambda1 = match cst with | Const_int _ -> @@ -2375,9 +2302,8 @@ let combine_constructor arg ex_pat cstr partial ctx def (tag_lambda_list, total1, pats) = if cstr.cstr_consts < 0 then begin (* Special cases for extensions *) - let fail, to_add, local_jumps = + let fail, local_jumps = mk_failaction_neg partial ctx def in - let tag_lambda_list = to_add@tag_lambda_list in let lambda1 = let consts, nonconsts = split_extension_cases tag_lambda_list in let default, consts, nonconsts = @@ -2420,42 +2346,53 @@ let combine_constructor arg ex_pat cstr partial ctx def let ncases = List.length tag_lambda_list and nconstrs = cstr.cstr_consts + cstr.cstr_nonconsts in let sig_complete = ncases = nconstrs in - let fails,local_jumps = - if sig_complete then [],jumps_empty + let fail_opt,fails,local_jumps = + if sig_complete then None,[],jumps_empty else mk_failaction_pos partial pats ctx def in let tag_lambda_list = fails @ tag_lambda_list in let (consts, nonconsts) = split_cases tag_lambda_list in let lambda1 = - match same_actions tag_lambda_list with - | Some act -> act + match fail_opt,same_actions tag_lambda_list with + | None,Some act -> act (* Identical actions, no failure *) | _ -> match (cstr.cstr_consts, cstr.cstr_nonconsts, consts, nonconsts) with | (1, 1, [0, act1], [0, act2]) -> + (* Typically, match on lists, will avoid isint primitive in that + case *) Lifthenelse(arg, act2, act1) - | (n,_,_,[]) -> - call_switcher None arg 0 (n-1) consts + | (n,0,_,[]) -> (* The type defines constant constructors only *) + call_switcher fail_opt arg 0 (n-1) consts | (n, _, _, _) -> - match same_actions nonconsts with - | None -> + let act0 = + (* = Some act when all non-const constructors match to act *) + match fail_opt,nonconsts with + | Some a,[] -> Some a + | Some _,_ -> + if List.length nonconsts = cstr.cstr_nonconsts then + same_actions nonconsts + else None + | None,_ -> same_actions nonconsts in + match act0 with + | Some act -> + Lifthenelse + (Lprim (Pisint, [arg]), + call_switcher + fail_opt arg + 0 (n-1) consts, + act) (* Emit a switch, as bytecode implements this sophisticated instruction *) + | None -> let sw = {sw_numconsts = cstr.cstr_consts; sw_consts = consts; sw_numblocks = cstr.cstr_nonconsts; sw_blocks = nonconsts; - sw_failaction = None} in + sw_failaction = fail_opt} in let hs,sw = share_actions_sw sw in let sw = reintroduce_fail sw in - hs (Lswitch (arg,sw)) - | Some act -> - Lifthenelse - (Lprim (Pisint, [arg]), - call_switcher - None arg - 0 (n-1) consts, - act) in + hs (Lswitch (arg,sw)) in lambda1, jumps_union local_jumps total1 end @@ -2490,14 +2427,13 @@ let combine_variant row arg partial ctx def (tag_lambda_list, total1, pats) = Lifthenelse(Lprim (Pisint, [arg]), if_int, if_block) in let sig_complete = List.length tag_lambda_list = !num_constr and one_action = same_actions tag_lambda_list in - let fail, to_add, local_jumps = + let fail, local_jumps = if sig_complete || (match partial with Total -> true | _ -> false) then - None, [], jumps_empty + None, jumps_empty else mk_failaction_neg partial ctx def in - let tag_lambda_list = to_add@tag_lambda_list in let (consts, nonconsts) = split_cases tag_lambda_list in let lambda1 = match fail, one_action with | None, Some act -> act @@ -2529,8 +2465,7 @@ let combine_variant row arg partial ctx def (tag_lambda_list, total1, pats) = let combine_array arg kind partial ctx def (len_lambda_list, total1, pats) = - let fail, to_add, local_jumps = mk_failaction_neg partial ctx def in - let len_lambda_list = to_add @ len_lambda_list in + let fail, local_jumps = mk_failaction_neg partial ctx def in let lambda1 = let newvar = Ident.create "len" in let switch = @@ -2633,8 +2568,8 @@ let compile_test compile_fun partial divide combine ctx to_match = match c_div with | [],_,_ -> begin match mk_failaction_neg partial ctx to_match.default with - | None,_,_ -> raise Unused - | Some l,_,total -> l,total + | None,_ -> raise Unused + | Some l,total -> l,total end | _ -> combine ctx to_match.default c_div @@ -2755,7 +2690,7 @@ let arg_to_var arg cls = match arg with *) let rec compile_match repr partial ctx m = match m with -| { cases = [] } -> comp_exit ctx m +| { cases = []; args = [] } -> comp_exit ctx m | { cases = ([], action) :: rem } -> if is_guarded action then begin let (lambda, total) = @@ -2865,7 +2800,7 @@ and compile_no_test divide up_ctx repr partial ctx to_match = and change the subject values. LM: Lazy pattern was PR #5992, initial patch by lwp25. - I have generalized teh patch, so as to also find mutable fields. + I have generalized the patch, so as to also find mutable fields. *) let find_in_pat pred = @@ -2921,6 +2856,7 @@ let check_partial is_mutable is_lazy pat_act_list = function | Partial -> Partial | Total -> if + pat_act_list = [] || (* allow empty case list *) List.exists (fun (pats, lam) -> is_mutable pats && (is_guarded lam || is_lazy pats)) @@ -2987,9 +2923,137 @@ let for_trywith param pat_act_list = (fun () -> Lprim(Praise Raise_reraise, [param])) param pat_act_list Partial -let for_let loc param pat body = +let simple_for_let loc param pat body = compile_matching loc None (partial_function loc) param [pat, body] Partial + +(* Optimize binding of immediate tuples + + The goal of the implementation of 'for_let' below, which replaces + 'simple_for_let', is to avoid tuple allocation in cases such as + this one: + + let (x,y) = + let foo = ... in + if foo then (1, 2) else (3,4) + in bar + + The compiler easily optimizes the simple `let (x,y) = (1,2) in ...` + case (call to Matching.for_multiple_match from Translcore), but + 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 following compilation method, based on Lassign: + + let x = dummy in let y = dummy in + begin + let foo = ... in + if foo then + (let x1 = 1 in let y1 = 2 in x <- x1; y <- y1) + else + (let x2 = 3 in let y2 = 4 in x <- x2; y <- y2) + end; + bar + + The current implementation from Gabriel Scherer uses Lstaticcatch / + Lstaticraise instead: + + catch + let foo = ... in + if foo then + (let x1 = 1 in let y1 = 2 in exit x1 y1) + else + (let x2 = 3 in let y2 = 4 in exit x2 y2) + with x y -> + bar + + The catch/exit is used to avoid duplication of the let body ('bar' + in the example), on 'if' branches for example; it is useless for + linear contexts such as 'let', but we don't need to be careful to + generate nice code because Simplif will remove such useless + catch/exit. +*) + +let rec map_return f = function + | Llet (k, id, l1, l2) -> Llet (k, id, l1, map_return f l2) + | Lletrec (l1, l2) -> Lletrec (l1, map_return f l2) + | Lifthenelse (lcond, lthen, lelse) -> + Lifthenelse (lcond, map_return f lthen, map_return f lelse) + | Lsequence (l1, l2) -> Lsequence (l1, map_return f l2) + | Levent (l, ev) -> Levent (map_return f l, ev) + | Ltrywith (l1, id, l2) -> Ltrywith (map_return f l1, id, map_return f l2) + | Lstaticcatch (l1, b, l2) -> + Lstaticcatch (map_return f l1, b, map_return f l2) + | Lstaticraise _ | Lprim(Praise _, _) as l -> l + | l -> f l + +(* The 'opt' reference indicates if the optimization is worthy. + + It is shared by the different calls to 'assign_pat' performed from + 'map_return'. For example with the code + let (x, y) = if foo then z else (1,2) + the else-branch will activate the optimization for both branches. + + That means that the optimization is activated if *there exists* an + interesting tuple in one hole of the let-rhs context. We could + choose to activate it only if *all* holes are interesting. We made + that choice because being optimistic is extremely cheap (one static + exit/catch overhead in the "wrong cases"), while being pessimistic + can be costly (one unnecessary tuple allocation). +*) + +let assign_pat opt nraise catch_ids loc pat lam = + let rec collect acc pat lam = match pat.pat_desc, lam with + | Tpat_tuple patl, Lprim(Pmakeblock _, lams) -> + opt := true; + List.fold_left2 collect acc patl lams + | Tpat_tuple patl, Lconst(Const_block(_, scl)) -> + opt := true; + let collect_const acc pat sc = collect acc pat (Lconst sc) in + List.fold_left2 collect_const acc patl scl + | _ -> + (* pattern idents will be bound in staticcatch (let body), so we + refresh them here to guarantee binders uniqueness *) + let pat_ids = pat_bound_idents pat in + let fresh_ids = List.map (fun id -> id, Ident.rename id) pat_ids in + (fresh_ids, alpha_pat fresh_ids pat, lam) :: acc + in + + (* sublets were accumulated by 'collect' with the leftmost tuple + pattern at the bottom of the list; to respect right-to-left + evaluation order for tuples, we must evaluate sublets + top-to-bottom. To preserve tail-rec, we will fold_left the + reversed list. *) + let rev_sublets = List.rev (collect [] pat lam) in + let exit = + (* build an Ident.tbl to avoid quadratic refreshing costs *) + let add t (id, fresh_id) = Ident.add id fresh_id t in + let add_ids acc (ids, _pat, _lam) = List.fold_left add acc ids in + let tbl = List.fold_left add_ids Ident.empty rev_sublets in + let fresh_var id = Lvar (Ident.find_same id tbl) in + Lstaticraise(nraise, List.map fresh_var catch_ids) + in + let push_sublet code (_ids, pat, lam) = simple_for_let loc lam pat code in + List.fold_left push_sublet exit rev_sublets + +let for_let loc param pat body = + match pat.pat_desc with + | Tpat_any -> + (* This eliminates a useless variable (and stack slot in bytecode) + for "let _ = ...". See #6865. *) + Lsequence(param, body) + | Tpat_var _ -> + (* fast path *) + simple_for_let loc param pat body + | _ -> + let opt = ref false in + let nraise = next_raise_count () in + let catch_ids = pat_bound_idents pat in + let bind = map_return (assign_pat opt nraise catch_ids loc pat) param in + if !opt then Lstaticcatch(bind, (nraise, catch_ids), body) + else simple_for_let loc param pat body + (* Handling of tupled functions and matchings *) (* Easy case since variables are available *) @@ -3131,13 +3195,6 @@ let do_for_multiple_match loc paraml pat_act_list partial = (* #PR4828: Believe it or not, the 'paraml' argument below may not be side effect free. *) -let arg_to_var arg cls = match arg with -| Lvar v -> v,arg -| _ -> - let v = name_pattern "match" cls in - v,Lvar v - - let param_to_var param = match param with | Lvar v -> v,None | _ -> Ident.create "match",Some param diff --git a/bytecomp/matching.mli b/bytecomp/matching.mli index 88002e05..916479a8 100644 --- a/bytecomp/matching.mli +++ b/bytecomp/matching.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compilation of pattern-matching *) diff --git a/bytecomp/meta.ml b/bytecomp/meta.ml index f7711ff1..175cce3f 100644 --- a/bytecomp/meta.ml +++ b/bytecomp/meta.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) external global_data : unit -> Obj.t array = "caml_get_global_data" external realloc_global_data : int -> unit = "caml_realloc_global" @@ -23,3 +26,8 @@ external invoke_traced_function : Obj.t -> Obj.t -> Obj.t -> Obj.t = "caml_invoke_traced_function" external get_section_table : unit -> (string * Obj.t) list = "caml_get_section_table" +external add_debug_info : + bytes -> int -> Instruct.debug_event list array -> unit + = "caml_add_debug_info" +external remove_debug_info : bytes -> unit + = "caml_remove_debug_info" diff --git a/bytecomp/meta.mli b/bytecomp/meta.mli index cb3565dc..ab006637 100644 --- a/bytecomp/meta.mli +++ b/bytecomp/meta.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* To control the runtime system and bytecode interpreter *) @@ -25,3 +28,8 @@ external invoke_traced_function : Obj.t -> Obj.t -> Obj.t -> Obj.t = "caml_invoke_traced_function" external get_section_table : unit -> (string * Obj.t) list = "caml_get_section_table" +external add_debug_info : + bytes -> int -> Instruct.debug_event list array -> unit + = "caml_add_debug_info" +external remove_debug_info : bytes -> unit + = "caml_remove_debug_info" diff --git a/bytecomp/printinstr.ml b/bytecomp/printinstr.ml index 43d8d360..62bdfd22 100644 --- a/bytecomp/printinstr.ml +++ b/bytecomp/printinstr.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Pretty-print lists of instructions *) diff --git a/bytecomp/printinstr.mli b/bytecomp/printinstr.mli index dd4fd15b..3cf3539d 100644 --- a/bytecomp/printinstr.mli +++ b/bytecomp/printinstr.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Pretty-print lists of instructions *) diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml index d528a357..fb7bdc00 100644 --- a/bytecomp/printlambda.ml +++ b/bytecomp/printlambda.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format open Asttypes @@ -40,14 +43,17 @@ let rec struct_const ppf = function List.iter (fun f -> fprintf ppf "@ %s" f) fl in fprintf ppf "@[<1>[|@[%s%a@]|]@]" f1 floats fl +let array_kind = function + | Pgenarray -> "gen" + | Paddrarray -> "addr" + | Pintarray -> "int" + | Pfloatarray -> "float" + let boxed_integer_name = function | Pnativeint -> "nativeint" | Pint32 -> "int32" | Pint64 -> "int64" -let print_boxed_integer name ppf bi = - fprintf ppf "%s_%s" (boxed_integer_name bi) name - let print_boxed_integer_conversion ppf bi1 bi2 = fprintf ppf "%s_of_%s" (boxed_integer_name bi2) (boxed_integer_name bi1) @@ -84,7 +90,9 @@ let print_bigarray name unsafe kind ppf layout = let record_rep ppf r = match r with | Record_regular -> fprintf ppf "regular" + | Record_inlined i -> fprintf ppf "inlined(%i)" i | Record_float -> fprintf ppf "float" + | Record_extension -> fprintf ppf "ext" ;; let string_of_loc_kind = function @@ -105,11 +113,26 @@ let primitive ppf = function | Pmakeblock(tag, Immutable) -> fprintf ppf "makeblock %i" tag | Pmakeblock(tag, Mutable) -> fprintf ppf "makemutable %i" tag | Pfield n -> fprintf ppf "field %i" n - | Psetfield(n, ptr) -> - let instr = if ptr then "setfield_ptr " else "setfield_imm " in - fprintf ppf "%s%i" instr n + | Psetfield(n, ptr, init) -> + let instr = + match ptr with + | Pointer -> "ptr" + | Immediate -> "imm" + in + let init = + match init with + | Initialization -> "(init)" + | Assignment -> "" + in + fprintf ppf "setfield_%s%s %i" instr init n | Pfloatfield n -> fprintf ppf "floatfield %i" n - | Psetfloatfield n -> fprintf ppf "setfloatfield %i" n + | Psetfloatfield (n, init) -> + let init = + match init with + | Initialization -> "(init)" + | Assignment -> "" + in + fprintf ppf "setfloatfield%s %i" init n | Pduprecord (rep, size) -> fprintf ppf "duprecord %a %i" record_rep rep size | Plazyforce -> fprintf ppf "force" | Pccall p -> fprintf ppf "%s" p.prim_name @@ -156,16 +179,21 @@ let primitive ppf = function | Pstringsetu -> fprintf ppf "string.unsafe_set" | Pstringrefs -> fprintf ppf "string.get" | Pstringsets -> fprintf ppf "string.set" - | Parraylength _ -> fprintf ppf "array.length" - | Pmakearray _ -> fprintf ppf "makearray " - | Parrayrefu _ -> fprintf ppf "array.unsafe_get" - | Parraysetu _ -> fprintf ppf "array.unsafe_set" - | Parrayrefs _ -> fprintf ppf "array.get" - | Parraysets _ -> fprintf ppf "array.set" + | Parraylength k -> fprintf ppf "array.length[%s]" (array_kind k) + | Pmakearray (k, Mutable) -> fprintf ppf "makearray[%s]" (array_kind k) + | Pmakearray (k, Immutable) -> fprintf ppf "makearray_imm[%s]" (array_kind k) + | Pduparray (k, Mutable) -> fprintf ppf "duparray[%s]" (array_kind k) + | Pduparray (k, Immutable) -> fprintf ppf "duparray_imm[%s]" (array_kind k) + | Parrayrefu k -> fprintf ppf "array.unsafe_get[%s]" (array_kind k) + | Parraysetu k -> fprintf ppf "array.unsafe_set[%s]" (array_kind k) + | Parrayrefs k -> fprintf ppf "array.get[%s]" (array_kind k) + | Parraysets k -> fprintf ppf "array.set[%s]" (array_kind k) | Pctconst c -> let const_name = match c with | Big_endian -> "big_endian" | Word_size -> "word_size" + | Int_size -> "int_size" + | Max_wosize -> "max_wosize" | Ostype_unix -> "ostype_unix" | Ostype_win32 -> "ostype_win32" | Ostype_cygwin -> "ostype_cygwin" in @@ -238,17 +266,147 @@ let primitive ppf = function | Pbswap16 -> fprintf ppf "bswap16" | Pbbswap(bi) -> print_boxed_integer "bswap" ppf bi | Pint_as_pointer -> fprintf ppf "int_as_pointer" + | Popaque -> fprintf ppf "opaque" + +let name_of_primitive = function + | Pidentity -> "Pidentity" + | Pignore -> "Pignore" + | Prevapply _ -> "Prevapply" + | Pdirapply _ -> "Pdirapply" + | Ploc _ -> "Ploc" + | Pgetglobal _ -> "Pgetglobal" + | Psetglobal _ -> "Psetglobal" + | Pmakeblock _ -> "Pmakeblock" + | Pfield _ -> "Pfield" + | Psetfield _ -> "Psetfield" + | Pfloatfield _ -> "Pfloatfield" + | Psetfloatfield _ -> "Psetfloatfield" + | Pduprecord _ -> "Pduprecord" + | Plazyforce -> "Plazyforce" + | Pccall _ -> "Pccall" + | Praise _ -> "Praise" + | Psequand -> "Psequand" + | Psequor -> "Psequor" + | Pnot -> "Pnot" + | Pnegint -> "Pnegint" + | Paddint -> "Paddint" + | Psubint -> "Psubint" + | Pmulint -> "Pmulint" + | Pdivint -> "Pdivint" + | Pmodint -> "Pmodint" + | Pandint -> "Pandint" + | Porint -> "Porint" + | Pxorint -> "Pxorint" + | Plslint -> "Plslint" + | Plsrint -> "Plsrint" + | Pasrint -> "Pasrint" + | Pintcomp _ -> "Pintcomp" + | Poffsetint _ -> "Poffsetint" + | Poffsetref _ -> "Poffsetref" + | Pintoffloat -> "Pintoffloat" + | Pfloatofint -> "Pfloatofint" + | Pnegfloat -> "Pnegfloat" + | Pabsfloat -> "Pabsfloat" + | Paddfloat -> "Paddfloat" + | Psubfloat -> "Psubfloat" + | Pmulfloat -> "Pmulfloat" + | Pdivfloat -> "Pdivfloat" + | Pfloatcomp _ -> "Pfloatcomp" + | Pstringlength -> "Pstringlength" + | Pstringrefu -> "Pstringrefu" + | Pstringsetu -> "Pstringsetu" + | Pstringrefs -> "Pstringrefs" + | Pstringsets -> "Pstringsets" + | Parraylength _ -> "Parraylength" + | Pmakearray _ -> "Pmakearray" + | Pduparray _ -> "Pduparray" + | Parrayrefu _ -> "Parrayrefu" + | Parraysetu _ -> "Parraysetu" + | Parrayrefs _ -> "Parrayrefs" + | Parraysets _ -> "Parraysets" + | Pctconst _ -> "Pctconst" + | Pisint -> "Pisint" + | Pisout -> "Pisout" + | Pbittest -> "Pbittest" + | Pbintofint _ -> "Pbintofint" + | Pintofbint _ -> "Pintofbint" + | Pcvtbint _ -> "Pcvtbint" + | Pnegbint _ -> "Pnegbint" + | Paddbint _ -> "Paddbint" + | Psubbint _ -> "Psubbint" + | Pmulbint _ -> "Pmulbint" + | Pdivbint _ -> "Pdivbint" + | Pmodbint _ -> "Pmodbint" + | Pandbint _ -> "Pandbint" + | Porbint _ -> "Porbint" + | Pxorbint _ -> "Pxorbint" + | Plslbint _ -> "Plslbint" + | Plsrbint _ -> "Plsrbint" + | Pasrbint _ -> "Pasrbint" + | Pbintcomp _ -> "Pbintcomp" + | Pbigarrayref _ -> "Pbigarrayref" + | Pbigarrayset _ -> "Pbigarrayset" + | Pbigarraydim _ -> "Pbigarraydim" + | Pstring_load_16 _ -> "Pstring_load_16" + | Pstring_load_32 _ -> "Pstring_load_32" + | Pstring_load_64 _ -> "Pstring_load_64" + | Pstring_set_16 _ -> "Pstring_set_16" + | Pstring_set_32 _ -> "Pstring_set_32" + | Pstring_set_64 _ -> "Pstring_set_64" + | Pbigstring_load_16 _ -> "Pbigstring_load_16" + | Pbigstring_load_32 _ -> "Pbigstring_load_32" + | Pbigstring_load_64 _ -> "Pbigstring_load_64" + | Pbigstring_set_16 _ -> "Pbigstring_set_16" + | Pbigstring_set_32 _ -> "Pbigstring_set_32" + | Pbigstring_set_64 _ -> "Pbigstring_set_64" + | Pbswap16 -> "Pbswap16" + | Pbbswap _ -> "Pbbswap" + | Pint_as_pointer -> "Pint_as_pointer" + | Popaque -> "Popaque" + +let function_attribute ppf { inline; specialise; is_a_functor } = + if is_a_functor then + fprintf ppf "is_a_functor@ "; + begin match inline with + | Default_inline -> () + | Always_inline -> fprintf ppf "always_inline@ " + | Never_inline -> fprintf ppf "never_inline@ " + | Unroll i -> fprintf ppf "unroll(%i)@ " i + end; + begin match specialise with + | Default_specialise -> () + | Always_specialise -> fprintf ppf "always_specialise@ " + | Never_specialise -> fprintf ppf "never_specialise@ " + end + +let apply_tailcall_attribute ppf tailcall = + if tailcall then + fprintf ppf " @@tailcall" + +let apply_inlined_attribute ppf = function + | Default_inline -> () + | Always_inline -> fprintf ppf " always_inline" + | Never_inline -> fprintf ppf " never_inline" + | Unroll i -> fprintf ppf " never_inline(%i)" i + +let apply_specialised_attribute ppf = function + | Default_specialise -> () + | Always_specialise -> fprintf ppf " always_specialise" + | Never_specialise -> fprintf ppf " never_specialise" let rec lam ppf = function | Lvar id -> Ident.print ppf id | Lconst cst -> struct_const ppf cst - | Lapply(lfun, largs, _) -> + | Lapply ap -> let lams ppf largs = List.iter (fun l -> fprintf ppf "@ %a" lam l) largs in - fprintf ppf "@[<2>(apply@ %a%a)@]" lam lfun lams largs - | Lfunction(kind, params, body) -> + fprintf ppf "@[<2>(apply@ %a%a%a%a%a)@]" lam ap.ap_func lams ap.ap_args + apply_tailcall_attribute ap.ap_should_be_tailcall + apply_inlined_attribute ap.ap_inlined + apply_specialised_attribute ap.ap_specialised + | Lfunction{kind; params; body; attr} -> let pr_params ppf params = match kind with | Curried -> @@ -262,7 +420,8 @@ let rec lam ppf = function Ident.print ppf param) params; fprintf ppf ")" in - fprintf ppf "@[<2>(function%a@ %a)@]" pr_params params lam body + fprintf ppf "@[<2>(function%a@ %a%a)@]" pr_params params + function_attribute attr lam body | Llet(str, id, arg, body) -> let kind = function Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v" in @@ -370,7 +529,9 @@ let rec lam ppf = function match ev.lev_kind with | Lev_before -> "before" | Lev_after _ -> "after" - | Lev_function -> "funct-body" in + | Lev_function -> "funct-body" + | Lev_pseudo -> "pseudo" + in fprintf ppf "@[<2>(%s %s(%i)%s:%i-%i@ %a)@]" kind ev.lev_loc.Location.loc_start.Lexing.pos_fname ev.lev_loc.Location.loc_start.Lexing.pos_lnum @@ -390,3 +551,5 @@ and sequence ppf = function let structured_constant = struct_const let lambda = lam + +let program ppf { code } = lambda ppf code diff --git a/bytecomp/printlambda.mli b/bytecomp/printlambda.mli index 4a546b63..7b81ce2d 100644 --- a/bytecomp/printlambda.mli +++ b/bytecomp/printlambda.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Lambda @@ -16,4 +19,6 @@ open Format val structured_constant: formatter -> structured_constant -> unit val lambda: formatter -> lambda -> unit +val program: formatter -> program -> unit val primitive: formatter -> primitive -> unit +val name_of_primitive : primitive -> string diff --git a/bytecomp/runtimedef.mli b/bytecomp/runtimedef.mli index c06038a4..3baabb64 100644 --- a/bytecomp/runtimedef.mli +++ b/bytecomp/runtimedef.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Values and functions known and/or provided by the runtime system *) diff --git a/bytecomp/simplif.ml b/bytecomp/simplif.ml index fd3d21c1..fe1d005b 100644 --- a/bytecomp/simplif.ml +++ b/bytecomp/simplif.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Elimination of useless Llet(Alias) bindings. Also transform let-bound references into variables. *) @@ -24,9 +27,10 @@ let rec eliminate_ref id = function Lvar v as lam -> if Ident.same v id then raise Real_reference else lam | Lconst cst as lam -> lam - | Lapply(e1, el, loc) -> - Lapply(eliminate_ref id e1, List.map (eliminate_ref id) el, loc) - | Lfunction(kind, params, body) as lam -> + | Lapply ap -> + Lapply{ap with ap_func = eliminate_ref id ap.ap_func; + ap_args = List.map (eliminate_ref id) ap.ap_args} + | Lfunction{kind; params; body} as lam -> if IdentSet.mem id (free_variables lam) then raise Real_reference else lam @@ -37,7 +41,7 @@ let rec eliminate_ref id = function eliminate_ref id e2) | Lprim(Pfield 0, [Lvar v]) when Ident.same v id -> Lvar id - | Lprim(Psetfield(0, _), [Lvar v; e]) when Ident.same v id -> + | Lprim(Psetfield(0, _, _), [Lvar v; e]) when Ident.same v id -> Lassign(id, eliminate_ref id e) | Lprim(Poffsetref delta, [Lvar v]) when Ident.same v id -> Lassign(id, Lprim(Poffsetint delta, [Lvar id])) @@ -106,8 +110,8 @@ let simplify_exits lam = let rec count = function | (Lvar _| Lconst _) -> () - | Lapply(l1, ll, _) -> count l1; List.iter count ll - | Lfunction(kind, params, l) -> count l + | Lapply ap -> count ap.ap_func; List.iter count ap.ap_args + | Lfunction{kind; params; body = l} -> count l | Llet(str, v, l1, l2) -> count l2; count l1 | Lletrec(bindings, body) -> @@ -193,8 +197,11 @@ let simplify_exits lam = let rec simplif = function | (Lvar _|Lconst _) as l -> l - | Lapply(l1, ll, loc) -> Lapply(simplif l1, List.map simplif ll, loc) - | Lfunction(kind, params, l) -> Lfunction(kind, params, simplif l) + | Lapply ap -> + Lapply{ap with ap_func = simplif ap.ap_func; + ap_args = List.map simplif ap.ap_args} + | Lfunction{kind; params; body = l; attr} -> + Lfunction{kind; params; body = simplif l; attr} | Llet(kind, v, l1, l2) -> Llet(kind, v, simplif l1, simplif l2) | Lletrec(bindings, body) -> Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body) @@ -202,16 +209,26 @@ let simplify_exits lam = let ll = List.map simplif ll in match p, ll with (* Simplify %revapply, for n-ary functions with n > 1 *) - | Prevapply loc, [x; Lapply(f, args, _)] - | Prevapply loc, [x; Levent (Lapply(f, args, _),_)] -> - Lapply(f, args@[x], loc) - | Prevapply loc, [x; f] -> Lapply(f, [x], loc) + | Prevapply loc, [x; Lapply ap] + | Prevapply loc, [x; Levent (Lapply ap,_)] -> + Lapply {ap with ap_args = ap.ap_args @ [x]; ap_loc = loc} + | Prevapply loc, [x; f] -> Lapply {ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=f; + ap_args=[x]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} (* Simplify %apply, for n-ary functions with n > 1 *) - | Pdirapply loc, [Lapply(f, args, _); x] - | Pdirapply loc, [Levent (Lapply(f, args, _),_); x] -> - Lapply(f, args@[x], loc) - | Pdirapply loc, [f; x] -> Lapply(f, [x], loc) + | Pdirapply loc, [Lapply ap; x] + | Pdirapply loc, [Levent (Lapply ap,_); x] -> + Lapply {ap with ap_args = ap.ap_args @ [x]; ap_loc = loc} + | Pdirapply loc, [f; x] -> Lapply {ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=f; + ap_args=[x]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} | _ -> Lprim(p, ll) end @@ -338,15 +355,16 @@ let simplify_lets lam = | Lconst cst -> () | Lvar v -> use_var bv v 1 - | Lapply(Lfunction(Curried, params, body), args, _) + | Lapply{ap_func = Lfunction{kind = Curried; params; body}; ap_args = args} when optimize && List.length params = List.length args -> count bv (beta_reduce params body args) - | Lapply(Lfunction(Tupled, params, body), [Lprim(Pmakeblock _, args)], _) + | Lapply{ap_func = Lfunction{kind = Tupled; params; body}; + ap_args = [Lprim(Pmakeblock _, args)]} when optimize && List.length params = List.length args -> count bv (beta_reduce params body args) - | Lapply(l1, ll, _) -> + | Lapply{ap_func = l1; ap_args = ll} -> count bv l1; List.iter (count bv) ll - | Lfunction(kind, params, l) -> + | Lfunction{kind; params; body = l} -> count Tbl.empty l | Llet(str, v, Lvar w, l2) when optimize -> (* v will be replaced by w in l2, so each occurrence of v in l2 @@ -430,14 +448,23 @@ let simplify_lets lam = l end | Lconst cst as l -> l - | Lapply(Lfunction(Curried, params, body), args, _) + | Lapply{ap_func = Lfunction{kind = Curried; params; body}; ap_args = args} when optimize && List.length params = List.length args -> simplif (beta_reduce params body args) - | Lapply(Lfunction(Tupled, params, body), [Lprim(Pmakeblock _, args)], _) + | Lapply{ap_func = Lfunction{kind = Tupled; params; body}; + ap_args = [Lprim(Pmakeblock _, args)]} when optimize && List.length params = List.length args -> simplif (beta_reduce params body args) - | Lapply(l1, ll, loc) -> Lapply(simplif l1, List.map simplif ll, loc) - | Lfunction(kind, params, l) -> Lfunction(kind, params, simplif l) + | Lapply ap -> Lapply {ap with ap_func = simplif ap.ap_func; + ap_args = List.map simplif ap.ap_args} + | Lfunction{kind; params; body = l; attr} -> + begin match simplif l with + Lfunction{kind=Curried; params=params'; body; attr} + when kind = Curried && optimize -> + Lfunction{kind; params = params @ params'; body; attr} + | body -> + Lfunction{kind; params; body; attr} + end | Llet(str, v, Lvar w, l2) when optimize -> Hashtbl.add subst v (simplif (Lvar w)); simplif l2 @@ -516,10 +543,16 @@ let rec emit_tail_infos is_tail lambda = match lambda with | Lvar _ -> () | Lconst _ -> () - | Lapply (func, l, loc) -> - list_emit_tail_infos false l; - Stypes.record (Stypes.An_call (loc, call_kind l)) - | Lfunction (_, _, lam) -> + | Lapply ap -> + if ap.ap_should_be_tailcall + && not is_tail + && Warnings.is_active Warnings.Expect_tailcall + then Location.prerr_warning ap.ap_loc Warnings.Expect_tailcall; + emit_tail_infos false ap.ap_func; + list_emit_tail_infos false ap.ap_args; + if !Clflags.annotations then + Stypes.record (Stypes.An_call (ap.ap_loc, call_kind ap.ap_args)) + | Lfunction {body = lam} -> emit_tail_infos true lam | Llet (_, _, lam, body) -> emit_tail_infos false lam; @@ -574,7 +607,8 @@ let rec emit_tail_infos is_tail lambda = emit_tail_infos false meth; emit_tail_infos false obj; list_emit_tail_infos false args; - Stypes.record (Stypes.An_call (loc, call_kind (obj :: args))) + if !Clflags.annotations then + Stypes.record (Stypes.An_call (loc, call_kind (obj :: args))); | Levent (lam, _) -> emit_tail_infos is_tail lam | Lifused (_, lam) -> @@ -584,10 +618,68 @@ and list_emit_tail_infos_fun f is_tail = and list_emit_tail_infos is_tail = List.iter (emit_tail_infos is_tail) +(* Split a function with default parameters into a wrapper and an + inner function. The wrapper fills in missing optional parameters + with their default value and tail-calls the inner function. The + wrapper can then hopefully be inlined on most call sites to avoid + the overhead associated with boxing an optional argument with a + 'Some' constructor, only to deconstruct it immediately in the + function's body. *) + +let split_default_wrapper ?(create_wrapper_body = fun lam -> lam) + fun_id kind params body attr = + let rec aux map = function + | Llet(Strict, id, (Lifthenelse(Lvar optparam, _, _) as def), rest) when + Ident.name optparam = "*opt*" && List.mem optparam params + && not (List.mem_assoc optparam map) + -> + let wrapper_body, inner = aux ((optparam, id) :: map) rest in + Llet(Strict, id, def, wrapper_body), inner + | _ when map = [] -> raise Exit + | body -> + (* Check that those *opt* identifiers don't appear in the remaining + body. This should not appear, but let's be on the safe side. *) + let fv = Lambda.free_variables body in + List.iter (fun (id, _) -> if IdentSet.mem id fv then raise Exit) map; + + let inner_id = Ident.create (Ident.name fun_id ^ "_inner") in + let map_param p = try List.assoc p map with Not_found -> p in + let args = List.map (fun p -> Lvar (map_param p)) params in + let wrapper_body = + Lapply { + ap_func = Lvar inner_id; + ap_args = args; + ap_loc = Location.none; + ap_should_be_tailcall = false; + ap_inlined = Default_inline; + ap_specialised = Default_specialise; + } + in + let inner_params = List.map map_param params in + let new_ids = List.map Ident.rename inner_params in + let subst = List.fold_left2 + (fun s id new_id -> + Ident.add id (Lvar new_id) s) + Ident.empty inner_params new_ids + in + let body = Lambda.subst_lambda subst body in + let inner_fun = + Lfunction { kind = Curried; params = new_ids; body; attr; } + in + (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}); inner] + with Exit -> + [(fun_id, Lfunction{kind; params; body; attr})] + (* The entry point: simplification + emission of tailcall annotations, if needed. *) let simplify_lambda lam = let res = simplify_lets (simplify_exits lam) in - if !Clflags.annotations then emit_tail_infos true res; + if !Clflags.annotations || Warnings.is_active Warnings.Expect_tailcall + then emit_tail_infos true res; res diff --git a/bytecomp/simplif.mli b/bytecomp/simplif.mli index 4cc6dab9..65b8fb03 100644 --- a/bytecomp/simplif.mli +++ b/bytecomp/simplif.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Elimination of useless Llet(Alias) bindings. Transformation of let-bound references into variables. @@ -19,6 +22,15 @@ open Lambda val simplify_lambda: lambda -> lambda +val split_default_wrapper + : ?create_wrapper_body:(lambda -> lambda) + -> Ident.t + -> function_kind + -> Ident.t list + -> lambda + -> function_attribute + -> (Ident.t * lambda) list + (* To be filled by asmcomp/selectgen.ml *) val is_tail_native_heuristic: (int -> bool) ref (* # arguments -> can tailcall *) diff --git a/bytecomp/switch.ml b/bytecomp/switch.ml index da9a48f1..dfcf77e3 100644 --- a/bytecomp/switch.ml +++ b/bytecomp/switch.ml @@ -1,22 +1,21 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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 'a shared = Shared of 'a | Single of 'a -let share_out = function - | Shared act|Single act -> act - - type 'a t_store = {act_get : unit -> 'a array ; act_get_shared : unit -> 'a shared array ; @@ -143,6 +142,7 @@ type 'a t_ctx = {off : int ; arg : 'a} let cut = ref 8 and more_cut = ref 16 +(* let pint chan i = if i = min_int then Printf.fprintf chan "-oo" else if i=max_int then Printf.fprintf chan "oo" @@ -157,8 +157,9 @@ let pcases chan cases = Printf.fprintf chan "%a..%a:%d " pint l pint h act done - let prerr_inter i = Printf.fprintf stderr +let prerr_inter i = Printf.fprintf stderr "cases=%a" pcases i.cases +*) let get_act cases i = let _,_,r = cases.(i) in @@ -174,6 +175,7 @@ type ctests = { let too_much = {n=max_int ; ni=max_int} +(* let ptests chan {n=n ; ni=ni} = Printf.fprintf chan "{n=%d ; ni=%d}" n ni @@ -181,23 +183,7 @@ let pta chan t = for i =0 to Array.length t-1 do Printf.fprintf chan "%d: %a\n" i ptests t.(i) done - -let count_tests s = - let r = - Array.init - (Array.length s.actions) - (fun _ -> {n=0 ; ni=0 }) in - let c = s.cases in - let imax = Array.length c-1 in - for i=0 to imax do - let l,h,act = c.(i) in - let x = r.(act) in - x.n <- x.n+1 ; - if l < h && i<> 0 && i<>imax then - x.ni <- x.ni+1 ; - done ; - r - +*) let less_tests c1 c2 = if c1.n < c2.n then @@ -212,8 +198,6 @@ let less_tests c1 c2 = and eq_tests c1 c2 = c1.n = c2.n && c1.ni=c2.ni -let min_tests c1 c2 = if less_tests c1 c2 then c1 else c2 - let less2tests (c1,d1) (c2,d2) = if eq_tests c1 c2 then less_tests d1 d2 @@ -226,10 +210,12 @@ let add_test t1 t2 = type t_ret = Inter of int * int | Sep of int | No +(* let pret chan = function | Inter (i,j)-> Printf.fprintf chan "Inter %d %d" i j | Sep i -> Printf.fprintf chan "Sep %d" i | No -> Printf.fprintf chan "No" +*) let coupe cases i = let l,_,_ = cases.(i) in @@ -310,6 +296,7 @@ let coupe_inter i j cases = type kind = Kvalue of int | Kinter of int | Kempty +(* let pkind chan = function | Kvalue i ->Printf.fprintf chan "V%d" i | Kinter i -> Printf.fprintf chan "I%d" i @@ -320,6 +307,7 @@ let rec pkey chan = function | [k] -> pkind chan k | k::rem -> Printf.fprintf chan "%a %a" pkey rem pkind k +*) let t = Hashtbl.create 17 @@ -390,8 +378,7 @@ let ok_inter = ref false let rec opt_count top cases = let key = make_key cases in try - let r = Hashtbl.find t key in - r + Hashtbl.find t key with | Not_found -> let r = @@ -552,18 +539,6 @@ and enum top cases = | _ -> make_if_test Arg.ltint arg i ifso ifnot - and make_if_le arg i ifso ifnot = match i with - | -1 -> - make_if_test Arg.ltint arg 0 ifso ifnot - | _ -> - make_if_test Arg.leint arg i ifso ifnot - - and make_if_gt arg i ifso ifnot = match i with - | -1 -> - make_if_test Arg.geint arg 0 ifso ifnot - | _ -> - make_if_test Arg.gtint arg i ifso ifnot - and make_if_ge arg i ifso ifnot = match i with | 1 -> make_if_test Arg.gtint arg 0 ifso ifnot @@ -832,15 +807,15 @@ let do_zyva (low,high) arg cases actions = if !ok_inter <> old_ok then Hashtbl.clear t ; let s = {cases=cases ; actions=actions} in + (* - Printf.eprintf "ZYVA: %b\n" !ok_inter ; + Printf.eprintf "ZYVA: %b [low=%i,high=%i]\n" !ok_inter low high ; pcases stderr cases ; prerr_endline "" ; *) let n_clusters,k = comp_clusters s in let clusters = make_clusters s n_clusters k in - let r = c_test {arg=arg ; off=0} clusters in - r + c_test {arg=arg ; off=0} clusters let abstract_shared actions = let handlers = ref (fun x -> x) in @@ -857,11 +832,13 @@ let abstract_shared actions = !handlers,actions let zyva lh arg cases actions = + assert (Array.length cases > 0) ; let actions = actions.act_get_shared () in let hs,actions = abstract_shared actions in hs (do_zyva lh arg cases actions) and test_sequence arg cases actions = + assert (Array.length cases > 0) ; let actions = actions.act_get_shared () in let hs,actions = abstract_shared actions in let old_ok = !ok_inter in diff --git a/bytecomp/switch.mli b/bytecomp/switch.mli index 53fd9974..d0eadf0c 100644 --- a/bytecomp/switch.mli +++ b/bytecomp/switch.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* This module transforms generic switches in combinations diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml index a0ce2737..22810cfc 100644 --- a/bytecomp/symtable.ml +++ b/bytecomp/symtable.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* To assign numbers to globals and primitives *) diff --git a/bytecomp/symtable.mli b/bytecomp/symtable.mli index ffc878bf..2aa0eaa9 100644 --- a/bytecomp/symtable.mli +++ b/bytecomp/symtable.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Assign locations and numbers to globals and primitives *) diff --git a/bytecomp/translattribute.ml b/bytecomp/translattribute.ml new file mode 100644 index 00000000..fae55ccb --- /dev/null +++ b/bytecomp/translattribute.ml @@ -0,0 +1,255 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +open Typedtree +open Lambda +open Location + +let is_inline_attribute = function + | {txt=("inline"|"ocaml.inline")}, _ -> true + | _ -> false + +let is_inlined_attribute = function + | {txt=("inlined"|"ocaml.inlined")}, _ -> true + | {txt=("unrolled"|"ocaml.unrolled")}, _ when Config.flambda -> true + | _ -> false + +let is_specialise_attribute = function + | {txt=("specialise"|"ocaml.specialise")}, _ when Config.flambda -> true + | _ -> false + +let is_specialised_attribute = function + | {txt=("specialised"|"ocaml.specialised")}, _ when Config.flambda -> true + | _ -> false + +let find_attribute p attributes = + let inline_attribute, other_attributes = + List.partition p attributes + in + let attr = + match inline_attribute with + | [] -> None + | [attr] -> Some attr + | _ :: ({txt;loc}, _) :: _ -> + Location.prerr_warning loc (Warnings.Duplicated_attribute txt); + None + in + attr, other_attributes + +let is_unrolled = function + | {txt="unrolled"|"ocaml.unrolled"} -> true + | {txt="inline"|"ocaml.inline"|"inlined"|"ocaml.inlined"} -> false + | _ -> assert false + +let parse_inline_attribute attr = + match attr with + | None -> Default_inline + | Some ({txt;loc} as id, payload) -> + let open Parsetree in + if is_unrolled id then begin + (* the 'unrolled' attributes must be used as [@unrolled n]. *) + let warning txt = Warnings.Attribute_payload + (txt, "It must be an integer literal") + in + match payload with + | PStr [{pstr_desc = Pstr_eval ({pexp_desc},[])}] -> begin + match pexp_desc with + | Pexp_constant (Pconst_integer(s, None)) -> begin + try + Unroll (Misc.Int_literal_converter.int s) + with Failure _ -> + Location.prerr_warning loc (warning txt); + Default_inline + end + | _ -> + Location.prerr_warning loc (warning txt); + Default_inline + end + | _ -> + Location.prerr_warning loc (warning txt); + Default_inline + end else begin + (* the 'inline' and 'inlined' attributes can be used as + [@inline], [@inline never] or [@inline always]. + [@inline] is equivalent to [@inline always] *) + let warning txt = + Warnings.Attribute_payload + (txt, "It must be either empty, 'always' or 'never'") + in + match payload with + | PStr [] -> Always_inline + | PStr [{pstr_desc = Pstr_eval ({pexp_desc},[])}] -> begin + match pexp_desc with + | Pexp_ident { txt = Longident.Lident "never" } -> + Never_inline + | Pexp_ident { txt = Longident.Lident "always" } -> + Always_inline + | _ -> + Location.prerr_warning loc (warning txt); + Default_inline + end + | _ -> + Location.prerr_warning loc (warning txt); + Default_inline + end + +let parse_specialise_attribute attr = + match attr with + | None -> Default_specialise + | Some ({txt; loc}, payload) -> + let open Parsetree in + let warning txt = + Warnings.Attribute_payload + (txt, "It must be either empty, 'always' or 'never'") + in + match payload with + | PStr [] -> Always_specialise + | PStr [{pstr_desc = Pstr_eval ({pexp_desc},[])}] -> begin + (* the 'specialise' and 'specialised' attributes can be used as + [@specialise], [@specialise never] or [@specialise always]. + [@specialise] is equivalent to [@specialise always] *) + match pexp_desc with + | Pexp_ident { txt = Longident.Lident "never" } -> + Never_specialise + | Pexp_ident { txt = Longident.Lident "always" } -> + Always_specialise + | _ -> + Location.prerr_warning loc (warning txt); + Default_specialise + end + | _ -> + Location.prerr_warning loc (warning txt); + Default_specialise + +let get_inline_attribute l = + let attr, _ = find_attribute is_inline_attribute l in + parse_inline_attribute attr + +let get_specialise_attribute l = + let attr, _ = find_attribute is_specialise_attribute l in + parse_specialise_attribute attr + +let add_inline_attribute expr loc attributes = + match expr, get_inline_attribute attributes with + | expr, Default_inline -> expr + | Lfunction({ attr } as funct), inline_attribute -> + 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 + Lfunction { funct with attr = attr } + | expr, (Always_inline | Never_inline | Unroll _) -> + Location.prerr_warning loc + (Warnings.Misplaced_attribute "inline"); + expr + +let add_specialise_attribute expr loc attributes = + match expr, get_specialise_attribute attributes with + | expr, Default_specialise -> expr + | Lfunction({ attr } as funct), specialise_attribute -> + 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 + Lfunction { funct with attr } + | expr, (Always_specialise | Never_specialise) -> + Location.prerr_warning loc + (Warnings.Misplaced_attribute "specialise"); + expr + +(* Get the [@inlined] attribute payload (or default if not present). + It also returns the expression without this attribute. This is + used to ensure that this attribute is not misplaced: If it + appears on any expression, it is an error, otherwise it would + have been removed by this function *) +let get_and_remove_inlined_attribute e = + let attr, exp_attributes = + find_attribute is_inlined_attribute e.exp_attributes + in + let inlined = parse_inline_attribute attr in + inlined, { e with exp_attributes } + +let get_and_remove_inlined_attribute_on_module e = + let attr, mod_attributes = + find_attribute is_inlined_attribute e.mod_attributes + in + let inlined = parse_inline_attribute attr in + inlined, { e with mod_attributes } + +let get_and_remove_specialised_attribute e = + let attr, exp_attributes = + find_attribute is_specialised_attribute e.exp_attributes + in + let specialised = parse_specialise_attribute attr in + specialised, { e with exp_attributes } + +(* It also remove the attribute from the expression, like + get_inlined_attribute *) +let get_tailcall_attribute e = + let is_tailcall_attribute = function + | {txt=("tailcall"|"ocaml.tailcall")}, _ -> true + | _ -> false + in + let tailcalls, exp_attributes = + List.partition is_tailcall_attribute e.exp_attributes + in + match tailcalls with + | [] -> false, e + | _ :: r -> + begin match r with + | [] -> () + | ({txt;loc}, _) :: _ -> + Location.prerr_warning loc (Warnings.Duplicated_attribute txt) + end; + true, { e with exp_attributes } + +let check_attribute e ({ txt; loc }, _) = + match txt with + | "inline" | "ocaml.inline" + | "specialise" | "ocaml.specialise" -> begin + match e.exp_desc with + | Texp_function _ -> () + | _ -> + Location.prerr_warning loc + (Warnings.Misplaced_attribute txt) + end + | "inlined" | "ocaml.inlined" + | "specialised" | "ocaml.specialised" + | "tailcall" | "ocaml.tailcall" -> + (* Removed by the Texp_apply cases *) + Location.prerr_warning loc + (Warnings.Misplaced_attribute txt) + | _ -> () + +let check_attribute_on_module e ({ txt; loc }, _) = + match txt with + | "inline" | "ocaml.inline" -> begin + match e.mod_desc with + | Tmod_functor _ -> () + | _ -> + Location.prerr_warning loc + (Warnings.Misplaced_attribute txt) + end + | "inlined" | "ocaml.inlined" -> + (* Removed by the Texp_apply cases *) + Location.prerr_warning loc + (Warnings.Misplaced_attribute txt) + | _ -> () diff --git a/bytecomp/translattribute.mli b/bytecomp/translattribute.mli new file mode 100644 index 00000000..be855c28 --- /dev/null +++ b/bytecomp/translattribute.mli @@ -0,0 +1,60 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +val check_attribute + : Typedtree.expression + -> string Location.loc * _ + -> unit + +val check_attribute_on_module + : Typedtree.module_expr + -> string Location.loc * _ + -> unit + +val add_inline_attribute + : Lambda.lambda + -> Location.t + -> Parsetree.attributes + -> Lambda.lambda + +val get_inline_attribute + : Parsetree.attributes + -> Lambda.inline_attribute + +val add_specialise_attribute + : Lambda.lambda + -> Location.t + -> Parsetree.attributes + -> Lambda.lambda + +val get_specialise_attribute + : Parsetree.attributes + -> Lambda.specialise_attribute + +val get_and_remove_inlined_attribute + : Typedtree.expression + -> Lambda.inline_attribute * Typedtree.expression + +val get_and_remove_inlined_attribute_on_module + : Typedtree.module_expr + -> Lambda.inline_attribute * Typedtree.module_expr + +val get_and_remove_specialised_attribute + : Typedtree.expression + -> Lambda.specialise_attribute * Typedtree.expression + +val get_tailcall_attribute + : Typedtree.expression + -> bool * Typedtree.expression diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml index 0fb68457..a2478099 100644 --- a/bytecomp/translclass.ml +++ b/bytecomp/translclass.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Asttypes open Types @@ -17,7 +20,7 @@ open Lambda open Translobj open Translcore -(* XXX Rajouter des evenements... *) +(* XXX Rajouter des evenements... | Add more events... *) type error = Illegal_class_expr | Tags of label * label @@ -26,19 +29,27 @@ exception Error of Location.t * error let lfunction params body = if params = [] then body else match body with - Lfunction (Curried, params', body') -> - Lfunction (Curried, params @ params', body') + | Lfunction {kind = Curried; params = params'; body = body'; attr} -> + Lfunction {kind = Curried; params = params @ params'; body = body'; attr} | _ -> - Lfunction (Curried, params, body) - -let lapply func args loc = - match func with - Lapply(func', args', _) -> - Lapply(func', args' @ args, loc) + Lfunction {kind = Curried; params; + body; + attr = default_function_attribute} + +let lapply ap = + match ap.ap_func with + Lapply ap' -> + Lapply {ap with ap_func = ap'.ap_func; ap_args = ap'.ap_args @ ap.ap_args} | _ -> - Lapply(func, args, loc) + Lapply ap -let mkappl (func, args) = Lapply (func, args, Location.none);; +let mkappl (func, args) = + Lapply {ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=func; + ap_args=args; + ap_inlined=Default_inline; + ap_specialised=Default_specialise};; let lsequence l1 l2 = if l2 = lambda_unit then l1 else Lsequence(l1, l2) @@ -53,19 +64,13 @@ let transl_meth_list lst = (0, List.map (fun lab -> Const_immstring lab) lst)) let set_inst_var obj id expr = - let kind = if Typeopt.maybe_pointer expr then Paddrarray else Pintarray in + let kind = + match Typeopt.maybe_pointer expr with + | Pointer -> Paddrarray + | Immediate -> Pintarray + in Lprim(Parraysetu kind, [Lvar obj; Lvar id; transl_exp expr]) -let copy_inst_var obj id expr templ offset = - let kind = if Typeopt.maybe_pointer expr then Paddrarray else Pintarray in - let id' = Ident.create (Ident.name id) in - Llet(Strict, id', Lprim (Pidentity, [Lvar id]), - Lprim(Parraysetu kind, - [Lvar obj; Lvar id'; - Lprim(Parrayrefu kind, [Lvar templ; Lprim(Paddint, - [Lvar id'; - Lvar offset])])])) - let transl_val tbl create name = mkappl (oo_prim (if create then "new_variable" else "get_variable"), [Lvar tbl; transl_label name]) @@ -167,13 +172,14 @@ let rec build_object_init cl_table obj params inh_init obj_init cl = (inh_init, let build params rem = let param = name_pattern "param" pat in - Lfunction (Curried, param::params, - Matching.for_function - pat.pat_loc None (Lvar param) [pat, rem] partial) + Lfunction {kind = Curried; params = param::params; + attr = default_function_attribute; + body = Matching.for_function + pat.pat_loc None (Lvar param) [pat, rem] partial} in begin match obj_init with - Lfunction (Curried, params, rem) -> build params rem - | rem -> build [] rem + Lfunction {kind = Curried; params; body = rem} -> build params rem + | rem -> build [] rem end) | Tcl_apply (cl, oexprs) -> let (inh_init, obj_init) = @@ -397,6 +403,7 @@ let rec get_class_meths cl = (* XXX Il devrait etre peu couteux d'ecrire des classes : + | Writing classes should be cheap class c x y = d e f *) let rec transl_class_rebind obj_init cl vf = @@ -411,14 +418,15 @@ let rec transl_class_rebind obj_init cl vf = let path, obj_init = transl_class_rebind obj_init cl vf in let build params rem = let param = name_pattern "param" pat in - Lfunction (Curried, param::params, - Matching.for_function - pat.pat_loc None (Lvar param) [pat, rem] partial) + Lfunction {kind = Curried; params = param::params; + attr = default_function_attribute; + body = Matching.for_function + pat.pat_loc None (Lvar param) [pat, rem] partial} in (path, match obj_init with - Lfunction (Curried, params, rem) -> build params rem - | rem -> build [] rem) + Lfunction {kind = Curried; params; body} -> build params body + | rem -> build [] rem) | Tcl_apply (cl, oexprs) -> let path, obj_init = transl_class_rebind obj_init cl vf in (path, transl_apply obj_init oexprs Location.none) @@ -449,7 +457,14 @@ let transl_class_rebind ids cl vf = try let obj_init = Ident.create "obj_init" and self = Ident.create "self" in - let obj_init0 = lapply (Lvar obj_init) [Lvar self] Location.none in + let obj_init0 = + lapply {ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=Lvar obj_init; + ap_args=[Lvar self]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} + in let path, obj_init' = transl_class_rebind_0 self obj_init0 cl vf in if not (Translcore.check_recursive_lambda ids obj_init') then raise(Error(cl.cl_loc, Illegal_class_expr)); @@ -490,7 +505,7 @@ let rec module_path = function let const_path local = function Lvar id -> not (List.mem id local) | Lconst _ -> true - | Lfunction (Curried, _, body) -> + | Lfunction {kind = Curried; body} -> let fv = free_variables body in List.for_all (fun x -> not (IdentSet.mem x fv)) local | p -> module_path p @@ -511,12 +526,12 @@ let rec builtin_meths self env env2 body = match body with | Llet(_, s', Lvar s, body) when List.mem s self -> builtin_meths (s'::self) env env2 body - | Lapply(f, [arg], _) when const_path f -> + | Lapply{ap_func = f; ap_args = [arg]} when const_path f -> let s, args = conv arg in ("app_"^s, f :: args) - | Lapply(f, [arg; p], _) when const_path f && const_path p -> + | Lapply{ap_func = f; ap_args = [arg; p]} when const_path f && const_path p -> let s, args = conv arg in ("app_"^s^"_const", f :: args @ [p]) - | Lapply(f, [p; arg], _) when const_path f && const_path p -> + | Lapply{ap_func = f; ap_args = [p; arg]} when const_path f && const_path p -> let s, args = conv arg in ("app_const_"^s, f :: p :: args) | Lsend(Self, Lvar n, Lvar s, [arg], _) when List.mem s self -> @@ -530,7 +545,7 @@ let rec builtin_meths self env env2 body = | Lsend(Cached, met, arg, [_;_], _) -> let s, args = conv arg in ("send_"^s, met :: args) - | Lfunction (Curried, [x], body) -> + | Lfunction {kind = Curried; params = [x]; body} -> let rec enter self = function | Lprim(Parraysetu _, [Lvar s; Lvar n; Lvar x']) when Ident.same x x' && List.mem s self -> @@ -580,26 +595,29 @@ open M (* - Traduction d'une classe. - Plusieurs cas: - * reapplication d'une classe connue -> transl_class_rebind - * classe sans dependances locales -> traduction directe - * avec dependances locale -> creation d'un arbre de stubs, - avec un noeud pour chaque classe locale heritee - Une classe est un 4-uplet: + Class translation. + Three subcases: + * reapplication of a known class -> transl_class_rebind + * class without local dependencies -> direct translation + * with local dependencies -> generate a stubs tree, + with a node for every local classes inherited + A class is a 4-tuple: (obj_init, class_init, env_init, env) - obj_init: fonction de creation d'objet (unit -> obj) - class_init: fonction d'heritage (table -> env_init) - (une seule par code source) - env_init: parametrage par l'environnement local (env -> params -> obj_init) - (une par combinaison de class_init herites) + obj_init: creation function (unit -> obj) + class_init: inheritance function (table -> env_init) + (one by source code) + env_init: parameterisation by the local environment + (env -> params -> obj_init) + (one for each combination of inherited class_init ) env: environnement local - Si ids=0 (objet immediat), alors on ne conserve que env_init. + If ids=0 (immediate object), then only env_init is conserved. *) +(* let prerr_ids msg ids = let names = List.map Ident.unique_toplevel_name ids in prerr_endline (String.concat " " (msg :: names)) +*) let transl_class ids cl_id pub_meths cl vflag = (* First check if it is not only a rebind *) @@ -638,7 +656,7 @@ let transl_class ids cl_id pub_meths cl vflag = in let new_ids_meths = ref [] in let msubst arr = function - Lfunction (Curried, self :: args, body) -> + Lfunction {kind = Curried; params = self :: args; body} -> let env = Ident.create "env" in let body' = if new_ids = [] then body else @@ -710,7 +728,9 @@ let transl_class ids cl_id pub_meths cl vflag = let concrete = (vflag = Concrete) and lclass lam = - let cl_init = llets (Lfunction(Curried, [cla], cl_init)) in + let cl_init = llets (Lfunction{kind = Curried; + attr = default_function_attribute; + params = [cla]; body = cl_init}) in Llet(Strict, class_init, cl_init, lam (free_variables cl_init)) and lbody fv = if List.for_all (fun id -> not (IdentSet.mem id fv)) ids then @@ -727,7 +747,10 @@ let transl_class ids cl_id pub_meths cl vflag = Lvar class_init; Lvar env_init; lambda_unit])))) and lbody_virt lenvs = Lprim(Pmakeblock(0, Immutable), - [lambda_unit; Lfunction(Curried,[cla], cl_init); lambda_unit; lenvs]) + [lambda_unit; Lfunction{kind = Curried; + attr = default_function_attribute; + params = [cla]; body = cl_init}; + lambda_unit; lenvs]) in (* Still easy: a class defined at toplevel *) if top && concrete then lclass lbody else @@ -769,7 +792,9 @@ let transl_class ids cl_id pub_meths cl vflag = List.map (fun (_,p) -> Lprim(Pfield 1, [transl_normal_path p])) inh_paths in let lclass lam = Llet(Strict, class_init, - Lfunction(Curried, [cla], def_ids cla cl_init), lam) + Lfunction{kind = Curried; params = [cla]; + attr = default_function_attribute; + body = def_ids cla cl_init}, lam) and lcache lam = if inh_keys = [] then Llet(Alias, cached, Lvar tables, lam) else Llet(Strict, cached, @@ -777,7 +802,7 @@ let transl_class ids cl_id pub_meths cl vflag = [Lvar tables; Lprim(Pmakeblock(0, Immutable), inh_keys)]), lam) and lset cached i lam = - Lprim(Psetfield(i, true), [Lvar cached; lam]) + Lprim(Psetfield(i, Pointer, Assignment), [Lvar cached; lam]) in let ldirect () = ltable cla @@ -785,7 +810,8 @@ let transl_class ids cl_id pub_meths cl vflag = Lsequence(mkappl (oo_prim "init_class", [Lvar cla]), lset cached 0 (Lvar env_init)))) and lclass_virt () = - lset cached 0 (Lfunction(Curried, [cla], def_ids cla cl_init)) + lset cached 0 (Lfunction{kind = Curried; attr = default_function_attribute; + params = [cla]; body = def_ids cla cl_init}) in llets ( lcache ( diff --git a/bytecomp/translclass.mli b/bytecomp/translclass.mli index f7858da2..bbd21e93 100644 --- a/bytecomp/translclass.mli +++ b/bytecomp/translclass.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Typedtree open Lambda diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml index ef7d82cd..42d02702 100644 --- a/bytecomp/translcore.ml +++ b/bytecomp/translcore.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Translation from typed abstract syntax to lambda terms, for the core language *) @@ -26,9 +29,12 @@ type error = | Illegal_letrec_expr | Free_super_var | Unknown_builtin_primitive of string + | Unreachable_reached exception Error of Location.t * error +let use_dup_for_constant_arrays_bigger_than = 4 + (* Forward declaration -- to be filled in by Translmod.transl_module *) let transl_module = ref((fun cc rootpath modl -> assert false) : @@ -42,99 +48,81 @@ let transl_object = let comparisons_table = create_hashtable 11 [ "%equal", - (Pccall{prim_name = "caml_equal"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, + (Pccall(Primitive.simple ~name:"caml_equal" ~arity:2 ~alloc:true), Pintcomp Ceq, Pfloatcomp Ceq, - Pccall{prim_name = "caml_string_equal"; prim_arity = 2; - prim_alloc = false; - prim_native_name = ""; prim_native_float = false}, + Pccall(Primitive.simple ~name:"caml_string_equal" ~arity:2 + ~alloc:false), Pbintcomp(Pnativeint, Ceq), Pbintcomp(Pint32, Ceq), Pbintcomp(Pint64, Ceq), true); "%notequal", - (Pccall{prim_name = "caml_notequal"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, + (Pccall(Primitive.simple ~name:"caml_notequal" ~arity:2 ~alloc:true), Pintcomp Cneq, Pfloatcomp Cneq, - Pccall{prim_name = "caml_string_notequal"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, + Pccall(Primitive.simple ~name:"caml_string_notequal" ~arity:2 + ~alloc:false), Pbintcomp(Pnativeint, Cneq), Pbintcomp(Pint32, Cneq), Pbintcomp(Pint64, Cneq), true); "%lessthan", - (Pccall{prim_name = "caml_lessthan"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, + (Pccall(Primitive.simple ~name:"caml_lessthan" ~arity:2 ~alloc:true), Pintcomp Clt, Pfloatcomp Clt, - Pccall{prim_name = "caml_string_lessthan"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, + Pccall(Primitive.simple ~name:"caml_string_lessthan" ~arity:2 + ~alloc:false), Pbintcomp(Pnativeint, Clt), Pbintcomp(Pint32, Clt), Pbintcomp(Pint64, Clt), false); "%greaterthan", - (Pccall{prim_name = "caml_greaterthan"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, + (Pccall(Primitive.simple ~name:"caml_greaterthan" ~arity:2 ~alloc:true), Pintcomp Cgt, Pfloatcomp Cgt, - Pccall{prim_name = "caml_string_greaterthan"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, + Pccall(Primitive.simple ~name:"caml_string_greaterthan" ~arity:2 + ~alloc: false), Pbintcomp(Pnativeint, Cgt), Pbintcomp(Pint32, Cgt), Pbintcomp(Pint64, Cgt), false); "%lessequal", - (Pccall{prim_name = "caml_lessequal"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, + (Pccall(Primitive.simple ~name:"caml_lessequal" ~arity:2 ~alloc:true), Pintcomp Cle, Pfloatcomp Cle, - Pccall{prim_name = "caml_string_lessequal"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, + Pccall(Primitive.simple ~name:"caml_string_lessequal" ~arity:2 + ~alloc:false), Pbintcomp(Pnativeint, Cle), Pbintcomp(Pint32, Cle), Pbintcomp(Pint64, Cle), false); "%greaterequal", - (Pccall{prim_name = "caml_greaterequal"; prim_arity = 2; - prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, + (Pccall(Primitive.simple ~name:"caml_greaterequal" ~arity:2 ~alloc:true), Pintcomp Cge, Pfloatcomp Cge, - Pccall{prim_name = "caml_string_greaterequal"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, + Pccall(Primitive.simple ~name:"caml_string_greaterequal" ~arity:2 + ~alloc:false), Pbintcomp(Pnativeint, Cge), Pbintcomp(Pint32, Cge), Pbintcomp(Pint64, Cge), false); "%compare", - (Pccall{prim_name = "caml_compare"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false}, - Pccall{prim_name = "caml_int_compare"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, - Pccall{prim_name = "caml_float_compare"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, - Pccall{prim_name = "caml_string_compare"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, - Pccall{prim_name = "caml_nativeint_compare"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, - Pccall{prim_name = "caml_int32_compare"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, - Pccall{prim_name = "caml_int64_compare"; prim_arity = 2; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false}, + let unboxed_compare name native_repr = + Pccall( Primitive.make ~name ~alloc:false + ~native_name:(name^"_unboxed") + ~native_repr_args:[native_repr;native_repr] + ~native_repr_res:Untagged_int + ) in + (Pccall(Primitive.simple ~name:"caml_compare" ~arity:2 ~alloc:true), + (* Not unboxed since the comparison is done directly on tagged int *) + Pccall(Primitive.simple ~name:"caml_int_compare" ~arity:2 ~alloc:false), + unboxed_compare "caml_float_compare" Unboxed_float, + Pccall(Primitive.simple ~name:"caml_string_compare" ~arity:2 + ~alloc:false), + unboxed_compare "caml_nativeint_compare" (Unboxed_integer Pnativeint), + unboxed_compare "caml_int32_compare" (Unboxed_integer Pint32), + unboxed_compare "caml_int64_compare" (Unboxed_integer Pint64), false) ] @@ -143,7 +131,7 @@ let primitives_table = create_hashtable 57 [ "%ignore", Pignore; "%field0", Pfield 0; "%field1", Pfield 1; - "%setfield0", Psetfield(0, true); + "%setfield0", Psetfield(0, Pointer, Assignment); "%makeblock", Pmakeblock(0, Immutable); "%makemutable", Pmakeblock(0, Mutable); "%raise", Praise Raise_regular; @@ -154,6 +142,8 @@ let primitives_table = create_hashtable 57 [ "%boolnot", Pnot; "%big_endian", Pctconst Big_endian; "%word_size", Pctconst Word_size; + "%int_size", Pctconst Int_size; + "%max_wosize", Pctconst Max_wosize; "%ostype_unix", Pctconst Ostype_unix; "%ostype_win32", Pctconst Ostype_win32; "%ostype_cygwin", Pctconst Ostype_cygwin; @@ -312,15 +302,11 @@ let primitives_table = create_hashtable 57 [ "%bswap_int64", Pbbswap(Pint64); "%bswap_native", Pbbswap(Pnativeint); "%int_as_pointer", Pint_as_pointer; + "%opaque", Popaque; ] -let prim_makearray = - { prim_name = "caml_make_vect"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false } - let prim_obj_dup = - { prim_name = "caml_obj_dup"; prim_arity = 1; prim_alloc = true; - prim_native_name = ""; prim_native_float = false } + Primitive.simple ~name:"caml_obj_dup" ~arity:1 ~alloc:true let find_primitive loc prim_name = match prim_name with @@ -333,103 +319,122 @@ let find_primitive loc prim_name = | "%loc_MODULE" -> Ploc Loc_MODULE | name -> Hashtbl.find primitives_table name -let transl_prim loc prim args = - let prim_name = prim.prim_name in +let specialize_comparison table env ty = + let (gencomp, intcomp, floatcomp, stringcomp, + nativeintcomp, int32comp, int64comp, _) = table in + match () with + | () when is_base_type env ty Predef.path_int + || is_base_type env ty Predef.path_char + || (maybe_pointer_type env ty = Immediate) -> intcomp + | () when is_base_type env ty Predef.path_float -> floatcomp + | () when is_base_type env ty Predef.path_string -> stringcomp + | () when is_base_type env ty Predef.path_nativeint -> nativeintcomp + | () when is_base_type env ty Predef.path_int32 -> int32comp + | () when is_base_type env ty Predef.path_int64 -> int64comp + | () -> gencomp + +(* Specialize a primitive from available type information, + raise Not_found if primitive is unknown *) + +let specialize_primitive loc p env ty ~has_constant_constructor = try - let (gencomp, intcomp, floatcomp, stringcomp, - nativeintcomp, int32comp, int64comp, - simplify_constant_constructor) = - Hashtbl.find comparisons_table prim_name in - begin match args with - [arg1; {exp_desc = Texp_construct(_, {cstr_tag = Cstr_constant _}, _)}] - when simplify_constant_constructor -> - intcomp - | [{exp_desc = Texp_construct(_, {cstr_tag = Cstr_constant _}, _)}; arg2] - when simplify_constant_constructor -> - intcomp - | [arg1; {exp_desc = Texp_variant(_, None)}] - when simplify_constant_constructor -> - intcomp - | [{exp_desc = Texp_variant(_, None)}; exp2] - when simplify_constant_constructor -> - intcomp - | [arg1; arg2] when has_base_type arg1 Predef.path_int - || has_base_type arg1 Predef.path_char -> - intcomp - | [arg1; arg2] when has_base_type arg1 Predef.path_float -> - floatcomp - | [arg1; arg2] when has_base_type arg1 Predef.path_string -> - stringcomp - | [arg1; arg2] when has_base_type arg1 Predef.path_nativeint -> - nativeintcomp - | [arg1; arg2] when has_base_type arg1 Predef.path_int32 -> - int32comp - | [arg1; arg2] when has_base_type arg1 Predef.path_int64 -> - int64comp - | _ -> - gencomp - end + let table = Hashtbl.find comparisons_table p.prim_name in + let (gencomp, intcomp, _, _, _, _, _, simplify_constant_constructor) = + table in + if has_constant_constructor && simplify_constant_constructor then + intcomp + else + match is_function_type env ty with + | Some (lhs,rhs) -> specialize_comparison table env lhs + | None -> gencomp with Not_found -> - try - let p = find_primitive loc prim_name in + let p = find_primitive loc p.prim_name in (* Try strength reduction based on the type of the argument *) - begin match (p, args) with - (Psetfield(n, _), [arg1; arg2]) -> Psetfield(n, maybe_pointer arg2) - | (Parraylength Pgenarray, [arg]) -> Parraylength(array_kind arg) - | (Parrayrefu Pgenarray, arg1 :: _) -> Parrayrefu(array_kind arg1) - | (Parraysetu Pgenarray, arg1 :: _) -> Parraysetu(array_kind arg1) - | (Parrayrefs Pgenarray, arg1 :: _) -> Parrayrefs(array_kind arg1) - | (Parraysets Pgenarray, arg1 :: _) -> Parraysets(array_kind arg1) - | (Pbigarrayref(unsafe, n, Pbigarray_unknown, Pbigarray_unknown_layout), - arg1 :: _) -> - let (k, l) = bigarray_kind_and_layout arg1 in - Pbigarrayref(unsafe, n, k, l) - | (Pbigarrayset(unsafe, n, Pbigarray_unknown, Pbigarray_unknown_layout), - arg1 :: _) -> - let (k, l) = bigarray_kind_and_layout arg1 in - Pbigarrayset(unsafe, n, k, l) - | _ -> p - end - with Not_found -> - if String.length prim_name > 0 && prim_name.[0] = '%' then - raise(Error(loc, Unknown_builtin_primitive prim_name)); - Pccall prim - - -(* Eta-expand a primitive without knowing the types of its arguments *) - -let transl_primitive loc p = + let params = match is_function_type env ty with + | None -> [] + | Some (p1, rhs) -> match is_function_type env rhs with + | None -> [p1] + | Some (p2, _) -> [p1;p2] + in + match (p, params) with + (Psetfield(n, _, init), [p1; p2]) -> + Psetfield(n, maybe_pointer_type env p2, init) + | (Parraylength Pgenarray, [p]) -> Parraylength(array_type_kind env p) + | (Parrayrefu Pgenarray, p1 :: _) -> Parrayrefu(array_type_kind env p1) + | (Parraysetu Pgenarray, p1 :: _) -> Parraysetu(array_type_kind env p1) + | (Parrayrefs Pgenarray, p1 :: _) -> Parrayrefs(array_type_kind env p1) + | (Parraysets Pgenarray, p1 :: _) -> Parraysets(array_type_kind env p1) + | (Pbigarrayref(unsafe, n, Pbigarray_unknown, Pbigarray_unknown_layout), + p1 :: _) -> + let (k, l) = bigarray_type_kind_and_layout env p1 in + Pbigarrayref(unsafe, n, k, l) + | (Pbigarrayset(unsafe, n, Pbigarray_unknown, Pbigarray_unknown_layout), + p1 :: _) -> + let (k, l) = bigarray_type_kind_and_layout env p1 in + Pbigarrayset(unsafe, n, k, l) + | _ -> p + +(* Eta-expand a primitive *) + +let used_primitives = Hashtbl.create 7 +let add_used_primitive loc p env path = + match path with + Some (Path.Pdot _ as path) -> + let path = Env.normalize_path (Some loc) env path in + let unit = Path.head path in + if Ident.global unit && not (Hashtbl.mem used_primitives path) + then Hashtbl.add used_primitives path loc + | _ -> () + +let transl_primitive loc p env ty path = let prim = - try - let (gencomp, _, _, _, _, _, _, _) = - Hashtbl.find comparisons_table p.prim_name in - gencomp - with Not_found -> - try - find_primitive loc p.prim_name + try specialize_primitive loc p env ty ~has_constant_constructor:false with Not_found -> - Pccall p in + add_used_primitive loc p env path; + Pccall p + in match prim with | Plazyforce -> let parm = Ident.create "prim" in - Lfunction(Curried, [parm], - Matching.inline_lazy_force (Lvar parm) Location.none) + Lfunction{kind = Curried; params = [parm]; + body = Matching.inline_lazy_force (Lvar parm) Location.none; + attr = default_function_attribute } | Ploc kind -> let lam = lam_of_loc kind loc in begin match p.prim_arity with | 0 -> lam | 1 -> (* TODO: we should issue a warning ? *) let param = Ident.create "prim" in - Lfunction(Curried, [param], - Lprim(Pmakeblock(0, Immutable), [lam; Lvar param])) + Lfunction{kind = Curried; params = [param]; + attr = default_function_attribute; + body = Lprim(Pmakeblock(0, Immutable), [lam; Lvar param])} | _ -> assert false end | _ -> let rec make_params n = if n <= 0 then [] else Ident.create "prim" :: make_params (n-1) in let params = make_params p.prim_arity in - Lfunction(Curried, params, - Lprim(prim, List.map (fun id -> Lvar id) params)) + Lfunction{ kind = Curried; params; + attr = default_function_attribute; + body = Lprim(prim, List.map (fun id -> Lvar id) params) } + +let transl_primitive_application loc prim env ty path args = + let prim_name = prim.prim_name in + try + let has_constant_constructor = match args with + [_; {exp_desc = Texp_construct(_, {cstr_tag = Cstr_constant _}, _)}] + | [{exp_desc = Texp_construct(_, {cstr_tag = Cstr_constant _}, _)}; _] + | [_; {exp_desc = Texp_variant(_, None)}] + | [{exp_desc = Texp_variant(_, None)}; _] -> true + | _ -> false + in + specialize_primitive loc prim env ty ~has_constant_constructor + with Not_found -> + if String.length prim_name > 0 && prim_name.[0] = '%' then + raise(Error(loc, Unknown_builtin_primitive prim_name)); + add_used_primitive loc prim env path; + Pccall prim + (* To check the well-formedness of r.h.s. of "let rec" definitions *) @@ -444,14 +449,16 @@ let check_recursive_lambda idlist lam = let idlist' = add_letrec bindings idlist in List.for_all (fun (id, arg) -> check idlist' arg) bindings && check_top idlist' body - | Lprim (Pmakearray (Pgenarray), args) -> false + | Lprim (Pmakearray (Pgenarray, _), args) -> false + | Lprim (Pmakearray (Pfloatarray, _), args) -> + List.for_all (check idlist) args | Lsequence (lam1, lam2) -> check idlist lam1 && check_top idlist lam2 | Levent (lam, _) -> check_top idlist lam | lam -> check idlist lam and check idlist = function | Lvar _ -> true - | Lfunction(kind, params, body) -> true + | Lfunction{kind; params; body} -> true | Llet (_, _, _, _) as lam when check_recursive_recordwith idlist lam -> true | Llet(str, id, arg, body) -> @@ -462,7 +469,8 @@ let check_recursive_lambda idlist lam = check idlist' body | Lprim(Pmakeblock(tag, mut), args) -> List.for_all (check idlist) args - | Lprim(Pmakearray(_), args) -> + | Lprim (Pmakearray (Pfloatarray, _), _) -> false + | Lprim (Pmakearray _, args) -> List.for_all (check idlist) args | Lsequence (lam1, lam2) -> check idlist lam1 && check idlist lam2 | Levent (lam, _) -> check idlist lam @@ -520,6 +528,11 @@ let rec name_pattern default = function | _ -> name_pattern default rem (* Push the default values under the functional abstractions *) +(* Also push bindings of module patterns, since this sound *) + +type binding = + | Bind_value of value_binding list + | Bind_module of Ident.t * string loc * module_expr let rec push_defaults loc bindings cases partial = match cases with @@ -532,13 +545,25 @@ let rec push_defaults loc bindings cases partial = c_rhs={exp_attributes=[{txt="#default"},_]; exp_desc = Texp_let (Nonrecursive, binds, ({exp_desc = Texp_function _} as e2))}}] -> - push_defaults loc (binds :: bindings) [{c_lhs=pat;c_guard=None;c_rhs=e2}] - partial + push_defaults loc (Bind_value binds :: bindings) + [{c_lhs=pat;c_guard=None;c_rhs=e2}] + partial + | [{c_lhs=pat; c_guard=None; + c_rhs={exp_attributes=[{txt="#modulepat"},_]; + exp_desc = Texp_letmodule + (id, name, mexpr, ({exp_desc = Texp_function _} as e2))}}] -> + push_defaults loc (Bind_module (id, name, mexpr) :: bindings) + [{c_lhs=pat;c_guard=None;c_rhs=e2}] + partial | [case] -> let exp = List.fold_left (fun exp binds -> - {exp with exp_desc = Texp_let(Nonrecursive, binds, exp)}) + {exp with exp_desc = + match binds with + | Bind_value binds -> Texp_let(Nonrecursive, binds, exp) + | Bind_module (id, name, mexpr) -> + Texp_letmodule (id, name, mexpr, exp)}) case.c_rhs bindings in [{case with c_rhs=exp}] @@ -599,7 +624,8 @@ let primitive_is_ccall = function (* Determine if a primitive is a Pccall or will be turned later into a C function call that may raise an exception *) | Pccall _ | Pstringrefs | Pstringsets | Parrayrefs _ | Parraysets _ | - Pbigarrayref _ | Pbigarrayset _ | Pduprecord _ -> true + Pbigarrayref _ | Pbigarrayset _ | Pduprecord _ | Pdirapply _ | + Prevapply _ -> true | _ -> false (* Assertions *) @@ -626,6 +652,7 @@ let rec cut n l = let try_ids = Hashtbl.create 8 let rec transl_exp e = + List.iter (Translattribute.check_attribute e) e.exp_attributes; let eval_once = (* Whether classes for immediate objects must be cached *) match e.exp_desc with @@ -642,16 +669,18 @@ and transl_exp0 e = if public_send || p.prim_name = "%sendself" then let kind = if public_send then Public else Self in let obj = Ident.create "obj" and meth = Ident.create "meth" in - Lfunction(Curried, [obj; meth], Lsend(kind, Lvar meth, Lvar obj, [], - e.exp_loc)) + Lfunction{kind = Curried; params = [obj; meth]; + attr = default_function_attribute; + 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(Curried, [obj; meth; cache; pos], - Lsend(Cached, Lvar meth, Lvar obj, [Lvar cache; Lvar pos], - e.exp_loc)) + Lfunction{kind = Curried; params = [obj; meth; cache; pos]; + attr = default_function_attribute; + body = Lsend(Cached, Lvar meth, Lvar obj, + [Lvar cache; Lvar pos], e.exp_loc)} else - transl_primitive e.exp_loc p + transl_primitive e.exp_loc p e.exp_env e.exp_type (Some path) | Texp_ident(path, _, {val_kind = Val_anc _}) -> raise(Error(e.exp_loc, Free_super_var)) | Texp_ident(path, _, {val_kind = Val_reg | Val_self _}) -> @@ -668,21 +697,40 @@ and transl_exp0 e = let pl = push_defaults e.exp_loc [] pat_expr_list partial in transl_function e.exp_loc !Clflags.native_code repr partial pl) in - Lfunction(kind, params, body) - | Texp_apply({exp_desc = Texp_ident(path, _, {val_kind = Val_prim p})}, - oargs) + let attr = { + default_function_attribute with + inline = Translattribute.get_inline_attribute e.exp_attributes; + specialise = Translattribute.get_specialise_attribute e.exp_attributes; + } + in + Lfunction{kind; params; body; attr} + | Texp_apply({ exp_desc = Texp_ident(path, _, {val_kind = Val_prim p}); + exp_type = prim_type } as funct, oargs) when List.length oargs >= p.prim_arity - && List.for_all (fun (_, arg,_) -> arg <> None) oargs -> + && List.for_all (fun (_, arg) -> arg <> None) oargs -> let args, args' = cut p.prim_arity oargs in let wrap f = if args' = [] then event_after e f - else event_after e (transl_apply f args' e.exp_loc) + else + let should_be_tailcall, funct = + Translattribute.get_tailcall_attribute funct + in + let inlined, funct = + Translattribute.get_and_remove_inlined_attribute funct + in + let specialised, funct = + Translattribute.get_and_remove_specialised_attribute funct + in + let e = { e with exp_desc = Texp_apply(funct, oargs) } in + event_after e + (transl_apply ~should_be_tailcall ~inlined ~specialised + f args' e.exp_loc) in let wrap0 f = if args' = [] then f else wrap f in let args = - List.map (function _, Some x, _ -> x | _ -> assert false) args in + List.map (function _, Some x -> x | _ -> assert false) args in let argl = transl_list args in let public_send = p.prim_name = "%send" || not !Clflags.native_code && p.prim_name = "%sendcache"in @@ -695,7 +743,8 @@ and transl_exp0 e = wrap (Lsend(Cached, meth, obj, [cache; pos], e.exp_loc)) | _ -> assert false else begin - let prim = transl_prim e.exp_loc p args in + let prim = transl_primitive_application + e.exp_loc p e.exp_env prim_type (Some path) args in match (prim, args) with (Praise k, [arg1]) -> let targ = List.hd argl in @@ -724,7 +773,19 @@ and transl_exp0 e = end end | Texp_apply(funct, oargs) -> - event_after e (transl_apply (transl_exp funct) oargs e.exp_loc) + let should_be_tailcall, funct = + Translattribute.get_tailcall_attribute funct + in + let inlined, funct = + Translattribute.get_and_remove_inlined_attribute funct + in + let specialised, funct = + Translattribute.get_and_remove_specialised_attribute funct + in + let e = { e with exp_desc = Texp_apply(funct, oargs) } in + event_after e + (transl_apply ~should_be_tailcall ~inlined ~specialised + (transl_exp funct) oargs e.exp_loc) | 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) -> @@ -740,7 +801,10 @@ and transl_exp0 e = end | Texp_construct(_, cstr, args) -> let ll = transl_list args in - begin match cstr.cstr_tag with + if cstr.cstr_inlined <> None then begin match ll with + | [x] -> x + | _ -> assert false + end else begin match cstr.cstr_tag with Cstr_constant n -> Lconst(Const_pointer n) | Cstr_block n -> @@ -756,6 +820,8 @@ and transl_exp0 e = Lprim(Pmakeblock(0, Immutable), transl_path e.exp_env path :: ll) end + | Texp_extension_constructor (_, path) -> + transl_path e.exp_env path | Texp_variant(l, arg) -> let tag = Btype.hash_variant l in begin match arg with @@ -770,39 +836,71 @@ and transl_exp0 e = [Lconst(Const_base(Const_int tag)); lam]) end | Texp_record ((_, lbl1, _) :: _ as lbl_expr_list, opt_init_expr) -> - transl_record lbl1.lbl_all lbl1.lbl_repres lbl_expr_list opt_init_expr + transl_record e.exp_env lbl1.lbl_all lbl1.lbl_repres lbl_expr_list + opt_init_expr | Texp_record ([], _) -> fatal_error "Translcore.transl_exp: bad Texp_record" | Texp_field(arg, _, lbl) -> let access = match lbl.lbl_repres with - Record_regular -> Pfield lbl.lbl_pos - | Record_float -> Pfloatfield lbl.lbl_pos in + Record_regular | Record_inlined _ -> Pfield lbl.lbl_pos + | Record_float -> Pfloatfield lbl.lbl_pos + | Record_extension -> Pfield (lbl.lbl_pos + 1) + in Lprim(access, [transl_exp arg]) | Texp_setfield(arg, _, lbl, newval) -> let access = match lbl.lbl_repres with - Record_regular -> Psetfield(lbl.lbl_pos, maybe_pointer newval) - | Record_float -> Psetfloatfield lbl.lbl_pos in + Record_regular + | Record_inlined _ -> + Psetfield(lbl.lbl_pos, maybe_pointer newval, Assignment) + | Record_float -> Psetfloatfield (lbl.lbl_pos, Assignment) + | Record_extension -> + Psetfield (lbl.lbl_pos + 1, maybe_pointer newval, Assignment) + in Lprim(access, [transl_exp arg; transl_exp newval]) | Texp_array expr_list -> let kind = array_kind e in let ll = transl_list expr_list in begin try + (* For native code the decision as to which compilation strategy to + use is made later. This enables the Flambda passes to lift certain + kinds of array definitions to symbols. *) (* Deactivate constant optimization if array is small enough *) - if List.length ll <= 4 then raise Not_constant; - let cl = List.map extract_constant ll in - let master = - match kind with - | Paddrarray | Pintarray -> - Lconst(Const_block(0, cl)) - | Pfloatarray -> - Lconst(Const_float_array(List.map extract_float cl)) - | Pgenarray -> - raise Not_constant in (* can this really happen? *) - Lprim(Pccall prim_obj_dup, [master]) + if List.length ll <= use_dup_for_constant_arrays_bigger_than + then begin + raise Not_constant + end; + begin match List.map extract_constant ll with + | exception Not_constant when kind = Pfloatarray -> + (* We cannot currently lift [Pintarray] arrays safely in Flambda + because [caml_modify] might be called upon them (e.g. from + code operating on polymorphic arrays, or functions such as + [caml_array_blit]. + To avoid having different Lambda code for + bytecode/Closure vs. Flambda, we always generate + [Pduparray] here, and deal with it in [Bytegen] (or in + the case of Closure, in [Cmmgen], which already has to + handle [Pduparray Pmakearray Pfloatarray] in the case + where the array turned out to be inconstant). + When not [Pfloatarray], the exception propagates to the handler + below. *) + let imm_array = Lprim (Pmakearray (kind, Immutable), ll) in + Lprim (Pduparray (kind, Mutable), [imm_array]) + | cl -> + let imm_array = + match kind with + | Paddrarray | Pintarray -> + Lconst(Const_block(0, cl)) + | Pfloatarray -> + Lconst(Const_float_array(List.map extract_float cl)) + | Pgenarray -> + raise Not_constant (* can this really happen? *) + in + Lprim (Pduparray (kind, Mutable), [imm_array]) + end with Not_constant -> - Lprim(Pmakearray kind, ll) + Lprim(Pmakearray (kind, Mutable), ll) end | Texp_ifthenelse(cond, ifso, Some ifnot) -> Lifthenelse(transl_exp cond, @@ -832,8 +930,12 @@ and transl_exp0 e = in event_after e lam | Texp_new (cl, {Location.loc=loc}, _) -> - Lapply(Lprim(Pfield 0, [transl_path ~loc e.exp_env cl]), - [lambda_unit], Location.none) + Lapply{ap_should_be_tailcall=false; + ap_loc=loc; + ap_func=Lprim(Pfield 0, [transl_path ~loc e.exp_env cl]); + ap_args=[lambda_unit]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} | Texp_instvar(path_self, path, _) -> Lprim(Parrayrefu Paddrarray, [transl_normal_path path_self; transl_normal_path path]) @@ -842,8 +944,12 @@ and transl_exp0 e = | Texp_override(path_self, modifs) -> let cpy = Ident.create "copy" in Llet(Strict, cpy, - Lapply(Translobj.oo_prim "copy", [transl_normal_path path_self], - Location.none), + Lapply{ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=Translobj.oo_prim "copy"; + ap_args=[transl_normal_path path_self]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise}, List.fold_right (fun (path, _, expr) rem -> Lsequence(transl_setinstvar (Lvar cpy) path expr, rem)) @@ -905,7 +1011,9 @@ and transl_exp0 e = end (* other cases compile to a lazy block holding a function *) | _ -> - let fn = Lfunction (Curried, [Ident.create "param"], transl_exp e) in + let fn = Lfunction {kind = Curried; params = [Ident.create "param"]; + attr = default_function_attribute; + body = transl_exp e} in Lprim(Pmakeblock(Config.lazy_tag, Mutable), [fn]) end | Texp_object (cs, meths) -> @@ -918,6 +1026,8 @@ and transl_exp0 e = cl_env = e.exp_env; cl_attributes = []; } + | Texp_unreachable -> + raise (Error (e.exp_loc, Unreachable_reached)) and transl_list expr_list = List.map transl_exp expr_list @@ -933,6 +1043,8 @@ and transl_case {c_lhs; c_guard; c_rhs} = c_lhs, transl_guard c_guard c_rhs and transl_cases cases = + let cases = + List.filter (fun c -> c.c_rhs.exp_desc <> Texp_unreachable) cases in List.map transl_case cases and transl_case_try {c_lhs; c_guard; c_rhs} = @@ -947,23 +1059,34 @@ and transl_case_try {c_lhs; c_guard; c_rhs} = c_lhs, transl_guard c_guard c_rhs and transl_cases_try cases = + let cases = + List.filter (fun c -> c.c_rhs.exp_desc <> Texp_unreachable) cases in List.map transl_case_try cases and transl_tupled_cases patl_expr_list = + let patl_expr_list = + List.filter (fun (_,_,e) -> e.exp_desc <> Texp_unreachable) + patl_expr_list in List.map (fun (patl, guard, expr) -> (patl, transl_guard guard expr)) patl_expr_list -and transl_apply lam sargs loc = +and transl_apply ?(should_be_tailcall=false) ?(inlined = Default_inline) + ?(specialised = Default_specialise) lam sargs loc = let lapply funct args = match funct with Lsend(k, lmet, lobj, largs, loc) -> Lsend(k, lmet, lobj, largs @ args, loc) | Levent(Lsend(k, lmet, lobj, largs, loc), _) -> Lsend(k, lmet, lobj, largs @ args, loc) - | Lapply(lexp, largs, _) -> - Lapply(lexp, largs @ args, loc) + | Lapply ap -> + Lapply {ap with ap_args = ap.ap_args @ args; ap_loc = loc} | lexp -> - Lapply(lexp, args, loc) + Lapply {ap_should_be_tailcall=should_be_tailcall; + ap_loc=loc; + ap_func=lexp; + ap_args=args; + ap_inlined=inlined; + ap_specialised=specialised;} in let rec build_apply lam args = function (None, optional) :: l -> @@ -977,7 +1100,7 @@ and transl_apply lam sargs loc = Lvar id in let args, args' = - if List.for_all (fun (_,opt) -> opt = Optional) args then [], args + if List.for_all (fun (_,opt) -> opt) args then [], args else args, [] in let lam = if args = [] then lam else lapply lam (List.rev_map fst args) in @@ -986,12 +1109,14 @@ and transl_apply lam sargs loc = and id_arg = Ident.create "param" in let body = match build_apply handle ((Lvar id_arg, optional)::args') l with - Lfunction(Curried, ids, lam) -> - Lfunction(Curried, id_arg::ids, lam) - | Levent(Lfunction(Curried, ids, lam), _) -> - Lfunction(Curried, id_arg::ids, lam) + Lfunction{kind = Curried; params = ids; body = lam; attr} -> + Lfunction{kind = Curried; params = id_arg::ids; body = lam; attr} + | Levent(Lfunction{kind = Curried; params = ids; + body = lam; attr}, _) -> + Lfunction{kind = Curried; params = id_arg::ids; body = lam; attr} | lam -> - Lfunction(Curried, [id_arg], lam) + Lfunction{kind = Curried; params = [id_arg]; body = lam; + attr = default_function_attribute} in List.fold_left (fun body (id, lam) -> Llet(Strict, id, lam, body)) @@ -1001,7 +1126,10 @@ and transl_apply lam sargs loc = | [] -> lapply lam (List.rev_map fst args) in - build_apply lam [] (List.map (fun (l, x,o) -> may_map transl_exp x, o) sargs) + (build_apply lam [] (List.map (fun (l, x) -> + may_map transl_exp x, Btype.is_optional l) + sargs) + : Lambda.lambda) and transl_function loc untuplify_fn repr partial cases = match cases with @@ -1043,8 +1171,15 @@ and transl_let rec_flag pat_expr_list body = let rec transl = function [] -> body - | {vb_pat=pat; vb_expr=expr} :: rem -> - Matching.for_let pat.pat_loc (transl_exp expr) pat (transl rem) + | {vb_pat=pat; vb_expr=expr; vb_attributes=attr; vb_loc} :: rem -> + let lam = transl_exp expr in + let lam = + Translattribute.add_inline_attribute lam vb_loc attr + in + let lam = + Translattribute.add_specialise_attribute lam vb_loc attr + in + Matching.for_let pat.pat_loc lam pat (transl rem) in transl pat_expr_list | Recursive -> let idlist = @@ -1054,18 +1189,30 @@ and transl_let rec_flag pat_expr_list body = | Tpat_alias ({pat_desc=Tpat_any}, id,_) -> id | _ -> raise(Error(pat.pat_loc, Illegal_letrec_pat))) pat_expr_list in - let transl_case {vb_pat=pat; vb_expr=expr} id = + let transl_case {vb_pat=pat; vb_expr=expr; vb_attributes; vb_loc} id = let lam = transl_exp expr in + let lam = + Translattribute.add_inline_attribute lam vb_loc + vb_attributes + in + let lam = + Translattribute.add_specialise_attribute lam vb_loc + vb_attributes + in if not (check_recursive_lambda idlist lam) then raise(Error(expr.exp_loc, Illegal_letrec_expr)); (id, lam) in Lletrec(List.map2 transl_case pat_expr_list idlist, body) and transl_setinstvar self var expr = - Lprim(Parraysetu (if maybe_pointer expr then Paddrarray else Pintarray), - [self; transl_normal_path var; transl_exp expr]) + let prim = + match maybe_pointer expr with + | Pointer -> Paddrarray + | Immediate -> Pintarray + in + Lprim(Parraysetu prim, [self; transl_normal_path var; transl_exp expr]) -and transl_record all_labels repres lbl_expr_list opt_init_expr = +and transl_record env all_labels repres lbl_expr_list opt_init_expr = let size = Array.length all_labels in (* Determine if there are "enough" new fields *) if 3 + 2 * List.length lbl_expr_list >= size @@ -1080,7 +1227,8 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr = for i = 0 to Array.length all_labels - 1 do let access = match all_labels.(i).lbl_repres with - Record_regular -> Pfield i + Record_regular | Record_inlined _ -> Pfield i + | Record_extension -> Pfield (i + 1) | Record_float -> Pfloatfield i in lv.(i) <- Lprim(access, [Lvar init_id]) done @@ -1090,7 +1238,8 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr = lbl_expr_list; let ll = Array.to_list lv in let mut = - if List.exists (fun (_, lbl, expr) -> lbl.lbl_mut = Mutable) lbl_expr_list + if List.exists (fun lbl -> lbl.lbl_mut = Mutable) + (Array.to_list all_labels) then Mutable else Immutable in let lam = @@ -1098,13 +1247,26 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr = if mut = Mutable then raise Not_constant; let cl = List.map extract_constant ll in match repres with - Record_regular -> Lconst(Const_block(0, cl)) + | Record_regular -> Lconst(Const_block(0, cl)) + | Record_inlined tag -> Lconst(Const_block(tag, cl)) | Record_float -> Lconst(Const_float_array(List.map extract_float cl)) + | Record_extension -> + raise Not_constant with Not_constant -> match repres with Record_regular -> Lprim(Pmakeblock(0, mut), ll) - | Record_float -> Lprim(Pmakearray Pfloatarray, ll) in + | Record_inlined tag -> Lprim(Pmakeblock(tag, mut), ll) + | Record_float -> Lprim(Pmakearray (Pfloatarray, mut), ll) + | Record_extension -> + let path = + match all_labels.(0).lbl_res.desc with + | Tconstr(p, _, _) -> p + | _ -> assert false + in + let slot = transl_path env path in + Lprim(Pmakeblock(0, mut), slot :: ll) + in begin match opt_init_expr with None -> lam | Some init_expr -> Llet(Strict, init_id, transl_exp init_expr, lam) @@ -1118,8 +1280,13 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr = let update_field (_, lbl, expr) cont = let upd = match lbl.lbl_repres with - Record_regular -> Psetfield(lbl.lbl_pos, maybe_pointer expr) - | Record_float -> Psetfloatfield lbl.lbl_pos in + Record_regular + | Record_inlined _ -> + Psetfield(lbl.lbl_pos, maybe_pointer expr, Assignment) + | Record_float -> Psetfloatfield (lbl.lbl_pos, Assignment) + | Record_extension -> + Psetfield(lbl.lbl_pos + 1, maybe_pointer expr, Assignment) + in Lsequence(Lprim(upd, [Lvar copy_id; transl_exp expr]), cont) in begin match opt_init_expr with None -> assert false @@ -1133,7 +1300,7 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr = and transl_match e arg pat_expr_list exn_pat_expr_list partial = let id = name_pattern "exn" exn_pat_expr_list and cases = transl_cases pat_expr_list - and exn_cases = transl_cases exn_pat_expr_list in + and exn_cases = transl_cases_try exn_pat_expr_list in let static_catch body val_ids handler = let static_exception_id = next_negative_raise_count () in Lstaticcatch @@ -1186,7 +1353,9 @@ let report_error ppf = function fprintf ppf "Ancestor names can only be used to select inherited methods" | Unknown_builtin_primitive prim_name -> - fprintf ppf "Unknown builtin primitive \"%s\"" prim_name + fprintf ppf "Unknown builtin primitive \"%s\"" prim_name + | Unreachable_reached -> + fprintf ppf "Unreachable expression was reached" let () = Location.register_error_of_exn diff --git a/bytecomp/translcore.mli b/bytecomp/translcore.mli index 70f700fc..16f2c895 100644 --- a/bytecomp/translcore.mli +++ b/bytecomp/translcore.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Translation from typed abstract syntax to lambda terms, for the core language *) @@ -18,18 +21,25 @@ open Typedtree open Lambda val transl_exp: expression -> lambda -val transl_apply: lambda -> (label * expression option * optional) list +val transl_apply: ?should_be_tailcall:bool + -> ?inlined:inline_attribute + -> ?specialised:specialise_attribute + -> lambda -> (arg_label * expression option) list -> Location.t -> lambda val transl_let: rec_flag -> value_binding list -> lambda -> lambda -val transl_primitive: Location.t -> Primitive.description -> lambda +val transl_primitive: Location.t -> Primitive.description -> Env.t + -> Types.type_expr -> Path.t option -> lambda val check_recursive_lambda: Ident.t list -> lambda -> bool +val used_primitives: (Path.t, Location.t) Hashtbl.t + type error = Illegal_letrec_pat | Illegal_letrec_expr | Free_super_var | Unknown_builtin_primitive of string + | Unreachable_reached exception Error of Location.t * error diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml index d3c6ca2b..52b744c4 100644 --- a/bytecomp/translmod.ml +++ b/bytecomp/translmod.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Translation from typed abstract syntax to lambda terms, for the module language *) @@ -45,23 +48,21 @@ let field_path path field = (* Compile type extensions *) -let prim_set_oo_id = - Pccall {Primitive.prim_name = "caml_set_oo_id"; prim_arity = 1; - prim_alloc = false; prim_native_name = ""; - prim_native_float = false} +let prim_fresh_oo_id = + Pccall (Primitive.simple ~name:"caml_fresh_oo_id" ~arity:1 ~alloc:false) let transl_extension_constructor env path ext = let name = - match path with - None -> Ident.name ext.ext_id - | Some p -> Path.name p + match path, !Clflags.for_package with + None, _ -> Ident.name ext.ext_id + | Some p, None -> Path.name p + | Some p, Some pack -> Printf.sprintf "%s.%s" pack (Path.name p) in match ext.ext_kind with Text_decl(args, ret) -> - Lprim(prim_set_oo_id, - [Lprim(Pmakeblock(Obj.object_tag, Mutable), - [Lconst(Const_base(Const_string (name,None))); - Lconst(Const_base(Const_int 0))])]) + Lprim (Pmakeblock (Obj.object_tag, Immutable), + [Lconst (Const_base (Const_string (name, None))); + Lprim (prim_fresh_oo_id, [Lconst (Const_base (Const_int 0))])]) | Text_rebind(path, lid) -> transl_path ~loc:ext.ext_loc env path @@ -92,12 +93,20 @@ let rec apply_coercion strict restr arg = | Tcoerce_functor(cc_arg, cc_res) -> let param = Ident.create "funarg" in name_lambda strict arg (fun id -> - Lfunction(Curried, [param], - apply_coercion Strict cc_res - (Lapply(Lvar id, [apply_coercion Alias cc_arg (Lvar param)], - Location.none)))) - | Tcoerce_primitive p -> - transl_primitive Location.none p + Lfunction{kind = Curried; params = [param]; + attr = { default_function_attribute with + is_a_functor = true }; + body = apply_coercion + Strict cc_res + (Lapply{ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=Lvar id; + ap_args=[apply_coercion Alias cc_arg + (Lvar param)]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise})}) + | Tcoerce_primitive { pc_loc; pc_desc; pc_env; pc_type; } -> + transl_primitive pc_loc pc_desc pc_env pc_type None | Tcoerce_alias (path, cc) -> name_lambda strict arg (fun id -> apply_coercion Alias cc (transl_normal_path path)) @@ -206,15 +215,19 @@ let init_shape modl = and init_shape_struct env sg = match sg with [] -> [] - | Sig_value(id, vdesc) :: rem -> + | Sig_value(_id, {val_kind=Val_reg; val_type=ty}) :: rem -> let init_v = - match Ctype.expand_head env vdesc.val_type with + match Ctype.expand_head env ty with {desc = Tarrow(_,_,_,_)} -> Const_pointer 0 (* camlinternalMod.Function *) | {desc = Tconstr(p, _, _)} when Path.same p Predef.path_lazy_t -> Const_pointer 1 (* camlinternalMod.Lazy *) | _ -> raise Not_found in init_v :: init_shape_struct env rem + | Sig_value(_, {val_kind=Val_prim _}) :: rem -> + init_shape_struct env rem + | Sig_value _ :: _rem -> + assert false | Sig_type(id, tdecl, _) :: rem -> init_shape_struct (Env.add_type ~check:false id tdecl env) rem | Sig_typext(id, ext, _) :: rem -> @@ -279,7 +292,13 @@ let eval_rec_bindings bindings cont = | (id, None, rhs) :: rem -> bind_inits rem | (id, Some(loc, shape), rhs) :: rem -> - Llet(Strict, id, Lapply(mod_prim "init_mod", [loc; shape], Location.none), + Llet(Strict, id, + Lapply{ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=mod_prim "init_mod"; + ap_args=[loc; shape]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise}, bind_inits rem) and bind_strict = function [] -> @@ -294,8 +313,12 @@ let eval_rec_bindings bindings cont = | (id, None, rhs) :: rem -> patch_forwards rem | (id, Some(loc, shape), rhs) :: rem -> - Lsequence(Lapply(mod_prim "update_mod", [shape; Lvar id; rhs], - Location.none), + Lsequence(Lapply{ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=mod_prim "update_mod"; + ap_args=[shape; Lvar id; rhs]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise}, patch_forwards rem) in bind_inits bindings @@ -323,140 +346,211 @@ let rec bound_value_identifiers = function | Sig_class(id, decl, _) :: rem -> id :: bound_value_identifiers rem | _ :: rem -> bound_value_identifiers rem + +(* Code to translate class entries in a structure *) + +let transl_class_bindings cl_list = + let ids = List.map (fun (ci, _) -> ci.ci_id_class) cl_list in + (ids, + List.map + (fun ({ci_id_class=id; ci_expr=cl; ci_virt=vf}, meths) -> + (id, transl_class ids id meths cl vf)) + cl_list) + (* Compile a module expression *) let rec transl_module cc rootpath mexp = + List.iter (Translattribute.check_attribute_on_module mexp) + mexp.mod_attributes; match mexp.mod_type with Mty_alias _ -> apply_coercion Alias cc lambda_unit | _ -> - match mexp.mod_desc with - Tmod_ident (path,_) -> - apply_coercion Strict cc - (transl_path ~loc:mexp.mod_loc mexp.mod_env path) - | Tmod_structure str -> - transl_struct [] cc rootpath str - | Tmod_functor( param, _, mty, body) -> - let bodypath = functor_path rootpath param in - oo_wrap mexp.mod_env true - (function - | Tcoerce_none -> - Lfunction(Curried, [param], - transl_module Tcoerce_none bodypath body) - | Tcoerce_functor(ccarg, ccres) -> - let param' = Ident.create "funarg" in - Lfunction(Curried, [param'], - Llet(Alias, param, - apply_coercion Alias ccarg (Lvar param'), - transl_module ccres bodypath body)) - | _ -> - fatal_error "Translmod.transl_module") - cc - | Tmod_apply(funct, arg, ccarg) -> - oo_wrap mexp.mod_env true - (apply_coercion Strict cc) - (Lapply(transl_module Tcoerce_none None funct, - [transl_module ccarg None arg], mexp.mod_loc)) - | Tmod_constraint(arg, mty, _, ccarg) -> - transl_module (compose_coercions cc ccarg) rootpath arg - | Tmod_unpack(arg, _) -> - apply_coercion Strict cc (Translcore.transl_exp arg) + match mexp.mod_desc with + Tmod_ident (path,_) -> + apply_coercion Strict cc + (transl_path ~loc:mexp.mod_loc mexp.mod_env path) + | Tmod_structure str -> + fst (transl_struct [] cc rootpath str) + | Tmod_functor( param, _, mty, body) -> + let bodypath = functor_path rootpath param in + let inline_attribute = + Translattribute.get_inline_attribute mexp.mod_attributes + in + oo_wrap mexp.mod_env true + (function + | Tcoerce_none -> + Lfunction{kind = Curried; params = [param]; + attr = { inline = inline_attribute; + specialise = Default_specialise; + is_a_functor = true }; + body = transl_module Tcoerce_none bodypath body} + | Tcoerce_functor(ccarg, ccres) -> + let param' = Ident.create "funarg" in + Lfunction{kind = Curried; params = [param']; + attr = { inline = inline_attribute; + specialise = Default_specialise; + is_a_functor = true }; + body = Llet(Alias, param, + apply_coercion Alias ccarg + (Lvar param'), + transl_module ccres bodypath body)} + | _ -> + fatal_error "Translmod.transl_module") + cc + | Tmod_apply(funct, arg, ccarg) -> + let inlined_attribute, funct = + Translattribute.get_and_remove_inlined_attribute_on_module funct + in + oo_wrap mexp.mod_env true + (apply_coercion Strict cc) + (Lapply{ap_should_be_tailcall=false; + ap_loc=mexp.mod_loc; + ap_func=transl_module Tcoerce_none None funct; + ap_args=[transl_module ccarg None arg]; + ap_inlined=inlined_attribute; + ap_specialised=Default_specialise}) + | Tmod_constraint(arg, mty, _, ccarg) -> + transl_module (compose_coercions cc ccarg) rootpath arg + | Tmod_unpack(arg, _) -> + apply_coercion Strict cc (Translcore.transl_exp arg) and transl_struct fields cc rootpath str = - transl_structure fields cc rootpath str.str_items + transl_structure fields cc rootpath str.str_final_env str.str_items -and transl_structure fields cc rootpath = function +and transl_structure fields cc rootpath final_env = function [] -> - begin match cc with - Tcoerce_none -> - Lprim(Pmakeblock(0, Immutable), - List.map (fun id -> Lvar id) (List.rev fields)) - | Tcoerce_structure(pos_cc_list, id_pos_list) -> - (* Do not ignore id_pos_list ! *) - (*Format.eprintf "%a@.@[" Includemod.print_coercion cc; - List.iter (fun l -> Format.eprintf "%a@ " Ident.print l) - fields; - Format.eprintf "@]@.";*) - let v = Array.of_list (List.rev fields) in - let get_field pos = Lvar v.(pos) - and ids = List.fold_right IdentSet.add fields IdentSet.empty in - let lam = - (Lprim(Pmakeblock(0, Immutable), - List.map - (fun (pos, cc) -> - match cc with - Tcoerce_primitive p -> transl_primitive Location.none p - | _ -> apply_coercion Strict cc (get_field pos)) - pos_cc_list)) - and id_pos_list = - List.filter (fun (id,_,_) -> not (IdentSet.mem id ids)) id_pos_list - in - wrap_id_pos_list id_pos_list get_field lam - | _ -> - fatal_error "Translmod.transl_structure" - end + let body, size = + match cc with + Tcoerce_none -> + Lprim(Pmakeblock(0, Immutable), + List.map (fun id -> Lvar id) (List.rev fields)), + List.length fields + | Tcoerce_structure(pos_cc_list, id_pos_list) -> + (* Do not ignore id_pos_list ! *) + (*Format.eprintf "%a@.@[" Includemod.print_coercion cc; + List.iter (fun l -> Format.eprintf "%a@ " Ident.print l) + fields; + Format.eprintf "@]@.";*) + let v = Array.of_list (List.rev fields) in + let get_field pos = Lvar v.(pos) + and ids = List.fold_right IdentSet.add fields IdentSet.empty in + let lam = + (Lprim(Pmakeblock(0, Immutable), + List.map + (fun (pos, cc) -> + match cc with + Tcoerce_primitive p -> + transl_primitive p.pc_loc + p.pc_desc p.pc_env p.pc_type None + | _ -> apply_coercion Strict cc (get_field pos)) + pos_cc_list)) + and id_pos_list = + List.filter (fun (id,_,_) -> not (IdentSet.mem id ids)) + id_pos_list + in + wrap_id_pos_list id_pos_list get_field lam, + List.length pos_cc_list + | _ -> + fatal_error "Translmod.transl_structure" + in + (* This debugging event provides information regarding the structure + items. It is ignored by the OCaml debugger but is used by + Js_of_ocaml to preserve variable names. *) + (if !Clflags.debug then + Levent(body, + {lev_loc = Location.none; + lev_kind = Lev_pseudo; + lev_repr = None; + lev_env = Env.summary final_env}) + else + body), + size | item :: rem -> match item.str_desc with | Tstr_eval (expr, _) -> - Lsequence(transl_exp expr, transl_structure fields cc rootpath rem) - | Tstr_value(rec_flag, pat_expr_list) -> - let ext_fields = rev_let_bound_idents pat_expr_list @ fields in - transl_let rec_flag pat_expr_list - (transl_structure ext_fields cc rootpath rem) - | Tstr_primitive descr -> - record_primitive descr.val_val; - transl_structure fields cc rootpath rem - | Tstr_type decls -> - transl_structure fields cc rootpath rem - | Tstr_typext(tyext) -> - let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in - transl_type_extension item.str_env rootpath tyext - (transl_structure (List.rev_append ids fields) cc rootpath rem) - | Tstr_exception ext -> - let id = ext.ext_id in - let path = field_path rootpath id in - Llet(Strict, id, transl_extension_constructor item.str_env path ext, - transl_structure (id :: fields) cc rootpath rem) - | Tstr_module mb -> - let id = mb.mb_id in - Llet(pure_module mb.mb_expr, id, - transl_module Tcoerce_none (field_path rootpath id) mb.mb_expr, - transl_structure (id :: fields) cc rootpath rem) - | Tstr_recmodule bindings -> - let ext_fields = - List.rev_append (List.map (fun mb -> mb.mb_id) bindings) fields - in - compile_recmodule - (fun id modl -> - transl_module Tcoerce_none (field_path rootpath id) modl) - bindings - (transl_structure ext_fields cc rootpath rem) - | Tstr_class cl_list -> - let ids = List.map (fun (ci,_,_) -> ci.ci_id_class) cl_list in - Lletrec(List.map - (fun (ci, meths, vf) -> - let id = ci.ci_id_class in - let cl = ci.ci_expr in - (id, transl_class ids id meths cl vf )) - cl_list, - transl_structure (List.rev_append ids fields) cc rootpath rem) - | Tstr_include incl -> - let ids = bound_value_identifiers incl.incl_type in - let modl = incl.incl_mod in - let mid = Ident.create "include" in - let rec rebind_idents pos newfields = function - [] -> - transl_structure newfields cc rootpath rem - | id :: ids -> - Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]), - rebind_idents (pos + 1) (id :: newfields) ids) in - Llet(pure_module modl, mid, transl_module Tcoerce_none None modl, - rebind_idents 0 fields ids) + let body, size = transl_structure fields cc rootpath final_env rem in + Lsequence(transl_exp expr, body), size + | Tstr_value(rec_flag, pat_expr_list) -> + let ext_fields = rev_let_bound_idents pat_expr_list @ fields in + let body, size = + transl_structure ext_fields cc rootpath final_env rem in + transl_let rec_flag pat_expr_list body, size + | Tstr_primitive descr -> + record_primitive descr.val_val; + transl_structure fields cc rootpath final_env rem + | Tstr_type(_, decls) -> + transl_structure fields cc rootpath final_env rem + | Tstr_typext(tyext) -> + let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in + let body, size = + transl_structure (List.rev_append ids fields) + cc rootpath final_env rem + in + transl_type_extension item.str_env rootpath tyext body, size + | Tstr_exception ext -> + let id = ext.ext_id in + let path = field_path rootpath id in + let body, size = + transl_structure (id :: fields) cc rootpath final_env rem in + Llet(Strict, id, transl_extension_constructor item.str_env path ext, + body), size + | Tstr_module mb -> + let id = mb.mb_id in + let body, size = + transl_structure (id :: fields) cc rootpath final_env rem in + let module_body = + transl_module Tcoerce_none (field_path rootpath id) mb.mb_expr + in + let module_body = + Translattribute.add_inline_attribute module_body mb.mb_loc + mb.mb_attributes + in + Llet(pure_module mb.mb_expr, id, + module_body, + body), size + | Tstr_recmodule bindings -> + let ext_fields = + List.rev_append (List.map (fun mb -> mb.mb_id) bindings) fields + in + let body, size = + transl_structure ext_fields cc rootpath final_env rem in + let lam = + compile_recmodule + (fun id modl -> + transl_module Tcoerce_none (field_path rootpath id) modl) + bindings + body + in + lam, size + | Tstr_class cl_list -> + let (ids, class_bindings) = transl_class_bindings cl_list in + let body, size = + transl_structure (List.rev_append ids fields) + cc rootpath final_env rem + in + Lletrec(class_bindings, body), size + | Tstr_include incl -> + let ids = bound_value_identifiers incl.incl_type in + let modl = incl.incl_mod in + let mid = Ident.create "include" in + let rec rebind_idents pos newfields = function + [] -> + transl_structure newfields cc rootpath final_env rem + | id :: ids -> + let body, size = + rebind_idents (pos + 1) (id :: newfields) ids + in + Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]), body), size + in + let body, size = rebind_idents 0 fields ids in + Llet(pure_module modl, mid, transl_module Tcoerce_none None modl, + body), size - | Tstr_modtype _ - | Tstr_open _ - | Tstr_class_type _ - | Tstr_attribute _ -> - transl_structure fields cc rootpath rem + | Tstr_modtype _ + | Tstr_open _ + | Tstr_class_type _ + | Tstr_attribute _ -> + transl_structure fields cc rootpath final_env rem and pure_module m = match m.mod_desc with @@ -468,16 +562,63 @@ and pure_module m = let _ = Translcore.transl_module := transl_module +(* Introduce dependencies on modules referenced only by "external". *) + +let scan_used_globals lam = + let globals = ref IdentSet.empty in + let rec scan lam = + Lambda.iter scan lam; + match lam with + Lprim ((Pgetglobal id | Psetglobal id), _) -> + globals := IdentSet.add id !globals + | _ -> () + in + scan lam; !globals + +let wrap_globals ~flambda body = + let globals = scan_used_globals body in + let add_global id req = + if not flambda && IdentSet.mem id globals then + req + else + IdentSet.add id req + in + let required = + Hashtbl.fold + (fun path loc -> add_global (Path.head path)) used_primitives + (if flambda then globals else IdentSet.empty) + in + let required = + List.fold_right add_global (Env.get_required_globals ()) required + in + Env.reset_required_globals (); + Hashtbl.clear used_primitives; + IdentSet.fold + (fun id expr -> Lsequence(Lprim(Popaque, [Lprim(Pgetglobal id, [])]), expr)) + required body + (* Location.prerr_warning loc + (Warnings.Nonrequired_global (Ident.name (Path.head path), + "uses the primitive " ^ + Printtyp.string_of_path path))) *) + (* Compile an implementation *) -let transl_implementation module_name (str, cc) = +let transl_implementation_flambda module_name (str, cc) = reset_labels (); primitive_declarations := []; + Hashtbl.clear used_primitives; let module_id = Ident.create_persistent module_name in - Lprim(Psetglobal module_id, - [transl_label_init - (transl_struct [] cc (global_path module_id) str)]) + let body, size = + Translobj.transl_label_init + (fun () -> transl_struct [] cc (global_path module_id) str) + in + (module_id, size), wrap_globals ~flambda:true body +let transl_implementation module_name (str, cc) = + let (module_id, _size), module_initializer = + transl_implementation_flambda module_name (str, cc) + in + Lprim (Psetglobal module_id, [module_initializer]) (* Build the list of value identifiers defined by a toplevel structure (excluding primitive declarations). *) @@ -490,7 +631,7 @@ let rec defined_idents = function | Tstr_value(rec_flag, pat_expr_list) -> let_bound_idents pat_expr_list @ defined_idents rem | Tstr_primitive desc -> defined_idents rem - | Tstr_type decls -> defined_idents rem + | Tstr_type (_, decls) -> defined_idents rem | Tstr_typext tyext -> List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @ defined_idents rem @@ -501,7 +642,7 @@ let rec defined_idents = function | Tstr_modtype _ -> defined_idents rem | Tstr_open _ -> defined_idents rem | Tstr_class cl_list -> - List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list @ defined_idents rem + List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ defined_idents rem | Tstr_class_type cl_list -> defined_idents rem | Tstr_include incl -> bound_value_identifiers incl.incl_type @ defined_idents rem @@ -516,7 +657,7 @@ let rec more_idents = function | Tstr_eval (expr, _attrs) -> more_idents rem | Tstr_value(rec_flag, pat_expr_list) -> more_idents rem | Tstr_primitive _ -> more_idents rem - | Tstr_type decls -> more_idents rem + | Tstr_type (_, decls) -> more_idents rem | Tstr_typext tyext -> more_idents rem | Tstr_exception _ -> more_idents rem | Tstr_recmodule decls -> more_idents rem @@ -525,7 +666,10 @@ let rec more_idents = function | Tstr_class cl_list -> more_idents rem | Tstr_class_type cl_list -> more_idents rem | Tstr_include _ -> more_idents rem - | Tstr_module {mb_expr={mod_desc = Tmod_structure str}} -> + | Tstr_module {mb_expr={mod_desc = Tmod_structure str}} + | Tstr_module{mb_expr={mod_desc = + Tmod_constraint ({mod_desc = Tmod_structure str}, + _, _, _)}} -> all_idents str.str_items @ more_idents rem | Tstr_module _ -> more_idents rem | Tstr_attribute _ -> more_idents rem @@ -538,7 +682,7 @@ and all_idents = function | Tstr_value(rec_flag, pat_expr_list) -> let_bound_idents pat_expr_list @ all_idents rem | Tstr_primitive _ -> all_idents rem - | Tstr_type decls -> all_idents rem + | Tstr_type (_, decls) -> all_idents rem | Tstr_typext tyext -> List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @ all_idents rem @@ -548,11 +692,15 @@ and all_idents = function | Tstr_modtype _ -> all_idents rem | Tstr_open _ -> all_idents rem | Tstr_class cl_list -> - List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list @ all_idents rem + List.map (fun (ci, _) -> ci.ci_id_class) cl_list @ all_idents rem | Tstr_class_type cl_list -> 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 = Tmod_structure str}} + | Tstr_module{mb_id; + mb_expr={mod_desc = + Tmod_constraint ({mod_desc = Tmod_structure str}, + _, _, _)}} -> mb_id :: all_idents str.str_items @ all_idents rem | Tstr_module mb -> mb.mb_id :: all_idents rem | Tstr_attribute _ -> all_idents rem @@ -585,101 +733,142 @@ let transl_store_structure glob map prims str = lambda_unit | item :: rem -> match item.str_desc with - | Tstr_eval (expr, _attrs) -> - Lsequence(subst_lambda subst (transl_exp expr), - transl_store rootpath subst rem) - | Tstr_value(rec_flag, pat_expr_list) -> - let ids = let_bound_idents pat_expr_list in - let lam = transl_let rec_flag pat_expr_list (store_idents ids) in - Lsequence(subst_lambda subst lam, - transl_store rootpath (add_idents false ids subst) rem) - | Tstr_primitive descr -> - record_primitive descr.val_val; - transl_store rootpath subst rem - | Tstr_type decls -> - transl_store rootpath subst rem - | Tstr_typext(tyext) -> - let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in - let lam = - transl_type_extension item.str_env rootpath tyext (store_idents ids) - in - Lsequence(subst_lambda subst lam, - transl_store rootpath (add_idents false ids subst) rem) - | Tstr_exception ext -> - let id = ext.ext_id in - let path = field_path rootpath id in - let lam = transl_extension_constructor item.str_env path ext in - Lsequence(Llet(Strict, id, subst_lambda subst lam, store_ident id), - transl_store rootpath (add_ident false id subst) rem) - | Tstr_module{mb_id=id; mb_expr={mod_desc = Tmod_structure str}} -> - let lam = transl_store (field_path rootpath id) subst str.str_items in - (* Careful: see next case *) - let subst = !transl_store_subst in - Lsequence(lam, - Llet(Strict, id, - subst_lambda subst - (Lprim(Pmakeblock(0, Immutable), - List.map (fun id -> Lvar id) - (defined_idents str.str_items))), - Lsequence(store_ident id, - transl_store rootpath (add_ident true id subst) - rem))) - | Tstr_module{mb_id=id; mb_expr=modl} -> - let lam = transl_module Tcoerce_none (field_path rootpath id) modl in - (* Careful: the module value stored in the global may be different - from the local module value, in case a coercion is applied. - If so, keep using the local module value (id) in the remainder of - the compilation unit (add_ident true returns subst unchanged). - If not, we can use the value from the global - (add_ident true adds id -> Pgetglobal... to subst). *) - Llet(Strict, id, subst_lambda subst lam, - Lsequence(store_ident id, - transl_store rootpath (add_ident true id subst) rem)) - | Tstr_recmodule bindings -> - let ids = List.map (fun mb -> mb.mb_id) bindings in - compile_recmodule - (fun id modl -> - subst_lambda subst - (transl_module Tcoerce_none - (field_path rootpath id) modl)) - bindings - (Lsequence(store_idents ids, - transl_store rootpath (add_idents true ids subst) rem)) - | Tstr_class cl_list -> - let ids = List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list in - let lam = - Lletrec(List.map - (fun (ci, meths, vf) -> - let id = ci.ci_id_class in - let cl = ci.ci_expr in - (id, transl_class ids id meths cl vf)) - cl_list, - store_idents ids) in - Lsequence(subst_lambda subst lam, - transl_store rootpath (add_idents false ids subst) rem) - | Tstr_include incl -> - let ids = bound_value_identifiers incl.incl_type in - let modl = incl.incl_mod in - let mid = Ident.create "include" in - let rec store_idents pos = function - [] -> transl_store rootpath (add_idents true ids subst) rem - | id :: idl -> - Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]), - Lsequence(store_ident id, store_idents (pos + 1) idl)) in - Llet(Strict, mid, - subst_lambda subst (transl_module Tcoerce_none None modl), - store_idents 0 ids) - | Tstr_modtype _ - | Tstr_open _ - | Tstr_class_type _ - | Tstr_attribute _ -> - transl_store rootpath subst rem + | Tstr_eval (expr, _attrs) -> + Lsequence(subst_lambda subst (transl_exp expr), + transl_store rootpath subst rem) + | Tstr_value(rec_flag, pat_expr_list) -> + let ids = let_bound_idents pat_expr_list in + let lam = transl_let rec_flag pat_expr_list (store_idents ids) in + Lsequence(subst_lambda subst lam, + transl_store rootpath (add_idents false ids subst) rem) + | Tstr_primitive descr -> + record_primitive descr.val_val; + transl_store rootpath subst rem + | Tstr_type(_, decls) -> + transl_store rootpath subst rem + | Tstr_typext(tyext) -> + let ids = + List.map (fun ext -> ext.ext_id) tyext.tyext_constructors + in + let lam = + transl_type_extension item.str_env rootpath tyext + (store_idents ids) + in + Lsequence(subst_lambda subst lam, + transl_store rootpath (add_idents false ids subst) rem) + | Tstr_exception ext -> + let id = ext.ext_id in + let path = field_path rootpath id in + let lam = transl_extension_constructor item.str_env path ext in + Lsequence(Llet(Strict, id, subst_lambda subst lam, store_ident id), + transl_store rootpath (add_ident false id subst) rem) + | Tstr_module{mb_id=id; + mb_expr={mod_desc = Tmod_structure str} as mexp; + mb_attributes} -> + List.iter (Translattribute.check_attribute_on_module mexp) + mb_attributes; + let lam = + transl_store (field_path rootpath id) subst str.str_items + in + (* Careful: see next case *) + let subst = !transl_store_subst in + Lsequence(lam, + Llet(Strict, id, + subst_lambda subst + (Lprim(Pmakeblock(0, Immutable), + List.map (fun id -> Lvar id) + (defined_idents str.str_items))), + Lsequence(store_ident id, + transl_store rootpath + (add_ident true id subst) + rem))) + | Tstr_module{ + mb_id=id; + mb_expr= { + mod_desc = Tmod_constraint ( + {mod_desc = Tmod_structure str} as mexp, _, _, + (Tcoerce_structure (map, _) as _cc))}; + mb_attributes + } -> + (* Format.printf "coerc id %s: %a@." (Ident.unique_name id) + Includemod.print_coercion cc; *) + List.iter (Translattribute.check_attribute_on_module mexp) + mb_attributes; + let lam = + transl_store (field_path rootpath id) subst str.str_items + 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 Strict cc (Lvar ids.(pos)) + in + Lsequence(lam, + Llet(Strict, id, + subst_lambda subst + (Lprim(Pmakeblock(0, Immutable), + List.map field map)), + Lsequence(store_ident id, + transl_store rootpath + (add_ident true id subst) + rem))) + | Tstr_module{mb_id=id; mb_expr=modl; mb_loc; mb_attributes} -> + let lam = + Translattribute.add_inline_attribute + (transl_module Tcoerce_none (field_path rootpath id) modl) + mb_loc mb_attributes + in + (* Careful: the module value stored in the global may be different + from the local module value, in case a coercion is applied. + If so, keep using the local module value (id) in the remainder of + the compilation unit (add_ident true returns subst unchanged). + If not, we can use the value from the global + (add_ident true adds id -> Pgetglobal... to subst). *) + Llet(Strict, id, subst_lambda subst lam, + Lsequence(store_ident id, + transl_store rootpath (add_ident true id subst) rem)) + | Tstr_recmodule bindings -> + let ids = List.map (fun mb -> mb.mb_id) bindings in + compile_recmodule + (fun id modl -> + subst_lambda subst + (transl_module Tcoerce_none + (field_path rootpath id) modl)) + bindings + (Lsequence(store_idents ids, + transl_store rootpath (add_idents true ids subst) rem)) + | Tstr_class cl_list -> + let (ids, class_bindings) = transl_class_bindings cl_list in + let lam = Lletrec(class_bindings, store_idents ids) in + Lsequence(subst_lambda subst lam, + transl_store rootpath (add_idents false ids subst) rem) + | Tstr_include incl -> + let ids = bound_value_identifiers incl.incl_type in + let modl = incl.incl_mod in + let mid = Ident.create "include" in + let rec store_idents pos = function + [] -> transl_store rootpath (add_idents true ids subst) rem + | id :: idl -> + Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]), + Lsequence(store_ident id, store_idents (pos + 1) idl)) in + Llet(Strict, mid, + subst_lambda subst (transl_module Tcoerce_none None modl), + store_idents 0 ids) + | Tstr_modtype _ + | Tstr_open _ + | Tstr_class_type _ + | Tstr_attribute _ -> + transl_store rootpath subst rem and store_ident id = try let (pos, cc) = Ident.find_same id map in let init_val = apply_coercion Alias cc (Lvar id) in - Lprim(Psetfield(pos, false), [Lprim(Pgetglobal glob, []); init_val]) + Lprim(Psetfield(pos, Pointer, Initialization), + [Lprim(Pgetglobal glob, []); init_val]) with Not_found -> fatal_error("Translmod.store_ident: " ^ Ident.unique_name id) @@ -701,9 +890,10 @@ 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, false), + Lsequence(Lprim(Psetfield(pos, Pointer, Initialization), [Lprim(Pgetglobal glob, []); - transl_primitive Location.none prim]), + transl_primitive Location.none + prim.pc_desc prim.pc_env prim.pc_type None]), cont) in List.fold_right store_primitive prims @@ -723,10 +913,10 @@ let transl_store_structure glob map prims str = let build_ident_map restr idlist more_ids = let rec natural_map pos map prims = function - [] -> - (map, prims, pos) - | id :: rem -> - natural_map (pos+1) (Ident.add id (pos, Tcoerce_none) map) prims rem in + [] -> + (map, prims, pos) + | id :: rem -> + natural_map (pos+1) (Ident.add id (pos, Tcoerce_none) map) prims rem in let (map, prims, pos) = match restr with Tcoerce_none -> @@ -755,6 +945,7 @@ let build_ident_map restr idlist more_ids = let transl_store_gen module_name ({ str_items = str }, restr) topl = reset_labels (); primitive_declarations := []; + Hashtbl.clear used_primitives; let module_id = Ident.create_persistent module_name in let (map, prims, size) = build_ident_map restr (defined_idents str) (more_idents str) in @@ -772,9 +963,10 @@ let transl_store_phrases module_name str = let transl_store_implementation module_name (str, restr) = let s = !transl_store_subst in transl_store_subst := Ident.empty; - let r = transl_store_gen module_name (str, restr) false in + let (i, r) = transl_store_gen module_name (str, restr) false in transl_store_subst := s; - r + { Lambda.main_module_block_size = i; + code = wrap_globals ~flambda:false r; } (* Compile a toplevel phrase *) @@ -793,38 +985,55 @@ let toplevel_name id = with Not_found -> Ident.name id let toploop_getvalue id = - Lapply(Lprim(Pfield toploop_getvalue_pos, - [Lprim(Pgetglobal toploop_ident, [])]), - [Lconst(Const_base(Const_string (toplevel_name id, None)))], - Location.none) + Lapply{ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=Lprim(Pfield toploop_getvalue_pos, + [Lprim(Pgetglobal toploop_ident, [])]); + ap_args=[Lconst(Const_base(Const_string (toplevel_name id, None)))]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} let toploop_setvalue id lam = - Lapply(Lprim(Pfield toploop_setvalue_pos, - [Lprim(Pgetglobal toploop_ident, [])]), - [Lconst(Const_base(Const_string (toplevel_name id, None))); lam], - Location.none) + Lapply{ap_should_be_tailcall=false; + ap_loc=Location.none; + ap_func=Lprim(Pfield toploop_setvalue_pos, + [Lprim(Pgetglobal toploop_ident, [])]); + ap_args=[Lconst(Const_base(Const_string (toplevel_name id, None))); + lam]; + ap_inlined=Default_inline; + ap_specialised=Default_specialise} let toploop_setvalue_id id = toploop_setvalue id (Lvar id) -let close_toplevel_term lam = +let close_toplevel_term (lam, ()) = IdentSet.fold (fun id l -> Llet(Strict, id, toploop_getvalue id, l)) (free_variables lam) lam let transl_toplevel_item item = match item.str_desc with - Tstr_eval (expr, _attrs) -> + Tstr_eval (expr, _) + | Tstr_value(Nonrecursive, + [{vb_pat = {pat_desc=Tpat_any};vb_expr = expr}]) -> + (* special compilation for toplevel "let _ = expr", so + that Toploop can display the result of the expression. + Otherwise, the normal compilation would result + in a Lsequence returning unit. *) transl_exp expr | Tstr_value(rec_flag, pat_expr_list) -> let idents = let_bound_idents pat_expr_list in transl_let rec_flag pat_expr_list - (make_sequence toploop_setvalue_id idents) + (make_sequence toploop_setvalue_id idents) | Tstr_typext(tyext) -> let idents = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in + (* we need to use unique name in case of multiple + definitions of the same extension constructor in the toplevel *) + List.iter set_toplevel_unique_name idents; transl_type_extension item.str_env None tyext (make_sequence toploop_setvalue_id idents) | Tstr_exception ext -> + set_toplevel_unique_name ext.ext_id; toploop_setvalue ext.ext_id (transl_extension_constructor item.str_env None ext) | Tstr_module {mb_id=id; mb_expr=modl} -> @@ -842,17 +1051,9 @@ let transl_toplevel_item item = | Tstr_class cl_list -> (* we need to use unique names for the classes because there might be a value named identically *) - let ids = List.map (fun (ci, _, _) -> ci.ci_id_class) cl_list in + let (ids, class_bindings) = transl_class_bindings cl_list in List.iter set_toplevel_unique_name ids; - Lletrec(List.map - (fun (ci, meths, vf) -> - let id = ci.ci_id_class in - let cl = ci.ci_expr in - (id, transl_class ids id meths cl vf)) - cl_list, - make_sequence - (fun (ci, _, _) -> toploop_setvalue_id ci.ci_id_class) - cl_list) + Lletrec(class_bindings, make_sequence toploop_setvalue_id ids) | Tstr_include incl -> let ids = bound_value_identifiers incl.incl_type in let modl = incl.incl_mod in @@ -873,10 +1074,12 @@ let transl_toplevel_item item = lambda_unit let transl_toplevel_item_and_close itm = - close_toplevel_term (transl_label_init (transl_toplevel_item itm)) + close_toplevel_term + (transl_label_init (fun () -> transl_toplevel_item itm, ())) let transl_toplevel_definition str = reset_labels (); + Hashtbl.clear used_primitives; make_sequence transl_toplevel_item_and_close str.str_items (* Compile the initialization code for a packed library *) @@ -885,6 +1088,19 @@ let get_component = function None -> Lconst const_unit | Some id -> Lprim(Pgetglobal id, []) +let transl_package_flambda component_names target_name coercion = + let size = + match coercion with + | Tcoerce_none -> List.length component_names + | Tcoerce_structure (l, _) -> List.length l + | Tcoerce_functor _ + | Tcoerce_primitive _ + | Tcoerce_alias _ -> assert false + in + size, + apply_coercion Strict coercion + (Lprim(Pmakeblock(0, Immutable), List.map get_component component_names)) + let transl_package component_names target_name coercion = let components = Lprim(Pmakeblock(0, Immutable), List.map get_component component_names) in @@ -915,7 +1131,7 @@ let transl_store_package component_names target_name coercion = (List.length component_names, make_sequence (fun pos id -> - Lprim(Psetfield(pos, false), + Lprim(Psetfield(pos, Pointer, Initialization), [Lprim(Pgetglobal target_name, []); get_component id])) 0 component_names) @@ -928,7 +1144,7 @@ let transl_store_package component_names target_name coercion = Llet (Strict, blk, apply_coercion Strict coercion components, make_sequence (fun pos id -> - Lprim(Psetfield(pos, false), + Lprim(Psetfield(pos, Pointer, Initialization), [Lprim(Pgetglobal target_name, []); Lprim(Pfield pos, [Lvar blk])])) 0 pos_cc_list)) @@ -969,4 +1185,6 @@ let reset () = primitive_declarations := []; transl_store_subst := Ident.empty; toploop_ident.Ident.flags <- 0; - aliased_idents := Ident.empty + aliased_idents := Ident.empty; + Env.reset_required_globals (); + Hashtbl.clear used_primitives diff --git a/bytecomp/translmod.mli b/bytecomp/translmod.mli index 1d84aaab..3628a998 100644 --- a/bytecomp/translmod.mli +++ b/bytecomp/translmod.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Translation from typed abstract syntax to lambda terms, for the module language *) @@ -19,13 +22,20 @@ open Lambda val transl_implementation: string -> structure * module_coercion -> lambda val transl_store_phrases: string -> structure -> int * lambda val transl_store_implementation: - string -> structure * module_coercion -> int * lambda + string -> structure * module_coercion -> Lambda.program + +val transl_implementation_flambda: + string -> structure * module_coercion -> (Ident.t * int) * lambda + val transl_toplevel_definition: structure -> lambda val transl_package: Ident.t option list -> Ident.t -> module_coercion -> lambda val transl_store_package: Ident.t option list -> Ident.t -> module_coercion -> int * lambda +val transl_package_flambda: + Ident.t option list -> Ident.t -> module_coercion -> int * lambda + val toplevel_name: Ident.t -> string val nat_toplevel_name: Ident.t -> Ident.t * int diff --git a/bytecomp/translobj.ml b/bytecomp/translobj.ml index 02731ec6..1e860502 100644 --- a/bytecomp/translobj.ml +++ b/bytecomp/translobj.ml @@ -1,17 +1,19 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Misc -open Primitive open Asttypes open Longident open Lambda @@ -86,42 +88,67 @@ let reset_labels () = (* Insert labels *) -let string s = Lconst (Const_base (Const_string (s, None))) let int n = Lconst (Const_base (Const_int n)) let prim_makearray = - { prim_name = "caml_make_vect"; prim_arity = 2; prim_alloc = true; - prim_native_name = ""; prim_native_float = false } + Primitive.simple ~name:"caml_make_vect" ~arity:2 ~alloc:true (* Also use it for required globals *) -let transl_label_init expr = +let transl_label_init_general f = + let expr, size = f () in let expr = Hashtbl.fold (fun c id expr -> Llet(Alias, id, Lconst c, expr)) consts expr in - let expr = + (*let expr = List.fold_right (fun id expr -> Lsequence(Lprim(Pgetglobal id, []), expr)) (Env.get_required_globals ()) expr in - Env.reset_required_globals (); + Env.reset_required_globals ();*) reset_labels (); - expr + expr, size + +let transl_label_init_flambda f = + assert(Config.flambda); + let method_cache_id = Ident.create "method_cache" in + method_cache := Lvar method_cache_id; + (* Calling f (usualy Translmod.transl_struct) requires the + method_cache variable to be initialised to be able to generate + method accesses. *) + let expr, size = f () in + let expr = + if !method_count = 0 then expr + else + Llet (Strict, method_cache_id, + Lprim (Pccall prim_makearray, [int !method_count; int 0]), + expr) + in + transl_label_init_general (fun () -> expr, size) let transl_store_label_init glob size f arg = + assert(not Config.flambda); + assert(!Clflags.native_code); method_cache := Lprim(Pfield size, [Lprim(Pgetglobal glob, [])]); let expr = f arg in let (size, expr) = if !method_count = 0 then (size, expr) else (size+1, Lsequence( - Lprim(Psetfield(size, false), + Lprim(Psetfield(size, Pointer, Initialization), [Lprim(Pgetglobal glob, []); Lprim (Pccall prim_makearray, [int !method_count; int 0])]), expr)) in - (size, transl_label_init expr) + let lam, size = transl_label_init_general (fun () -> (expr, size)) in + size, lam + +let transl_label_init f = + if !Clflags.native_code then + transl_label_init_flambda f + else + transl_label_init_general f (* Share classes *) diff --git a/bytecomp/translobj.mli b/bytecomp/translobj.mli index a44ac683..d7426241 100644 --- a/bytecomp/translobj.mli +++ b/bytecomp/translobj.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Lambda @@ -18,7 +21,7 @@ val share: structured_constant -> lambda val meth: lambda -> string -> lambda * lambda list val reset_labels: unit -> unit -val transl_label_init: lambda -> lambda +val transl_label_init: (unit -> lambda * 'a) -> lambda * 'a val transl_store_label_init: Ident.t -> int -> ('a -> lambda) -> 'a -> int * lambda diff --git a/bytecomp/typeopt.ml b/bytecomp/typeopt.ml index c96e32b6..60aff406 100644 --- a/bytecomp/typeopt.ml +++ b/bytecomp/typeopt.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1998 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1998 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. *) +(* *) +(**************************************************************************) (* Auxiliaries for type-based optimizations, e.g. array kinds *) @@ -20,28 +23,26 @@ open Lambda let scrape env ty = (Ctype.repr (Ctype.expand_head_opt env (Ctype.correct_levels ty))).desc -let has_base_type exp base_ty_path = - match scrape exp.exp_env exp.exp_type with +let is_function_type env ty = + match scrape env ty with + | Tarrow (_, lhs, rhs, _) -> Some (lhs, rhs) + | _ -> None + +let is_base_type env ty base_ty_path = + match scrape env ty with | Tconstr(p, _, _) -> Path.same p base_ty_path | _ -> false -let maybe_pointer exp = - match scrape exp.exp_env exp.exp_type with - | Tconstr(p, args, abbrev) -> - not (Path.same p Predef.path_int) && - not (Path.same p Predef.path_char) && - begin try - match Env.find_type p exp.exp_env with - | {type_kind = Type_variant []} -> true (* type exn *) - | {type_kind = Type_variant cstrs} -> - List.exists (fun c -> c.Types.cd_args <> []) cstrs - | _ -> true - with Not_found -> true - (* This can happen due to e.g. missing -I options, - causing some .cmi files to be unavailable. - Maybe we should emit a warning. *) - end - | _ -> true +let has_base_type exp base_ty_path = + is_base_type exp.exp_env exp.exp_type base_ty_path + +let maybe_pointer_type env ty = + if Ctype.maybe_pointer_type env ty then + Pointer + else + Immediate + +let maybe_pointer exp = maybe_pointer_type exp.exp_env exp.exp_type let array_element_kind env ty = match scrape env ty with @@ -64,7 +65,8 @@ let array_element_kind env ty = {type_kind = Type_abstract} -> Pgenarray | {type_kind = Type_variant cstrs} - when List.for_all (fun c -> c.Types.cd_args = []) cstrs -> + when List.for_all (fun c -> c.Types.cd_args = Types.Cstr_tuple []) + cstrs -> Pintarray | {type_kind = _} -> Paddrarray @@ -77,7 +79,7 @@ let array_element_kind env ty = | _ -> Paddrarray -let array_kind_gen ty env = +let array_type_kind env ty = match scrape env ty with | Tconstr(p, [elt_ty], _) | Tpoly({desc = Tconstr(p, [elt_ty], _)}, _) when Path.same p Predef.path_array -> @@ -86,9 +88,9 @@ let array_kind_gen ty env = (* This can happen with e.g. Obj.field *) Pgenarray -let array_kind exp = array_kind_gen exp.exp_type exp.exp_env +let array_kind exp = array_type_kind exp.exp_env exp.exp_type -let array_pattern_kind pat = array_kind_gen pat.pat_type pat.pat_env +let array_pattern_kind pat = array_type_kind pat.pat_env pat.pat_type let bigarray_decode_type env ty tbl dfl = match scrape env ty with @@ -116,11 +118,11 @@ let layout_table = ["c_layout", Pbigarray_c_layout; "fortran_layout", Pbigarray_fortran_layout] -let bigarray_kind_and_layout exp = - match scrape exp.exp_env exp.exp_type with +let bigarray_type_kind_and_layout env typ = + match scrape env typ with | Tconstr(p, [caml_type; elt_type; layout_type], abbrev) -> - (bigarray_decode_type exp.exp_env elt_type kind_table Pbigarray_unknown, - bigarray_decode_type exp.exp_env layout_type layout_table + (bigarray_decode_type env elt_type kind_table Pbigarray_unknown, + bigarray_decode_type env layout_type layout_table Pbigarray_unknown_layout) | _ -> (Pbigarray_unknown, Pbigarray_unknown_layout) diff --git a/bytecomp/typeopt.mli b/bytecomp/typeopt.mli index a90df8ae..d69f09eb 100644 --- a/bytecomp/typeopt.mli +++ b/bytecomp/typeopt.mli @@ -1,20 +1,31 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1998 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1998 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. *) +(* *) +(**************************************************************************) (* Auxiliaries for type-based optimizations, e.g. array kinds *) +val is_function_type : + Env.t -> Types.type_expr -> (Types.type_expr * Types.type_expr) option +val is_base_type : Env.t -> Types.type_expr -> Path.t -> bool val has_base_type : Typedtree.expression -> Path.t -> bool -val maybe_pointer : Typedtree.expression -> bool + +val maybe_pointer_type : Env.t -> Types.type_expr + -> Lambda.immediate_or_pointer +val maybe_pointer : Typedtree.expression -> Lambda.immediate_or_pointer + +val array_type_kind : Env.t -> Types.type_expr -> Lambda.array_kind val array_kind : Typedtree.expression -> Lambda.array_kind val array_pattern_kind : Typedtree.pattern -> Lambda.array_kind -val bigarray_kind_and_layout : - Typedtree.expression -> Lambda.bigarray_kind * Lambda.bigarray_layout +val bigarray_type_kind_and_layout : + Env.t -> Types.type_expr -> Lambda.bigarray_kind * Lambda.bigarray_layout diff --git a/byterun/.depend b/byterun/.depend index 7bb76fe0..c1a4243c 100644 --- a/byterun/.depend +++ b/byterun/.depend @@ -1,729 +1,900 @@ 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/major_gc.h caml/minor_gc.h \ - caml/address_class.h caml/mlvalues.h caml/stacks.h caml/memory.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/misc.h \ - caml/mlvalues.h -backtrace.o: backtrace.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/misc.h caml/alloc.h caml/mlvalues.h caml/io.h \ - caml/instruct.h caml/intext.h caml/io.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/exec.h caml/stacks.h \ - caml/memory.h caml/sys.h caml/backtrace.h caml/fail.h + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.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 +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/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/mlvalues.h caml/interp.h caml/instruct.h caml/fix_code.h \ - caml/stacks.h caml/memory.h -compact.o: compact.c caml/address_class.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/mlvalues.h caml/config.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/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/mlvalues.h \ - caml/roots.h caml/weak.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 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/minor_gc.h caml/address_class.h caml/misc.h caml/mlvalues.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 \ - caml/mlvalues.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/config.h caml/debugger.h caml/misc.h caml/fail.h \ - caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/io.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/sys.h + caml/mlvalues.h caml/debugger.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/config.h caml/mlvalues.h caml/dynlink.h caml/fail.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/misc.h caml/osdeps.h \ - caml/prims.h caml/signals.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/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/misc.h \ - caml/mlvalues.h caml/reverse.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/gc.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/misc.h caml/mlvalues.h caml/printexc.h caml/signals.h \ - caml/stacks.h caml/memory.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/fail.h caml/mlvalues.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/s.h caml/misc.h caml/fail.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 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/config.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/misc.h caml/mlvalues.h caml/reverse.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/mlvalues.h \ - caml/misc.h caml/reverse.h caml/stacks.h caml/memory.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/config.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/major_gc.h caml/misc.h caml/mlvalues.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/compact.h caml/custom.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/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/minor_gc.h caml/misc.h \ - caml/mlvalues.h caml/stacks.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/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/misc.h caml/mlvalues.h caml/roots.h \ - caml/memory.h caml/globroots.h caml/roots.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/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.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/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/mlvalues.h caml/misc.h caml/reverse.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/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/major_gc.h caml/minor_gc.h caml/address_class.h caml/misc.h \ - caml/mlvalues.h caml/prims.h caml/signals.h caml/stacks.h caml/memory.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 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 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/config.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/misc.h caml/mlvalues.h caml/signals.h \ - caml/sys.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/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/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/misc.h \ - caml/sys.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/custom.h \ - caml/mlvalues.h caml/config.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/freelist.h caml/gc.h caml/gc_ctrl.h \ - caml/major_gc.h caml/misc.h caml/mlvalues.h caml/roots.h caml/weak.h + caml/mlvalues.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/compatibility.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/mlvalues.h \ - caml/io.h caml/reverse.h -memory.o: memory.c caml/address_class.h caml/misc.h caml/compatibility.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ - caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h caml/minor_gc.h caml/misc.h \ - caml/mlvalues.h caml/signals.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/config.h caml/fail.h caml/fix_code.h caml/interp.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/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/prims.h caml/stacks.h \ - caml/memory.h -minor_gc.o: minor_gc.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/config.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/address_class.h caml/gc.h caml/gc_ctrl.h caml/major_gc.h \ - caml/memory.h caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/roots.h \ - caml/signals.h caml/weak.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/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/config.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/compatibility.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/version.h obj.o: obj.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/gc.h caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/prims.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 parsing.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h \ - caml/config.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/alloc.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/callback.h caml/debugger.h \ - caml/fail.h caml/misc.h caml/mlvalues.h caml/printexc.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/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/misc.h caml/mlvalues.h caml/roots.h caml/stacks.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/config.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/misc.h caml/mlvalues.h caml/roots.h \ - caml/memory.h caml/signals.h caml/signals_machdep.h caml/sys.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 signals_byt.o: signals_byt.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/memory.h caml/config.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.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/signals_machdep.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/config.h caml/mlvalues.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/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/config.h caml/mlvalues.h caml/backtrace.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/exec.h caml/fail.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/io.h caml/memory.h caml/gc.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/minor_gc.h caml/misc.h caml/mlvalues.h caml/osdeps.h caml/prims.h \ - caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h \ - caml/memory.h caml/sys.h caml/startup.h caml/exec.h caml/version.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/mlvalues.h caml/misc.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/config.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/instruct.h \ - caml/mlvalues.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/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 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/config.h caml/mlvalues.h caml/fail.h caml/io.h caml/mlvalues.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/memory.h caml/config.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/misc.h caml/osdeps.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 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/major_gc.h caml/minor_gc.h \ - caml/address_class.h caml/mlvalues.h -win32.o: win32.c caml/address_class.h caml/misc.h caml/compatibility.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/misc.h \ - caml/osdeps.h caml/signals.h caml/sys.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/major_gc.h caml/minor_gc.h \ - caml/address_class.h caml/mlvalues.h caml/stacks.h caml/memory.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/misc.h \ - caml/mlvalues.h -backtrace.d.o: backtrace.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/misc.h caml/alloc.h caml/mlvalues.h caml/io.h \ - caml/instruct.h caml/intext.h caml/io.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/exec.h caml/stacks.h \ - caml/memory.h caml/sys.h caml/backtrace.h caml/fail.h + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.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 +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/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/mlvalues.h caml/interp.h caml/instruct.h caml/fix_code.h \ - caml/stacks.h caml/memory.h -compact.d.o: compact.c caml/address_class.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/mlvalues.h caml/config.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/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/mlvalues.h \ - caml/roots.h caml/weak.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 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/minor_gc.h caml/address_class.h caml/misc.h caml/mlvalues.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 \ - caml/mlvalues.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/config.h caml/debugger.h caml/misc.h caml/fail.h \ - caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/io.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/sys.h + caml/mlvalues.h caml/debugger.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/config.h caml/mlvalues.h caml/dynlink.h caml/fail.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/misc.h caml/osdeps.h \ - caml/prims.h caml/signals.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/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/misc.h \ - caml/mlvalues.h caml/reverse.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/gc.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/misc.h caml/mlvalues.h caml/printexc.h caml/signals.h \ - caml/stacks.h caml/memory.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/fail.h caml/mlvalues.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/s.h caml/misc.h caml/fail.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 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/config.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/misc.h caml/mlvalues.h caml/reverse.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/mlvalues.h \ - caml/misc.h caml/reverse.h caml/stacks.h caml/memory.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/config.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/major_gc.h caml/misc.h caml/mlvalues.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/compact.h caml/custom.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/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/minor_gc.h caml/misc.h \ - caml/mlvalues.h caml/stacks.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/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/misc.h caml/mlvalues.h caml/roots.h \ - caml/memory.h caml/globroots.h caml/roots.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/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.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/instruct.h caml/misc.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/mlvalues.h caml/misc.h caml/opnames.h \ - caml/prims.h caml/stacks.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/../../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/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/mlvalues.h caml/misc.h caml/reverse.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/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/major_gc.h caml/minor_gc.h caml/address_class.h caml/misc.h \ - caml/mlvalues.h caml/prims.h caml/signals.h caml/stacks.h caml/memory.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/memory.h caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.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 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/config.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/misc.h caml/mlvalues.h caml/signals.h \ - caml/sys.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/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/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/misc.h \ - caml/sys.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/custom.h \ - caml/mlvalues.h caml/config.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/freelist.h caml/gc.h caml/gc_ctrl.h \ - caml/major_gc.h caml/misc.h caml/mlvalues.h caml/roots.h caml/weak.h + caml/mlvalues.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/compatibility.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/mlvalues.h \ - caml/io.h caml/reverse.h -memory.d.o: memory.c caml/address_class.h caml/misc.h caml/compatibility.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ - caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h caml/minor_gc.h caml/misc.h \ - caml/mlvalues.h caml/signals.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/config.h caml/fail.h caml/fix_code.h caml/interp.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/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/prims.h caml/stacks.h \ - caml/memory.h -minor_gc.d.o: minor_gc.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/config.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/address_class.h caml/gc.h caml/gc_ctrl.h caml/major_gc.h \ - caml/memory.h caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/roots.h \ - caml/signals.h caml/weak.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/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/config.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/compatibility.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/version.h obj.d.o: obj.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/gc.h caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/prims.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 parsing.d.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h \ - caml/config.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/alloc.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/callback.h caml/debugger.h \ - caml/fail.h caml/misc.h caml/mlvalues.h caml/printexc.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/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/misc.h caml/mlvalues.h caml/roots.h caml/stacks.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/config.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/misc.h caml/mlvalues.h caml/roots.h \ - caml/memory.h caml/signals.h caml/signals_machdep.h caml/sys.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 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/config.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.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/signals_machdep.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/config.h caml/mlvalues.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/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/config.h caml/mlvalues.h caml/backtrace.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/exec.h caml/fail.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/io.h caml/memory.h caml/gc.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/minor_gc.h caml/misc.h caml/mlvalues.h caml/osdeps.h caml/prims.h \ - caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h \ - caml/memory.h caml/sys.h caml/startup.h caml/exec.h caml/version.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/mlvalues.h caml/misc.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/config.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/instruct.h \ - caml/mlvalues.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/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 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/config.h caml/mlvalues.h caml/fail.h caml/io.h caml/mlvalues.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/memory.h caml/config.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/misc.h caml/osdeps.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 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/major_gc.h caml/minor_gc.h \ - caml/address_class.h caml/mlvalues.h -win32.d.o: win32.c caml/address_class.h caml/misc.h caml/compatibility.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 +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 +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/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 +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 +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/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 \ + 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/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/fail.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 +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/misc.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/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 +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/custom.h \ + caml/mlvalues.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/compatibility.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/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/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/../../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 +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 +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/signals_machdep.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 +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 +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 +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 +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 +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/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 +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/major_gc.h caml/minor_gc.h \ - caml/address_class.h caml/mlvalues.h caml/stacks.h caml/memory.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/misc.h \ - caml/mlvalues.h -backtrace.pic.o: backtrace.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h \ - caml/config.h caml/misc.h caml/alloc.h caml/mlvalues.h caml/io.h \ - caml/instruct.h caml/intext.h caml/io.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/exec.h caml/stacks.h \ - caml/memory.h caml/sys.h caml/backtrace.h caml/fail.h + caml/freelist.h caml/minor_gc.h caml/address_class.h caml/signals.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 +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/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/mlvalues.h caml/interp.h caml/instruct.h caml/fix_code.h \ - caml/stacks.h caml/memory.h -compact.pic.o: compact.c caml/address_class.h caml/misc.h \ - caml/compatibility.h caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/mlvalues.h caml/config.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/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/memory.h caml/mlvalues.h \ - caml/roots.h caml/weak.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 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/minor_gc.h caml/address_class.h caml/misc.h caml/mlvalues.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 \ - caml/mlvalues.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/config.h caml/debugger.h caml/misc.h caml/fail.h \ - caml/fix_code.h caml/instruct.h caml/intext.h caml/io.h caml/io.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/sys.h + caml/mlvalues.h caml/debugger.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/config.h caml/mlvalues.h caml/dynlink.h caml/fail.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/misc.h caml/osdeps.h \ - caml/prims.h caml/signals.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/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/misc.h \ - caml/mlvalues.h caml/reverse.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/gc.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/misc.h caml/mlvalues.h caml/printexc.h caml/signals.h \ - caml/stacks.h caml/memory.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/fail.h caml/mlvalues.h \ - caml/roots.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.h \ + caml/../../config/s.h caml/misc.h caml/fail.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 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/config.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/misc.h caml/mlvalues.h caml/reverse.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/mlvalues.h \ - caml/misc.h caml/reverse.h caml/stacks.h caml/memory.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/config.h caml/mlvalues.h caml/gc.h caml/gc_ctrl.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/freelist.h caml/minor_gc.h \ - caml/address_class.h caml/major_gc.h caml/misc.h caml/mlvalues.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/compact.h caml/custom.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/freelist.h caml/gc.h \ - caml/gc_ctrl.h caml/major_gc.h caml/minor_gc.h caml/misc.h \ - caml/mlvalues.h caml/stacks.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/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/misc.h caml/mlvalues.h caml/roots.h \ - caml/memory.h caml/globroots.h caml/roots.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/mlvalues.h caml/memory.h caml/gc.h caml/major_gc.h caml/freelist.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/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/mlvalues.h caml/misc.h caml/reverse.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/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/major_gc.h caml/minor_gc.h caml/address_class.h caml/misc.h \ - caml/mlvalues.h caml/prims.h caml/signals.h caml/stacks.h caml/memory.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 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 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/config.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/misc.h caml/mlvalues.h caml/signals.h \ - caml/sys.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/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/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/misc.h \ - caml/sys.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/custom.h \ - caml/mlvalues.h caml/config.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/freelist.h caml/gc.h caml/gc_ctrl.h \ - caml/major_gc.h caml/misc.h caml/mlvalues.h caml/roots.h caml/weak.h + caml/mlvalues.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/compatibility.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/mlvalues.h \ - caml/io.h caml/reverse.h -memory.pic.o: memory.c caml/address_class.h caml/misc.h caml/compatibility.h \ - caml/config.h caml/../../config/m.h caml/../../config/s.h \ - caml/mlvalues.h caml/fail.h caml/freelist.h caml/gc.h caml/gc_ctrl.h \ - caml/major_gc.h caml/freelist.h caml/memory.h caml/gc.h caml/major_gc.h \ - caml/minor_gc.h caml/address_class.h caml/minor_gc.h caml/misc.h \ - caml/mlvalues.h caml/signals.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/config.h caml/fail.h caml/fix_code.h caml/interp.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/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/prims.h caml/stacks.h \ - caml/memory.h -minor_gc.pic.o: minor_gc.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/fail.h caml/misc.h \ - caml/config.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/address_class.h caml/gc.h caml/gc_ctrl.h caml/major_gc.h \ - caml/memory.h caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/roots.h \ - caml/signals.h caml/weak.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/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/config.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/compatibility.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/version.h obj.pic.o: obj.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/gc.h caml/interp.h caml/major_gc.h caml/freelist.h caml/memory.h \ - caml/gc.h caml/major_gc.h caml/minor_gc.h caml/address_class.h \ - caml/minor_gc.h caml/misc.h caml/mlvalues.h caml/prims.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 parsing.pic.o: parsing.c caml/config.h caml/../../config/m.h \ - caml/../../config/s.h caml/compatibility.h caml/mlvalues.h \ - caml/config.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/alloc.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/callback.h caml/debugger.h \ - caml/fail.h caml/misc.h caml/mlvalues.h caml/printexc.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/major_gc.h caml/memory.h caml/minor_gc.h \ - caml/misc.h caml/mlvalues.h caml/roots.h caml/stacks.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/config.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/misc.h caml/mlvalues.h caml/roots.h \ - caml/memory.h caml/signals.h caml/signals_machdep.h caml/sys.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 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/config.h \ - caml/gc.h caml/mlvalues.h caml/misc.h caml/major_gc.h caml/freelist.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/signals_machdep.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/config.h caml/mlvalues.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/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/config.h caml/mlvalues.h caml/backtrace.h caml/callback.h \ - caml/custom.h caml/debugger.h caml/dynlink.h caml/exec.h caml/fail.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/io.h caml/memory.h caml/gc.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/minor_gc.h caml/misc.h caml/mlvalues.h caml/osdeps.h caml/prims.h \ - caml/printexc.h caml/reverse.h caml/signals.h caml/stacks.h \ - caml/memory.h caml/sys.h caml/startup.h caml/exec.h caml/version.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/mlvalues.h caml/misc.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/config.h \ - caml/mlvalues.h caml/debugger.h caml/fail.h caml/instruct.h \ - caml/mlvalues.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/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 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/config.h caml/mlvalues.h caml/fail.h caml/io.h caml/mlvalues.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/memory.h caml/config.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/misc.h caml/osdeps.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 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/major_gc.h caml/minor_gc.h \ - caml/address_class.h caml/mlvalues.h -win32.pic.o: win32.c caml/address_class.h caml/misc.h caml/compatibility.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/misc.h \ - caml/osdeps.h caml/signals.h caml/sys.h + caml/memory.h caml/gc.h caml/minor_gc.h caml/address_class.h \ + caml/weak.h diff --git a/byterun/.ignore b/byterun/.ignore deleted file mode 100644 index 7eab2b62..00000000 --- a/byterun/.ignore +++ /dev/null @@ -1,16 +0,0 @@ -caml/jumptbl.h -primitives -prims.c -caml/opnames.h -caml/version.h -ocamlrun -ocamlrun.exe -ocamlrund -ocamlrund.exe -ld.conf -interp.a.lst -*.[sd]obj -*.lib -.gdb_history -*.d.c -*.pic.c diff --git a/byterun/Makefile b/byterun/Makefile index ae57e2a7..5070c695 100644 --- a/byterun/Makefile +++ b/byterun/Makefile @@ -1,23 +1,27 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 Makefile.common 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) @@ -30,6 +34,9 @@ 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 @@ -38,6 +45,10 @@ libcamlrund.a: $(DOBJS) $(ARCMD) rc libcamlrund.a $(DOBJS) $(RANLIB) libcamlrund.a +libcamlruni.a: $(IOBJS) + $(ARCMD) rc $@ $^ + $(RANLIB) $@ + all-noshared: .PHONY: all-noshared @@ -45,7 +56,7 @@ all-shared: libcamlrun_pic.a libcamlrun_shared.so .PHONY: all-shared libcamlrun_pic.a: $(PICOBJS) - ar rc libcamlrun_pic.a $(PICOBJS) + $(ARCMD) rc libcamlrun_pic.a $(PICOBJS) $(RANLIB) libcamlrun_pic.a libcamlrun_shared.so: $(PICOBJS) @@ -57,9 +68,9 @@ install-noshared: .PHONY: install-noshared 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 + 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 clean:: @@ -68,12 +79,18 @@ clean:: %.d.o: %.c $(CC) -c $(DFLAGS) $< -o $@ +%.i.o: %.c + $(CC) -c $(IFLAGS) -o $@ $< + %.pic.o: %.c $(CC) -c $(CFLAGS) $(SHAREDCCCOMPOPTS) $< -o $@ 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/' >> .depend + -$(CC) -MM $(BYTECCCOMPOPTS) -DDEBUG *.c | sed -e 's/\.o/.d.o/' \ + >> .depend + -$(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 diff --git a/byterun/Makefile.common b/byterun/Makefile.common old mode 100755 new mode 100644 index 2c56c43f..5bcd6779 --- a/byterun/Makefile.common +++ b/byterun/Makefile.common @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 @@ -18,9 +20,9 @@ CAMLYACC ?= ../boot/ocamlyacc CC=$(BYTECC) COMMONOBJS=\ - interp.o misc.o stacks.o fix_code.o startup.o \ + 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.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 \ @@ -30,7 +32,7 @@ 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.c + dynlink.c backtrace_prim.c backtrace.c PUBLIC_INCLUDES=\ address_class.h alloc.h callback.h config.h custom.h fail.h gc.h \ @@ -48,6 +50,10 @@ 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 @@ -59,15 +65,16 @@ 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 + 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 $(PUBLIC_INCLUDES); do \ - sed -f ../tools/cleanup-header caml/$$i > $(INSTALL_LIBDIR)/caml/$$i; \ + sed -f ../tools/cleanup-header caml/$$i \ + > "$(INSTALL_LIBDIR)/caml/$$i"; \ done - cp ld.conf $(INSTALL_LIBDIR)/ld.conf + cp ld.conf "$(INSTALL_LIBDIR)/ld.conf" .PHONY: install install:: install-$(RUNTIMED) @@ -80,10 +87,16 @@ install-noruntimed: # 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) + 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 @@ -118,7 +131,8 @@ caml/opnames.h : caml/instruct.h -e '/^#/d' \ -e 's/enum /char * names_of_/' \ -e 's/{$$/[] = {/' \ - -e 's/\([[:upper:]][[:upper:]_0-9]*\)/"\1"/g' caml/instruct.h > caml/opnames.h + -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 diff --git a/byterun/Makefile.nt b/byterun/Makefile.nt index 71873f21..06b39c69 100644 --- a/byterun/Makefile.nt +++ b/byterun/Makefile.nt @@ -1,27 +1,36 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 Makefile.common CFLAGS=-DOCAML_STDLIB_DIR='"$(LIBDIR)"' $(IFLEXDIR) +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) - $(MKEXE) -o ocamlrun$(EXE) prims.$(O) $(call SYSLIB,ws2_32) \ - $(EXTRALIBS) libcamlrun.$(A) + $(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) $(BYTECCDBGCOMPOPTS) prims.$(O) \ @@ -41,12 +50,14 @@ libcamlrund.$(A): $(DOBJS) .depend.nt: .depend rm -f .depend.win32 - echo "win32.o: win32.c \\" >> .depend.win32 - echo " caml/fail.h caml/compatibility.h caml/misc.h \\" >> .depend.win32 - echo " caml/config.h ../config/m.h ../config/s.h \\" >> .depend.win32 - echo " caml/mlvalues.h caml/memory.h caml/gc.h \\" >> .depend.win32 - echo " caml/major_gc.h caml/freelist.h caml/minor_gc.h \\" >> .depend.win32 - echo " caml/osdeps.h caml/signals.h" >> .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 -e '/\.d\.o/q' -e 's/^\(.*\)\.o:/\1.$$(O) \1.$$(DBGO):/' \ .depend.win32 > .depend.nt diff --git a/byterun/alloc.c b/byterun/alloc.c index b421cace..54b83608 100644 --- a/byterun/alloc.c +++ b/byterun/alloc.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* 1. Allocation functions doing the same work as the macros in the case where [Setup_for_gc] and [Restore_after_gc] are no-ops. @@ -62,11 +64,13 @@ CAMLexport value caml_alloc_small (mlsize_t wosize, tag_t tag) return result; } +/* [n] is a number of words (fields) */ CAMLexport value caml_alloc_tuple(mlsize_t n) { return caml_alloc(n, 0); } +/* [len] is a number of bytes (chars) */ CAMLexport value caml_alloc_string (mlsize_t len) { value result; @@ -85,6 +89,9 @@ CAMLexport value caml_alloc_string (mlsize_t len) return result; } +/* [len] is a number of words. + [mem] and [max] are relative (without unit). +*/ CAMLexport value caml_alloc_final (mlsize_t len, final_fun fun, mlsize_t mem, mlsize_t max) { @@ -145,23 +152,26 @@ CAMLexport int caml_convert_flag_list(value list, int *flags) /* For compiling let rec over values */ +/* [size] is a [value] representing number of words (fields) */ CAMLprim value caml_alloc_dummy(value size) { - mlsize_t wosize = Int_val(size); + mlsize_t wosize = Long_val(size); if (wosize == 0) return Atom(0); return caml_alloc (wosize, 0); } +/* [size] is a [value] representing number of words (fields) */ CAMLprim value caml_alloc_dummy_function(value size,value arity) { /* the arity argument is used by the js_of_ocaml runtime */ return caml_alloc_dummy(size); } +/* [size] is a [value] representing number of floats. */ CAMLprim value caml_alloc_dummy_float (value size) { - mlsize_t wosize = Int_val(size) * Double_wosize; + mlsize_t wosize = Long_val(size) * Double_wosize; if (wosize == 0) return Atom(0); return caml_alloc (wosize, 0); @@ -190,7 +200,3 @@ CAMLprim value caml_update_dummy(value dummy, value newval) } return Val_unit; } - - - - diff --git a/byterun/array.c b/byterun/array.c index 76713bf8..ccfe2488 100644 --- a/byterun/array.c +++ b/byterun/array.c @@ -1,25 +1,28 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Operations on arrays */ - #include #include "caml/alloc.h" #include "caml/fail.h" #include "caml/memory.h" #include "caml/misc.h" #include "caml/mlvalues.h" +#include "caml/signals.h" +/* returns number of elements (either fields or floats) */ CAMLexport mlsize_t caml_array_length(value array) { if (Tag_val(array) == Double_array_tag) @@ -135,6 +138,7 @@ CAMLprim value caml_array_unsafe_set(value array, value index, value newval) return caml_array_unsafe_set_addr(array, index, newval); } +/* [len] is a [value] representing number of floats */ CAMLprim value caml_make_float_vect(value len) { mlsize_t wosize = Long_val(len) * Double_wosize; @@ -148,7 +152,7 @@ CAMLprim value caml_make_float_vect(value len) #undef Setup_for_gc #undef Restore_after_gc }else if (wosize > Max_wosize) - caml_invalid_argument("Array.make_float"); + caml_invalid_argument("Array.create_float"); else { result = caml_alloc_shr (wosize, Double_array_tag); result = caml_check_urgent_gc (result); @@ -156,6 +160,7 @@ CAMLprim value caml_make_float_vect(value len) return result; } +/* [len] is a [value] representing number of words or floats */ CAMLprim value caml_make_vect(value len, value init) { CAMLparam2 (len, init); @@ -179,12 +184,16 @@ CAMLprim value caml_make_vect(value len, value init) } } else { if (size > Max_wosize) caml_invalid_argument("Array.make"); - if (size < Max_young_wosize) { + if (size <= Max_young_wosize) { res = caml_alloc_small(size, 0); for (i = 0; i < size; i++) Field(res, i) = init; } else if (Is_block(init) && Is_young(init)) { - caml_minor_collection(); + /* We don't want to create so many major-to-minor references, + so [init] is moved to the major heap by doing a minor GC. */ + CAML_INSTR_INT ("force_minor/make_vect@", 1); + caml_request_minor_gc (); + caml_gc_dispatch (); res = caml_alloc_shr(size, 0); for (i = 0; i < size; i++) Field(res, i) = init; res = caml_check_urgent_gc (res); @@ -322,7 +331,7 @@ static value caml_array_gather(intnat num_arrays, /* Array of values, too big. */ caml_invalid_argument("Array.concat"); } - else if (size < Max_young_wosize) { + else if (size <= Max_young_wosize) { /* Array of values, small enough to fit in young generation. We can use memcpy directly. */ res = caml_alloc_small(size, 0); @@ -337,7 +346,6 @@ static value caml_array_gather(intnat num_arrays, /* Array of values, must be allocated in old generation and filled using caml_initialize. */ res = caml_alloc_shr(size, 0); - pos = 0; for (i = 0, pos = 0; i < num_arrays; i++) { for (src = &Field(arrays[i], offsets[i]), count = lengths[i]; count > 0; @@ -388,8 +396,17 @@ CAMLprim value caml_array_concat(value al) lengths = static_lengths; } else { arrays = caml_stat_alloc(n * sizeof(value)); - offsets = caml_stat_alloc(n * sizeof(intnat)); - lengths = caml_stat_alloc(n * sizeof(value)); + offsets = malloc(n * sizeof(intnat)); + if (offsets == NULL) { + caml_stat_free(arrays); + caml_raise_out_of_memory(); + } + lengths = malloc(n * sizeof(value)); + if (lengths == NULL) { + caml_stat_free(offsets); + caml_stat_free(arrays); + caml_raise_out_of_memory(); + } } /* Build the parameters to caml_array_gather */ for (i = 0, l = al; l != Val_int(0); l = Field(l, 1), i++) { diff --git a/byterun/backtrace.c b/byterun/backtrace.c index 008b199f..12435722 100644 --- a/byterun/backtrace.c +++ b/byterun/backtrace.c @@ -1,70 +1,44 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ /* Stack backtrace for uncaught exceptions */ -#include #include #include #include -#include "caml/config.h" -#ifdef HAS_UNISTD -#include -#endif - -#include "caml/mlvalues.h" #include "caml/alloc.h" -#include "caml/io.h" -#include "caml/instruct.h" -#include "caml/intext.h" -#include "caml/exec.h" -#include "caml/fix_code.h" #include "caml/memory.h" -#include "caml/startup.h" -#include "caml/stacks.h" -#include "caml/sys.h" #include "caml/backtrace.h" +#include "caml/backtrace_prim.h" #include "caml/fail.h" +/* The table of debug information fragments */ +struct ext_table caml_debug_info; + CAMLexport int caml_backtrace_active = 0; CAMLexport int caml_backtrace_pos = 0; -CAMLexport code_t * caml_backtrace_buffer = NULL; +CAMLexport backtrace_slot * caml_backtrace_buffer = NULL; CAMLexport value caml_backtrace_last_exn = Val_unit; -CAMLexport char * caml_cds_file = NULL; -#define BACKTRACE_BUFFER_SIZE 1024 - -/* Location of fields in the Instruct.debug_event record */ -enum { EV_POS = 0, - EV_MODULE = 1, - EV_LOC = 2, - EV_KIND = 3 }; - -/* Location of fields in the Location.t record. */ -enum { LOC_START = 0, - LOC_END = 1, - LOC_GHOST = 2 }; - -/* Location of fields in the Lexing.position record. */ -enum { - POS_FNAME = 0, - POS_LNUM = 1, - POS_BOL = 2, - POS_CNUM = 3 -}; -/* Start or stop the backtrace machinery */ +void caml_init_backtrace(void) +{ + caml_register_global_root(&caml_backtrace_last_exn); +} +/* Start or stop the backtrace machinery */ CAMLprim value caml_record_backtrace(value vflag) { int flag = Int_val(vflag); @@ -72,11 +46,7 @@ CAMLprim value caml_record_backtrace(value vflag) if (flag != caml_backtrace_active) { caml_backtrace_active = flag; caml_backtrace_pos = 0; - if (flag) { - caml_register_global_root(&caml_backtrace_last_exn); - } else { - caml_remove_global_root(&caml_backtrace_last_exn); - } + 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 */ @@ -85,295 +55,20 @@ CAMLprim value caml_record_backtrace(value vflag) } /* Return the status of the backtrace machinery */ - CAMLprim value caml_backtrace_status(value vunit) { return Val_bool(caml_backtrace_active); } -/* Store the return addresses contained in the given stack fragment - into the backtrace array */ - -void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) -{ - code_t end_code = (code_t) ((char *) caml_start_code + caml_code_size); - if (pc != NULL) pc = pc - 1; - if (exn != caml_backtrace_last_exn || !reraise) { - 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(code_t)); - if (caml_backtrace_buffer == NULL) return; - } - if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; - if (pc >= caml_start_code && pc < end_code){ - /* testing the code region is needed: PR#1554 */ - caml_backtrace_buffer[caml_backtrace_pos++] = pc; - } - for (/*nothing*/; sp < caml_trapsp; sp++) { - code_t p = (code_t) *sp; - if (p >= caml_start_code && p < end_code) { - if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; - caml_backtrace_buffer[caml_backtrace_pos++] = p; - } - } -} - -/* In order to prevent the GC from walking through the debug - information (which have no headers), we transform code pointers to - 31/63 bits ocaml integers by shifting them by 1 to the right. We do - not lose information as code pointers are aligned. +/* Print location information -- same behavior as in Printexc - In particular, we do not need to use [caml_initialize] when setting - an array element with such a value. -*/ -#define Val_Codet(p) Val_long((uintnat)p>>1) -#define Codet_Val(v) ((code_t)(Long_val(v)<<1)) - -/* returns the next frame pointer (or NULL if none is available); - updates *sp to point to the following one, and *trsp to the next - trap frame, which we will skip when we reach it */ - -code_t caml_next_frame_pointer(value ** sp, value ** trsp) -{ - code_t end_code = (code_t) ((char *) caml_start_code + caml_code_size); - - while (*sp < caml_stack_high) { - code_t *p = (code_t*) (*sp)++; - if(&Trap_pc(*trsp) == p) { - *trsp = Trap_link(*trsp); - continue; - } - if (*p >= caml_start_code && *p < end_code) return *p; - } - return NULL; -} - -/* Stores upto [max_frames_value] frames of the current call stack to - return to the user. This is used not in an exception-raising - context, but only when the user requests to save the trace - (hopefully less often). Instead of using a bounded buffer as - [caml_stash_backtrace], we first traverse the stack to compute the - right size, then allocate space for the trace. */ - -CAMLprim value caml_get_current_callstack(value max_frames_value) { - CAMLparam1(max_frames_value); - CAMLlocal1(trace); - - /* we use `intnat` here because, were it only `int`, passing `max_int` - from the OCaml side would overflow on 64bits machines. */ - intnat max_frames = Long_val(max_frames_value); - intnat trace_size; - - /* first compute the size of the trace */ - { - value * sp = caml_extern_sp; - value * trsp = caml_trapsp; - - for (trace_size = 0; trace_size < max_frames; trace_size++) { - code_t p = caml_next_frame_pointer(&sp, &trsp); - if (p == NULL) break; - } - } - - trace = caml_alloc(trace_size, 0); - - /* then collect the trace */ - { - value * sp = caml_extern_sp; - value * trsp = caml_trapsp; - uintnat trace_pos; - - for (trace_pos = 0; trace_pos < trace_size; trace_pos++) { - code_t p = caml_next_frame_pointer(&sp, &trsp); - Assert(p != NULL); - Field(trace, trace_pos) = Val_Codet(p); - } - } - - CAMLreturn(trace); -} - -/* Read the debugging info contained in the current bytecode executable. */ - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -struct ev_info { - code_t ev_pc; - char * ev_filename; - int ev_lnum; - int ev_startchr; - int ev_endchr; -}; - -static int cmp_ev_info(const void *a, const void *b) { - code_t pc_a = ((const struct ev_info*)a)->ev_pc; - code_t pc_b = ((const struct ev_info*)b)->ev_pc; - if (pc_a > pc_b) return 1; - if (pc_a < pc_b) return -1; - return 0; -} - -static char *read_debug_info_error = ""; -static uintnat n_events; -static struct ev_info *events = NULL; -static void read_debug_info(void) -{ - CAMLparam0(); - CAMLlocal1(events_heap); - char * exec_name; - int fd; - struct exec_trailer trail; - struct channel * chan; - uint32 num_events, orig, i; - intnat j; - value evl, l, ev_start; - - if(events != NULL) - CAMLreturn0; - - if (caml_cds_file != NULL) { - exec_name = caml_cds_file; - } else { - exec_name = caml_exe_name; - } - fd = caml_attempt_open(&exec_name, &trail, 1); - if (fd < 0){ - read_debug_info_error = "executable program file not found"; - CAMLreturn0; - } - caml_read_section_descriptors(fd, &trail); - if (caml_seek_optional_section(fd, &trail, "DBUG") == -1) { - close(fd); - read_debug_info_error = "program not linked with -g"; - CAMLreturn0; - } - chan = caml_open_descriptor_in(fd); - num_events = caml_getword(chan); - n_events = 0; - events_heap = caml_alloc(num_events, 0); - for (i = 0; i < num_events; i++) { - orig = caml_getword(chan); - evl = caml_input_val(chan); - caml_input_val(chan); // Skip the list of absolute directory names - /* Relocate events in event list */ - for (l = evl; l != Val_int(0); l = Field(l, 1)) { - value ev = Field(l, 0); - Field(ev, EV_POS) = Val_long(Long_val(Field(ev, EV_POS)) + orig); - n_events++; - } - /* Record event list */ - Store_field(events_heap, i, evl); - } - caml_close_channel(chan); - - events = (struct ev_info*)malloc(n_events * sizeof(struct ev_info)); - if(events == NULL) { - read_debug_info_error = "out of memory"; - CAMLreturn0; - } - - j = 0; - for (i = 0; i < num_events; i++) { - for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) { - uintnat fnsz; - value ev = Field(l, 0); - - events[j].ev_pc = - (code_t)((char*)caml_start_code + Long_val(Field(ev, EV_POS))); - - ev_start = Field (Field (ev, EV_LOC), LOC_START); - - fnsz = caml_string_length(Field (ev_start, POS_FNAME))+1; - events[j].ev_filename = (char*)malloc(fnsz); - if(events[j].ev_filename == NULL) { - for(j--; j >= 0; j--) - free(events[j].ev_filename); - free(events); - events = NULL; - read_debug_info_error = "out of memory"; - CAMLreturn0; - } - memcpy(events[j].ev_filename, String_val (Field (ev_start, POS_FNAME)), - fnsz); - - events[j].ev_lnum = Int_val (Field (ev_start, POS_LNUM)); - events[j].ev_startchr = - Int_val (Field (ev_start, POS_CNUM)) - - Int_val (Field (ev_start, POS_BOL)); - events[j].ev_endchr = - Int_val (Field (Field (Field (ev, EV_LOC), LOC_END), POS_CNUM)) - - Int_val (Field (ev_start, POS_BOL)); - - j++; - } - } - - Assert(j == n_events); - - qsort(events, n_events, sizeof(struct ev_info), cmp_ev_info); - - CAMLreturn0; -} - -/* Search the event index for the given PC. Return -1 if not found. */ - -static intnat event_for_location(code_t pc) -{ - uintnat low = 0, high = n_events; - Assert(pc >= caml_start_code && pc < caml_start_code + caml_code_size); - Assert(events != NULL); - while(low+1 < high) { - uintnat m = (low+high)/2; - if(pc < events[m].ev_pc) high = m; - else low = m; - } - if(events[low].ev_pc == pc) - return low; - /* ocamlc sometimes moves an event past a following PUSH instruction; - allow mismatch by 1 instruction. */ - if(events[low].ev_pc == pc + 1) - return low; - if(low+1 < n_events && events[low+1].ev_pc == pc + 1) - return low+1; - return -1; -} - -/* Extract location information for the given PC */ - -struct loc_info { - int loc_valid; - int loc_is_raise; - char * loc_filename; - int loc_lnum; - int loc_startchr; - int loc_endchr; -}; - -static void extract_location_info(code_t pc, - /*out*/ struct loc_info * li) -{ - intnat ev = event_for_location(pc); - li->loc_is_raise = caml_is_instruction(*pc, RAISE) || - caml_is_instruction(*pc, RERAISE); - if (ev == -1) { - li->loc_valid = 0; - return; - } - li->loc_valid = 1; - li->loc_filename = events[ev].ev_filename; - li->loc_lnum = events[ev].ev_lnum; - li->loc_startchr = events[ev].ev_startchr; - li->loc_endchr = events[ev].ev_endchr; -} - -/* Print location information -- same behavior as in Printexc */ - -static void print_location(struct loc_info * li, int index) + note that the test for compiler-inserted raises is slightly redundant: + (!li->loc_valid && li->loc_is_raise) + caml_extract_location_info above guarantees that when li->loc_valid is + 0, then li->loc_is_raise is always 1, so the latter test is + useless. We kept it to keep code identical to the byterun/ + implementation. */ +static void print_location(struct caml_loc_info * li, int index) { char * info; @@ -402,36 +97,74 @@ static void print_location(struct loc_info * li, int index) } /* Print a backtrace */ - CAMLexport void caml_print_exception_backtrace(void) { int i; - struct loc_info li; + struct caml_loc_info li; - read_debug_info(); - if (events == NULL) { - fprintf(stderr, "(Cannot print stack backtrace: %s)\n", - read_debug_info_error); + if (!caml_debug_info_available()) { + fprintf(stderr, "(Cannot print stack backtrace: " + "no debug information available)\n"); return; } + for (i = 0; i < caml_backtrace_pos; i++) { - extract_location_info(caml_backtrace_buffer[i], &li); + caml_extract_location_info(caml_backtrace_buffer[i], &li); print_location(&li, i); } } -/* Convert the backtrace to a data structure usable from OCaml */ +/* Get a copy of the latest backtrace */ +CAMLprim value caml_get_exception_raw_backtrace(value unit) +{ + CAMLparam0(); + CAMLlocal1(res); + + /* Beware: the allocations below may cause finalizers to be run, and another + backtrace---possibly of a different length---to be stashed (for example + if the finalizer raises then catches an exception). We choose to ignore + any such finalizer backtraces and return the original one. */ + + if (!caml_backtrace_active || + caml_backtrace_buffer == NULL || + caml_backtrace_pos == 0) { + res = caml_alloc(0, 0); + } + else { + backtrace_slot saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE]; + int saved_caml_backtrace_pos; + intnat i; + + saved_caml_backtrace_pos = caml_backtrace_pos; + + if (saved_caml_backtrace_pos > BACKTRACE_BUFFER_SIZE) { + saved_caml_backtrace_pos = BACKTRACE_BUFFER_SIZE; + } + + memcpy(saved_caml_backtrace_buffer, caml_backtrace_buffer, + saved_caml_backtrace_pos * sizeof(backtrace_slot)); + + res = caml_alloc(saved_caml_backtrace_pos, 0); + for (i = 0; i < saved_caml_backtrace_pos; i++) { + Field(res, i) = + caml_val_raw_backtrace_slot(saved_caml_backtrace_buffer[i]); + } + } + + CAMLreturn(res); +} -CAMLprim value caml_convert_raw_backtrace_slot(value backtrace_slot) { +/* Convert the raw backtrace to a data structure usable from OCaml */ +CAMLprim value caml_convert_raw_backtrace_slot(value backtrace_slot) +{ CAMLparam1(backtrace_slot); CAMLlocal2(p, fname); - struct loc_info li; + struct caml_loc_info li; - read_debug_info(); - if (events == NULL) - caml_failwith(read_debug_info_error); + if (!caml_debug_info_available()) + caml_failwith("No debug information available"); - extract_location_info(Codet_Val(backtrace_slot), &li); + caml_extract_location_info(caml_raw_backtrace_slot_val(backtrace_slot), &li); if (li.loc_valid) { fname = caml_copy_string(li.loc_filename); @@ -445,23 +178,8 @@ CAMLprim value caml_convert_raw_backtrace_slot(value backtrace_slot) { p = caml_alloc_small(1, 1); Field(p, 0) = Val_bool(li.loc_is_raise); } - CAMLreturn(p); -} -/* Get a copy of the latest backtrace */ - -CAMLprim value caml_get_exception_raw_backtrace(value unit) -{ - CAMLparam0(); - CAMLlocal1(res); - - res = caml_alloc(caml_backtrace_pos, 0); - if(caml_backtrace_buffer != NULL) { - intnat i; - for(i = 0; i < caml_backtrace_pos; i++) - Field(res, i) = Val_Codet(caml_backtrace_buffer[i]); - } - CAMLreturn(res); + CAMLreturn(p); } /* the function below is deprecated: we previously returned directly @@ -471,32 +189,25 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit) It is not used by the Printexc library anymore, or anywhere else in the compiler, but we have kept it in case some user still depends - on it as an external. -*/ - + on it as an external. */ CAMLprim value caml_get_exception_backtrace(value unit) { CAMLparam0(); - CAMLlocal4(arr, raw_slot, slot, res); + CAMLlocal3(arr, res, backtrace); + intnat i; - read_debug_info(); - if (events == NULL) { + if (!caml_debug_info_available()) { res = Val_int(0); /* None */ } else { - arr = caml_alloc(caml_backtrace_pos, 0); - if(caml_backtrace_buffer == NULL) { - Assert(caml_backtrace_pos == 0); - } else { - intnat i; - for(i = 0; i < caml_backtrace_pos; i++) { - raw_slot = Val_Codet(caml_backtrace_buffer[i]); - /* caml_convert_raw_backtrace_slot will not fail with - caml_failwith as we checked (events != NULL) already */ - slot = caml_convert_raw_backtrace_slot(raw_slot); - caml_modify(&Field(arr, i), slot); - } - } - res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */ + backtrace = caml_get_exception_raw_backtrace(Val_unit); + + arr = caml_alloc(Wosize_val(backtrace), 0); + for (i = 0; i < Wosize_val(backtrace); i++) { + Store_field(arr, i, caml_convert_raw_backtrace_slot(Field(backtrace, i))); + } + + res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */ } + CAMLreturn(res); } diff --git a/byterun/backtrace_prim.c b/byterun/backtrace_prim.c new file mode 100644 index 00000000..081c97fa --- /dev/null +++ b/byterun/backtrace_prim.c @@ -0,0 +1,456 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ + +/* Stack backtrace for uncaught exceptions */ + +#include +#include +#include +#include + +#include "caml/config.h" +#ifdef HAS_UNISTD +#include +#endif + +#include "caml/mlvalues.h" +#include "caml/alloc.h" +#include "caml/custom.h" +#include "caml/io.h" +#include "caml/instruct.h" +#include "caml/intext.h" +#include "caml/exec.h" +#include "caml/fix_code.h" +#include "caml/memory.h" +#include "caml/startup.h" +#include "caml/stacks.h" +#include "caml/sys.h" +#include "caml/backtrace.h" +#include "caml/fail.h" +#include "caml/backtrace_prim.h" + +/* The table of debug information fragments */ +struct ext_table caml_debug_info; + +CAMLexport char * caml_cds_file = NULL; + +/* Location of fields in the Instruct.debug_event record */ +enum { + EV_POS = 0, + EV_MODULE = 1, + EV_LOC = 2, + EV_KIND = 3 +}; + +/* Location of fields in the Location.t record. */ +enum { + LOC_START = 0, + LOC_END = 1, + LOC_GHOST = 2 +}; + +/* Location of fields in the Lexing.position record. */ +enum { + POS_FNAME = 0, + POS_LNUM = 1, + POS_BOL = 2, + POS_CNUM = 3 +}; + +/* Runtime representation of the debug information, optimized + for quick lookup */ +struct ev_info { + code_t ev_pc; + char *ev_filename; + int ev_lnum; + int ev_startchr; + int ev_endchr; +}; + +struct debug_info { + code_t start; + code_t end; + mlsize_t num_events; + struct ev_info *events; + int already_read; +}; + +static struct debug_info *find_debug_info(code_t pc) +{ + int i; + for (i = 0; i < caml_debug_info.size; i++) { + struct debug_info *di = caml_debug_info.contents[i]; + if (pc >= di->start && pc < di->end) + return di; + } + return NULL; +} + +static int cmp_ev_info(const void *a, const void *b) +{ + code_t pc_a = ((const struct ev_info*)a)->ev_pc; + code_t pc_b = ((const struct ev_info*)b)->ev_pc; + if (pc_a > pc_b) return 1; + if (pc_a < pc_b) return -1; + return 0; +} + +struct ev_info *process_debug_events(code_t code_start, value events_heap, + mlsize_t *num_events) +{ + CAMLparam1(events_heap); + CAMLlocal3(l, ev, ev_start); + mlsize_t i, j; + struct ev_info *events; + + /* Compute the size of the required event buffer. */ + *num_events = 0; + for (i = 0; i < caml_array_length(events_heap); i++) + for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) + (*num_events)++; + + if (*num_events == 0) + CAMLreturnT(struct ev_info *, NULL); + + events = malloc(*num_events * sizeof(struct ev_info)); + if(events == NULL) + caml_fatal_error ("caml_add_debug_info: out of memory"); + + j = 0; + for (i = 0; i < caml_array_length(events_heap); i++) { + for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) { + ev = Field(l, 0); + + events[j].ev_pc = (code_t)((char*)code_start + + Long_val(Field(ev, EV_POS))); + + ev_start = Field(Field(ev, EV_LOC), LOC_START); + + { + uintnat fnsz = caml_string_length(Field(ev_start, POS_FNAME)) + 1; + events[j].ev_filename = (char*)malloc(fnsz); + if(events[j].ev_filename == NULL) + caml_fatal_error ("caml_add_debug_info: out of memory"); + memcpy(events[j].ev_filename, + String_val(Field(ev_start, POS_FNAME)), + fnsz); + } + + events[j].ev_lnum = Int_val(Field(ev_start, POS_LNUM)); + events[j].ev_startchr = + Int_val(Field(ev_start, POS_CNUM)) + - Int_val(Field(ev_start, POS_BOL)); + events[j].ev_endchr = + Int_val(Field(Field(Field(ev, EV_LOC), LOC_END), POS_CNUM)) + - Int_val(Field(ev_start, POS_BOL)); + + j++; + } + } + + Assert(j == *num_events); + + qsort(events, *num_events, sizeof(struct ev_info), cmp_ev_info); + + CAMLreturnT(struct ev_info *, events); +} + +/* Processes a (Instruct.debug_event list array) into a form suitable + for quick lookup and registers it for the (code_start,code_size) pc range. */ +CAMLprim value caml_add_debug_info(code_t code_start, value code_size, + value events_heap) +{ + CAMLparam1(events_heap); + struct debug_info *debug_info; + + /* build the OCaml-side debug_info value */ + debug_info = caml_stat_alloc(sizeof(struct debug_info)); + + debug_info->start = code_start; + debug_info->end = (code_t)((char*) code_start + Long_val(code_size)); + if (events_heap == Val_unit) { + debug_info->events = NULL; + debug_info->num_events = 0; + debug_info->already_read = 0; + } else { + debug_info->events = + process_debug_events(code_start, events_heap, &debug_info->num_events); + debug_info->already_read = 1; + } + + caml_ext_table_add(&caml_debug_info, debug_info); + + CAMLreturn(Val_unit); +} + +CAMLprim value caml_remove_debug_info(code_t start) +{ + CAMLparam0(); + CAMLlocal2(dis, prev); + + int i; + for (i = 0; i < caml_debug_info.size; i++) { + struct debug_info *di = caml_debug_info.contents[i]; + if (di->start == start) { + /* note that caml_ext_table_remove calls caml_stat_free on the + removed resource, bracketing the caml_stat_alloc call in + caml_add_debug_info. */ + caml_ext_table_remove(&caml_debug_info, di); + break; + } + } + + CAMLreturn(Val_unit); +} + +/* Store the return addresses contained in the given stack fragment + into the backtrace array */ + +void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise) +{ + if (pc != NULL) pc = pc - 1; + if (exn != caml_backtrace_last_exn || !reraise) { + 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(code_t)); + if (caml_backtrace_buffer == NULL) return; + } + + if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; + /* testing the code region is needed: PR#1554 */ + if (find_debug_info(pc) != NULL) + caml_backtrace_buffer[caml_backtrace_pos++] = pc; + + /* Traverse the stack and put all values pointing into bytecode + into the backtrace buffer. */ + for (/*nothing*/; sp < caml_trapsp; sp++) { + code_t p = (code_t) *sp; + if (caml_backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; + if (find_debug_info(p) != NULL) + caml_backtrace_buffer[caml_backtrace_pos++] = p; + } +} + +/* In order to prevent the GC from walking through the debug + information (which have no headers), we transform code pointers to + 31/63 bits ocaml integers by shifting them by 1 to the right. We do + not lose information as code pointers are aligned. + + In particular, we do not need to use [caml_modify] when setting + an array element with such a value. +*/ +value caml_val_raw_backtrace_slot(backtrace_slot pc) +{ + return Val_long ((uintnat)pc >> 1); +} + +backtrace_slot caml_raw_backtrace_slot_val(value v) +{ + return ((backtrace_slot)(Long_val(v) << 1)); +} + +/* returns the next frame pointer (or NULL if none is available); + updates *sp to point to the following one, and *trsp to the next + trap frame, which we will skip when we reach it */ + +code_t caml_next_frame_pointer(value ** sp, value ** trsp) +{ + while (*sp < caml_stack_high) { + code_t *p = (code_t*) (*sp)++; + if(&Trap_pc(*trsp) == p) { + *trsp = Trap_link(*trsp); + continue; + } + + if (find_debug_info(*p) != NULL) + return *p; + } + return NULL; +} + +/* Stores upto [max_frames_value] frames of the current call stack to + return to the user. This is used not in an exception-raising + context, but only when the user requests to save the trace + (hopefully less often). Instead of using a bounded buffer as + [caml_stash_backtrace], we first traverse the stack to compute the + right size, then allocate space for the trace. */ + +CAMLprim value caml_get_current_callstack(value max_frames_value) +{ + CAMLparam1(max_frames_value); + CAMLlocal1(trace); + + /* we use `intnat` here because, were it only `int`, passing `max_int` + from the OCaml side would overflow on 64bits machines. */ + intnat max_frames = Long_val(max_frames_value); + intnat trace_size; + + /* first compute the size of the trace */ + { + value * sp = caml_extern_sp; + value * trsp = caml_trapsp; + + for (trace_size = 0; trace_size < max_frames; trace_size++) { + code_t p = caml_next_frame_pointer(&sp, &trsp); + if (p == NULL) break; + } + } + + trace = caml_alloc(trace_size, 0); + + /* then collect the trace */ + { + value * sp = caml_extern_sp; + value * trsp = caml_trapsp; + uintnat trace_pos; + + for (trace_pos = 0; trace_pos < trace_size; trace_pos++) { + code_t p = caml_next_frame_pointer(&sp, &trsp); + Assert(p != NULL); + Store_field(trace, trace_pos, caml_val_raw_backtrace_slot(p)); + } + } + + CAMLreturn(trace); +} + +/* Read the debugging info contained in the current bytecode executable. */ + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +void read_main_debug_info(struct debug_info *di) +{ + CAMLparam0(); + CAMLlocal3(events, evl, l); + char *exec_name; + int fd, num_events, orig, i; + struct channel *chan; + struct exec_trailer trail; + + Assert(di->already_read == 0); + di->already_read = 1; + + if (caml_cds_file != NULL) { + exec_name = caml_cds_file; + } else { + exec_name = caml_exe_name; + } + + fd = caml_attempt_open(&exec_name, &trail, 1); + if (fd < 0){ + caml_fatal_error ("executable program file not found"); + CAMLreturn0; + } + + caml_read_section_descriptors(fd, &trail); + if (caml_seek_optional_section(fd, &trail, "DBUG") != -1) { + chan = caml_open_descriptor_in(fd); + + num_events = caml_getword(chan); + events = caml_alloc(num_events, 0); + + for (i = 0; i < num_events; i++) { + orig = caml_getword(chan); + evl = caml_input_val(chan); + caml_input_val(chan); /* Skip the list of absolute directory names */ + /* Relocate events in event list */ + for (l = evl; l != Val_int(0); l = Field(l, 1)) { + value ev = Field(l, 0); + Field(ev, EV_POS) = Val_long(Long_val(Field(ev, EV_POS)) + orig); + } + /* Record event list */ + Store_field(events, i, evl); + } + + caml_close_channel(chan); + + di->events = process_debug_events(caml_start_code, events, &di->num_events); + } + + CAMLreturn0; +} + +CAMLexport void caml_init_debug_info(void) +{ + caml_ext_table_init(&caml_debug_info, 1); + caml_add_debug_info(caml_start_code, Val_long(caml_code_size), Val_unit); +} + +int caml_debug_info_available(void) +{ + return (caml_debug_info.size != 0); +} + +/* Search the event index for the given PC. Return -1 if not found. */ + +static struct ev_info *event_for_location(code_t pc) +{ + uintnat low, high; + struct debug_info *di = find_debug_info(pc); + + if (di == NULL) + return NULL; + + if (!di->already_read) + read_main_debug_info(di); + + if (di->num_events == 0) + return NULL; + + low = 0; + high = di->num_events; + while (low+1 < high) { + uintnat m = (low+high)/2; + if(pc < di->events[m].ev_pc) high = m; + else low = m; + } + if (di->events[low].ev_pc == pc) + return &di->events[low]; + /* ocamlc sometimes moves an event past a following PUSH instruction; + allow mismatch by 1 instruction. */ + if (di->events[low].ev_pc == pc + 1) + return &di->events[low]; + if (low+1 < di->num_events && di->events[low+1].ev_pc == pc + 1) + return &di->events[low+1]; + + return NULL; +} + +/* Extract location information for the given PC */ + +void caml_extract_location_info(backtrace_slot slot, + /*out*/ struct caml_loc_info * li) +{ + code_t pc = slot; + struct ev_info *event = event_for_location(pc); + li->loc_is_raise = + caml_is_instruction(*pc, RAISE) || + caml_is_instruction(*pc, RERAISE); + if (event == NULL) { + li->loc_valid = 0; + return; + } + li->loc_valid = 1; + li->loc_filename = event->ev_filename; + li->loc_lnum = event->ev_lnum; + li->loc_startchr = event->ev_startchr; + li->loc_endchr = event->ev_endchr; +} diff --git a/byterun/callback.c b/byterun/callback.c index 30109851..7697edcc 100644 --- a/byterun/callback.c +++ b/byterun/callback.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Callbacks from C to OCaml */ diff --git a/byterun/caml/address_class.h b/byterun/caml/address_class.h index f7908b6d..36921e69 100644 --- a/byterun/caml/address_class.h +++ b/byterun/caml/address_class.h @@ -1,21 +1,24 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Classification of addresses for GC and runtime purposes. */ #ifndef CAML_ADDRESS_CLASS_H #define CAML_ADDRESS_CLASS_H +#include "config.h" #include "misc.h" #include "mlvalues.h" @@ -43,7 +46,7 @@ /***********************************************************************/ /* The rest of this file is private and may change without notice. */ -extern char *caml_young_start, *caml_young_end; +extern value *caml_young_start, *caml_young_end; extern char * caml_code_area_start, * caml_code_area_end; #define Not_in_heap 0 diff --git a/byterun/caml/alloc.h b/byterun/caml/alloc.h index f00a7ef0..64a250d7 100644 --- a/byterun/caml/alloc.h +++ b/byterun/caml/alloc.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_ALLOC_H #define CAML_ALLOC_H @@ -25,22 +27,22 @@ extern "C" { #endif -CAMLextern value caml_alloc (mlsize_t, tag_t); -CAMLextern value caml_alloc_small (mlsize_t, tag_t); -CAMLextern value caml_alloc_tuple (mlsize_t); -CAMLextern value caml_alloc_string (mlsize_t); /* size in bytes */ +CAMLextern value caml_alloc (mlsize_t wosize, tag_t); +CAMLextern value caml_alloc_small (mlsize_t wosize, tag_t); +CAMLextern value caml_alloc_tuple (mlsize_t wosize); +CAMLextern value caml_alloc_string (mlsize_t len); /* len in bytes (chars) */ CAMLextern value caml_copy_string (char const *); CAMLextern value caml_copy_string_array (char const **); CAMLextern value caml_copy_double (double); -CAMLextern value caml_copy_int32 (int32); /* defined in [ints.c] */ -CAMLextern value caml_copy_int64 (int64); /* defined in [ints.c] */ +CAMLextern value caml_copy_int32 (int32_t); /* defined in [ints.c] */ +CAMLextern value caml_copy_int64 (int64_t); /* defined in [ints.c] */ CAMLextern value caml_copy_nativeint (intnat); /* defined in [ints.c] */ CAMLextern value caml_alloc_array (value (*funct) (char const *), char const ** array); CAMLextern value caml_alloc_sprintf(const char * format, ...); typedef void (*final_fun)(value); -CAMLextern value caml_alloc_final (mlsize_t, /*size in words*/ +CAMLextern value caml_alloc_final (mlsize_t wosize, final_fun, /*finalization function*/ mlsize_t, /*resources consumed*/ mlsize_t /*max resources*/); diff --git a/byterun/caml/backtrace.h b/byterun/caml/backtrace.h index ec499919..a1630f2b 100644 --- a/byterun/caml/backtrace.h +++ b/byterun/caml/backtrace.h @@ -1,31 +1,132 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_BACKTRACE_H #define CAML_BACKTRACE_H #include "mlvalues.h" +#include "exec.h" +/* Runtime support for backtrace generation. + * + * It has two kind of users: + * - high-level API to capture and decode backtraces; + * - low-level runtime routines, to introspect machine state and determine + * whether a backtrace should be generated when using "raise". + * + * Backtrace generation is split in multiple steps. + * The lowest-level one, done by [backtrace_prim.c] just fills the + * [caml_backtrace_buffer] variable each time a frame is unwinded. + * At that point, we don't know whether the backtrace will be useful or not so + * this code should be as fast as possible. + * + * If the backtrace happens to be useful, later passes will read + * [caml_backtrace_buffer] and turn it into a [raw_backtrace] and then a + * [backtrace]. + * This is done in [backtrace.c] and [stdlib/printexc.ml]. + * + * Content of buffers + * ------------------ + * + * [caml_backtrace_buffer] (really cheap) + * Backend and process image dependent, abstracted by C-type backtrace_slot. + * [raw_backtrace] (cheap) + * OCaml values of abstract type [Printexc.raw_backtrace_slot], + * still backend and process image dependent (unsafe to marshal). + * [backtrace] (more expensive) + * OCaml values of algebraic data-type [Printexc.backtrace_slot] + */ + +/* Non zero iff backtraces are recorded. + * One should use to change this variable [caml_record_backtrace]. + */ CAMLextern int caml_backtrace_active; + +/* The [backtrace_slot] type represents values stored in the + * [caml_backtrace_buffer]. In bytecode, it is the same as a + * [code_t], in native code it as a [frame_descr *]. The difference + * doesn't matter for code outside [backtrace_prim.c], so it is just + * exposed as a [backtrace_slot]. + */ +typedef void * backtrace_slot; + +/* The [caml_backtrace_buffer] and [caml_backtrace_last_exn] + * variables are valid only if [caml_backtrace_active != 0]. + * + * They are part of the state specific to each thread, and threading libraries + * are responsible for copying them on context switch. + * See [otherlibs/systhreads/st_stubs.c] and [otherlibs/threads/scheduler.c]. + */ + +/* [caml_backtrace_buffer] is filled by runtime when unwinding stack. + * It is an array ranging from [0] to [caml_backtrace_pos - 1]. + * [caml_backtrace_pos] is always zero if [!caml_backtrace_active]. + * + * Its maximum size is determined by [BACKTRACE_BUFFER_SIZE] from + * [backtrace_prim.h], but this shouldn't affect users. + */ +CAMLextern backtrace_slot * caml_backtrace_buffer; CAMLextern int caml_backtrace_pos; -CAMLextern code_t * caml_backtrace_buffer; + +/* [caml_backtrace_last_exn] stores the last exception value that was raised, + * iff [caml_backtrace_active != 0]. + * It is tested for equality to determine whether a raise is a re-raise of the + * same exception. + * + * FIXME: this shouldn't matter anymore. Since OCaml 4.02, non-parameterized + * exceptions are constant, so physical equality is no longer appropriate. + * raise and re-raise are distinguished by: + * - passing reraise = 1 to [caml_stash_backtrace] (see below) in the bytecode + * interpreter; + * - directly resetting [caml_backtrace_pos] to 0 in native runtimes for raise. + */ CAMLextern value caml_backtrace_last_exn; -CAMLextern char * caml_cds_file; +/* [caml_record_backtrace] toggle backtrace recording on and off. + * This function can be called at runtime by user-code, or during + * initialization if backtraces were requested. + * + * It might be called before GC initialization, so it shouldn't do OCaml + * allocation. + */ CAMLprim value caml_record_backtrace(value vflag); + + #ifndef NATIVE_CODE + +/* Path to the file containing debug information, if any, or NULL. */ +CAMLextern char * caml_cds_file; + +/* Primitive called _only_ by runtime to record unwinded frames to + * backtrace. A similar primitive exists for native code, but with a + * different prototype. */ extern void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise); + #endif + + +/* Default (C-level) printer for backtraces. It is called if an + * exception causes a termination of the program or of a thread. + * + * [Printexc] provide a higher-level printer mimicking its output but making + * use of registered exception printers, and is used when possible in place of + * this function after [Printexc] initialization. + */ CAMLextern void caml_print_exception_backtrace(void); +void caml_init_backtrace(void); +CAMLexport void caml_init_debug_info(void); + #endif /* CAML_BACKTRACE_H */ diff --git a/byterun/caml/backtrace_prim.h b/byterun/caml/backtrace_prim.h new file mode 100644 index 00000000..c59dbc33 --- /dev/null +++ b/byterun/caml/backtrace_prim.h @@ -0,0 +1,69 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ + +#ifndef CAML_BACKTRACE_PRIM_H +#define CAML_BACKTRACE_PRIM_H + +#include "backtrace.h" + +/* Backtrace generation is split in [backtrace.c] and [backtrace_prim.c]. + * + * [backtrace_prim.c] contains all backend-specific code, and has two different + * implementations in [byterun/backtrace_prim.c] and [asmrun/backtrace_prim.c]. + * + * [backtrace.c] has a unique implementation, and expose a uniform + * higher level API above [backtrace_prim.c]. + */ + +/* Extract location information for the given raw_backtrace_slot */ + +struct caml_loc_info { + int loc_valid; + int loc_is_raise; + char * loc_filename; + int loc_lnum; + int loc_startchr; + int loc_endchr; +}; + +/* Check availability of debug information before extracting a trace. + * Relevant for bytecode, always true for native code. */ +int caml_debug_info_available(void); + +/* Extract locations from backtrace_slot */ +void caml_extract_location_info(backtrace_slot pc, + /*out*/ struct caml_loc_info * li); + +/* Expose a [backtrace_slot] as a OCaml value of type [raw_backtrace_slot]. + * The value returned should be an immediate and not an OCaml block, so that it + * is safe to store using direct assignment and [Field], and not [Store_field] / + * [caml_modify]. */ +value caml_val_raw_backtrace_slot(backtrace_slot pc); +backtrace_slot caml_raw_backtrace_slot_val(value slot); + +#define BACKTRACE_BUFFER_SIZE 1024 + +/* Besides decoding backtrace info, [backtrace_prim] has two other + * responsibilities: + * + * It defines the [caml_stash_backtrace] function, which is called to quickly + * fill the backtrace buffer by walking the stack when an exception is raised. + * + * It also defines the [caml_get_current_callstack] OCaml primitive, which also + * walks the stack but directly turns it into a [raw_backtrace] and is called + * explicitly. + */ + +#endif /* CAML_BACKTRACE_PRIM_H */ diff --git a/byterun/caml/callback.h b/byterun/caml/callback.h index ef50945c..58d3faff 100644 --- a/byterun/caml/callback.h +++ b/byterun/caml/callback.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Callbacks from C to OCaml */ diff --git a/byterun/caml/compact.h b/byterun/caml/compact.h index 2abac167..72950583 100644 --- a/byterun/caml/compact.h +++ b/byterun/caml/compact.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_COMPACT_H #define CAML_COMPACT_H diff --git a/byterun/caml/compare.h b/byterun/caml/compare.h index 41d6a0c9..d6456f46 100644 --- a/byterun/caml/compare.h +++ b/byterun/caml/compare.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, Projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, Projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_COMPARE_H #define CAML_COMPARE_H diff --git a/byterun/caml/compatibility.h b/byterun/caml/compatibility.h index 11181176..082943c6 100644 --- a/byterun/caml/compatibility.h +++ b/byterun/caml/compatibility.h @@ -1,21 +1,27 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /* definitions for compatibility with old identifiers */ #ifndef CAML_COMPATIBILITY_H #define CAML_COMPATIBILITY_H +/* internal global variables renamed between 4.02.1 and 4.03.0 */ +#define caml_stat_top_heap_size Bsize_wsize(caml_stat_top_heap_wsz) +#define caml_stat_heap_size Bsize_wsize(caml_stat_heap_wsz) + #ifndef CAML_NAME_SPACE /* diff --git a/byterun/caml/config.h b/byterun/caml/config.h index 6f608364..a77b4e55 100644 --- a/byterun/caml/config.h +++ b/byterun/caml/config.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_CONFIG_H #define CAML_CONFIG_H @@ -19,30 +21,39 @@ /* */ #include "../../config/m.h" #include "../../config/s.h" +#ifdef BOOTSTRAPPING_FLEXLINK +#undef SUPPORT_DYNAMIC_LINKING +#endif /* */ #ifndef CAML_NAME_SPACE #include "compatibility.h" #endif -/* Types for 32-bit integers, 64-bit integers, +#ifdef HAS_STDINT_H +#include +#endif + +/* Types for 32-bit integers, 64-bit integers, and native integers (as wide as a pointer type) */ +#ifndef ARCH_INT32_TYPE #if SIZEOF_INT == 4 -typedef int int32; -typedef unsigned int uint32; +#define ARCH_INT32_TYPE int +#define ARCH_UINT32_TYPE unsigned int #define ARCH_INT32_PRINTF_FORMAT "" #elif SIZEOF_LONG == 4 -typedef long int32; -typedef unsigned long uint32; +#define ARCH_INT32_TYPE long +#define ARCH_UINT32_TYPE unsigned long #define ARCH_INT32_PRINTF_FORMAT "l" #elif SIZEOF_SHORT == 4 -typedef short int32; -typedef unsigned short uint32; +#define ARCH_INT32_TYPE short +#define ARCH_UINT32_TYPE unsigned short #define ARCH_INT32_PRINTF_FORMAT "" #else #error "No 32-bit integer type available" #endif +#endif #ifndef ARCH_INT64_TYPE #if SIZEOF_LONGLONG == 8 @@ -58,8 +69,19 @@ typedef unsigned short uint32; #endif #endif -typedef ARCH_INT64_TYPE int64; -typedef ARCH_UINT64_TYPE uint64; +#ifndef HAS_STDINT_H +/* Not a C99 compiler, typically MSVC. Define the C99 types we use. */ +typedef ARCH_INT32_TYPE int32_t; +typedef ARCH_UINT32_TYPE uint32_t; +typedef ARCH_INT64_TYPE int64_t; +typedef ARCH_UINT64_TYPE uint64_t; +#if SIZEOF_SHORT == 2 +typedef short int16_t; +typedef unsigned short uint16_t; +#else +#error "No 16-bit integer type available" +#endif +#endif #if SIZEOF_PTR == SIZEOF_LONG /* Standard models: ILP32 or I32LP64 */ @@ -72,9 +94,9 @@ typedef int intnat; typedef unsigned int uintnat; #define ARCH_INTNAT_PRINTF_FORMAT "" #elif SIZEOF_PTR == 8 -/* Win64 model: IL32LLP64 */ -typedef int64 intnat; -typedef uint64 uintnat; +/* Win64 model: IL32P64 */ +typedef int64_t intnat; +typedef uint64_t uintnat; #define ARCH_INTNAT_PRINTF_FORMAT ARCH_INT64_PRINTF_FORMAT #else #error "No integer type available to represent pointers" @@ -95,6 +117,7 @@ typedef uint64 uintnat; #define ARCH_FLOAT_ENDIANNESS 0x01234567 #endif + /* We use threaded code interpretation if the compiler provides labels as first-class values (GCC 2.x). */ @@ -104,14 +127,14 @@ typedef uint64 uintnat; #endif -/* Do not change this definition. */ -#define Page_size (1 << Page_log) - /* Memory model parameters */ /* The size of a page for memory management (in bytes) is [1 << Page_log]. - It must be a multiple of [sizeof (value)] and >= 8 and <= 20. */ + [Page_size] must be a multiple of [sizeof (value)]. + [Page_log] must be be >= 8 and <= 20. + Do not change the definition of [Page_size]. */ #define Page_log 12 /* A page is 4 kilobytes. */ +#define Page_size (1 << Page_log) /* Initial size of stack (bytes). */ #define Stack_size (4096 * sizeof(value)) @@ -126,10 +149,11 @@ typedef uint64 uintnat; /* Maximum size of a block allocated in the young generation (words). */ /* Must be > 4 */ #define Max_young_wosize 256 +#define Max_young_whsize (Whsize_wosize (Max_young_wosize)) /* Minimum size of the minor zone (words). - This must be at least [Max_young_wosize + 1]. */ + This must be at least [2 * Max_young_whsize]. */ #define Minor_heap_min 4096 /* Maximum size of the minor zone (words). @@ -168,5 +192,12 @@ typedef uint64 uintnat; */ #define Max_percent_free_def 500 +/* Default setting for the major GC slice smoothing window: 1 + (i.e. no smoothing) +*/ +#define Major_window_def 1 + +/* Maximum size of the major GC slice smoothing window. */ +#define Max_major_window 50 #endif /* CAML_CONFIG_H */ diff --git a/byterun/caml/custom.h b/byterun/caml/custom.h index ff3cd89a..a3119d0f 100644 --- a/byterun/caml/custom.h +++ b/byterun/caml/custom.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_CUSTOM_H #define CAML_CUSTOM_H @@ -26,8 +28,8 @@ struct custom_operations { int (*compare)(value v1, value v2); intnat (*hash)(value v); void (*serialize)(value v, - /*out*/ uintnat * wsize_32 /*size in bytes*/, - /*out*/ uintnat * wsize_64 /*size in bytes*/); + /*out*/ uintnat * bsize_32 /*size in bytes*/, + /*out*/ uintnat * bsize_64 /*size in bytes*/); uintnat (*deserialize)(void * dst); int (*compare_ext)(value v1, value v2); }; diff --git a/byterun/caml/debugger.h b/byterun/caml/debugger.h index b5079eb3..00a97749 100644 --- a/byterun/caml/debugger.h +++ b/byterun/caml/debugger.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Interface with the debugger */ @@ -37,17 +39,17 @@ void caml_debugger_cleanup_fork (void); /* Requests from the debugger to the runtime system */ enum debugger_request { - REQ_SET_EVENT = 'e', /* uint32 pos */ + REQ_SET_EVENT = 'e', /* uint32_t pos */ /* Set an event on the instruction at position pos */ - REQ_SET_BREAKPOINT = 'B', /* uint32 pos, (char k) */ + REQ_SET_BREAKPOINT = 'B', /* uint32_t pos, (char k) */ /* Set a breakpoint at position pos */ /* In profiling mode, the breakpoint kind is set to k */ - REQ_RESET_INSTR = 'i', /* uint32 pos */ + REQ_RESET_INSTR = 'i', /* uint32_t pos */ /* Clear an event or breapoint at position pos, restores initial instr. */ REQ_CHECKPOINT = 'c', /* no args */ /* Checkpoint the runtime system by forking a child process. Reply is pid of child process or -1 if checkpoint failed. */ - REQ_GO = 'g', /* uint32 n */ + REQ_GO = 'g', /* uint32_t n */ /* Run the program for n events. Reply is one of debugger_reply described below. */ REQ_STOP = 's', /* no args */ @@ -59,38 +61,38 @@ enum debugger_request { Reply is stack offset and current pc. */ REQ_GET_FRAME = 'f', /* no args */ /* Return current frame location (stack offset + current pc). */ - REQ_SET_FRAME = 'S', /* uint32 stack_offset */ + REQ_SET_FRAME = 'S', /* uint32_t stack_offset */ /* Set current frame to given stack offset. No reply. */ - REQ_UP_FRAME = 'U', /* uint32 n */ + REQ_UP_FRAME = 'U', /* uint32_t n */ /* Move one frame up. Argument n is size of current frame (in words). Reply is stack offset and current pc, or -1 if top of stack reached. */ - REQ_SET_TRAP_BARRIER = 'b', /* uint32 offset */ + REQ_SET_TRAP_BARRIER = 'b', /* uint32_t offset */ /* Set the trap barrier at the given offset. */ - REQ_GET_LOCAL = 'L', /* uint32 slot_number */ + REQ_GET_LOCAL = 'L', /* uint32_t slot_number */ /* Return the local variable at the given slot in the current frame. Reply is one value. */ - REQ_GET_ENVIRONMENT = 'E', /* uint32 slot_number */ + REQ_GET_ENVIRONMENT = 'E', /* uint32_t slot_number */ /* Return the local variable at the given slot in the heap environment of the current frame. Reply is one value. */ - REQ_GET_GLOBAL = 'G', /* uint32 global_number */ + REQ_GET_GLOBAL = 'G', /* uint32_t global_number */ /* Return the specified global variable. Reply is one value. */ REQ_GET_ACCU = 'A', /* no args */ /* Return the current contents of the accumulator. Reply is one value. */ REQ_GET_HEADER = 'H', /* mlvalue v */ /* As REQ_GET_OBJ, but sends only the header. */ - REQ_GET_FIELD = 'F', /* mlvalue v, uint32 fieldnum */ + REQ_GET_FIELD = 'F', /* mlvalue v, uint32_t fieldnum */ /* As REQ_GET_OBJ, but sends only one field. */ REQ_MARSHAL_OBJ = 'M', /* mlvalue v */ /* Send a copy of the data structure rooted at v, using the same format as [caml_output_value]. */ REQ_GET_CLOSURE_CODE = 'C', /* mlvalue v */ /* Send the code address of the given closure. - Reply is one uint32. */ - REQ_SET_FORK_MODE = 'K' /* uint32 m */ + Reply is one uint32_t. */ + REQ_SET_FORK_MODE = 'K' /* uint32_t m */ /* Set whether to follow the child (m=0) or the parent on fork. */ }; -/* Replies to a REQ_GO request. All replies are followed by three uint32: +/* Replies to a REQ_GO request. All replies are followed by three uint32_t: - the value of the event counter - the position of the stack - the current pc. */ diff --git a/byterun/caml/dynlink.h b/byterun/caml/dynlink.h index 74cfdb66..3c5b9b73 100644 --- a/byterun/caml/dynlink.h +++ b/byterun/caml/dynlink.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ /* Dynamic loading of C primitives. */ diff --git a/byterun/caml/exec.h b/byterun/caml/exec.h index a58bcf8b..eee7596d 100644 --- a/byterun/caml/exec.h +++ b/byterun/caml/exec.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* exec.h : format of executable bytecode files */ @@ -39,13 +41,13 @@ struct section_descriptor { char name[4]; /* Section name */ - uint32 len; /* Length of data in bytes */ + uint32_t len; /* Length of data in bytes */ }; /* Structure of the trailer. */ struct exec_trailer { - uint32 num_sections; /* Number of sections */ + uint32_t num_sections; /* Number of sections */ char magic[12]; /* The magic number */ struct section_descriptor * section; /* Not part of file */ }; diff --git a/byterun/caml/fail.h b/byterun/caml/fail.h index da72c780..aa417b75 100644 --- a/byterun/caml/fail.h +++ b/byterun/caml/fail.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_FAIL_H #define CAML_FAIL_H @@ -60,22 +62,65 @@ int caml_is_special_exception(value exn); extern "C" { #endif -CAMLextern void caml_raise (value bucket) Noreturn; -CAMLextern void caml_raise_constant (value tag) Noreturn; -CAMLextern void caml_raise_with_arg (value tag, value arg) Noreturn; +CAMLnoreturn_start +CAMLextern void caml_raise (value bucket) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_constant (value tag) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_with_arg (value tag, value arg) +CAMLnoreturn_end; + +CAMLnoreturn_start CAMLextern void caml_raise_with_args (value tag, int nargs, value arg[]) - Noreturn; -CAMLextern void caml_raise_with_string (value tag, char const * msg) Noreturn; -CAMLextern void caml_failwith (char const *) Noreturn; -CAMLextern void caml_invalid_argument (char const *) Noreturn; -CAMLextern void caml_raise_out_of_memory (void) Noreturn; -CAMLextern void caml_raise_stack_overflow (void) Noreturn; -CAMLextern void caml_raise_sys_error (value) Noreturn; -CAMLextern void caml_raise_end_of_file (void) Noreturn; -CAMLextern void caml_raise_zero_divide (void) Noreturn; -CAMLextern void caml_raise_not_found (void) Noreturn; -CAMLextern void caml_array_bound_error (void) Noreturn; -CAMLextern void caml_raise_sys_blocked_io (void) Noreturn; +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_with_string (value tag, char const * msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_failwith (char const *) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_invalid_argument (char const *) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_out_of_memory (void) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_stack_overflow (void) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_sys_error (value) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_end_of_file (void) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_zero_divide (void) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_not_found (void) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_array_bound_error (void) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_raise_sys_blocked_io (void) +CAMLnoreturn_end; #ifdef __cplusplus } diff --git a/byterun/caml/finalise.h b/byterun/caml/finalise.h index 96853f52..9fbac826 100644 --- a/byterun/caml/finalise.h +++ b/byterun/caml/finalise.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_FINALISE_H #define CAML_FINALISE_H diff --git a/byterun/caml/fix_code.h b/byterun/caml/fix_code.h index 419ad327..9c39d481 100644 --- a/byterun/caml/fix_code.h +++ b/byterun/caml/fix_code.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Handling of blocks of bytecode (endianness switch, threading). */ @@ -25,7 +27,7 @@ extern code_t caml_start_code; extern asize_t caml_code_size; extern unsigned char * caml_saved_code; -void caml_init_code_fragments(); +void caml_init_code_fragments(void); void caml_load_code (int fd, asize_t len); void caml_fixup_endianness (code_t code, asize_t len); void caml_set_instruction (code_t pos, opcode_t instr); diff --git a/byterun/caml/freelist.h b/byterun/caml/freelist.h index 146961fa..f6c812ee 100644 --- a/byterun/caml/freelist.h +++ b/byterun/caml/freelist.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Free lists of heap blocks. */ @@ -20,14 +22,14 @@ #include "misc.h" #include "mlvalues.h" -extern asize_t caml_fl_cur_size; /* size in words */ +extern asize_t caml_fl_cur_wsz; -char *caml_fl_allocate (mlsize_t); +header_t *caml_fl_allocate (mlsize_t wo_sz); void caml_fl_init_merge (void); void caml_fl_reset (void); -char *caml_fl_merge_block (char *); -void caml_fl_add_blocks (char *); -void caml_make_free_blocks (value *, mlsize_t, int, int); +header_t *caml_fl_merge_block (value); +void caml_fl_add_blocks (value); +void caml_make_free_blocks (value *, mlsize_t wsz, int, int); void caml_set_allocation_policy (uintnat); diff --git a/byterun/caml/gc.h b/byterun/caml/gc.h index 3cbf08a2..a57a2bc2 100644 --- a/byterun/caml/gc.h +++ b/byterun/caml/gc.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_GC_H #define CAML_GC_H diff --git a/byterun/caml/gc_ctrl.h b/byterun/caml/gc_ctrl.h index de6933e8..924a1091 100644 --- a/byterun/caml/gc_ctrl.h +++ b/byterun/caml/gc_ctrl.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_GC_CTRL_H #define CAML_GC_CTRL_H @@ -24,15 +26,23 @@ extern double extern intnat caml_stat_minor_collections, caml_stat_major_collections, - caml_stat_heap_size, - caml_stat_top_heap_size, + caml_stat_heap_wsz, + caml_stat_top_heap_wsz, caml_stat_compactions, caml_stat_heap_chunks; uintnat caml_normalize_heap_increment (uintnat); -void caml_init_gc (uintnat, uintnat, uintnat, - uintnat, uintnat); +/* + minor_size: cf. minor_heap_size in gc.mli + major_size: Size in words of the initial major heap + major_incr: cf. major_heap_increment in gc.mli + percent_fr: cf. space_overhead in gc.mli + percent_m : cf. max_overhead in gc.mli + window : cf. window_size in gc.mli +*/ +void caml_init_gc (uintnat minor_size, uintnat major_size, uintnat major_incr, + uintnat percent_fr, uintnat percent_m, uintnat window); #ifdef DEBUG diff --git a/byterun/caml/globroots.h b/byterun/caml/globroots.h index 1c3ebab2..b580e6de 100644 --- a/byterun/caml/globroots.h +++ b/byterun/caml/globroots.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ /* Registration of global memory roots */ diff --git a/byterun/caml/hash.h b/byterun/caml/hash.h index 452a0925..fcc7589f 100644 --- a/byterun/caml/hash.h +++ b/byterun/caml/hash.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ -/* */ -/* Copyright 2011 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2011 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. */ +/* */ +/**************************************************************************/ /* Auxiliary functions for custom hash functions */ @@ -22,15 +24,16 @@ extern "C" { #endif -CAMLextern uint32 caml_hash_mix_uint32(uint32 h, uint32 d); -CAMLextern uint32 caml_hash_mix_intnat(uint32 h, intnat d); -CAMLextern uint32 caml_hash_mix_int64(uint32 h, int64 d); -CAMLextern uint32 caml_hash_mix_double(uint32 h, double d); -CAMLextern uint32 caml_hash_mix_float(uint32 h, float d); -CAMLextern uint32 caml_hash_mix_string(uint32 h, value s); +CAMLextern uint32_t caml_hash_mix_uint32(uint32_t h, uint32_t d); +CAMLextern uint32_t caml_hash_mix_intnat(uint32_t h, intnat d); +CAMLextern uint32_t caml_hash_mix_int64(uint32_t h, int64_t d); +CAMLextern uint32_t caml_hash_mix_double(uint32_t h, double d); +CAMLextern uint32_t caml_hash_mix_float(uint32_t h, float d); +CAMLextern uint32_t caml_hash_mix_string(uint32_t h, value s); #ifdef __cplusplus } #endif + #endif /* CAML_HASH_H */ diff --git a/byterun/caml/instrtrace.h b/byterun/caml/instrtrace.h index 30201608..9ff363fb 100644 --- a/byterun/caml/instrtrace.h +++ b/byterun/caml/instrtrace.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Trace the instructions executed */ @@ -20,7 +22,6 @@ #include "mlvalues.h" #include "misc.h" -extern int caml_trace_flag; extern intnat caml_icount; void caml_stop_here (void); void caml_disasm_instr (code_t pc); diff --git a/byterun/caml/instruct.h b/byterun/caml/instruct.h index f9cc80ee..94816bca 100644 --- a/byterun/caml/instruct.h +++ b/byterun/caml/instruct.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The instruction set. */ diff --git a/byterun/caml/int64_emul.h b/byterun/caml/int64_emul.h index ba7904a4..970bfe49 100644 --- a/byterun/caml/int64_emul.h +++ b/byterun/caml/int64_emul.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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. */ +/* */ +/**************************************************************************/ /* Software emulation of 64-bit integer arithmetic, for C compilers that do not support it. */ @@ -28,7 +30,7 @@ #define I64_split(x,hi,lo) (hi = (x).h, lo = (x).l) /* Unsigned comparison */ -static int I64_ucompare(uint64 x, uint64 y) +static int I64_ucompare(uint64_t x, uint64_t y) { if (x.h > y.h) return 1; if (x.h < y.h) return -1; @@ -40,19 +42,19 @@ static int I64_ucompare(uint64 x, uint64 y) #define I64_ult(x, y) (I64_ucompare(x, y) < 0) /* Signed comparison */ -static int I64_compare(int64 x, int64 y) +static int I64_compare(int64_t x, int64_t y) { - if ((int32)x.h > (int32)y.h) return 1; - if ((int32)x.h < (int32)y.h) return -1; + if ((int32_t)x.h > (int32_t)y.h) return 1; + if ((int32_t)x.h < (int32_t)y.h) return -1; if (x.l > y.l) return 1; if (x.l < y.l) return -1; return 0; } /* Negation */ -static int64 I64_neg(int64 x) +static int64_t I64_neg(int64_t x) { - int64 res; + int64_t res; res.l = -x.l; res.h = ~x.h; if (res.l == 0) res.h++; @@ -60,9 +62,9 @@ static int64 I64_neg(int64 x) } /* Addition */ -static int64 I64_add(int64 x, int64 y) +static int64_t I64_add(int64_t x, int64_t y) { - int64 res; + int64_t res; res.l = x.l + y.l; res.h = x.h + y.h; if (res.l < x.l) res.h++; @@ -70,9 +72,9 @@ static int64 I64_add(int64 x, int64 y) } /* Subtraction */ -static int64 I64_sub(int64 x, int64 y) +static int64_t I64_sub(int64_t x, int64_t y) { - int64 res; + int64_t res; res.l = x.l - y.l; res.h = x.h - y.h; if (x.l < y.l) res.h--; @@ -80,13 +82,13 @@ static int64 I64_sub(int64 x, int64 y) } /* Multiplication */ -static int64 I64_mul(int64 x, int64 y) +static int64_t I64_mul(int64_t x, int64_t y) { - int64 res; - uint32 prod00 = (x.l & 0xFFFF) * (y.l & 0xFFFF); - uint32 prod10 = (x.l >> 16) * (y.l & 0xFFFF); - uint32 prod01 = (x.l & 0xFFFF) * (y.l >> 16); - uint32 prod11 = (x.l >> 16) * (y.l >> 16); + int64_t res; + uint32_t prod00 = (x.l & 0xFFFF) * (y.l & 0xFFFF); + uint32_t prod10 = (x.l >> 16) * (y.l & 0xFFFF); + uint32_t prod01 = (x.l & 0xFFFF) * (y.l >> 16); + uint32_t prod11 = (x.l >> 16) * (y.l >> 16); res.l = prod00; res.h = prod11 + (prod01 >> 16) + (prod10 >> 16); prod01 = prod01 << 16; res.l += prod01; if (res.l < prod01) res.h++; @@ -96,39 +98,39 @@ static int64 I64_mul(int64 x, int64 y) } #define I64_is_zero(x) (((x).l | (x).h) == 0) -#define I64_is_negative(x) ((int32) (x).h < 0) +#define I64_is_negative(x) ((int32_t) (x).h < 0) #define I64_is_min_int(x) ((x).l == 0 && (x).h == 0x80000000U) #define I64_is_minus_one(x) (((x).l & (x).h) == 0xFFFFFFFFU) /* Bitwise operations */ -static int64 I64_and(int64 x, int64 y) +static int64_t I64_and(int64_t x, int64_t y) { - int64 res; + int64_t res; res.l = x.l & y.l; res.h = x.h & y.h; return res; } -static int64 I64_or(int64 x, int64 y) +static int64_t I64_or(int64_t x, int64_t y) { - int64 res; + int64_t res; res.l = x.l | y.l; res.h = x.h | y.h; return res; } -static int64 I64_xor(int64 x, int64 y) +static int64_t I64_xor(int64_t x, int64_t y) { - int64 res; + int64_t res; res.l = x.l ^ y.l; res.h = x.h ^ y.h; return res; } /* Shifts */ -static int64 I64_lsl(int64 x, int s) +static int64_t I64_lsl(int64_t x, int s) { - int64 res; + int64_t res; s = s & 63; if (s == 0) return x; if (s < 32) { @@ -141,9 +143,9 @@ static int64 I64_lsl(int64 x, int s) return res; } -static int64 I64_lsr(int64 x, int s) +static int64_t I64_lsr(int64_t x, int s) { - int64 res; + int64_t res; s = s & 63; if (s == 0) return x; if (s < 32) { @@ -156,17 +158,17 @@ static int64 I64_lsr(int64 x, int s) return res; } -static int64 I64_asr(int64 x, int s) +static int64_t I64_asr(int64_t x, int s) { - int64 res; + int64_t res; s = s & 63; if (s == 0) return x; if (s < 32) { res.l = (x.l >> s) | (x.h << (32 - s)); - res.h = (int32) x.h >> s; + res.h = (int32_t) x.h >> s; } else { - res.l = (int32) x.h >> (s - 32); - res.h = (int32) x.h >> 31; + res.l = (int32_t) x.h >> (s - 32); + res.h = (int32_t) x.h >> 31; } return res; } @@ -176,15 +178,15 @@ static int64 I64_asr(int64 x, int s) #define I64_SHL1(x) x.h = (x.h << 1) | (x.l >> 31); x.l <<= 1 #define I64_SHR1(x) x.l = (x.l >> 1) | (x.h << 31); x.h >>= 1 -static void I64_udivmod(uint64 modulus, uint64 divisor, - uint64 * quo, uint64 * mod) +static void I64_udivmod(uint64_t modulus, uint64_t divisor, + uint64_t * quo, uint64_t * mod) { - int64 quotient, mask; + int64_t quotient, mask; int cmp; quotient.h = 0; quotient.l = 0; mask.h = 0; mask.l = 1; - while ((int32) divisor.h >= 0) { + while ((int32_t) divisor.h >= 0) { cmp = I64_ucompare(divisor, modulus); I64_SHL1(divisor); I64_SHL1(mask); @@ -202,27 +204,27 @@ static void I64_udivmod(uint64 modulus, uint64 divisor, *mod = modulus; } -static int64 I64_div(int64 x, int64 y) +static int64_t I64_div(int64_t x, int64_t y) { - int64 q, r; - int32 sign; + int64_t q, r; + int32_t sign; sign = x.h ^ y.h; - if ((int32) x.h < 0) x = I64_neg(x); - if ((int32) y.h < 0) y = I64_neg(y); + if ((int32_t) x.h < 0) x = I64_neg(x); + if ((int32_t) y.h < 0) y = I64_neg(y); I64_udivmod(x, y, &q, &r); if (sign < 0) q = I64_neg(q); return q; } -static int64 I64_mod(int64 x, int64 y) +static int64_t I64_mod(int64_t x, int64_t y) { - int64 q, r; - int32 sign; + int64_t q, r; + int32_t sign; sign = x.h; - if ((int32) x.h < 0) x = I64_neg(x); - if ((int32) y.h < 0) y = I64_neg(y); + if ((int32_t) x.h < 0) x = I64_neg(x); + if ((int32_t) y.h < 0) y = I64_neg(y); I64_udivmod(x, y, &q, &r); if (sign < 0) r = I64_neg(r); return r; @@ -230,49 +232,49 @@ static int64 I64_mod(int64 x, int64 y) /* Coercions */ -static int64 I64_of_int32(int32 x) +static int64_t I64_of_int32(int32_t x) { - int64 res; + int64_t res; res.l = x; res.h = x >> 31; return res; } -#define I64_to_int32(x) ((int32) (x).l) +#define I64_to_int32(x) ((int32_t) (x).l) /* Note: we assume sizeof(intnat) = 4 here, which is true otherwise autoconfiguration would have selected native 64-bit integers */ #define I64_of_intnat I64_of_int32 #define I64_to_intnat I64_to_int32 -static double I64_to_double(int64 x) +static double I64_to_double(int64_t x) { double res; - int32 sign = x.h; + int32_t sign = x.h; if (sign < 0) x = I64_neg(x); res = ldexp((double) x.h, 32) + x.l; if (sign < 0) res = -res; return res; } -static int64 I64_of_double(double f) +static int64_t I64_of_double(double f) { - int64 res; + int64_t res; double frac, integ; int neg; neg = (f < 0); f = fabs(f); frac = modf(ldexp(f, -32), &integ); - res.h = (uint32) integ; - res.l = (uint32) ldexp(frac, 32); + res.h = (uint32_t) integ; + res.l = (uint32_t) ldexp(frac, 32); if (neg) res = I64_neg(res); return res; } -static int64 I64_bswap(int64 x) +static int64_t I64_bswap(int64_t x) { - int64 res; + int64_t res; res.h = (((x.l & 0x000000FF) << 24) | ((x.l & 0x0000FF00) << 8) | ((x.l & 0x00FF0000) >> 8) | diff --git a/byterun/caml/int64_format.h b/byterun/caml/int64_format.h index b0de5272..e1570e37 100644 --- a/byterun/caml/int64_format.h +++ b/byterun/caml/int64_format.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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. */ +/* */ +/**************************************************************************/ /* printf-like formatting of 64-bit integers, in case the C library printf() function does not support them. */ @@ -17,7 +19,7 @@ #ifndef CAML_INT64_FORMAT_H #define CAML_INT64_FORMAT_H -static void I64_format(char * buffer, char * fmt, int64 x) +static void I64_format(char * buffer, char * fmt, int64_t x) { static char conv_lower[] = "0123456789abcdef"; static char conv_upper[] = "0123456789ABCDEF"; @@ -26,7 +28,7 @@ static void I64_format(char * buffer, char * fmt, int64 x) int base, width, sign, i, rawlen; char * cvtbl; char * p, * r; - int64 wbase, digit; + int64_t wbase, digit; /* Parsing of format */ justify = '+'; diff --git a/byterun/caml/int64_native.h b/byterun/caml/int64_native.h index e9ffe674..269811c5 100644 --- a/byterun/caml/int64_native.h +++ b/byterun/caml/int64_native.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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. */ +/* */ +/**************************************************************************/ /* Wrapper macros around native 64-bit integer arithmetic, so that it has the same interface as the software emulation @@ -18,36 +20,36 @@ #ifndef CAML_INT64_NATIVE_H #define CAML_INT64_NATIVE_H -#define I64_literal(hi,lo) ((int64)(hi) << 32 | (lo)) -#define I64_split(x,hi,lo) (hi = (uint32)((x)>>32), lo = (uint32)(x)) +#define I64_literal(hi,lo) ((int64_t)(hi) << 32 | (lo)) +#define I64_split(x,hi,lo) (hi = (uint32_t)((x)>>32), lo = (uint32_t)(x)) #define I64_compare(x,y) (((x) > (y)) - ((x) < (y))) -#define I64_ult(x,y) ((uint64)(x) < (uint64)(y)) +#define I64_ult(x,y) ((uint64_t)(x) < (uint64_t)(y)) #define I64_neg(x) (-(x)) #define I64_add(x,y) ((x) + (y)) #define I64_sub(x,y) ((x) - (y)) #define I64_mul(x,y) ((x) * (y)) #define I64_is_zero(x) ((x) == 0) #define I64_is_negative(x) ((x) < 0) -#define I64_is_min_int(x) ((x) == ((int64)1 << 63)) +#define I64_is_min_int(x) ((x) == ((int64_t)1 << 63)) #define I64_is_minus_one(x) ((x) == -1) #define I64_div(x,y) ((x) / (y)) #define I64_mod(x,y) ((x) % (y)) #define I64_udivmod(x,y,quo,rem) \ - (*(rem) = (uint64)(x) % (uint64)(y), \ - *(quo) = (uint64)(x) / (uint64)(y)) + (*(rem) = (uint64_t)(x) % (uint64_t)(y), \ + *(quo) = (uint64_t)(x) / (uint64_t)(y)) #define I64_and(x,y) ((x) & (y)) #define I64_or(x,y) ((x) | (y)) #define I64_xor(x,y) ((x) ^ (y)) #define I64_lsl(x,y) ((x) << (y)) #define I64_asr(x,y) ((x) >> (y)) -#define I64_lsr(x,y) ((uint64)(x) >> (y)) +#define I64_lsr(x,y) ((uint64_t)(x) >> (y)) #define I64_to_intnat(x) ((intnat) (x)) #define I64_of_intnat(x) ((intnat) (x)) -#define I64_to_int32(x) ((int32) (x)) -#define I64_of_int32(x) ((int64) (x)) +#define I64_to_int32(x) ((int32_t) (x)) +#define I64_of_int32(x) ((int64_t) (x)) #define I64_to_double(x) ((double)(x)) -#define I64_of_double(x) ((int64)(x)) +#define I64_of_double(x) ((int64_t)(x)) #define I64_bswap(x) ((((x) & 0x00000000000000FFULL) << 56) | \ (((x) & 0x000000000000FF00ULL) << 40) | \ diff --git a/byterun/caml/interp.h b/byterun/caml/interp.h index c8e2f89f..120c2d95 100644 --- a/byterun/caml/interp.h +++ b/byterun/caml/interp.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The bytecode interpreter */ diff --git a/byterun/caml/intext.h b/byterun/caml/intext.h index f7aa655c..3deaf3a0 100644 --- a/byterun/caml/intext.h +++ b/byterun/caml/intext.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Structured input/output */ @@ -27,7 +29,25 @@ /* Magic number */ -#define Intext_magic_number 0x8495A6BE +#define Intext_magic_number_small 0x8495A6BE +#define Intext_magic_number_big 0x8495A6BF + +/* Header format for the "small" model: 20 bytes + 0 "small" magic number + 4 length of marshaled data, in bytes + 8 number of shared blocks + 12 size in words when read on a 32-bit platform + 16 size in words when read on a 64-bit platform + The 4 numbers are 32 bits each, in big endian. + + Header format for the "big" model: 32 bytes + 0 "big" magic number + 4 four reserved bytes, currently set to 0 + 8 length of marshaled data, in bytes + 16 number of shared blocks + 24 size in words when read on a 64-bit platform + The 3 numbers are 64 bits each, in big endian. +*/ /* Codes for the compact format */ @@ -41,16 +61,20 @@ #define CODE_SHARED8 0x4 #define CODE_SHARED16 0x5 #define CODE_SHARED32 0x6 +#define CODE_SHARED64 0x14 #define CODE_BLOCK32 0x8 #define CODE_BLOCK64 0x13 #define CODE_STRING8 0x9 #define CODE_STRING32 0xA +#define CODE_STRING64 0x15 #define CODE_DOUBLE_BIG 0xB #define CODE_DOUBLE_LITTLE 0xC #define CODE_DOUBLE_ARRAY8_BIG 0xD #define CODE_DOUBLE_ARRAY8_LITTLE 0xE #define CODE_DOUBLE_ARRAY32_BIG 0xF #define CODE_DOUBLE_ARRAY32_LITTLE 0x7 +#define CODE_DOUBLE_ARRAY64_BIG 0x16 +#define CODE_DOUBLE_ARRAY64_LITTLE 0x17 #define CODE_CODEPOINTER 0x10 #define CODE_INFIXPOINTER 0x11 #define CODE_CUSTOM 0x12 @@ -59,10 +83,12 @@ #define CODE_DOUBLE_NATIVE CODE_DOUBLE_BIG #define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_BIG #define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_BIG +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_BIG #else #define CODE_DOUBLE_NATIVE CODE_DOUBLE_LITTLE #define CODE_DOUBLE_ARRAY8_NATIVE CODE_DOUBLE_ARRAY8_LITTLE #define CODE_DOUBLE_ARRAY32_NATIVE CODE_DOUBLE_ARRAY32_LITTLE +#define CODE_DOUBLE_ARRAY64_NATIVE CODE_DOUBLE_ARRAY64_LITTLE #endif /* Size-ing data structures for extern. Chosen so that @@ -119,8 +145,8 @@ CAMLextern value caml_input_value_from_block(char * data, intnat len); CAMLextern void caml_serialize_int_1(int i); CAMLextern void caml_serialize_int_2(int i); -CAMLextern void caml_serialize_int_4(int32 i); -CAMLextern void caml_serialize_int_8(int64 i); +CAMLextern void caml_serialize_int_4(int32_t i); +CAMLextern void caml_serialize_int_8(int64_t i); CAMLextern void caml_serialize_float_4(float f); CAMLextern void caml_serialize_float_8(double f); CAMLextern void caml_serialize_block_1(void * data, intnat len); @@ -133,10 +159,10 @@ CAMLextern int caml_deserialize_uint_1(void); CAMLextern int caml_deserialize_sint_1(void); CAMLextern int caml_deserialize_uint_2(void); CAMLextern int caml_deserialize_sint_2(void); -CAMLextern uint32 caml_deserialize_uint_4(void); -CAMLextern int32 caml_deserialize_sint_4(void); -CAMLextern uint64 caml_deserialize_uint_8(void); -CAMLextern int64 caml_deserialize_sint_8(void); +CAMLextern uint32_t caml_deserialize_uint_4(void); +CAMLextern int32_t caml_deserialize_sint_4(void); +CAMLextern uint64_t caml_deserialize_uint_8(void); +CAMLextern int64_t caml_deserialize_sint_8(void); CAMLextern float caml_deserialize_float_4(void); CAMLextern double caml_deserialize_float_8(void); CAMLextern void caml_deserialize_block_1(void * data, intnat len); diff --git a/byterun/caml/io.h b/byterun/caml/io.h index 64a8bf50..e17b3e9a 100644 --- a/byterun/caml/io.h +++ b/byterun/caml/io.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Buffered input/output */ @@ -45,6 +47,7 @@ struct channel { int refcount; /* For flush_all and for Cash */ int flags; /* Bitfield */ char buff[IO_BUFFER_SIZE]; /* The buffer itself */ + char * name; /* Optional name (to report fd leaks) */ }; enum { @@ -78,12 +81,12 @@ CAMLextern value caml_alloc_channel(struct channel *chan); CAMLextern int caml_flush_partial (struct channel *); CAMLextern void caml_flush (struct channel *); -CAMLextern void caml_putword (struct channel *, uint32); +CAMLextern void caml_putword (struct channel *, uint32_t); CAMLextern int caml_putblock (struct channel *, char *, intnat); CAMLextern void caml_really_putblock (struct channel *, char *, intnat); CAMLextern unsigned char caml_refill (struct channel *); -CAMLextern uint32 caml_getword (struct channel *); +CAMLextern uint32_t caml_getword (struct channel *); CAMLextern int caml_getblock (struct channel *, char *, intnat); CAMLextern int caml_really_getblock (struct channel *, char *, intnat); @@ -107,7 +110,7 @@ CAMLextern struct channel * caml_all_opened_channels; #define Unlock_exn() \ if (caml_channel_mutex_unlock_exn != NULL) (*caml_channel_mutex_unlock_exn)() -/* Conversion between file_offset and int64 */ +/* Conversion between file_offset and int64_t */ #define Val_file_offset(fofs) caml_copy_int64(fofs) #define File_offset_val(v) ((file_offset) Int64_val(v)) diff --git a/byterun/caml/major_gc.h b/byterun/caml/major_gc.h index f473df94..15d46e48 100644 --- a/byterun/caml/major_gc.h +++ b/byterun/caml/major_gc.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_MAJOR_GC_H #define CAML_MAJOR_GC_H @@ -19,7 +21,7 @@ #include "misc.h" typedef struct { - void *block; /* address of the malloced block this chunk live in */ + void *block; /* address of the malloced block this chunk lives in */ asize_t alloc; /* in bytes, used for compaction */ asize_t size; /* in bytes */ char *next; @@ -35,26 +37,44 @@ extern int caml_gc_subphase; extern uintnat caml_allocated_words; extern double caml_extra_heap_resources; extern uintnat caml_dependent_size, caml_dependent_allocated; -extern uintnat caml_fl_size_at_phase_change; +extern uintnat caml_fl_wsz_at_phase_change; #define Phase_mark 0 -#define Phase_sweep 1 -#define Phase_idle 2 -#define Subphase_main 10 -#define Subphase_weak1 11 -#define Subphase_weak2 12 -#define Subphase_final 13 +#define Phase_clean 1 +#define Phase_sweep 2 +#define Phase_idle 3 + +/* Subphase of mark */ +#define Subphase_mark_roots 10 +/* Subphase_mark_roots: At the end of this subphase all the global + roots are marked. */ +#define Subphase_mark_main 11 +/* Subphase_mark_main: At the end of this subphase all the value alive at + the start of this subphase and created during it are marked. */ +#define Subphase_mark_final 12 +/* Subphase_mark_final: At the start of this subphase register which + value with an ocaml finalizer are not marked, the associated + finalizer will be run later. So we mark now these value as alive, + since they must be available for their finalizer. + */ CAMLextern char *caml_heap_start; extern uintnat total_heap_size; extern char *caml_gc_sweep_hp; +extern int caml_major_window; +double caml_major_ring[Max_major_window]; +int caml_major_ring_index; +double caml_major_work_credit; +extern double caml_gc_clock; + void caml_init_major_heap (asize_t); /* size in bytes */ -asize_t caml_round_heap_chunk_size (asize_t); /* size in bytes */ +asize_t caml_clip_heap_chunk_wsz (asize_t wsz); void caml_darken (value, value *); -intnat caml_major_collection_slice (intnat); +void caml_major_collection_slice (intnat); void major_collection (void); void caml_finish_major_cycle (void); +void caml_set_major_window (int); #endif /* CAML_MAJOR_GC_H */ diff --git a/byterun/caml/md5.h b/byterun/caml/md5.h index d8aff097..f88fa8bf 100644 --- a/byterun/caml/md5.h +++ b/byterun/caml/md5.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* 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 Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ /* MD5 message digest */ @@ -26,8 +28,8 @@ CAMLextern void caml_md5_block(unsigned char digest[16], void * data, uintnat len); struct MD5Context { - uint32 buf[4]; - uint32 bits[2]; + uint32_t buf[4]; + uint32_t bits[2]; unsigned char in[64]; }; @@ -35,7 +37,7 @@ CAMLextern void caml_MD5Init (struct MD5Context *context); CAMLextern void caml_MD5Update (struct MD5Context *context, unsigned char *buf, uintnat len); CAMLextern void caml_MD5Final (unsigned char *digest, struct MD5Context *ctx); -CAMLextern void caml_MD5Transform (uint32 *buf, uint32 *in); +CAMLextern void caml_MD5Transform (uint32_t *buf, uint32_t *in); #endif /* CAML_MD5_H */ diff --git a/byterun/caml/memory.h b/byterun/caml/memory.h index fe6d7823..9a1287c6 100644 --- a/byterun/caml/memory.h +++ b/byterun/caml/memory.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Allocation macros and functions */ @@ -33,25 +35,43 @@ extern "C" { #endif -CAMLextern value caml_alloc_shr (mlsize_t, tag_t); +CAMLextern value caml_alloc_shr (mlsize_t wosize, tag_t); +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); -CAMLextern void caml_free_dependent_memory (mlsize_t); +CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); +CAMLextern void caml_free_dependent_memory (mlsize_t bsz); CAMLextern void caml_modify (value *, value); CAMLextern void caml_initialize (value *, value); CAMLextern value caml_check_urgent_gc (value); CAMLextern void * caml_stat_alloc (asize_t); /* Size in bytes. */ CAMLextern void caml_stat_free (void *); CAMLextern void * caml_stat_resize (void *, asize_t); /* Size in bytes. */ -char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */ -void caml_free_for_heap (char *mem); -int caml_add_to_heap (char *mem); -color_t caml_allocation_color (void *hp); +CAMLextern int caml_init_alloc_for_heap (void); +CAMLextern char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */ +CAMLextern void caml_free_for_heap (char *mem); +CAMLextern int caml_add_to_heap (char *mem); +CAMLextern color_t caml_allocation_color (void *hp); + +CAMLextern int caml_huge_fallback_count; /* void caml_shrink_heap (char *); Only used in compact.c */ /* */ - + +extern uintnat caml_use_huge_pages; + +#ifdef HAS_HUGE_PAGES +#include +#define Heap_page_size HUGE_PAGE_SIZE +#define Round_mmap_size(x) \ + (((x) + (Heap_page_size - 1)) & ~ (Heap_page_size - 1)) +#endif + + +int caml_page_table_add(int kind, void * start, void * end); +int caml_page_table_remove(int kind, void * start, void * end); +int caml_page_table_initialize(mlsize_t bytesize); + #ifdef DEBUG #define DEBUG_clear(result, wosize) do{ \ uintnat caml__DEBUG_i; \ @@ -66,13 +86,14 @@ color_t caml_allocation_color (void *hp); #define Alloc_small(result, wosize, tag) do{ CAMLassert ((wosize) >= 1); \ CAMLassert ((tag_t) (tag) < 256); \ CAMLassert ((wosize) <= Max_young_wosize); \ - caml_young_ptr -= Bhsize_wosize (wosize); \ - if (caml_young_ptr < caml_young_start){ \ - caml_young_ptr += Bhsize_wosize (wosize); \ + caml_young_ptr -= Whsize_wosize (wosize); \ + if (caml_young_ptr < caml_young_trigger){ \ + caml_young_ptr += Whsize_wosize (wosize); \ + CAML_INSTR_INT ("force_minor/alloc_small@", 1); \ Setup_for_gc; \ - caml_minor_collection (); \ + caml_gc_dispatch (); \ Restore_after_gc; \ - caml_young_ptr -= Bhsize_wosize (wosize); \ + caml_young_ptr -= Whsize_wosize (wosize); \ } \ Hd_hp (caml_young_ptr) = Make_header ((wosize), (tag), Caml_black); \ (result) = Val_hp (caml_young_ptr); \ @@ -116,7 +137,9 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ Your function may raise an exception or return a [value] with the [CAMLreturn] macro. Its argument is simply the [value] returned by your function. Do NOT directly return a [value] with the [return] - keyword. If your function returns void, use [CAMLreturn0]. + keyword. If your function returns void, use [CAMLreturn0]. If you + un-register the local roots (i.e. undo the effects of the [CAMLparam*] + and [CAMLlocal] macros) without returning immediately, use [CAMLdrop]. All the identifiers beginning with "caml__" are reserved by OCaml. Do not use them for anything (local or global variables, struct or @@ -150,37 +173,54 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ CAMLparam0 (); \ CAMLxparamN (x, (size)) - +/* CAMLunused is preserved for compatibility reasons. + Instead of the legacy GCC/Clang-only + CAMLunused foo; + you should prefer + CAMLunused_start foo CAMLunused_end; + which supports both GCC/Clang and MSVC. +*/ #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7)) + #define CAMLunused_start __attribute__ ((unused)) + #define CAMLunused_end #define CAMLunused __attribute__ ((unused)) +#elif _MSC_VER >= 1500 + #define CAMLunused_start __pragma( warning (push) ) \ + __pragma( warning (disable:4189 ) ) + #define CAMLunused_end __pragma( warning (pop)) + #define CAMLunused #else + #define CAMLunused_start + #define CAMLunused_end #define CAMLunused #endif #define CAMLxparam1(x) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused int caml__dummy_##x = ( \ + CAMLunused_start int caml__dummy_##x = ( \ (caml__roots_##x.next = caml_local_roots), \ (caml_local_roots = &caml__roots_##x), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 1), \ (caml__roots_##x.tables [0] = &x), \ - 0) + 0) \ + CAMLunused_end #define CAMLxparam2(x, y) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused int caml__dummy_##x = ( \ + CAMLunused_start int caml__dummy_##x = ( \ (caml__roots_##x.next = caml_local_roots), \ (caml_local_roots = &caml__roots_##x), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 2), \ (caml__roots_##x.tables [0] = &x), \ (caml__roots_##x.tables [1] = &y), \ - 0) + 0) \ + CAMLunused_end #define CAMLxparam3(x, y, z) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused int caml__dummy_##x = ( \ + CAMLunused_start int caml__dummy_##x = ( \ (caml__roots_##x.next = caml_local_roots), \ (caml_local_roots = &caml__roots_##x), \ (caml__roots_##x.nitems = 1), \ @@ -188,11 +228,12 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ (caml__roots_##x.tables [0] = &x), \ (caml__roots_##x.tables [1] = &y), \ (caml__roots_##x.tables [2] = &z), \ - 0) + 0) \ + CAMLunused_end #define CAMLxparam4(x, y, z, t) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused int caml__dummy_##x = ( \ + CAMLunused_start int caml__dummy_##x = ( \ (caml__roots_##x.next = caml_local_roots), \ (caml_local_roots = &caml__roots_##x), \ (caml__roots_##x.nitems = 1), \ @@ -201,11 +242,12 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ (caml__roots_##x.tables [1] = &y), \ (caml__roots_##x.tables [2] = &z), \ (caml__roots_##x.tables [3] = &t), \ - 0) + 0) \ + CAMLunused_end #define CAMLxparam5(x, y, z, t, u) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused int caml__dummy_##x = ( \ + CAMLunused_start int caml__dummy_##x = ( \ (caml__roots_##x.next = caml_local_roots), \ (caml_local_roots = &caml__roots_##x), \ (caml__roots_##x.nitems = 1), \ @@ -215,17 +257,19 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ (caml__roots_##x.tables [2] = &z), \ (caml__roots_##x.tables [3] = &t), \ (caml__roots_##x.tables [4] = &u), \ - 0) + 0) \ + CAMLunused_end #define CAMLxparamN(x, size) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused int caml__dummy_##x = ( \ + CAMLunused_start int caml__dummy_##x = ( \ (caml__roots_##x.next = caml_local_roots), \ (caml_local_roots = &caml__roots_##x), \ (caml__roots_##x.nitems = (size)), \ (caml__roots_##x.ntables = 1), \ (caml__roots_##x.tables[0] = &(x[0])), \ - 0) + 0) \ + CAMLunused_end #define CAMLlocal1(x) \ value x = Val_unit; \ @@ -256,15 +300,17 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */ CAMLxparamN (x, (size)) +#define CAMLdrop caml_local_roots = caml__frame + #define CAMLreturn0 do{ \ - caml_local_roots = caml__frame; \ + CAMLdrop; \ return; \ }while (0) #define CAMLreturnT(type, result) do{ \ type caml__temp_result = (result); \ - caml_local_roots = caml__frame; \ - return (caml__temp_result); \ + CAMLdrop; \ + return caml__temp_result; \ }while(0) #define CAMLreturn(result) CAMLreturnT(value, result) diff --git a/byterun/caml/minor_gc.h b/byterun/caml/minor_gc.h index d3e8ac50..7e15e6e0 100644 --- a/byterun/caml/minor_gc.h +++ b/byterun/caml/minor_gc.h @@ -1,44 +1,74 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_MINOR_GC_H #define CAML_MINOR_GC_H #include "address_class.h" +#include "config.h" -CAMLextern char *caml_young_start, *caml_young_ptr; -CAMLextern char *caml_young_end, *caml_young_limit; -extern asize_t caml_minor_heap_size; +CAMLextern value *caml_young_start, *caml_young_end; +CAMLextern value *caml_young_alloc_start, *caml_young_alloc_end; +CAMLextern value *caml_young_ptr, *caml_young_limit; +CAMLextern value *caml_young_trigger; +extern asize_t caml_minor_heap_wsz; extern int caml_in_minor_collection; -struct caml_ref_table { - value **base; - value **end; - value **threshold; - value **ptr; - value **limit; - asize_t size; - asize_t reserve; +#define CAML_TABLE_STRUCT(t) { \ + t *base; \ + t *end; \ + t *threshold; \ + t *ptr; \ + t *limit; \ + asize_t size; \ + asize_t reserve; \ +} + +struct caml_ref_table CAML_TABLE_STRUCT(value *); +CAMLextern struct caml_ref_table caml_ref_table; + +struct caml_ephe_ref_elt { + value ephe; /* an ephemeron in major heap */ + mlsize_t offset; /* the offset that points in the minor heap */ +}; + +struct caml_ephe_ref_table CAML_TABLE_STRUCT(struct caml_ephe_ref_elt); +CAMLextern struct caml_ephe_ref_table caml_ephe_ref_table; + +struct caml_custom_elt { + value block; /* The finalized block in the minor heap. */ + mlsize_t mem; /* The parameters for adjusting GC speed. */ + mlsize_t max; }; -CAMLextern struct caml_ref_table caml_ref_table, caml_weak_ref_table; + +struct caml_custom_table CAML_TABLE_STRUCT(struct caml_custom_elt); +CAMLextern struct caml_custom_table caml_custom_table; extern void caml_set_minor_heap_size (asize_t); /* size in bytes */ extern void caml_empty_minor_heap (void); -CAMLextern void caml_minor_collection (void); -CAMLextern void garbage_collection (void); /* def in asmrun/signals.c */ +CAMLextern void caml_gc_dispatch (void); +CAMLextern void garbage_collection (void); /* def in asmrun/signals_asm.c */ extern void caml_realloc_ref_table (struct caml_ref_table *); extern void caml_alloc_table (struct caml_ref_table *, asize_t, asize_t); +extern void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *); +extern void caml_alloc_ephe_table (struct caml_ephe_ref_table *, + asize_t, asize_t); +extern void caml_realloc_custom_table (struct caml_custom_table *); +extern void caml_alloc_custom_table (struct caml_custom_table *, + asize_t, asize_t); extern void caml_oldify_one (value, value *); extern void caml_oldify_mopup (void); @@ -49,4 +79,41 @@ extern void caml_oldify_mopup (void); } \ }while(0) +static inline void add_to_ref_table (struct caml_ref_table *tbl, value *p) +{ + if (tbl->ptr >= tbl->limit){ + CAMLassert (tbl->ptr == tbl->limit); + caml_realloc_ref_table (tbl); + } + *tbl->ptr++ = p; +} + +static inline void add_to_ephe_ref_table (struct caml_ephe_ref_table *tbl, + value ar, mlsize_t offset) +{ + struct caml_ephe_ref_elt *ephe_ref; + if (tbl->ptr >= tbl->limit){ + CAMLassert (tbl->ptr == tbl->limit); + caml_realloc_ephe_ref_table (tbl); + } + ephe_ref = tbl->ptr++; + ephe_ref->ephe = ar; + ephe_ref->offset = offset; + Assert(ephe_ref->offset < Wosize_val(ephe_ref->ephe)); +} + +static inline void add_to_custom_table (struct caml_custom_table *tbl, value v, + mlsize_t mem, mlsize_t max) +{ + struct caml_custom_elt *elt; + if (tbl->ptr >= tbl->limit){ + CAMLassert (tbl->ptr == tbl->limit); + caml_realloc_custom_table (tbl); + } + elt = tbl->ptr++; + elt->block = v; + elt->mem = mem; + elt->max = max; +} + #endif /* CAML_MINOR_GC_H */ diff --git a/byterun/caml/misc.h b/byterun/caml/misc.h index 9319635f..ce3ce161 100644 --- a/byterun/caml/misc.h +++ b/byterun/caml/misc.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Miscellaneous macros and variables. */ @@ -38,13 +40,33 @@ typedef size_t asize_t; typedef char * addr; /* */ +/* Noreturn is preserved for compatibility reasons. + Instead of the legacy GCC/Clang-only + foo Noreturn; + you should prefer + CAMLnoreturn_start foo CAMLnoreturn_end; + which supports both GCC/Clang and MSVC. + + Note: CAMLnoreturn is a different macro defined in memory.h, + to be used in function bodies rather than aprototype attribute. +*/ #ifdef __GNUC__ /* Works only in GCC 2.5 and later */ + #define CAMLnoreturn_start + #define CAMLnoreturn_end __attribute__ ((noreturn)) #define Noreturn __attribute__ ((noreturn)) +#elif _MSC_VER >= 1500 + #define CAMLnoreturn_start __declspec(noreturn) + #define CAMLnoreturn_end + #define Noreturn #else + #define CAMLnoreturn_start + #define CAMLnoreturn_end #define Noreturn #endif + + /* Export control (to mark primitives and to handle Windows DLL) */ #define CAMLexport @@ -77,15 +99,25 @@ extern caml_timing_hook caml_finalise_begin_hook, caml_finalise_end_hook; #ifdef DEBUG #define CAMLassert(x) \ ((x) ? (void) 0 : caml_failed_assert ( #x , __FILE__, __LINE__)) -CAMLextern int caml_failed_assert (char *, char *, int); +CAMLnoreturn_start +CAMLextern int caml_failed_assert (char *, char *, int) +CAMLnoreturn_end; #else #define CAMLassert(x) ((void) 0) #endif -CAMLextern void caml_fatal_error (char *msg) Noreturn; -CAMLextern void caml_fatal_error_arg (char *fmt, char *arg) Noreturn; +CAMLnoreturn_start +CAMLextern void caml_fatal_error (char *msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +CAMLextern void caml_fatal_error_arg (char *fmt, char *arg) +CAMLnoreturn_end; + +CAMLnoreturn_start CAMLextern void caml_fatal_error_arg2 (char *fmt1, char *arg1, - char *fmt2, char *arg2) Noreturn; + char *fmt2, char *arg2) +CAMLnoreturn_end; /* Safe string operations */ @@ -104,6 +136,7 @@ struct ext_table { extern void caml_ext_table_init(struct ext_table * tbl, int init_capa); extern int caml_ext_table_add(struct ext_table * tbl, void * data); +extern void caml_ext_table_remove(struct ext_table * tbl, void * data); extern void caml_ext_table_free(struct ext_table * tbl, int free_entries); /* GC flags and messages */ @@ -111,9 +144,13 @@ extern void caml_ext_table_free(struct ext_table * tbl, int free_entries); extern uintnat caml_verb_gc; void caml_gc_message (int, char *, uintnat); +/* Runtime warnings */ +extern uintnat caml_runtime_warnings; +int caml_runtime_warnings_active(void); + /* Memory routines */ -char *caml_aligned_malloc (asize_t, int, void **); +char *caml_aligned_malloc (asize_t bsize, int, void **); #ifdef DEBUG #ifdef ARCH_SIXTYFOUR @@ -148,7 +185,10 @@ char *caml_aligned_malloc (asize_t, int, void **); #define Debug_uninit_stat 0xD7 -extern void caml_set_fields (char *, unsigned long, unsigned long); +/* Note: the first argument is in fact a [value] but we don't have this + type available yet because we can't include [mlvalues.h] in this file. +*/ +extern void caml_set_fields (intnat v, unsigned long, unsigned long); #endif /* DEBUG */ @@ -158,11 +198,109 @@ extern void caml_set_fields (char *, unsigned long, unsigned long); /* snprintf emulation for Win32 */ -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_UCRT) extern int caml_snprintf(char * buf, size_t size, const char * format, ...); #define snprintf caml_snprintf #endif +#ifdef CAML_INSTR +/* Timers and counters for GC latency profiling (Linux-only) */ + +#include +#include + +extern intnat caml_stat_minor_collections; +extern intnat CAML_INSTR_STARTTIME, CAML_INSTR_STOPTIME; + +struct CAML_INSTR_BLOCK { + struct timespec ts[10]; + char *tag[10]; + int index; + struct CAML_INSTR_BLOCK *next; +}; + +extern struct CAML_INSTR_BLOCK *CAML_INSTR_LOG; + +/* Declare a timer/counter name. [t] must be a new variable name. */ +#define CAML_INSTR_DECLARE(t) \ + struct CAML_INSTR_BLOCK *t = NULL + +/* Allocate the data block for a given name. + [t] must have been declared with [CAML_INSTR_DECLARE]. */ +#define CAML_INSTR_ALLOC(t) do{ \ + if (caml_stat_minor_collections >= CAML_INSTR_STARTTIME \ + && caml_stat_minor_collections < CAML_INSTR_STOPTIME){ \ + t = malloc (sizeof (struct CAML_INSTR_BLOCK)); \ + t->index = 0; \ + t->tag[0] = ""; \ + t->next = CAML_INSTR_LOG; \ + CAML_INSTR_LOG = t; \ + } \ + }while(0) + +/* Allocate the data block and start the timer. + [t] must have been declared with [CAML_INSTR_DECLARE] + and allocated with [CAML_INSTR_ALLOC]. */ +#define CAML_INSTR_START(t, msg) do{ \ + if (t != NULL){ \ + t->tag[0] = msg; \ + clock_gettime (CLOCK_REALTIME, &(t->ts[0])); \ + } \ + }while(0) + +/* Declare a timer, allocate its data, and start it. + [t] must be a new variable name. */ +#define CAML_INSTR_SETUP(t, msg) \ + CAML_INSTR_DECLARE (t); \ + CAML_INSTR_ALLOC (t); \ + CAML_INSTR_START (t, msg) + +/* Record an intermediate time within a given timer. + [t] must have been declared, allocated, and started. */ +#define CAML_INSTR_TIME(t, msg) do{ \ + if (t != NULL){ \ + ++ t->index; \ + t->tag[t->index] = (msg); \ + clock_gettime (CLOCK_REALTIME, &(t->ts[t->index])); \ + } \ + }while(0) + +/* Record an integer data point. + If [msg] ends with # it will be interpreted as an integer-valued event. + If it ends with @ it will be interpreted as an event counter. +*/ +#define CAML_INSTR_INT(msg, data) do{ \ + CAML_INSTR_SETUP (__caml_tmp, ""); \ + if (__caml_tmp != NULL){ \ + __caml_tmp->index = 1; \ + __caml_tmp->tag[1] = msg; \ + __caml_tmp->ts[1].tv_sec = 0; \ + __caml_tmp->ts[1].tv_nsec = (data); \ + } \ + }while(0) + +/* This function is called at the start of the program to set up + the data for the above macros. +*/ +extern void CAML_INSTR_INIT (void); + +/* This function is automatically called by the runtime to output + the collected data to the dump file. */ +extern void CAML_INSTR_ATEXIT (void); + +#else /* CAML_INSTR */ + +#define CAML_INSTR_DECLARE(t) /**/ +#define CAML_INSTR_ALLOC(t) /**/ +#define CAML_INSTR_START(t, name) /**/ +#define CAML_INSTR_SETUP(t, name) /**/ +#define CAML_INSTR_TIME(t, msg) /**/ +#define CAML_INSTR_INT(msg, c) /**/ +#define CAML_INSTR_INIT() /**/ +#define CAML_INSTR_ATEXIT() /**/ + +#endif /* CAML_INSTR */ + /* */ #ifdef __cplusplus diff --git a/byterun/caml/mlvalues.h b/byterun/caml/mlvalues.h index fe4a8f09..05791433 100644 --- a/byterun/caml/mlvalues.h +++ b/byterun/caml/mlvalues.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_MLVALUES_H #define CAML_MLVALUES_H @@ -38,8 +40,8 @@ extern "C" { bp: Pointer to the first byte of a block. (a char *) op: Pointer to the first field of a block. (a value *) hp: Pointer to the header of a block. (a char *) - int32: Four bytes on all architectures. - int64: Eight bytes on all architectures. + int32_t: Four bytes on all architectures. + int64_t: Eight bytes on all architectures. Remark: A block size is always a multiple of the word size, and at least one word plus the header. @@ -68,7 +70,7 @@ typedef uintnat mark_t; /* Conversion macro names are always of the form "to_from". */ /* Example: Val_long as in "Val from long" or "Val of long". */ -#define Val_long(x) (((intnat)(x) << 1) + 1) +#define Val_long(x) ((intnat) (((uintnat)(x) << 1)) + 1) #define Long_val(x) ((x) >> 1) #define Max_long (((intnat)1 << (8 * sizeof(value) - 2)) - 1) #define Min_long (-((intnat)1 << (8 * sizeof(value) - 2))) @@ -101,7 +103,7 @@ bits 63 10 9 8 7 0 #define Hd_op(op) (Hd_val (op)) /* Also an l-value. */ #define Hd_bp(bp) (Hd_val (bp)) /* Also an l-value. */ #define Hd_hp(hp) (* ((header_t *) (hp))) /* Also an l-value. */ -#define Hp_val(val) ((char *) (((header_t *) (val)) - 1)) +#define Hp_val(val) (((header_t *) (val)) - 1) #define Hp_op(op) (Hp_val (op)) #define Hp_bp(bp) (Hp_val (bp)) #define Val_op(op) ((value) (op)) @@ -161,7 +163,7 @@ bits 63 10 9 8 7 0 /* Fields are numbered from 0. */ #define Field(x, i) (((value *)(x)) [i]) /* Also an l-value. */ -typedef int32 opcode_t; +typedef int32_t opcode_t; typedef opcode_t * code_t; /* NOTE: [Forward_tag] and [Infix_tag] must be just under @@ -217,7 +219,8 @@ CAMLextern value caml_hash_variant(char const * tag); #define Byte_u(x, i) (((unsigned char *) (x)) [i]) /* Also an l-value. */ /* Abstract things. Their contents is not traced by the GC; therefore they - must not contain any [value]. + must not contain any [value]. Must have odd number so that headers with + this tag cannot be mistaken for pointers (see caml_obj_truncate). */ #define Abstract_tag 251 @@ -225,6 +228,8 @@ CAMLextern value caml_hash_variant(char const * tag); #define String_tag 252 #define String_val(x) ((char *) Bp_val(x)) CAMLextern mlsize_t caml_string_length (value); /* size in bytes */ +CAMLextern int caml_string_is_c_safe (value); + /* true if string contains no '\0' null characters */ /* Floating-point numbers. */ #define Double_tag 253 @@ -262,12 +267,12 @@ struct custom_operations; /* defined in [custom.h] */ /* Int32.t, Int64.t and Nativeint.t are represented as custom blocks. */ -#define Int32_val(v) (*((int32 *) Data_custom_val(v))) +#define Int32_val(v) (*((int32_t *) Data_custom_val(v))) #define Nativeint_val(v) (*((intnat *) Data_custom_val(v))) #ifndef ARCH_ALIGN_INT64 -#define Int64_val(v) (*((int64 *) Data_custom_val(v))) +#define Int64_val(v) (*((int64_t *) Data_custom_val(v))) #else -CAMLextern int64 caml_Int64_val(value v); +CAMLextern int64_t caml_Int64_val(value v); #define Int64_val(v) caml_Int64_val(v) #endif diff --git a/byterun/caml/osdeps.h b/byterun/caml/osdeps.h index 8204205f..71c2197e 100644 --- a/byterun/caml/osdeps.h +++ b/byterun/caml/osdeps.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ /* Operating system - specific stuff */ @@ -18,6 +20,22 @@ #include "misc.h" +/* Read at most [n] bytes from file descriptor [fd] into buffer [buf]. + [flags] indicates whether [fd] is a socket + (bit [CHANNEL_FLAG_FROM_SOCKET] is set in this case, see [io.h]). + (This distinction matters for Win32, but not for Unix.) + Return number of bytes read. + In case of error, raises [Sys_error] or [Sys_blocked_io]. */ +extern int caml_read_fd(int fd, int flags, void * buf, int n); + +/* Write at most [n] bytes from buffer [buf] onto file descriptor [fd]. + [flags] indicates whether [fd] is a socket + (bit [CHANNEL_FLAG_FROM_SOCKET] is set in this case, see [io.h]). + (This distinction matters for Win32, but not for Unix.) + Return number of bytes written. + In case of error, raises [Sys_error] or [Sys_blocked_io]. */ +extern int caml_write_fd(int fd, int flags, void * buf, int n); + /* Decompose the given path into a list of directories, and add them to the given table. Return the block to be freed later. */ extern char * caml_decompose_path(struct ext_table * tbl, char * path); diff --git a/byterun/caml/prims.h b/byterun/caml/prims.h index 7a996781..5fdf29f2 100644 --- a/byterun/caml/prims.h +++ b/byterun/caml/prims.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Interface with C primitives. */ diff --git a/byterun/caml/printexc.h b/byterun/caml/printexc.h index 748faa9c..92c5af53 100644 --- a/byterun/caml/printexc.h +++ b/byterun/caml/printexc.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_PRINTEXC_H #define CAML_PRINTEXC_H @@ -24,7 +26,7 @@ extern "C" { CAMLextern char * caml_format_exception (value); -void caml_fatal_uncaught_exception (value) Noreturn; +CAMLnoreturn_start void caml_fatal_uncaught_exception (value) CAMLnoreturn_end; #ifdef __cplusplus } diff --git a/byterun/caml/reverse.h b/byterun/caml/reverse.h index 09d34a51..c1134356 100644 --- a/byterun/caml/reverse.h +++ b/byterun/caml/reverse.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Swap byte-order in 16, 32, and 64-bit integers or floats */ diff --git a/byterun/caml/roots.h b/byterun/caml/roots.h index ca6a5d26..f8440bec 100644 --- a/byterun/caml/roots.h +++ b/byterun/caml/roots.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_ROOTS_H #define CAML_ROOTS_H @@ -20,8 +22,10 @@ typedef void (*scanning_action) (value, value *); void caml_oldify_local_roots (void); -void caml_darken_all_roots (void); -void caml_do_roots (scanning_action); +void caml_darken_all_roots_start (void); +intnat caml_darken_all_roots_slice (intnat); +void caml_do_roots (scanning_action, int); +extern uintnat caml_incremental_roots_count; #ifndef NATIVE_CODE CAMLextern void caml_do_local_roots (scanning_action, value *, value *, struct caml__roots_block *); diff --git a/byterun/caml/signals.h b/byterun/caml/signals.h index 58451666..ce968251 100644 --- a/byterun/caml/signals.h +++ b/byterun/caml/signals.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_SIGNALS_H #define CAML_SIGNALS_H @@ -28,14 +30,16 @@ extern "C" { CAMLextern intnat volatile caml_signals_are_pending; CAMLextern intnat volatile caml_pending_signals[]; CAMLextern int volatile caml_something_to_do; -extern int volatile caml_force_major_slice; +extern int volatile caml_requested_major_slice; +extern int volatile caml_requested_minor_gc; /* */ CAMLextern void caml_enter_blocking_section (void); CAMLextern void caml_leave_blocking_section (void); /* */ -void caml_urge_major_slice (void); +void caml_request_major_slice (void); +void caml_request_minor_gc (void); CAMLextern int caml_convert_signal_number (int); CAMLextern int caml_rev_convert_signal_number (int); void caml_execute_signal(int signal_number, int in_signal_handler); diff --git a/byterun/caml/signals_machdep.h b/byterun/caml/signals_machdep.h index 4987e2f6..6dd2cbc0 100644 --- a/byterun/caml/signals_machdep.h +++ b/byterun/caml/signals_machdep.h @@ -1,22 +1,32 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Processor-specific operation: atomic "read and clear" */ #ifndef CAML_SIGNALS_MACHDEP_H #define CAML_SIGNALS_MACHDEP_H -#if defined(__GNUC__) && defined(__i386__) +#if defined(__GNUC__) && defined(__ATOMIC_SEQ_CST) \ + && defined(__GCC_ATOMIC_LONG_LOCK_FREE) + +/* Use the "atomic" builtins of GCC and Clang */ +#define Read_and_clear(dst,src) \ + ((dst) = __atomic_exchange_n(&(src), 0, __ATOMIC_SEQ_CST)) + +#elif defined(__GNUC__) && (defined(__i386__) || (defined(__x86_64__) \ + && defined(__ILP32__))) #define Read_and_clear(dst,src) \ asm("xorl %0, %0; xchgl %0, %1" \ diff --git a/byterun/caml/stacks.h b/byterun/caml/stacks.h index c596f255..9a0f634b 100644 --- a/byterun/caml/stacks.h +++ b/byterun/caml/stacks.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* structure of the stacks */ diff --git a/byterun/caml/startup.h b/byterun/caml/startup.h index 3dda64b3..2cf111a6 100644 --- a/byterun/caml/startup.h +++ b/byterun/caml/startup.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_STARTUP_H #define CAML_STARTUP_H @@ -30,9 +32,10 @@ enum { FILE_NOT_FOUND = -1, BAD_BYTECODE = -2 }; extern int caml_attempt_open(char **name, struct exec_trailer *trail, int do_open_script); extern void caml_read_section_descriptors(int fd, struct exec_trailer *trail); -extern int32 caml_seek_optional_section(int fd, struct exec_trailer *trail, +extern int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail, char *name); -extern int32 caml_seek_section(int fd, struct exec_trailer *trail, char *name); +extern int32_t caml_seek_section(int fd, struct exec_trailer *trail, + char *name); #endif /* CAML_STARTUP_H */ diff --git a/byterun/caml/startup_aux.h b/byterun/caml/startup_aux.h new file mode 100644 index 00000000..faa7b7ee --- /dev/null +++ b/byterun/caml/startup_aux.h @@ -0,0 +1,29 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, Jane Street Group, LLC */ +/* */ +/* Copyright 2015 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.h" + +extern void caml_init_atom_table (void); + +extern uintnat caml_init_percent_free; +extern uintnat caml_init_max_percent_free; +extern uintnat caml_init_minor_heap_wsz; +extern uintnat caml_init_heap_chunk_sz; +extern uintnat caml_init_heap_wsz; +extern uintnat caml_init_max_stack_wsz; +extern uintnat caml_init_major_window; +extern uintnat caml_trace_level; + +extern void caml_parse_ocamlrunparam (void); diff --git a/byterun/caml/sys.h b/byterun/caml/sys.h index 5eb18fc0..79ef3ddb 100644 --- a/byterun/caml/sys.h +++ b/byterun/caml/sys.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_SYS_H #define CAML_SYS_H diff --git a/byterun/caml/ui.h b/byterun/caml/ui.h index 29584650..9551ff48 100644 --- a/byterun/caml/ui.h +++ b/byterun/caml/ui.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Function declarations for non-Unix user interfaces */ diff --git a/byterun/caml/weak.h b/byterun/caml/weak.h index 0cf4b8b2..5cfc8133 100644 --- a/byterun/caml/weak.h +++ b/byterun/caml/weak.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 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. */ +/* */ +/**************************************************************************/ /* Operations on weak arrays */ @@ -18,7 +20,70 @@ #include "mlvalues.h" -extern value caml_weak_list_head; -extern value caml_weak_none; +extern value caml_ephe_list_head; +extern value caml_ephe_none; + + +/** The first field 0: weak list; + second field 1: data; + others 2..: keys; + + A weak pointer is an ephemeron with the data at caml_ephe_none + If fields are added, don't forget to update weak.ml [additional_values]. + */ + +#define CAML_EPHE_LINK_OFFSET 0 +#define CAML_EPHE_DATA_OFFSET 1 +#define CAML_EPHE_FIRST_KEY 2 + + +/* In the header, in order to let major_gc.c + and weak.c see the body of the function */ +static inline void caml_ephe_clean (value v){ + value child; + int release_data = 0; + mlsize_t size, i; + header_t hd; + Assert(caml_gc_phase == Phase_clean); + + hd = Hd_val (v); + size = Wosize_hd (hd); + for (i = 2; i < size; i++){ + child = Field (v, i); + ephemeron_again: + if (child != caml_ephe_none + && Is_block (child) && Is_in_heap_or_young (child)){ + if (Tag_val (child) == Forward_tag){ + value f = Forward_val (child); + if (Is_block (f)) { + if (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag){ + /* Do not short-circuit the pointer. */ + }else{ + Field (v, i) = child = f; + if (Is_block (f) && Is_young (f)) + add_to_ephe_ref_table(&caml_ephe_ref_table, v, i); + goto ephemeron_again; + } + } + } + if (Is_white_val (child) && !Is_young (child)){ + release_data = 1; + Field (v, i) = caml_ephe_none; + } + } + } + + child = Field (v, 1); + if(child != caml_ephe_none){ + if (release_data){ + Field (v, 1) = caml_ephe_none; + } else { + /* The mark phase must have marked it */ + Assert( !(Is_block (child) && Is_in_heap (child) + && Is_white_val (child)) ); + } + } +} #endif /* CAML_WEAK_H */ diff --git a/byterun/compact.c b/byterun/compact.c index 9af9688d..f9f604b2 100644 --- a/byterun/compact.c +++ b/byterun/compact.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 @@ -123,8 +125,8 @@ static void init_compact_allocate (void) compact_fl = caml_heap_start; } +/* [size] is a number of bytes and includes the header size */ static char *compact_allocate (mlsize_t size) - /* in bytes, including header */ { char *chunk, *adr; @@ -185,7 +187,7 @@ static void do_compaction (void) /* Invert roots first because the threads library needs some heap data structures to find its roots. Fortunately, it doesn't need the headers (see above). */ - caml_do_roots (invert_root); + caml_do_roots (invert_root, 1); caml_final_do_weak_roots (invert_root); ch = caml_heap_start; @@ -221,7 +223,7 @@ static void do_compaction (void) } /* Invert weak pointers. */ { - value *pp = &caml_weak_list_head; + value *pp = &caml_ephe_list_head; value p; word q; size_t sz, i; @@ -233,7 +235,7 @@ static void do_compaction (void) while (Ecolor (q) == 0) q = * (word *) q; sz = Wosize_ehd (q); for (i = 1; i < sz; i++){ - if (Field (p,i) != caml_weak_none){ + if (Field (p,i) != caml_ephe_none){ invert_pointer_at ((word *) &(Field (p,i))); } } @@ -397,9 +399,16 @@ uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */ void caml_compact_heap (void) { - uintnat target_words, target_size, live; + uintnat target_wsz, live; + CAML_INSTR_SETUP(tmr, "compact"); + + CAMLassert (caml_young_ptr == caml_young_alloc_end); + CAMLassert (caml_ref_table.ptr == caml_ref_table.base); + CAMLassert (caml_ephe_ref_table.ptr == caml_ephe_ref_table.base); + CAMLassert (caml_custom_table.ptr == caml_custom_table.base); do_compaction (); + CAML_INSTR_TIME (tmr, "compact/main"); /* Compaction may fail to shrink the heap to a reasonable size because it deals in complete chunks: if a very large chunk is at the beginning of the heap, everything gets moved to @@ -414,28 +423,36 @@ void caml_compact_heap (void) See PR#5389 */ /* We compute: - freewords = caml_fl_cur_size (exact) + freewords = caml_fl_cur_wsz (exact) heapwords = Wsize_bsize (caml_heap_size) (exact) live = heapwords - freewords wanted = caml_percent_free * (live / 100 + 1) (same as in do_compaction) - target_words = live + wanted + target_wsz = live + wanted We add one page to make sure a small difference in counting sizes won't make [do_compaction] keep the second block (and break all sorts of invariants). - We recompact if target_size < heap_size / 2 + We recompact if target_wsz < heap_size / 2 */ - live = Wsize_bsize (caml_stat_heap_size) - caml_fl_cur_size; - target_words = live + caml_percent_free * (live / 100 + 1) + live = caml_stat_heap_wsz - caml_fl_cur_wsz; + target_wsz = live + caml_percent_free * (live / 100 + 1) + Wsize_bsize (Page_size); - target_size = caml_round_heap_chunk_size (Bsize_wsize (target_words)); - if (target_size < caml_stat_heap_size / 2){ + target_wsz = caml_clip_heap_chunk_wsz (target_wsz); + +#ifdef HAS_HUGE_PAGES + if (caml_use_huge_pages + && Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE) + return; +#endif + + if (target_wsz < caml_stat_heap_wsz / 2){ + /* Recompact. */ char *chunk; - caml_gc_message (0x10, "Recompacting heap (target=%luk)\n", - target_size / 1024); + caml_gc_message (0x10, "Recompacting heap (target=%luk words)\n", + target_wsz / 1024); - chunk = caml_alloc_for_heap (target_size); + chunk = caml_alloc_for_heap (Bsize_wsize (target_wsz)); if (chunk == NULL) return; /* PR#5757: we need to make the new blocks blue, or they won't be recognized as free by the recompaction. */ @@ -448,24 +465,25 @@ void caml_compact_heap (void) Chunk_next (chunk) = caml_heap_start; caml_heap_start = chunk; ++ caml_stat_heap_chunks; - caml_stat_heap_size += Chunk_size (chunk); - if (caml_stat_heap_size > caml_stat_top_heap_size){ - caml_stat_top_heap_size = caml_stat_heap_size; + caml_stat_heap_wsz += Wsize_bsize (Chunk_size (chunk)); + if (caml_stat_heap_wsz > caml_stat_top_heap_wsz){ + caml_stat_top_heap_wsz = caml_stat_heap_wsz; } do_compaction (); Assert (caml_stat_heap_chunks == 1); Assert (Chunk_next (caml_heap_start) == NULL); - Assert (caml_stat_heap_size == Chunk_size (chunk)); + Assert (caml_stat_heap_wsz == Wsize_bsize (Chunk_size (chunk))); + CAML_INSTR_TIME (tmr, "compact/recompact"); } } void caml_compact_heap_maybe (void) { - /* Estimated free words in the heap: - FW = fl_size_at_change + 3 * (caml_fl_cur_size - - caml_fl_size_at_phase_change) - FW = 3 * caml_fl_cur_size - 2 * caml_fl_size_at_phase_change - Estimated live words: LW = caml_stat_heap_size - FW + /* Estimated free+garbage words in the heap: + FW = fl_size_at_phase_change + 3 * (caml_fl_cur_wsz + - caml_fl_wsz_at_phase_change) + FW = 3 * caml_fl_cur_wsz - 2 * caml_fl_wsz_at_phase_change + Estimated live words: LW = caml_stat_heap_wsz - FW Estimated free percentage: FP = 100 * FW / LW We compact the heap if FP > caml_percent_max */ @@ -473,29 +491,36 @@ void caml_compact_heap_maybe (void) Assert (caml_gc_phase == Phase_idle); if (caml_percent_max >= 1000000) return; if (caml_stat_major_collections < 3) return; + if (caml_stat_heap_wsz <= 2 * caml_clip_heap_chunk_wsz (0)) return; + +#ifdef HAS_HUGE_PAGES + if (caml_use_huge_pages + && Bsize_wsize (caml_stat_heap_wsz) <= HUGE_PAGE_SIZE) + return; +#endif - fw = 3.0 * caml_fl_cur_size - 2.0 * caml_fl_size_at_phase_change; - if (fw < 0) fw = caml_fl_cur_size; + fw = 3.0 * caml_fl_cur_wsz - 2.0 * caml_fl_wsz_at_phase_change; + if (fw < 0) fw = caml_fl_cur_wsz; - if (fw >= Wsize_bsize (caml_stat_heap_size)){ + if (fw >= caml_stat_heap_wsz){ fp = 1000000.0; }else{ - fp = 100.0 * fw / (Wsize_bsize (caml_stat_heap_size) - fw); + fp = 100.0 * fw / (caml_stat_heap_wsz - fw); if (fp > 1000000.0) fp = 1000000.0; } caml_gc_message (0x200, "FL size at phase change = %" - ARCH_INTNAT_PRINTF_FORMAT "u\n", - (uintnat) caml_fl_size_at_phase_change); + ARCH_INTNAT_PRINTF_FORMAT "u words\n", + (uintnat) caml_fl_wsz_at_phase_change); caml_gc_message (0x200, "Estimated overhead = %" ARCH_INTNAT_PRINTF_FORMAT "u%%\n", (uintnat) fp); if (fp >= caml_percent_max){ caml_gc_message (0x200, "Automatic compaction triggered.\n", 0); + caml_empty_minor_heap (); /* minor heap must be empty for compaction */ caml_finish_major_cycle (); - /* We just did a complete GC, so we can measure the overhead exactly. */ - fw = caml_fl_cur_size; - fp = 100.0 * fw / (Wsize_bsize (caml_stat_heap_size) - fw); + fw = caml_fl_cur_wsz; + fp = 100.0 * fw / (caml_stat_heap_wsz - fw); caml_gc_message (0x200, "Measured overhead: %" ARCH_INTNAT_PRINTF_FORMAT "u%%\n", (uintnat) fp); diff --git a/byterun/compare.c b/byterun/compare.c index 4e8d25af..42384a47 100644 --- a/byterun/compare.c +++ b/byterun/compare.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -205,11 +207,11 @@ static intnat compare_val(value v1, value v2, int total) } case Abstract_tag: compare_free_stack(); - caml_invalid_argument("equal: abstract value"); + caml_invalid_argument("compare: abstract value"); case Closure_tag: case Infix_tag: compare_free_stack(); - caml_invalid_argument("equal: functional value"); + caml_invalid_argument("compare: functional value"); case Object_tag: { intnat oid1 = Oid_val(v1); intnat oid2 = Oid_val(v2); @@ -227,7 +229,7 @@ static intnat compare_val(value v1, value v2, int total) } if (compare == NULL) { compare_free_stack(); - caml_invalid_argument("equal: abstract value"); + caml_invalid_argument("compare: abstract value"); } caml_compare_unordered = 0; res = compare(v1, v2); diff --git a/byterun/custom.c b/byterun/custom.c index eeb976d9..3875a4e5 100644 --- a/byterun/custom.c +++ b/byterun/custom.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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 @@ -19,6 +21,7 @@ #include "caml/memory.h" #include "caml/mlvalues.h" +/* [size] is a number of bytes */ CAMLexport value caml_alloc_custom(struct custom_operations * ops, uintnat size, mlsize_t mem, @@ -28,9 +31,13 @@ CAMLexport value caml_alloc_custom(struct custom_operations * ops, value result; wosize = 1 + (size + sizeof(value) - 1) / sizeof(value); - if (ops->finalize == NULL && wosize <= Max_young_wosize) { + if (wosize <= Max_young_wosize) { result = caml_alloc_small(wosize, Custom_tag); Custom_ops_val(result) = ops; + if (ops->finalize != NULL || mem != 0) { + /* Remember that the block needs processing after minor GC. */ + add_to_custom_table (&caml_custom_table, result, mem, max); + } } else { result = caml_alloc_shr(wosize, Custom_tag); Custom_ops_val(result) = ops; diff --git a/byterun/debugger.c b/byterun/debugger.c index 41a64b1c..5e61584b 100644 --- a/byterun/debugger.c +++ b/byterun/debugger.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Interface with the byte-code debugger */ @@ -27,7 +29,6 @@ int caml_debugger_in_use = 0; uintnat caml_event_count; int caml_debugger_fork_mode = 1; /* parent by default */ -value marshal_flags = Val_emptylist; #if !defined(HAS_SOCKETS) || defined(NATIVE_CODE) @@ -73,6 +74,8 @@ void caml_debugger_cleanup_fork(void) #include "caml/stacks.h" #include "caml/sys.h" +static value marshal_flags = Val_emptylist; + static int sock_domain; /* Socket domain for the debugger */ static union { /* Socket address for the debugger */ struct sockaddr s_gen; diff --git a/byterun/dynlink.c b/byterun/dynlink.c index 6d09a3c0..7142769c 100644 --- a/byterun/dynlink.c +++ b/byterun/dynlink.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ /* Dynamic loading of C primitives. */ @@ -192,7 +194,7 @@ void caml_build_primitive_table_builtin(void) caml_ext_table_add(&caml_prim_name_table, strdup(caml_names_of_builtin_cprim[i])); #endif -} + } } #endif /* NATIVE_CODE */ diff --git a/byterun/extern.c b/byterun/extern.c index 5965b8d5..221e206d 100644 --- a/byterun/extern.c +++ b/byterun/extern.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Structured output */ @@ -17,6 +19,7 @@ #include #include "caml/alloc.h" +#include "caml/config.h" #include "caml/custom.h" #include "caml/fail.h" #include "caml/gc.h" @@ -75,10 +78,22 @@ static struct extern_item * extern_stack_limit = extern_stack_init /* Forward declarations */ -static void extern_out_of_memory(void); -static void extern_invalid_argument(char *msg); -static void extern_failwith(char *msg); -static void extern_stack_overflow(void); +CAMLnoreturn_start +static void extern_out_of_memory(void) +CAMLnoreturn_end; + +CAMLnoreturn_start +static void extern_invalid_argument(char *msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +static void extern_failwith(char *msg) +CAMLnoreturn_end; + +CAMLnoreturn_start +static void extern_stack_overflow(void) +CAMLnoreturn_end; + static struct code_fragment * extern_find_code(char *addr); static void extern_replay_trail(void); static void free_extern_output(void); @@ -290,26 +305,47 @@ static void extern_stack_overflow(void) caml_raise_out_of_memory(); } +/* Conversion to big-endian */ + +static inline void store16(char * dst, int n) +{ + dst[0] = n >> 8; dst[1] = n; +} + +static inline void store32(char * dst, intnat n) +{ + dst[0] = n >> 24; dst[1] = n >> 16; dst[2] = n >> 8; dst[3] = n; +} + +static inline void store64(char * dst, int64_t n) +{ + dst[0] = n >> 56; dst[1] = n >> 48; dst[2] = n >> 40; dst[3] = n >> 32; + dst[4] = n >> 24; dst[5] = n >> 16; dst[6] = n >> 8; dst[7] = n; +} + /* Write characters, integers, and blocks in the output buffer */ -#define Write(c) \ - if (extern_ptr >= extern_limit) grow_extern_output(1); \ - *extern_ptr++ = (c) +static inline void write(int c) +{ + if (extern_ptr >= extern_limit) grow_extern_output(1); + *extern_ptr++ = c; +} -static void writeblock(char *data, intnat len) +static void writeblock(char * data, intnat len) { if (extern_ptr + len > extern_limit) grow_extern_output(len); - memmove(extern_ptr, data, len); + memcpy(extern_ptr, data, len); extern_ptr += len; } +static inline void writeblock_float8(double * data, intnat ndoubles) +{ #if ARCH_FLOAT_ENDIANNESS == 0x01234567 || ARCH_FLOAT_ENDIANNESS == 0x76543210 -#define writeblock_float8(data,ndoubles) \ - writeblock((char *)(data), (ndoubles) * 8) + writeblock((char *) data, ndoubles * 8); #else -#define writeblock_float8(data,ndoubles) \ - caml_serialize_block_float_8((data), (ndoubles)) + caml_serialize_block_float_8(data, ndoubles); #endif +} static void writecode8(int code, intnat val) { @@ -323,39 +359,25 @@ static void writecode16(int code, intnat val) { if (extern_ptr + 3 > extern_limit) grow_extern_output(3); extern_ptr[0] = code; - extern_ptr[1] = val >> 8; - extern_ptr[2] = val; + store16(extern_ptr + 1, val); extern_ptr += 3; } -static void write32(intnat val) -{ - if (extern_ptr + 4 > extern_limit) grow_extern_output(4); - extern_ptr[0] = val >> 24; - extern_ptr[1] = val >> 16; - extern_ptr[2] = val >> 8; - extern_ptr[3] = val; - extern_ptr += 4; -} - static void writecode32(int code, intnat val) { if (extern_ptr + 5 > extern_limit) grow_extern_output(5); extern_ptr[0] = code; - extern_ptr[1] = val >> 24; - extern_ptr[2] = val >> 16; - extern_ptr[3] = val >> 8; - extern_ptr[4] = val; + store32(extern_ptr + 1, val); extern_ptr += 5; } #ifdef ARCH_SIXTYFOUR static void writecode64(int code, intnat val) { - int i; if (extern_ptr + 9 > extern_limit) grow_extern_output(9); - *extern_ptr ++ = code; - for (i = 64 - 8; i >= 0; i -= 8) *extern_ptr++ = val >> i; + extern_ptr[0] = code; + store64(extern_ptr + 1, val); + extern_ptr += 9; } #endif @@ -371,7 +393,7 @@ static void extern_rec(value v) if (Is_long(v)) { intnat n = Long_val(v); if (n >= 0 && n < 0x40) { - Write(PREFIX_SMALL_INT + n); + write(PREFIX_SMALL_INT + n); } else if (n >= -(1 << 7) && n < (1 << 7)) { writecode8(CODE_INT8, n); } else if (n >= -(1 << 15) && n < (1 << 15)) { @@ -407,7 +429,7 @@ static void extern_rec(value v) in the externed block, and they are automatically shared. */ if (sz == 0) { if (tag < 16) { - Write(PREFIX_SMALL_BLOCK + tag); + write(PREFIX_SMALL_BLOCK + tag); } else { writecode32(CODE_BLOCK32, hd); } @@ -420,6 +442,10 @@ static void extern_rec(value v) writecode8(CODE_SHARED8, d); } else if (d < 0x10000) { writecode16(CODE_SHARED16, d); +#ifdef ARCH_SIXTYFOUR + } else if (d >= (uintnat)1 << 32) { + writecode64(CODE_SHARED64, d); +#endif } else { writecode32(CODE_SHARED32, d); } @@ -431,7 +457,7 @@ static void extern_rec(value v) case String_tag: { mlsize_t len = caml_string_length(v); if (len < 0x20) { - Write(PREFIX_SMALL_STRING + len); + write(PREFIX_SMALL_STRING + len); } else if (len < 0x100) { writecode8(CODE_STRING8, len); } else { @@ -439,8 +465,13 @@ static void extern_rec(value v) if (len > 0xFFFFFB && (extern_flags & COMPAT_32)) extern_failwith("output_value: string cannot be read back on " "32-bit platform"); -#endif + if (len < (uintnat)1 << 32) + writecode32(CODE_STRING32, len); + else + writecode64(CODE_STRING64, len); +#else writecode32(CODE_STRING32, len); +#endif } writeblock(String_val(v), len); size_32 += 1 + (len + 4) / 4; @@ -451,7 +482,7 @@ static void extern_rec(value v) case Double_tag: { if (sizeof(double) != 8) extern_invalid_argument("output_value: non-standard floats"); - Write(CODE_DOUBLE_NATIVE); + write(CODE_DOUBLE_NATIVE); writeblock_float8((double *) v, 1); size_32 += 1 + 2; size_64 += 1 + 1; @@ -470,8 +501,13 @@ static void extern_rec(value v) if (nfloats > 0x1FFFFF && (extern_flags & COMPAT_32)) extern_failwith("output_value: float array cannot be read back on " "32-bit platform"); -#endif + if (nfloats < (uintnat) 1 << 32) + writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); + else + writecode64(CODE_DOUBLE_ARRAY64_NATIVE, nfloats); +#else writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); +#endif } writeblock_float8((double *) v, nfloats); size_32 += 1 + nfloats * 2; @@ -489,12 +525,12 @@ static void extern_rec(value v) case Custom_tag: { uintnat sz_32, sz_64; char * ident = Custom_ops_val(v)->identifier; - void (*serialize)(value v, uintnat * wsize_32, - uintnat * wsize_64) + void (*serialize)(value v, uintnat * bsize_32, + uintnat * bsize_64) = Custom_ops_val(v)->serialize; if (serialize == NULL) extern_invalid_argument("output_value: abstract value (Custom)"); - Write(CODE_CUSTOM); + write(CODE_CUSTOM); writeblock(ident, strlen(ident) + 1); Custom_ops_val(v)->serialize(v, &sz_32, &sz_64); size_32 += 2 + ((sz_32 + 3) >> 2); /* header + ops + data */ @@ -505,19 +541,19 @@ static void extern_rec(value v) default: { value field0; if (tag < 16 && sz < 8) { - Write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); -#ifdef ARCH_SIXTYFOUR - } else if (hd >= ((uintnat)1 << 32)) { - /* Is this case useful? The overflow check in extern_value will fail.*/ - writecode64(CODE_BLOCK64, Whitehd_hd (hd)); -#endif + write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); } else { #ifdef ARCH_SIXTYFOUR if (sz > 0x3FFFFF && (extern_flags & COMPAT_32)) extern_failwith("output_value: array cannot be read back on " "32-bit platform"); -#endif + if (hd < (uintnat)1 << 32) + writecode32(CODE_BLOCK32, Whitehd_hd (hd)); + else + writecode64(CODE_BLOCK64, Whitehd_hd (hd)); +#else writecode32(CODE_BLOCK32, Whitehd_hd (hd)); +#endif } size_32 += 1 + sz; size_64 += 1 + sz; @@ -559,7 +595,9 @@ static void extern_rec(value v) static int extern_flag_values[] = { NO_SHARING, CLOSURES, COMPAT_32 }; -static intnat extern_value(value v, value flags) +static intnat extern_value(value v, value flags, + /*out*/ char header[32], + /*out*/ int * header_len) { intnat res_len; /* Parse flag list */ @@ -569,53 +607,58 @@ static intnat extern_value(value v, value flags) obj_counter = 0; size_32 = 0; size_64 = 0; - /* Write magic number */ - write32(Intext_magic_number); - /* Set aside space for the sizes */ - extern_ptr += 4*4; /* Marshal the object */ extern_rec(v); /* Record end of output */ close_extern_output(); /* Undo the modifications done on externed blocks */ extern_replay_trail(); - /* Write the sizes */ + /* Write the header */ res_len = extern_output_length(); #ifdef ARCH_SIXTYFOUR if (res_len >= ((intnat)1 << 32) || size_32 >= ((intnat)1 << 32) || size_64 >= ((intnat)1 << 32)) { - /* The object is so big its size cannot be written in the header. - Besides, some of the array lengths or string lengths or shared offsets - it contains may have overflowed the 32 bits used to write them. */ - free_extern_output(); - caml_failwith("output_value: object too big"); + /* The object is too big for the small header format. + Fail if we are in compat32 mode, or use big header. */ + if (extern_flags & COMPAT_32) { + free_extern_output(); + caml_failwith("output_value: object too big to be read back on " + "32-bit platform"); + } + store32(header, Intext_magic_number_big); + store32(header + 4, 0); + store64(header + 8, res_len); + store64(header + 16, obj_counter); + store64(header + 24, size_64); + *header_len = 32; + return res_len; } #endif - if (extern_userprovided_output != NULL) - extern_ptr = extern_userprovided_output + 4; - else { - extern_ptr = extern_output_first->data + 4; - extern_limit = extern_output_first->data + SIZE_EXTERN_OUTPUT_BLOCK; - } - write32(res_len - 5*4); - write32(obj_counter); - write32(size_32); - write32(size_64); + /* Use the small header format */ + store32(header, Intext_magic_number_small); + store32(header + 4, res_len); + store32(header + 8, obj_counter); + store32(header + 12, size_32); + store32(header + 16, size_64); + *header_len = 20; return res_len; } void caml_output_val(struct channel *chan, value v, value flags) { + char header[32]; + int header_len; struct output_block * blk, * nextblk; if (! caml_channel_binary_mode(chan)) caml_failwith("output_value: not a binary channel"); init_extern_output(); - extern_value(v, flags); + extern_value(v, flags, header, &header_len); /* During [caml_really_putblock], concurrent [caml_output_val] operations can take place (via signal handlers or context switching in systhreads), and [extern_output_first] may change. So, save it in a local variable. */ blk = extern_output_first; + caml_really_putblock(chan, header, header_len); while (blk != NULL) { caml_really_putblock(chan, blk->data, blk->end - blk->data); nextblk = blk->next; @@ -637,20 +680,24 @@ CAMLprim value caml_output_value(value vchan, value v, value flags) CAMLprim value caml_output_value_to_string(value v, value flags) { - intnat len, ofs; + char header[32]; + int header_len; + intnat data_len, ofs; value res; struct output_block * blk, * nextblk; init_extern_output(); - len = extern_value(v, flags); + data_len = extern_value(v, flags, header, &header_len); /* PR#4030: it is prudent to save extern_output_first before allocating the result, as in caml_output_val */ blk = extern_output_first; - res = caml_alloc_string(len); + res = caml_alloc_string(header_len + data_len); ofs = 0; + memcpy(&Byte(res, ofs), header, header_len); + ofs += header_len; while (blk != NULL) { int n = blk->end - blk->data; - memmove(&Byte(res, ofs), blk->data, n); + memcpy(&Byte(res, ofs), blk->data, n); ofs += n; nextblk = blk->next; free(blk); @@ -659,50 +706,64 @@ CAMLprim value caml_output_value_to_string(value v, value flags) return res; } +CAMLexport intnat caml_output_value_to_block(value v, value flags, + char * buf, intnat len) +{ + char header[32]; + int header_len; + intnat data_len; + /* At this point we don't know the size of the header. + Guess that it is small, and fix up later if not. */ + extern_userprovided_output = buf + 20; + extern_ptr = extern_userprovided_output; + extern_limit = buf + len; + data_len = extern_value(v, flags, header, &header_len); + if (header_len != 20) { + /* Bad guess! Need to shift the output to make room for big header. + Make sure there is room. */ + if (header_len + data_len > len) + caml_failwith("Marshal.to_buffer: buffer overflow"); + memmove(buf + header_len, buf + 20, data_len); + } + memcpy(buf, header, header_len); + return header_len + data_len; +} + CAMLprim value caml_output_value_to_buffer(value buf, value ofs, value len, value v, value flags) { - intnat len_res; - extern_userprovided_output = &Byte(buf, Long_val(ofs)); - extern_ptr = extern_userprovided_output; - extern_limit = extern_userprovided_output + Long_val(len); - len_res = extern_value(v, flags); - return Val_long(len_res); + intnat l = + caml_output_value_to_block(v, flags, + &Byte(buf, Long_val(ofs)), Long_val(len)); + return Val_long(l); } CAMLexport void caml_output_value_to_malloc(value v, value flags, /*out*/ char ** buf, /*out*/ intnat * len) { - intnat len_res; + char header[32]; + int header_len; + intnat data_len; char * res; struct output_block * blk; init_extern_output(); - len_res = extern_value(v, flags); - res = malloc(len_res); + data_len = extern_value(v, flags, header, &header_len); + res = malloc(header_len + data_len); if (res == NULL) extern_out_of_memory(); *buf = res; - *len = len_res; + *len = header_len + data_len; + memcpy(res, header, header_len); + res += header_len; for (blk = extern_output_first; blk != NULL; blk = blk->next) { int n = blk->end - blk->data; - memmove(res, blk->data, n); + memcpy(res, blk->data, n); res += n; } free_extern_output(); } -CAMLexport intnat caml_output_value_to_block(value v, value flags, - char * buf, intnat len) -{ - intnat len_res; - extern_userprovided_output = buf; - extern_ptr = extern_userprovided_output; - extern_limit = extern_userprovided_output + len; - len_res = extern_value(v, flags); - return len_res; -} - /* Functions for writing user-defined marshallers */ CAMLexport void caml_serialize_int_1(int i) @@ -715,24 +776,22 @@ CAMLexport void caml_serialize_int_1(int i) CAMLexport void caml_serialize_int_2(int i) { if (extern_ptr + 2 > extern_limit) grow_extern_output(2); - extern_ptr[0] = i >> 8; - extern_ptr[1] = i; + store16(extern_ptr, i); extern_ptr += 2; } -CAMLexport void caml_serialize_int_4(int32 i) +CAMLexport void caml_serialize_int_4(int32_t i) { if (extern_ptr + 4 > extern_limit) grow_extern_output(4); - extern_ptr[0] = i >> 24; - extern_ptr[1] = i >> 16; - extern_ptr[2] = i >> 8; - extern_ptr[3] = i; + store32(extern_ptr, i); extern_ptr += 4; } -CAMLexport void caml_serialize_int_8(int64 i) +CAMLexport void caml_serialize_int_8(int64_t i) { - caml_serialize_block_8(&i, 1); + if (extern_ptr + 8 > extern_limit) grow_extern_output(8); + store64(extern_ptr, i); + extern_ptr += 8; } CAMLexport void caml_serialize_float_4(float f) @@ -748,7 +807,7 @@ CAMLexport void caml_serialize_float_8(double f) CAMLexport void caml_serialize_block_1(void * data, intnat len) { if (extern_ptr + len > extern_limit) grow_extern_output(len); - memmove(extern_ptr, data, len); + memcpy(extern_ptr, data, len); extern_ptr += len; } @@ -764,7 +823,7 @@ CAMLexport void caml_serialize_block_2(void * data, intnat len) extern_ptr = q; } #else - memmove(extern_ptr, data, len * 2); + memcpy(extern_ptr, data, len * 2); extern_ptr += len * 2; #endif } @@ -781,7 +840,7 @@ CAMLexport void caml_serialize_block_4(void * data, intnat len) extern_ptr = q; } #else - memmove(extern_ptr, data, len * 4); + memcpy(extern_ptr, data, len * 4); extern_ptr += len * 4; #endif } @@ -798,7 +857,7 @@ CAMLexport void caml_serialize_block_8(void * data, intnat len) extern_ptr = q; } #else - memmove(extern_ptr, data, len * 8); + memcpy(extern_ptr, data, len * 8); extern_ptr += len * 8; #endif } @@ -807,7 +866,7 @@ CAMLexport void caml_serialize_block_float_8(void * data, intnat len) { if (extern_ptr + 8 * len > extern_limit) grow_extern_output(8 * len); #if ARCH_FLOAT_ENDIANNESS == 0x01234567 - memmove(extern_ptr, data, len * 8); + memcpy(extern_ptr, data, len * 8); extern_ptr += len * 8; #elif ARCH_FLOAT_ENDIANNESS == 0x76543210 { diff --git a/byterun/fail.c b/byterun/fail.c index 7943f9ae..8ba6c767 100644 --- a/byterun/fail.c +++ b/byterun/fail.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Raising exceptions from C. */ diff --git a/byterun/finalise.c b/byterun/finalise.c index fd1c29bc..9c707c1d 100644 --- a/byterun/finalise.c +++ b/byterun/finalise.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ /* Handling of finalised values. */ @@ -41,6 +43,7 @@ struct to_do { static struct to_do *to_do_hd = NULL; static struct to_do *to_do_tl = NULL; +/* [size] is a number of elements for the [to_do.item] array */ static void alloc_to_do (int size) { struct to_do *result = malloc (sizeof (struct to_do) @@ -58,16 +61,15 @@ static void alloc_to_do (int size) } } -/* Find white finalisable values, put them in the finalising set, and +/* Find white finalisable values, move them to the finalising set, and darken them. - The recent set is empty. */ void caml_final_update (void) { uintnat i, j, k; uintnat todo_count = 0; - Assert (young == old); + Assert (old <= young); for (i = 0; i < old; i++){ Assert (Is_block (final_table[i].val)); Assert (Is_in_heap (final_table[i].val)); @@ -78,35 +80,25 @@ void caml_final_update (void) alloc_to_do (todo_count); j = k = 0; for (i = 0; i < old; i++){ - again: Assert (Is_block (final_table[i].val)); Assert (Is_in_heap (final_table[i].val)); + Assert (Tag_val (final_table[i].val) != Forward_tag); if (Is_white_val (final_table[i].val)){ - if (Tag_val (final_table[i].val) == Forward_tag){ - value fv; - Assert (final_table[i].offset == 0); - fv = Forward_val (final_table[i].val); - if (Is_block (fv) - && (!Is_in_value_area(fv) || Tag_val (fv) == Forward_tag - || Tag_val (fv) == Lazy_tag || Tag_val (fv) == Double_tag)){ - /* Do not short-circuit the pointer. */ - }else{ - final_table[i].val = fv; - if (Is_block (final_table[i].val) - && Is_in_heap (final_table[i].val)){ - goto again; - } - } - } to_do_tl->item[k++] = final_table[i]; }else{ final_table[j++] = final_table[i]; } } - young = old = j; + CAMLassert (i == old); + old = j; + for(;i < young; i++){ + final_table[j++] = final_table[i]; + } + young = j; to_do_tl->size = k; for (i = 0; i < k; i++){ - CAMLassert (Is_white_val (to_do_tl->item[i].val)); + /* Note that item may already be dark due to multiple entries in + the final table. */ caml_darken (to_do_tl->item[i].val, NULL); } } @@ -123,7 +115,6 @@ void caml_final_do_calls (void) value res; if (running_finalisation_function) return; - if (to_do_hd != NULL){ if (caml_finalise_begin_hook != NULL) (*caml_finalise_begin_hook) (); caml_gc_message (0x80, "Calling finalisation functions.\n", 0); @@ -153,17 +144,15 @@ void caml_final_do_calls (void) /* Call [*f] on the closures of the finalisable set and the closures and values of the finalising set. - The recent set is empty. - This is called by the major GC and the compactor - through [caml_darken_all_roots]. + This is called by the major GC through [caml_darken_all_roots]. */ void caml_final_do_strong_roots (scanning_action f) { uintnat i; struct to_do *todo; - Assert (old == young); - for (i = 0; i < old; i++) Call_action (f, final_table[i].fun); + Assert (old <= young); + for (i = 0; i < young; i++) Call_action (f, final_table[i].fun); for (todo = to_do_hd; todo != NULL; todo = todo->next){ for (i = 0; i < todo->size; i++){ @@ -174,15 +163,14 @@ void caml_final_do_strong_roots (scanning_action f) } /* Call [*f] on the values of the finalisable set. - The recent set is empty. This is called directly by the compactor. */ void caml_final_do_weak_roots (scanning_action f) { uintnat i; - Assert (old == young); - for (i = 0; i < old; i++) Call_action (f, final_table[i].val); + CAMLassert (old <= young); + for (i = 0; i < young; i++) Call_action (f, final_table[i].val); } /* Call [*f] on the closures and values of the recent set. @@ -211,7 +199,11 @@ void caml_final_empty_young (void) /* Put (f,v) in the recent set. */ CAMLprim value caml_final_register (value f, value v) { - if (!(Is_block (v) && Is_in_heap_or_young(v))) { + if (!Is_block (v) + || !Is_in_heap_or_young(v) + || Tag_val (v) == Lazy_tag + || Tag_val (v) == Double_tag + || Tag_val (v) == Forward_tag) { caml_invalid_argument ("Gc.finalise"); } Assert (old <= young); diff --git a/byterun/fix_code.c b/byterun/fix_code.c index 95a7591b..45d52cad 100644 --- a/byterun/fix_code.c +++ b/byterun/fix_code.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Handling of blocks of bytecode (endianness switch, threading). */ @@ -35,7 +37,7 @@ unsigned char * caml_saved_code; /* Read the main bytecode block from a file */ -void caml_init_code_fragments() { +void caml_init_code_fragments(void) { struct code_fragment * cf; /* Register the code in the table of code fragments */ cf = caml_stat_alloc(sizeof(struct code_fragment)); @@ -96,7 +98,7 @@ char ** caml_instr_table; char * caml_instr_base; static int* opcode_nargs = NULL; -int* caml_init_opcode_nargs() +int* caml_init_opcode_nargs(void) { if( opcode_nargs == NULL ){ int* l = (int*)caml_stat_alloc(sizeof(int) * FIRST_UNIMPLEMENTED_OP); @@ -117,7 +119,7 @@ int* caml_init_opcode_nargs() l[C_CALL1] = l[C_CALL2] = l[C_CALL3] = l[C_CALL4] = l[C_CALL5] = l[CONSTINT] = l[PUSHCONSTINT] = l[OFFSETINT] = l[OFFSETREF] = l[OFFSETCLOSURE] = l[PUSHOFFSETCLOSURE] = 1; - + /* Instructions with two operands */ l[APPTERM] = l[CLOSURE] = l[PUSHGETGLOBALFIELD] = l[GETGLOBALFIELD] = l[MAKEBLOCK] = l[C_CALLN] = @@ -145,12 +147,12 @@ void caml_thread_code (code_t code, asize_t len) } *p++ = (opcode_t)(caml_instr_table[instr] - caml_instr_base); if (instr == SWITCH) { - uint32 sizes = *p++; - uint32 const_size = sizes & 0xFFFF; - uint32 block_size = sizes >> 16; + uint32_t sizes = *p++; + uint32_t const_size = sizes & 0xFFFF; + uint32_t block_size = sizes >> 16; p += const_size + block_size; } else if (instr == CLOSUREREC) { - uint32 nfuncs = *p++; + uint32_t nfuncs = *p++; p++; /* skip nvars */ p += nfuncs; } else { diff --git a/byterun/floats.c b/byterun/floats.c index de18c333..41204da2 100644 --- a/byterun/floats.c +++ b/byterun/floats.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The interface of this file is in "caml/mlvalues.h" and "caml/alloc.h" */ @@ -17,6 +19,8 @@ #include #include #include +#include +#include #include "caml/alloc.h" #include "caml/fail.h" @@ -28,9 +32,13 @@ #ifdef _MSC_VER #include +#ifndef isnan #define isnan _isnan +#endif +#ifndef isfinite #define isfinite _finite #endif +#endif #ifdef ARCH_ALIGN_DOUBLE @@ -93,46 +101,179 @@ CAMLprim value caml_format_float(value fmt, value arg) return res; } -#if 0 -/*CAMLprim*/ value caml_float_of_substring(value vs, value idx, value l) +CAMLprim value caml_hexstring_of_float(value arg, value vprec, value vstyle) { - char parse_buffer[64]; - char * buf, * src, * dst, * end; - mlsize_t len, lenvs; - double d; - intnat flen = Long_val(l); - intnat fidx = Long_val(idx); + union { uint64_t i; double d; } u; + int sign, exp; + uint64_t m; + char buffer[64]; + char * buf, * p; + intnat prec; + int d; + value res; - lenvs = caml_string_length(vs); - len = - fidx >= 0 && fidx < lenvs && flen > 0 && flen <= lenvs - fidx - ? flen : 0; - buf = len < sizeof(parse_buffer) ? parse_buffer : caml_stat_alloc(len + 1); - src = String_val(vs) + fidx; - dst = buf; - while (len--) { - char c = *src++; - if (c != '_') *dst++ = c; + /* Allocate output buffer */ + prec = Long_val(vprec); + /* 12 chars for sign, 0x, decimal point, exponent */ + buf = (prec + 12 <= 64 ? buffer : caml_stat_alloc(prec + 12)); + /* Extract sign, mantissa, and exponent */ + u.d = Double_val(arg); + sign = u.i >> 63; + exp = (u.i >> 52) & 0x7FF; + m = u.i & (((uint64_t) 1 << 52) - 1); + /* Put sign */ + p = buf; + if (sign) { + *p++ = '-'; + } else { + switch (Int_val(vstyle)) { + case '+': *p++ = '+'; break; + case ' ': *p++ = ' '; break; + } } - *dst = 0; - if (dst == buf) goto error; - d = strtod((const char *) buf, &end); - if (end != dst) goto error; - if (buf != parse_buffer) caml_stat_free(buf); - return caml_copy_double(d); - error: - if (buf != parse_buffer) caml_stat_free(buf); - caml_failwith("float_of_string"); + /* Treat special cases */ + if (exp == 0x7FF) { + char * txt; + if (m == 0) txt = "infinity"; else txt = "nan"; + memcpy(p, txt, strlen(txt)); + p[strlen(txt)] = 0; + res = caml_copy_string(buf); + } else { + /* Output "0x" prefix */ + *p++ = '0'; *p++ = 'x'; + /* Normalize exponent and mantissa */ + if (exp == 0) { + if (m != 0) exp = -1022; /* denormal */ + } else { + exp = exp - 1023; + m = m | ((uint64_t) 1 << 52); + } + /* If a precision is given, and is small, round mantissa accordingly */ + prec = Long_val(vprec); + if (prec >= 0 && prec < 13) { + int i = 52 - prec * 4; + uint64_t unit = (uint64_t) 1 << i; + uint64_t half = unit >> 1; + uint64_t mask = unit - 1; + uint64_t frac = m & mask; + m = m & ~mask; + /* Round to nearest, ties to even */ + if (frac > half || (frac == half && (m & unit) != 0)) { + m += unit; + } + } + /* Leading digit */ + d = m >> 52; + *p++ = (d < 10 ? d + '0' : d - 10 + 'a'); + m = (m << 4) & (((uint64_t) 1 << 56) - 1); + /* Fractional digits. If a precision is given, print that number of + digits. Otherwise, print as many digits as needed to represent + the mantissa exactly. */ + if (prec >= 0 ? prec > 0 : m != 0) { + *p++ = '.'; + while (prec >= 0 ? prec > 0 : m != 0) { + d = m >> 52; + *p++ = (d < 10 ? d + '0' : d - 10 + 'a'); + m = (m << 4) & (((uint64_t) 1 << 56) - 1); + prec--; + } + } + *p = 0; + /* Add exponent */ + res = caml_alloc_sprintf("%sp%+d", buf, exp); + } + if (buf != buffer) caml_stat_free(buf); + return res; +} + +static int caml_float_of_hex(const char * s, double * res) +{ + int64_t m = 0; /* the mantissa - top 60 bits at most */ + int n_bits = 0; /* total number of bits read */ + int m_bits = 0; /* number of bits in mantissa */ + int x_bits = 0; /* number of bits after mantissa */ + int dec_point = -1; /* bit count corresponding to decimal point */ + /* -1 if no decimal point seen */ + int exp = 0; /* exponent */ + char * p; /* for converting the exponent */ + double f; + + while (*s != 0) { + char c = *s++; + switch (c) { + case '_': + break; + case '.': + if (dec_point >= 0) return -1; /* multiple decimal points */ + dec_point = n_bits; + break; + case 'p': case 'P': { + long e; + if (*s == 0) return -1; /* nothing after exponent mark */ + e = strtol(s, &p, 10); + if (*p != 0) return -1; /* ill-formed exponent */ + if (e < INT_MIN || e > INT_MAX) return -1; /* unreasonable exponent */ + exp = e; + s = p; /* stop at next loop iteration */ + break; + } + default: { /* Nonzero digit */ + int d; + if (c >= '0' && c <= '9') d = c - '0'; + else if (c >= 'A' && c <= 'F') d = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') d = c - 'a' + 10; + else return -1; /* bad digit */ + n_bits += 4; + if (d == 0 && m == 0) break; /* leading zeros are skipped */ + if (m_bits < 60) { + /* There is still room in m. Add this digit to the mantissa. */ + m = (m << 4) + d; + m_bits += 4; + } else { + /* We've already collected 60 significant bits in m. + Now all we care about is whether there is a nonzero bit + after. In this case, round m to odd so that the later + rounding of m to FP produces the correct result. */ + if (d != 0) m |= 1; /* round to odd */ + x_bits += 4; + } + break; + } + } + } + /* Convert mantissa to FP. We use a signed conversion because we can + (m has 60 bits at most) and because it is faster + on several architectures. */ + f = (double) (int64_t) m; + /* Adjust exponent to take decimal point and extra digits into account */ + if (dec_point >= 0) exp = exp + (dec_point - n_bits); + exp = exp + x_bits; + /* Apply exponent if needed */ + if (exp != 0) f = ldexp(f, exp); + /* Done! */ + *res = f; + return 0; } -#endif CAMLprim value caml_float_of_string(value vs) { char parse_buffer[64]; char * buf, * src, * dst, * end; mlsize_t len; + int sign; double d; + /* Check for hexadecimal FP constant */ + src = String_val(vs); + sign = 1; + if (*src == '-') { sign = -1; src++; } + else if (*src == '+') { src++; }; + if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) { + if (caml_float_of_hex(src + 2, &d) == -1) + caml_failwith("float_of_string"); + return caml_copy_double(sign < 0 ? -d : d); + } + /* Remove '_' characters before calling strtod () */ len = caml_string_length(vs); buf = len < sizeof(parse_buffer) ? parse_buffer : caml_stat_alloc(len + 1); src = String_val(vs); @@ -143,6 +284,7 @@ CAMLprim value caml_float_of_string(value vs) } *dst = 0; if (dst == buf) goto error; + /* Convert using strtod */ d = strtod((const char *) buf, &end); if (end != dst) goto error; if (buf != parse_buffer) caml_stat_free(buf); @@ -221,6 +363,13 @@ CAMLprim value caml_frexp_float(value f) CAMLreturn (res); } +// Seems dumb but intnat could not correspond to int type. +double caml_ldexp_float_unboxed(double f, intnat i) +{ + return ldexp(f, i); +} + + CAMLprim value caml_ldexp_float(value f, value i) { return caml_copy_double(ldexp(Double_val(f), Int_val(i))); @@ -322,9 +471,11 @@ CAMLexport double caml_hypot(double x, double y) return hypot(x, y); #else double tmp, ratio; - if (x != x) return x; /* NaN */ - if (y != y) return y; /* NaN */ x = fabs(x); y = fabs(y); + if (x != x) /* x is NaN */ + return y > DBL_MAX ? y : x; /* PR#6321 */ + if (y != y) /* y is NaN */ + return x > DBL_MAX ? x : y; /* PR#6321 */ if (x < y) { tmp = x; x = y; y = tmp; } if (x == 0.0) return 0.0; ratio = y / x; @@ -379,9 +530,9 @@ CAMLprim value caml_log1p_float(value f) union double_as_two_int32 { double d; #if defined(ARCH_BIG_ENDIAN) || (defined(__arm__) && !defined(__ARM_EABI__)) - struct { uint32 h; uint32 l; } i; + struct { uint32_t h; uint32_t l; } i; #else - struct { uint32 l; uint32 h; } i; + struct { uint32_t l; uint32_t h; } i; #endif }; @@ -434,44 +585,46 @@ CAMLprim value caml_gt_float(value f, value g) return Val_bool(Double_val(f) > Double_val(g)); } +intnat caml_float_compare_unboxed(double f, double g) +{ + /* If one or both of f and g is NaN, order according to the convention + NaN = NaN and NaN < x for all other floats x. */ + /* This branchless implementation is from GPR#164. + Note that [f == f] if and only if f is not NaN. */ + return (f > g) - (f < g) + (f == f) - (g == g); +} + CAMLprim value caml_float_compare(value vf, value vg) { - double f = Double_val(vf); - double g = Double_val(vg); - if (f == g) return Val_int(0); - if (f < g) return Val_int(-1); - if (f > g) return Val_int(1); - /* One or both of f and g is NaN. Order according to the - convention NaN = NaN and NaN < x for all other floats x. */ - if (f == f) return Val_int(1); /* f is not NaN, g is NaN */ - if (g == g) return Val_int(-1); /* g is not NaN, f is NaN */ - return Val_int(0); /* both f and g are NaN */ + return Val_int(caml_float_compare_unboxed(Double_val(vf),Double_val(vg))); } enum { FP_normal, FP_subnormal, FP_zero, FP_infinite, FP_nan }; -CAMLprim value caml_classify_float(value vd) +value caml_classify_float_unboxed(double vd) { - /* Cygwin 1.3 has problems with fpclassify (PR#1293), so don't use it */ - /* FIXME Cygwin 1.3 is ancient! Revisit this decision. */ -#if defined(fpclassify) && !defined(__CYGWIN__) && !defined(__MINGW32__) - switch (fpclassify(Double_val(vd))) { - case FP_NAN: - return Val_int(FP_nan); - case FP_INFINITE: - return Val_int(FP_infinite); - case FP_ZERO: - return Val_int(FP_zero); - case FP_SUBNORMAL: - return Val_int(FP_subnormal); - default: /* case FP_NORMAL */ - return Val_int(FP_normal); +#ifdef ARCH_SIXTYFOUR + union { double d; uint64_t i; } u; + uint64_t n; + uint32_t e; + + u.d = vd; + n = u.i << 1; /* shift sign bit off */ + if (n == 0) return Val_int(FP_zero); + e = n >> 53; /* extract exponent */ + if (e == 0) return Val_int(FP_subnormal); + if (e == 0x7FF) { + if (n << 11 == 0) /* shift exponent off */ + return Val_int(FP_infinite); + else + return Val_int(FP_nan); } + return Val_int(FP_normal); #else union double_as_two_int32 u; - uint32 h, l; + uint32_t h, l; - u.d = Double_val(vd); + u.d = vd; h = u.i.h; l = u.i.l; l = l | (h & 0xFFFFF); h = h & 0x7FF00000; @@ -489,6 +642,11 @@ CAMLprim value caml_classify_float(value vd) #endif } +CAMLprim value caml_classify_float(value vd) +{ + return caml_classify_float_unboxed(Double_val(vd)); +} + /* The [caml_init_ieee_float] function should initialize floating-point hardware so that it behaves as much as possible like the IEEE standard. In particular, return special numbers like Infinity and NaN instead diff --git a/byterun/freelist.c b/byterun/freelist.c index a588a8b7..eaac36c4 100644 --- a/byterun/freelist.c +++ b/byterun/freelist.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #define FREELIST_DEBUG 0 #if FREELIST_DEBUG @@ -32,34 +34,34 @@ (See [caml_fl_merge_block].) */ -typedef struct { - char *next_bp; /* Pointer to the first byte of the next block. */ -} block; +/* A free list block is a [value] (integer representing a pointer to the + first word after the block's header). The end of the list is NULL. */ +#define Val_NULL ((value) NULL) /* The sentinel can be located anywhere in memory, but it must not be adjacent to any heap object. */ static struct { value filler1; /* Make sure the sentinel is never adjacent to any block. */ header_t h; - value first_bp; + value first_field; value filler2; /* Make sure the sentinel is never adjacent to any block. */ -} sentinel = {0, Make_header (0, 0, Caml_blue), 0, 0}; +} sentinel = {0, Make_header (0, 0, Caml_blue), Val_NULL, 0}; -#define Fl_head ((char *) (&(sentinel.first_bp))) -static char *fl_prev = Fl_head; /* Current allocation pointer. */ -static char *fl_last = NULL; /* Last block in the list. Only valid - just after [caml_fl_allocate] returns NULL. */ -char *caml_fl_merge = Fl_head; /* Current insertion pointer. Managed +#define Fl_head (Val_bp (&(sentinel.first_field))) +static value fl_prev = Fl_head; /* Current allocation pointer. */ +static value fl_last = Val_NULL; /* Last block in the list. Only valid + just after [caml_fl_allocate] returns NULL. */ +value caml_fl_merge = Fl_head; /* Current insertion pointer. Managed jointly with [sweep_slice]. */ -asize_t caml_fl_cur_size = 0; /* Number of words in the free list, +asize_t caml_fl_cur_wsz = 0; /* Number of words in the free list, including headers but not fragments. */ #define FLP_MAX 1000 -static char *flp [FLP_MAX]; +static value flp [FLP_MAX]; static int flp_size = 0; -static char *beyond = NULL; +static value beyond = Val_NULL; -#define Next(b) (((block *) (b))->next_bp) +#define Next(b) (Field (b, 0)) #define Policy_next_fit 0 #define Policy_first_fit 1 @@ -69,14 +71,14 @@ uintnat caml_allocation_policy = Policy_next_fit; #ifdef DEBUG static void fl_check (void) { - char *cur, *prev; + value cur, prev; int prev_found = 0, flp_found = 0, merge_found = 0; uintnat size_found = 0; int sz = 0; prev = Fl_head; cur = Next (prev); - while (cur != NULL){ + while (cur != Val_NULL){ size_found += Whsize_bp (cur); Assert (Is_in_heap (cur)); if (cur == fl_prev) prev_found = 1; @@ -86,7 +88,7 @@ static void fl_check (void) Assert (Next (flp[flp_found]) == cur); ++ flp_found; }else{ - Assert (beyond == NULL || cur >= Next (beyond)); + Assert (beyond == Val_NULL || cur >= Next (beyond)); } } if (cur == caml_fl_merge) merge_found = 1; @@ -96,36 +98,37 @@ static void fl_check (void) if (policy == Policy_next_fit) Assert (prev_found || fl_prev == Fl_head); if (policy == Policy_first_fit) Assert (flp_found == flp_size); Assert (merge_found || caml_fl_merge == Fl_head); - Assert (size_found == caml_fl_cur_size); + Assert (size_found == caml_fl_cur_wsz); } #endif /* [allocate_block] is called by [caml_fl_allocate]. Given a suitable free - block and the desired size, it allocates a new block from the free + block and the requested size, it allocates a new block from the free block. There are three cases: - 0. The free block has the desired size. Detach the block from the + 0. The free block has the requested size. Detach the block from the free-list and return it. - 1. The free block is 1 word longer than the desired size. Detach + 1. The free block is 1 word longer than the requested size. Detach the block from the free list. The remaining word cannot be linked: turn it into an empty block (header only), and return the rest. - 2. The free block is big enough. Split it in two and return the right + 2. The free block is large enough. Split it in two and return the right block. In all cases, the allocated block is right-justified in the free block: - it is located in the high-address words of the free block. This way, + it is located in the high-address words of the free block, so that the linking of the free-list does not change in case 2. */ -static char *allocate_block (mlsize_t wh_sz, int flpi, char *prev, char *cur) +static header_t *allocate_block (mlsize_t wh_sz, int flpi, value prev, + value cur) { header_t h = Hd_bp (cur); Assert (Whsize_hd (h) >= wh_sz); if (Wosize_hd (h) < wh_sz + 1){ /* Cases 0 and 1. */ - caml_fl_cur_size -= Whsize_hd (h); + caml_fl_cur_wsz -= Whsize_hd (h); Next (prev) = Next (cur); - Assert (Is_in_heap (Next (prev)) || Next (prev) == NULL); + Assert (Is_in_heap (Next (prev)) || Next (prev) == Val_NULL); if (caml_fl_merge == cur) caml_fl_merge = prev; #ifdef DEBUG - fl_last = NULL; + fl_last = Val_NULL; #endif /* In case 1, the following creates the empty block correctly. In case 0, it gives an invalid header to the block. The function @@ -135,41 +138,84 @@ static char *allocate_block (mlsize_t wh_sz, int flpi, char *prev, char *cur) if (flpi + 1 < flp_size && flp[flpi + 1] == cur){ flp[flpi + 1] = prev; }else if (flpi == flp_size - 1){ - beyond = (prev == Fl_head) ? NULL : prev; + beyond = (prev == Fl_head) ? Val_NULL : prev; -- flp_size; } } }else{ /* Case 2. */ - caml_fl_cur_size -= wh_sz; + caml_fl_cur_wsz -= wh_sz; Hd_op (cur) = Make_header (Wosize_hd (h) - wh_sz, 0, Caml_blue); } if (policy == Policy_next_fit) fl_prev = prev; - return cur + Bosize_hd (h) - Bsize_wsize (wh_sz); + return (header_t *) &Field (cur, Wosize_hd (h) - wh_sz); } +#ifdef CAML_INSTR +static uintnat instr_size [20] = + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +static char *instr_name [20] = { + NULL, + "alloc01@", + "alloc02@", + "alloc03@", + "alloc04@", + "alloc05@", + "alloc06@", + "alloc07@", + "alloc08@", + "alloc09@", + "alloc10-19@", + "alloc20-29@", + "alloc30-39@", + "alloc40-49@", + "alloc50-59@", + "alloc60-69@", + "alloc70-79@", + "alloc80-89@", + "alloc90-99@", + "alloc_large@", +}; +uintnat caml_instr_alloc_jump = 0; +/* number of pointers followed to allocate from the free list */ +#endif /*CAML_INSTR*/ + /* [caml_fl_allocate] does not set the header of the newly allocated block. The calling function must do it before any GC function gets called. [caml_fl_allocate] returns a head pointer. */ -char *caml_fl_allocate (mlsize_t wo_sz) +header_t *caml_fl_allocate (mlsize_t wo_sz) { - char *cur = NULL, *prev, *result; + value cur = Val_NULL, prev; + header_t *result; int i; mlsize_t sz, prevsz; Assert (sizeof (char *) == sizeof (value)); Assert (wo_sz >= 1); +#ifdef CAML_INSTR + if (wo_sz < 10){ + ++instr_size[wo_sz]; + }else if (wo_sz < 100){ + ++instr_size[wo_sz/10 + 9]; + }else{ + ++instr_size[19]; + } +#endif /* CAML_INSTR */ + switch (policy){ case Policy_next_fit: - Assert (fl_prev != NULL); + Assert (fl_prev != Val_NULL); /* Search from [fl_prev] to the end of the list. */ prev = fl_prev; cur = Next (prev); - while (cur != NULL){ Assert (Is_in_heap (cur)); + while (cur != Val_NULL){ Assert (Is_in_heap (cur)); if (Wosize_bp (cur) >= wo_sz){ return allocate_block (Whsize_wosize (wo_sz), 0, prev, cur); } prev = cur; cur = Next (prev); +#ifdef CAML_INSTR + ++ caml_instr_alloc_jump; +#endif } fl_last = prev; /* Search from the start of the list to [fl_prev]. */ @@ -181,6 +227,9 @@ char *caml_fl_allocate (mlsize_t wo_sz) } prev = cur; cur = Next (prev); +#ifdef CAML_INSTR + ++ caml_instr_alloc_jump; +#endif } /* No suitable block was found. */ return NULL; @@ -206,13 +255,13 @@ char *caml_fl_allocate (mlsize_t wo_sz) }else{ prev = Next (flp[flp_size - 1]); prevsz = Wosize_bp (prev); - if (beyond != NULL) prev = beyond; + if (beyond != Val_NULL) prev = beyond; } while (flp_size < FLP_MAX){ cur = Next (prev); - if (cur == NULL){ + if (cur == Val_NULL){ fl_last = prev; - beyond = (prev == Fl_head) ? NULL : prev; + beyond = (prev == Fl_head) ? Val_NULL : prev; return NULL; }else{ sz = Wosize_bp (cur); @@ -242,7 +291,7 @@ char *caml_fl_allocate (mlsize_t wo_sz) #if FREELIST_DEBUG fprintf (stderr, "FLP: table is full -- slow first-fit\n"); #endif - if (beyond != NULL){ + if (beyond != Val_NULL){ prev = beyond; }else{ prev = flp[flp_size - 1]; @@ -250,7 +299,7 @@ char *caml_fl_allocate (mlsize_t wo_sz) prevsz = Wosize_bp (Next (flp[FLP_MAX-1])); Assert (prevsz < wo_sz); cur = Next (prev); - while (cur != NULL){ + while (cur != Val_NULL){ Assert (Is_in_heap (cur)); sz = Wosize_bp (cur); if (sz < prevsz){ @@ -278,10 +327,10 @@ char *caml_fl_allocate (mlsize_t wo_sz) beyond = Next (flp[i]); -- flp_size; }else{ - beyond = NULL; + beyond = Val_NULL; } }else{ - char *buf [FLP_MAX]; + value buf [FLP_MAX]; int j = 0; mlsize_t oldsz = sz; @@ -304,19 +353,19 @@ char *caml_fl_allocate (mlsize_t wo_sz) #endif if (FLP_MAX >= flp_size + j - 1){ if (j != 1){ - memmove (&flp[i+j], &flp[i+1], sizeof (block *) * (flp_size-i-1)); + memmove (&flp[i+j], &flp[i+1], sizeof (value) * (flp_size-i-1)); } - if (j > 0) memmove (&flp[i], &buf[0], sizeof (block *) * j); + if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); flp_size += j - 1; }else{ if (FLP_MAX > i + j){ if (j != 1){ - memmove (&flp[i+j], &flp[i+1], sizeof (block *) * (FLP_MAX-i-j)); + memmove (&flp[i+j], &flp[i+1], sizeof (value) * (FLP_MAX-i-j)); } - if (j > 0) memmove (&flp[i], &buf[0], sizeof (block *) * j); + if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); }else{ if (i != FLP_MAX){ - memmove (&flp[i], &buf[0], sizeof (block *) * (FLP_MAX - i)); + memmove (&flp[i], &buf[0], sizeof (value) * (FLP_MAX - i)); } } flp_size = FLP_MAX - 1; @@ -335,10 +384,23 @@ char *caml_fl_allocate (mlsize_t wo_sz) return NULL; /* NOT REACHED */ } -static char *last_fragment; +/* Location of the last fragment seen by the sweeping code. + This is a pointer to the first word after the fragment, which is + the header of the next block. + Note that [last_fragment] doesn't point to the fragment itself, + but to the block after it. +*/ +static header_t *last_fragment; void caml_fl_init_merge (void) { +#ifdef CAML_INSTR + int i; + for (i = 1; i < 20; i++){ + CAML_INSTR_INT (instr_name[i], instr_size[i]); + instr_size[i] = 0; + } +#endif /* CAML_INSTR */ last_fragment = NULL; caml_fl_merge = Fl_head; #ifdef DEBUG @@ -346,21 +408,22 @@ void caml_fl_init_merge (void) #endif } -static void truncate_flp (char *changed) +static void truncate_flp (value changed) { if (changed == Fl_head){ flp_size = 0; - beyond = NULL; + beyond = Val_NULL; }else{ - while (flp_size > 0 && Next (flp[flp_size - 1]) >= changed) -- flp_size; - if (beyond >= changed) beyond = NULL; + while (flp_size > 0 && Next (flp[flp_size - 1]) >= changed) + -- flp_size; + if (beyond >= changed) beyond = Val_NULL; } } /* This is called by caml_compact_heap. */ void caml_fl_reset (void) { - Next (Fl_head) = NULL; + Next (Fl_head) = Val_NULL; switch (policy){ case Policy_next_fit: fl_prev = Fl_head; @@ -372,19 +435,20 @@ void caml_fl_reset (void) Assert (0); break; } - caml_fl_cur_size = 0; + caml_fl_cur_wsz = 0; caml_fl_init_merge (); } /* [caml_fl_merge_block] returns the head pointer of the next block after [bp], because merging blocks may change the size of [bp]. */ -char *caml_fl_merge_block (char *bp) +header_t *caml_fl_merge_block (value bp) { - char *prev, *cur, *adj; - header_t hd = Hd_bp (bp); + value prev, cur; + header_t *adj; + header_t hd = Hd_val (bp); mlsize_t prev_wosz; - caml_fl_cur_size += Whsize_hd (hd); + caml_fl_cur_wsz += Whsize_hd (hd); #ifdef DEBUG caml_set_fields (bp, 0, Debug_free_major); @@ -394,62 +458,62 @@ char *caml_fl_merge_block (char *bp) /* The sweep code makes sure that this is the right place to insert this block: */ Assert (prev < bp || prev == Fl_head); - Assert (cur > bp || cur == NULL); + Assert (cur > bp || cur == Val_NULL); if (policy == Policy_first_fit) truncate_flp (prev); /* If [last_fragment] and [bp] are adjacent, merge them. */ if (last_fragment == Hp_bp (bp)){ - mlsize_t bp_whsz = Whsize_bp (bp); + mlsize_t bp_whsz = Whsize_val (bp); if (bp_whsz <= Max_wosize){ hd = Make_header (bp_whsz, 0, Caml_white); - bp = last_fragment; - Hd_bp (bp) = hd; - caml_fl_cur_size += Whsize_wosize (0); + bp = (value) last_fragment; + Hd_val (bp) = hd; + caml_fl_cur_wsz += Whsize_wosize (0); } } /* If [bp] and [cur] are adjacent, remove [cur] from the free-list and merge them. */ - adj = bp + Bosize_hd (hd); - if (adj == Hp_bp (cur)){ - char *next_cur = Next (cur); - mlsize_t cur_whsz = Whsize_bp (cur); + adj = (header_t *) &Field (bp, Wosize_hd (hd)); + if (adj == Hp_val (cur)){ + value next_cur = Next (cur); + mlsize_t cur_whsz = Whsize_val (cur); if (Wosize_hd (hd) + cur_whsz <= Max_wosize){ Next (prev) = next_cur; if (policy == Policy_next_fit && fl_prev == cur) fl_prev = prev; hd = Make_header (Wosize_hd (hd) + cur_whsz, 0, Caml_blue); - Hd_bp (bp) = hd; - adj = bp + Bosize_hd (hd); + Hd_val (bp) = hd; + adj = (header_t *) &Field (bp, Wosize_hd (hd)); #ifdef DEBUG - fl_last = NULL; - Next (cur) = (char *) Debug_free_major; - Hd_bp (cur) = Debug_free_major; + fl_last = Val_NULL; + Next (cur) = (value) Debug_free_major; + Hd_val (cur) = Debug_free_major; #endif cur = next_cur; } } /* If [prev] and [bp] are adjacent merge them, else insert [bp] into the free-list if it is big enough. */ - prev_wosz = Wosize_bp (prev); - if (prev + Bsize_wsize (prev_wosz) == Hp_bp (bp) + prev_wosz = Wosize_val (prev); + if ((header_t *) &Field (prev, prev_wosz) == Hp_val (bp) && prev_wosz + Whsize_hd (hd) < Max_wosize){ - Hd_bp (prev) = Make_header (prev_wosz + Whsize_hd (hd), 0,Caml_blue); + Hd_val (prev) = Make_header (prev_wosz + Whsize_hd (hd), 0,Caml_blue); #ifdef DEBUG - Hd_bp (bp) = Debug_free_major; + Hd_val (bp) = Debug_free_major; #endif Assert (caml_fl_merge == prev); }else if (Wosize_hd (hd) != 0){ - Hd_bp (bp) = Bluehd_hd (hd); + Hd_val (bp) = Bluehd_hd (hd); Next (bp) = cur; Next (prev) = bp; caml_fl_merge = bp; }else{ /* This is a fragment. Leave it in white but remember it for eventual merging with the next block. */ - last_fragment = bp; - caml_fl_cur_size -= Whsize_wosize (0); + last_fragment = (header_t *) bp; + caml_fl_cur_wsz -= Whsize_wosize (0); } return adj; } @@ -457,46 +521,47 @@ char *caml_fl_merge_block (char *bp) /* This is a heap extension. We have to insert it in the right place in the free-list. [caml_fl_add_blocks] can only be called right after a call to - [caml_fl_allocate] that returned NULL. + [caml_fl_allocate] that returned Val_NULL. Most of the heap extensions are expected to be at the end of the free list. (This depends on the implementation of [malloc].) [bp] must point to a list of blocks chained by their field 0, - terminated by NULL, and field 1 of the first block must point to + terminated by Val_NULL, and field 1 of the first block must point to the last block. */ -void caml_fl_add_blocks (char *bp) +void caml_fl_add_blocks (value bp) { - Assert (fl_last != NULL); - Assert (Next (fl_last) == NULL); - caml_fl_cur_size += Whsize_bp (bp); + Assert (fl_last != Val_NULL); + Assert (Next (fl_last) == Val_NULL); + caml_fl_cur_wsz += Whsize_bp (bp); if (bp > fl_last){ Next (fl_last) = bp; - if (fl_last == caml_fl_merge && bp < caml_gc_sweep_hp){ - caml_fl_merge = (char *) Field (bp, 1); + if (fl_last == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ + caml_fl_merge = Field (bp, 1); } if (policy == Policy_first_fit && flp_size < FLP_MAX){ flp [flp_size++] = fl_last; } }else{ - char *cur, *prev; + value cur, prev; prev = Fl_head; cur = Next (prev); - while (cur != NULL && cur < bp){ Assert (prev < bp || prev == Fl_head); + while (cur != Val_NULL && cur < bp){ + Assert (prev < bp || prev == Fl_head); /* XXX TODO: extend flp on the fly */ prev = cur; cur = Next (prev); } Assert (prev < bp || prev == Fl_head); - Assert (cur > bp || cur == NULL); + Assert (cur > bp || cur == Val_NULL); Next (Field (bp, 1)) = cur; Next (prev) = bp; /* When inserting blocks between [caml_fl_merge] and [caml_gc_sweep_hp], we must advance [caml_fl_merge] to the new block, so that [caml_fl_merge] is always the last free-list block before [caml_gc_sweep_hp]. */ - if (prev == caml_fl_merge && bp < caml_gc_sweep_hp){ - caml_fl_merge = (char *) Field (bp, 1); + if (prev == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ + caml_fl_merge = Field (bp, 1); } if (policy == Policy_first_fit) truncate_flp (bp); } @@ -523,7 +588,7 @@ void caml_make_free_blocks (value *p, mlsize_t size, int do_merge, int color) sz = size; } *(header_t *)p = Make_header (Wosize_whsize (sz), 0, color); - if (do_merge) caml_fl_merge_block (Bp_hp (p)); + if (do_merge) caml_fl_merge_block (Val_hp (p)); size -= sz; p += sz; } @@ -538,7 +603,7 @@ void caml_set_allocation_policy (uintnat p) break; case Policy_first_fit: flp_size = 0; - beyond = NULL; + beyond = Val_NULL; policy = p; break; default: diff --git a/byterun/gc_ctrl.c b/byterun/gc_ctrl.c index 1f2a0238..51a2d79e 100644 --- a/byterun/gc_ctrl.c +++ b/byterun/gc_ctrl.c @@ -1,32 +1,39 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "caml/alloc.h" +#include "caml/backtrace.h" #include "caml/compact.h" #include "caml/custom.h" +#include "caml/fail.h" #include "caml/finalise.h" #include "caml/freelist.h" #include "caml/gc.h" #include "caml/gc_ctrl.h" #include "caml/major_gc.h" +#include "caml/memory.h" #include "caml/minor_gc.h" #include "caml/misc.h" #include "caml/mlvalues.h" +#include "caml/signals.h" #ifdef NATIVE_CODE #include "stack.h" #else #include "caml/stacks.h" #endif +#include "caml/startup_aux.h" #ifndef NATIVE_CODE extern uintnat caml_max_stack_size; /* defined in stacks.c */ @@ -38,8 +45,8 @@ double caml_stat_minor_words = 0.0, intnat caml_stat_minor_collections = 0, caml_stat_major_collections = 0, - caml_stat_heap_size = 0, /* bytes */ - caml_stat_top_heap_size = 0, /* bytes */ + caml_stat_heap_wsz = 0, + caml_stat_top_heap_wsz = 0, caml_stat_compactions = 0, caml_stat_heap_chunks = 0; @@ -48,7 +55,7 @@ extern uintnat caml_percent_free; /* see major_gc.c */ extern uintnat caml_percent_max; /* see compact.c */ extern uintnat caml_allocation_policy; /* see freelist.c */ -#define Next(hp) ((hp) + Bhsize_hp (hp)) +#define Next(hp) ((hp) + Whsize_hp (hp)) #ifdef DEBUG @@ -77,7 +84,7 @@ static void check_head (value v) } } -static void check_block (char *hp) +static void check_block (header_t *hp) { mlsize_t i; value v = Val_hp (hp); @@ -127,9 +134,9 @@ static value heap_stats (int returnstats) free_words = 0, free_blocks = 0, largest_free = 0, fragments = 0, heap_chunks = 0; char *chunk = caml_heap_start, *chunk_end; - char *cur_hp; + header_t *cur_hp; #ifdef DEBUG - char *prev_hp; + header_t *prev_hp; #endif header_t cur_hd; @@ -143,19 +150,20 @@ static value heap_stats (int returnstats) #ifdef DEBUG prev_hp = NULL; #endif - cur_hp = chunk; - while (cur_hp < chunk_end){ + cur_hp = (header_t *) chunk; + while (cur_hp < (header_t *) chunk_end){ cur_hd = Hd_hp (cur_hp); - Assert (Next (cur_hp) <= chunk_end); + Assert (Next (cur_hp) <= (header_t *) chunk_end); switch (Color_hd (cur_hd)){ case Caml_white: if (Wosize_hd (cur_hd) == 0){ ++ fragments; Assert (prev_hp == NULL || Color_hp (prev_hp) != Caml_blue - || cur_hp == caml_gc_sweep_hp); + || cur_hp == (header_t *) caml_gc_sweep_hp); }else{ - if (caml_gc_phase == Phase_sweep && cur_hp >= caml_gc_sweep_hp){ + if (caml_gc_phase == Phase_sweep + && cur_hp >= (header_t *) caml_gc_sweep_hp){ ++ free_blocks; free_words += Whsize_hd (cur_hd); if (Whsize_hd (cur_hd) > largest_free){ @@ -201,27 +209,26 @@ static value heap_stats (int returnstats) prev_hp = cur_hp; #endif cur_hp = Next (cur_hp); - } Assert (cur_hp == chunk_end); + } Assert (cur_hp == (header_t *) chunk_end); chunk = Chunk_next (chunk); } Assert (heap_chunks == caml_stat_heap_chunks); - Assert (live_words + free_words + fragments - == Wsize_bsize (caml_stat_heap_size)); + Assert (live_words + free_words + fragments == caml_stat_heap_wsz); if (returnstats){ CAMLlocal1 (res); /* get a copy of these before allocating anything... */ double minwords = caml_stat_minor_words - + (double) Wsize_bsize (caml_young_end - caml_young_ptr); + + (double) (caml_young_alloc_end - caml_young_ptr); double prowords = caml_stat_promoted_words; double majwords = caml_stat_major_words + (double) caml_allocated_words; intnat mincoll = caml_stat_minor_collections; intnat majcoll = caml_stat_major_collections; - intnat heap_words = Wsize_bsize (caml_stat_heap_size); + intnat heap_words = caml_stat_heap_wsz; intnat cpct = caml_stat_compactions; - intnat top_heap_words = Wsize_bsize (caml_stat_top_heap_size); + intnat top_heap_words = caml_stat_top_heap_wsz; res = caml_alloc_tuple (16); Store_field (res, 0, caml_copy_double (minwords)); @@ -255,8 +262,12 @@ void caml_heap_check (void) CAMLprim value caml_gc_stat(value v) { + value result; + CAML_INSTR_SETUP (tmr, ""); Assert (v == Val_unit); - return heap_stats (1); + result = heap_stats (1); + CAML_INSTR_TIME (tmr, "explicit/gc_stat"); + return result; } CAMLprim value caml_gc_quick_stat(value v) @@ -266,13 +277,13 @@ CAMLprim value caml_gc_quick_stat(value v) /* get a copy of these before allocating anything... */ double minwords = caml_stat_minor_words - + (double) Wsize_bsize (caml_young_end - caml_young_ptr); + + (double) (caml_young_alloc_end - caml_young_ptr); double prowords = caml_stat_promoted_words; double majwords = caml_stat_major_words + (double) caml_allocated_words; intnat mincoll = caml_stat_minor_collections; intnat majcoll = caml_stat_major_collections; - intnat heap_words = caml_stat_heap_size / sizeof (value); - intnat top_heap_words = caml_stat_top_heap_size / sizeof (value); + intnat heap_words = caml_stat_heap_wsz; + intnat top_heap_words = caml_stat_top_heap_wsz; intnat cpct = caml_stat_compactions; intnat heap_chunks = caml_stat_heap_chunks; @@ -303,7 +314,7 @@ CAMLprim value caml_gc_counters(value v) /* get a copy of these before allocating anything... */ double minwords = caml_stat_minor_words - + (double) Wsize_bsize (caml_young_end - caml_young_ptr); + + (double) (caml_young_alloc_end - caml_young_ptr); double prowords = caml_stat_promoted_words; double majwords = caml_stat_major_words + (double) caml_allocated_words; @@ -314,13 +325,18 @@ CAMLprim value caml_gc_counters(value v) CAMLreturn (res); } +CAMLprim value caml_gc_huge_fallback_count (value v) +{ + return Val_long (caml_huge_fallback_count); +} + CAMLprim value caml_gc_get(value v) { CAMLparam0 (); /* v is ignored */ CAMLlocal1 (res); - res = caml_alloc_tuple (7); - Store_field (res, 0, Val_long (Wsize_bsize (caml_minor_heap_size))); /* s */ + res = caml_alloc_tuple (8); + Store_field (res, 0, Val_long (caml_minor_heap_wsz)); /* s */ Store_field (res, 1, Val_long (caml_major_heap_increment)); /* i */ Store_field (res, 2, Val_long (caml_percent_free)); /* o */ Store_field (res, 3, Val_long (caml_verb_gc)); /* v */ @@ -331,6 +347,7 @@ CAMLprim value caml_gc_get(value v) Store_field (res, 5, Val_long (0)); #endif Store_field (res, 6, Val_long (caml_allocation_policy)); /* a */ + Store_field (res, 7, Val_long (caml_major_window)); /* w */ CAMLreturn (res); } @@ -353,12 +370,20 @@ static intnat norm_minsize (intnat s) return s; } +static uintnat norm_window (intnat w) +{ + if (w < 1) w = 1; + if (w > Max_major_window) w = Max_major_window; + return w; +} + CAMLprim value caml_gc_set(value v) { uintnat newpf, newpm; asize_t newheapincr; - asize_t newminsize; + asize_t newminwsz; uintnat oldpolicy; + CAML_INSTR_SETUP (tmr, ""); caml_verb_gc = Long_val (Field (v, 3)); @@ -396,20 +421,35 @@ CAMLprim value caml_gc_set(value v) caml_allocation_policy); } + /* This field was added in 4.03.0. */ + if (Wosize_val (v) >= 8){ + int old_window = caml_major_window; + caml_set_major_window (norm_window (Long_val (Field (v, 7)))); + if (old_window != caml_major_window){ + caml_gc_message (0x20, "New smoothing window size: %d\n", + caml_major_window); + } + } + /* Minor heap size comes last because it will trigger a minor collection (thus invalidating [v]) and it can raise [Out_of_memory]. */ - newminsize = Bsize_wsize (norm_minsize (Long_val (Field (v, 0)))); - if (newminsize != caml_minor_heap_size){ - caml_gc_message (0x20, "New minor heap size: %luk bytes\n", - newminsize/1024); - caml_set_minor_heap_size (newminsize); + newminwsz = norm_minsize (Long_val (Field (v, 0))); + if (newminwsz != caml_minor_heap_wsz){ + caml_gc_message (0x20, "New minor heap size: %luk words\n", + newminwsz / 1024); + caml_set_minor_heap_size (Bsize_wsize (newminwsz)); } + CAML_INSTR_TIME (tmr, "explicit/gc_set"); return Val_unit; } CAMLprim value caml_gc_minor(value v) -{ Assert (v == Val_unit); - caml_minor_collection (); +{ + CAML_INSTR_SETUP (tmr, ""); + Assert (v == Val_unit); + caml_request_minor_gc (); + caml_gc_dispatch (); + CAML_INSTR_TIME (tmr, "explicit/gc_minor"); return Val_unit; } @@ -417,8 +457,7 @@ static void test_and_compact (void) { float fp; - fp = 100.0 * caml_fl_cur_size - / (Wsize_bsize (caml_stat_heap_size) - caml_fl_cur_size); + fp = 100.0 * caml_fl_cur_wsz / (caml_stat_heap_wsz - caml_fl_cur_wsz); if (fp > 999999.0) fp = 999999.0; caml_gc_message (0x200, "Estimated overhead (lower bound) = %" ARCH_INTNAT_PRINTF_FORMAT "u%%\n", @@ -430,17 +469,22 @@ static void test_and_compact (void) } CAMLprim value caml_gc_major(value v) -{ Assert (v == Val_unit); +{ + CAML_INSTR_SETUP (tmr, ""); + Assert (v == Val_unit); caml_gc_message (0x1, "Major GC cycle requested\n", 0); caml_empty_minor_heap (); caml_finish_major_cycle (); test_and_compact (); caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "explicit/gc_major"); return Val_unit; } CAMLprim value caml_gc_full_major(value v) -{ Assert (v == Val_unit); +{ + CAML_INSTR_SETUP (tmr, ""); + Assert (v == Val_unit); caml_gc_message (0x1, "Full major GC cycle requested\n", 0); caml_empty_minor_heap (); caml_finish_major_cycle (); @@ -449,18 +493,23 @@ CAMLprim value caml_gc_full_major(value v) caml_finish_major_cycle (); test_and_compact (); caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "explicit/gc_full_major"); return Val_unit; } CAMLprim value caml_gc_major_slice (value v) { + CAML_INSTR_SETUP (tmr, ""); Assert (Is_long (v)); - caml_empty_minor_heap (); - return Val_long (caml_major_collection_slice (Long_val (v))); + caml_major_collection_slice (Long_val (v)); + CAML_INSTR_TIME (tmr, "explicit/gc_major_slice"); + return Val_long (0); } CAMLprim value caml_gc_compaction(value v) -{ Assert (v == Val_unit); +{ + CAML_INSTR_SETUP (tmr, ""); + Assert (v == Val_unit); caml_gc_message (0x10, "Heap compaction requested\n", 0); caml_empty_minor_heap (); caml_finish_major_cycle (); @@ -469,9 +518,35 @@ CAMLprim value caml_gc_compaction(value v) caml_finish_major_cycle (); caml_compact_heap (); caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "explicit/gc_compact"); return Val_unit; } +CAMLprim value caml_get_minor_free (value v) +{ + return Val_int (caml_young_ptr - caml_young_alloc_start); +} + +CAMLprim value caml_get_major_bucket (value v) +{ + long i = Long_val (v); + if (i < 0) caml_invalid_argument ("Gc.get_bucket"); + if (i < caml_major_window){ + i += caml_major_ring_index; + if (i >= caml_major_window) i -= caml_major_window; + CAMLassert (0 <= i && i < caml_major_window); + return Val_long ((long) (caml_major_ring[i] * 1e6)); + }else{ + return Val_long (0); + } +} + +CAMLprim value caml_get_major_credit (value v) +{ + CAMLassert (v == Val_unit); + return Val_long ((long) (caml_major_work_credit * 1e6)); +} + uintnat caml_normalize_heap_increment (uintnat i) { if (i < Bsize_wsize (Heap_chunk_min)){ @@ -480,13 +555,19 @@ uintnat caml_normalize_heap_increment (uintnat i) return ((i + Page_size - 1) >> Page_log) << Page_log; } +/* [minor_size] and [major_size] are numbers of words + [major_incr] is either a percentage or a number of words */ void caml_init_gc (uintnat minor_size, uintnat major_size, uintnat major_incr, uintnat percent_fr, - uintnat percent_m) + uintnat percent_m, uintnat window) { uintnat major_heap_size = Bsize_wsize (caml_normalize_heap_increment (major_size)); + CAML_INSTR_INIT (); + if (caml_init_alloc_for_heap () != 0){ + caml_fatal_error ("cannot initialize heap: mmap failed\n"); + } if (caml_page_table_initialize(Bsize_wsize(minor_size) + major_heap_size)){ caml_fatal_error ("OCaml runtime error: cannot initialize page table\n"); } @@ -495,8 +576,9 @@ void caml_init_gc (uintnat minor_size, uintnat major_size, caml_percent_free = norm_pfree (percent_fr); caml_percent_max = norm_pmax (percent_m); caml_init_major_heap (major_heap_size); - caml_gc_message (0x20, "Initial minor heap size: %luk bytes\n", - caml_minor_heap_size / 1024); + caml_major_window = norm_window (window); + caml_gc_message (0x20, "Initial minor heap size: %luk words\n", + caml_minor_heap_wsz / 1024); caml_gc_message (0x20, "Initial major heap size: %luk bytes\n", major_heap_size / 1024); caml_gc_message (0x20, "Initial space overhead: %lu%%\n", caml_percent_free); @@ -510,4 +592,63 @@ void caml_init_gc (uintnat minor_size, uintnat major_size, } caml_gc_message (0x20, "Initial allocation policy: %d\n", caml_allocation_policy); + caml_gc_message (0x20, "Initial smoothing window: %d\n", + caml_major_window); +} + + +/* FIXME After the startup_aux.c unification, move these functions there. */ + +CAMLprim value caml_runtime_variant (value unit) +{ + CAMLassert (unit == Val_unit); +#if defined (DEBUG) + return caml_copy_string ("d"); +#elif defined (CAML_INSTR) + return caml_copy_string ("i"); +#else + return caml_copy_string (""); +#endif +} + +extern int caml_parser_trace; + +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, + /* 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, +#else + /* l */ caml_max_stack_size, +#endif + /* o */ caml_percent_free, + /* O */ caml_percent_max, + /* p */ caml_parser_trace, + /* R */ /* missing */ + /* s */ caml_minor_heap_wsz, + /* t */ caml_trace_level, + /* v */ caml_verb_gc, + /* w */ caml_major_window, + /* W */ caml_runtime_warnings + ); +} + +/* Control runtime warnings */ + +CAMLprim value caml_ml_enable_runtime_warnings(value vbool) +{ + caml_runtime_warnings = Bool_val(vbool); + return Val_unit; +} + +CAMLprim value caml_ml_runtime_warnings_enabled(value vbool) +{ + return Val_bool(caml_runtime_warnings); } diff --git a/byterun/globroots.c b/byterun/globroots.c index d3dd9252..138b808b 100644 --- a/byterun/globroots.c +++ b/byterun/globroots.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ /* Registration of global memory roots */ @@ -43,11 +45,11 @@ struct global_root_list { (i.e. 2 * (NUM_LEVELS - 1)). Moreover, the congruential PRNG is faster and guaranteed to be deterministic (to reproduce bugs). */ -static uint32 random_seed = 0; +static uint32_t random_seed = 0; static int random_level(void) { - uint32 r; + uint32_t r; int level = 0; /* Linear congruence with modulus = 2^32, multiplier = 69069 @@ -70,6 +72,8 @@ static void caml_insert_global_root(struct global_root_list * rootlist, struct global_root * e, * f; int i, new_level; + Assert(0 <= rootlist->level && rootlist->level < NUM_LEVELS); + /* Init "cursor" to list head */ e = (struct global_root *) rootlist; /* Find place to insert new node */ @@ -109,6 +113,8 @@ static void caml_delete_global_root(struct global_root_list * rootlist, struct global_root * e, * f; int i; + Assert(0 <= rootlist->level && rootlist->level < NUM_LEVELS); + /* Init "cursor" to list head */ e = (struct global_root *) rootlist; /* Find element in list */ @@ -155,6 +161,8 @@ static void caml_empty_global_roots(struct global_root_list * rootlist) struct global_root * gr, * next; int i; + Assert(0 <= rootlist->level && rootlist->level < NUM_LEVELS); + for (gr = rootlist->forward[0]; gr != NULL; /**/) { next = gr->forward[0]; caml_stat_free(gr); diff --git a/byterun/hash.c b/byterun/hash.c index 8663a3db..6089dba2 100644 --- a/byterun/hash.c +++ b/byterun/hash.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The generic hashing primitive */ @@ -41,7 +43,7 @@ h *= 0xc2b2ae35; \ h ^= h >> 16; -CAMLexport uint32 caml_hash_mix_uint32(uint32 h, uint32 d) +CAMLexport uint32_t caml_hash_mix_uint32(uint32_t h, uint32_t d) { MIX(h, d); return h; @@ -49,17 +51,17 @@ CAMLexport uint32 caml_hash_mix_uint32(uint32 h, uint32 d) /* Mix a platform-native integer. */ -CAMLexport uint32 caml_hash_mix_intnat(uint32 h, intnat d) +CAMLexport uint32_t caml_hash_mix_intnat(uint32_t h, intnat d) { - uint32 n; + uint32_t n; #ifdef ARCH_SIXTYFOUR /* Mix the low 32 bits and the high 32 bits, in a way that preserves - 32/64 compatibility: we want n = (uint32) d + 32/64 compatibility: we want n = (uint32_t) d if d is in the range [-2^31, 2^31-1]. */ n = (d >> 32) ^ (d >> 63) ^ d; /* If 0 <= d < 2^31: d >> 32 = 0 d >> 63 = 0 If -2^31 <= d < 0: d >> 32 = -1 d >> 63 = -1 - In both cases, n = (uint32) d. */ + In both cases, n = (uint32_t) d. */ #else n = d; #endif @@ -69,9 +71,9 @@ CAMLexport uint32 caml_hash_mix_intnat(uint32 h, intnat d) /* Mix a 64-bit integer. */ -CAMLexport uint32 caml_hash_mix_int64(uint32 h, int64 d) +CAMLexport uint32_t caml_hash_mix_int64(uint32_t h, int64_t d) { - uint32 hi = (uint32) (d >> 32), lo = (uint32) d; + uint32_t hi = (uint32_t) (d >> 32), lo = (uint32_t) d; MIX(h, lo); MIX(h, hi); return h; @@ -82,17 +84,17 @@ CAMLexport uint32 caml_hash_mix_int64(uint32 h, int64 d) Treats all NaNs identically. */ -CAMLexport uint32 caml_hash_mix_double(uint32 hash, double d) +CAMLexport uint32_t caml_hash_mix_double(uint32_t hash, double d) { union { double d; #if defined(ARCH_BIG_ENDIAN) || (defined(__arm__) && !defined(__ARM_EABI__)) - struct { uint32 h; uint32 l; } i; + struct { uint32_t h; uint32_t l; } i; #else - struct { uint32 l; uint32 h; } i; + struct { uint32_t l; uint32_t h; } i; #endif } u; - uint32 h, l; + uint32_t h, l; /* Convert to two 32-bit halves */ u.d = d; h = u.i.h; l = u.i.l; @@ -115,14 +117,14 @@ CAMLexport uint32 caml_hash_mix_double(uint32 hash, double d) Treats all NaNs identically. */ -CAMLexport uint32 caml_hash_mix_float(uint32 hash, float d) +CAMLexport uint32_t caml_hash_mix_float(uint32_t hash, float d) { union { float f; - uint32 i; + uint32_t i; } u; - uint32 n; - /* Convert to int32 */ + uint32_t n; + /* Convert to int32_t */ u.f = d; n = u.i; /* Normalize NaNs */ if ((n & 0x7F800000) == 0x7F800000 && (n & 0x007FFFFF) != 0) { @@ -138,11 +140,11 @@ CAMLexport uint32 caml_hash_mix_float(uint32 hash, float d) /* Mix an OCaml string */ -CAMLexport uint32 caml_hash_mix_string(uint32 h, value s) +CAMLexport uint32_t caml_hash_mix_string(uint32_t h, value s) { mlsize_t len = caml_string_length(s); mlsize_t i; - uint32 w; + uint32_t w; /* Mix by 32-bit blocks (little-endian) */ for (i = 0; i + 4 <= len; i += 4) { @@ -152,7 +154,7 @@ CAMLexport uint32 caml_hash_mix_string(uint32 h, value s) | (Byte_u(s, i+2) << 16) | (Byte_u(s, i+3) << 24); #else - w = *((uint32 *) &Byte_u(s, i)); + w = *((uint32_t *) &Byte_u(s, i)); #endif MIX(h, w); } @@ -166,7 +168,7 @@ CAMLexport uint32 caml_hash_mix_string(uint32 h, value s) default: /*skip*/; /* len & 3 == 0, no extra bytes, do nothing */ } /* Finally, mix in the length. Ignore the upper 32 bits, generally 0. */ - h ^= (uint32) len; + h ^= (uint32_t) len; return h; } @@ -184,7 +186,7 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj) intnat wr; /* One past position of last value in queue */ intnat sz; /* Max number of values to put in queue */ intnat num; /* Max number of meaningful values to see */ - uint32 h; /* Rolling hash */ + uint32_t h; /* Rolling hash */ value v; mlsize_t i, len; @@ -245,7 +247,7 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj) /* If no hashing function provided, do nothing. */ /* Only use low 32 bits of custom hash, for 32/64 compatibility */ if (Custom_ops_val(v)->hash != NULL) { - uint32 n = (uint32) Custom_ops_val(v)->hash(v); + uint32_t n = (uint32_t) Custom_ops_val(v)->hash(v); h = caml_hash_mix_uint32(h, n); num--; } @@ -408,5 +410,5 @@ CAMLexport value caml_hash_variant(char const * tag) #endif /* Force sign extension of bit 31 for compatibility between 32 and 64-bit platforms */ - return (int32) accu; + return (int32_t) accu; } diff --git a/byterun/instrtrace.c b/byterun/instrtrace.c index 712b4636..bf2d3038 100644 --- a/byterun/instrtrace.c +++ b/byterun/instrtrace.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Trace the instructions executed */ @@ -19,12 +21,14 @@ #include #include +#include "caml/instrtrace.h" #include "caml/instruct.h" #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/opnames.h" #include "caml/prims.h" #include "caml/stacks.h" +#include "caml/startup_aux.h" extern code_t caml_start_code; @@ -32,8 +36,6 @@ intnat caml_icount = 0; void caml_stop_here () {} -int caml_trace_flag = 0; - void caml_disasm_instr(pc) code_t pc; { @@ -183,25 +185,26 @@ caml_trace_value_file (value v, code_t prog, int proglen, FILE * f) if (prog && v % sizeof (int) == 0 && (code_t) v >= prog && (code_t) v < (code_t) ((char *) prog + proglen)) - fprintf (f, "=code@%ld", (code_t) v - prog); + fprintf (f, "=code@%ld", (long) ((code_t) v - prog)); else if (Is_long (v)) fprintf (f, "=long%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val (v)); else if ((void*)v >= (void*)caml_stack_low && (void*)v < (void*)caml_stack_high) - fprintf (f, "=stack_%ld", (intnat*)caml_stack_high - (intnat*)v); + fprintf (f, "=stack_%ld", (long) ((intnat*)caml_stack_high - (intnat*)v)); else if (Is_block (v)) { int s = Wosize_val (v); int tg = Tag_val (v); int l = 0; switch (tg) { case Closure_tag: - fprintf (f, "=closure[s%d,cod%ld]", s, (code_t) (Code_val (v)) - prog); + fprintf (f, "=closure[s%d,cod%ld]", + s, (long) ((code_t) (Code_val (v)) - prog)); goto displayfields; case String_tag: l = caml_string_length (v); fprintf (f, "=string[s%dL%d]'", s, l); for (i = 0; i < ((l>0x1f)?0x1f:l) ; i++) { - if (isprint (Byte (v, i))) + if (isprint ((int) Byte (v, i))) putc (Byte (v, i), f); else putc ('?', f); @@ -251,10 +254,10 @@ caml_trace_accu_sp_file (value accu, value * sp, code_t prog, int proglen, fprintf (f, "accu="); caml_trace_value_file (accu, prog, proglen, f); fprintf (f, "\n sp=%#" ARCH_INTNAT_PRINTF_FORMAT "x @%ld:", - (intnat) sp, caml_stack_high - sp); - for (p = sp, i = 0; i < 12 + (1 << caml_trace_flag) && p < caml_stack_high; + (intnat) sp, (long) (caml_stack_high - sp)); + for (p = sp, i = 0; i < 12 + (1 << caml_trace_level) && p < caml_stack_high; p++, i++) { - fprintf (f, "\n[%ld] ", caml_stack_high - p); + fprintf (f, "\n[%ld] ", (long) (caml_stack_high - p)); caml_trace_value_file (*p, prog, proglen, f); }; putc ('\n', f); diff --git a/byterun/intern.c b/byterun/intern.c index d2943afb..96196ff2 100644 --- a/byterun/intern.c +++ b/byterun/intern.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Structured input, compact format */ @@ -19,6 +21,7 @@ #include #include "caml/alloc.h" #include "caml/callback.h" +#include "caml/config.h" #include "caml/custom.h" #include "caml/fail.h" #include "caml/gc.h" @@ -33,24 +36,20 @@ static unsigned char * intern_src; /* Reading pointer in block holding input data. */ -static unsigned char * intern_input; -/* Pointer to beginning of block holding input data. - Meaningful only if intern_input_malloced = 1. */ - -static int intern_input_malloced; -/* 1 if intern_input was allocated by caml_stat_alloc() - and needs caml_stat_free() on error, 0 otherwise. */ +static unsigned char * intern_input = NULL; +/* Pointer to beginning of block holding input data, + if non-NULL this pointer will be freed by the cleanup function. */ static header_t * intern_dest; /* Writing pointer in destination block */ -static char * intern_extra_block; +static char * intern_extra_block = NULL; /* If non-NULL, point to new heap chunk allocated with caml_alloc_for_heap. */ static asize_t obj_counter; /* Count how many objects seen so far */ -static value * intern_obj_table; +static value * intern_obj_table = NULL; /* The pointers to objects already seen */ static unsigned int intern_color; @@ -60,61 +59,109 @@ static header_t intern_header; /* Original header of the destination block. Meaningful only if intern_extra_block is NULL. */ -static value intern_block; +static value intern_block = 0; /* Point to the heap block allocated as destination block. Meaningful only if intern_extra_block is NULL. */ static char * intern_resolve_code_pointer(unsigned char digest[16], asize_t offset); -static void intern_bad_code_pointer(unsigned char digest[16]) Noreturn; + +CAMLnoreturn_start +static void intern_bad_code_pointer(unsigned char digest[16]) +CAMLnoreturn_end; static void intern_free_stack(void); -#define Sign_extend_shift ((sizeof(intnat) - 1) * 8) -#define Sign_extend(x) (((intnat)(x) << Sign_extend_shift) >> Sign_extend_shift) - -#define read8u() (*intern_src++) -#define read8s() Sign_extend(*intern_src++) -#define read16u() \ - (intern_src += 2, \ - (intern_src[-2] << 8) + intern_src[-1]) -#define read16s() \ - (intern_src += 2, \ - (Sign_extend(intern_src[-2]) << 8) + intern_src[-1]) -#define read32u() \ - (intern_src += 4, \ - ((uintnat)(intern_src[-4]) << 24) + (intern_src[-3] << 16) + \ - (intern_src[-2] << 8) + intern_src[-1]) -#define read32s() \ - (intern_src += 4, \ - (Sign_extend(intern_src[-4]) << 24) + (intern_src[-3] << 16) + \ - (intern_src[-2] << 8) + intern_src[-1]) +static inline unsigned char read8u(void) +{ return *intern_src++; } -#ifdef ARCH_SIXTYFOUR -static intnat read64s(void) +static inline signed char read8s(void) +{ return *intern_src++; } + +static inline uint16_t read16u(void) { - intnat res; - int i; - res = 0; - for (i = 0; i < 8; i++) res = (res << 8) + intern_src[i]; + uint16_t res = (intern_src[0] << 8) + intern_src[1]; + intern_src += 2; + return res; +} + +static inline int16_t read16s(void) +{ + int16_t res = (intern_src[0] << 8) + intern_src[1]; + intern_src += 2; + return res; +} + +static inline uint32_t read32u(void) +{ + uint32_t res = + ((uint32_t)(intern_src[0]) << 24) + (intern_src[1] << 16) + + (intern_src[2] << 8) + intern_src[3]; + intern_src += 4; + return res; +} + +static inline int32_t read32s(void) +{ + int32_t res = + ((uint32_t)(intern_src[0]) << 24) + (intern_src[1] << 16) + + (intern_src[2] << 8) + intern_src[3]; + intern_src += 4; + return res; +} + +#ifdef ARCH_SIXTYFOUR +static uintnat read64u(void) +{ + uintnat res = + ((uintnat) (intern_src[0]) << 56) + + ((uintnat) (intern_src[1]) << 48) + + ((uintnat) (intern_src[2]) << 40) + + ((uintnat) (intern_src[3]) << 32) + + ((uintnat) (intern_src[4]) << 24) + + ((uintnat) (intern_src[5]) << 16) + + ((uintnat) (intern_src[6]) << 8) + + (uintnat) (intern_src[7]); intern_src += 8; return res; } #endif -#define readblock(dest,len) \ - (memmove((dest), intern_src, (len)), intern_src += (len)) +static inline void readblock(void * dest, intnat len) +{ + memcpy(dest, intern_src, len); + intern_src += len; +} + +static void intern_init(void * src, void * input) +{ + /* This is asserted at the beginning of demarshaling primitives. + If it fails, it probably means that an exception was raised + without calling intern_cleanup() during the previous demarshaling. */ + Assert (intern_input == NULL && intern_obj_table == NULL \ + && intern_extra_block == NULL && intern_block == 0); + intern_src = src; + intern_input = input; +} static void intern_cleanup(void) { - if (intern_input_malloced) caml_stat_free(intern_input); - if (intern_obj_table != NULL) caml_stat_free(intern_obj_table); + if (intern_input != NULL) { + caml_stat_free(intern_input); + intern_input = NULL; + } + if (intern_obj_table != NULL) { + caml_stat_free(intern_obj_table); + intern_obj_table = NULL; + } if (intern_extra_block != NULL) { /* free newly allocated heap chunk */ caml_free_for_heap(intern_extra_block); + intern_extra_block = NULL; } else if (intern_block != 0) { /* restore original header for heap block, otherwise GC is confused */ Hd_val(intern_block) = intern_header; + intern_block = 0; } /* free the recursion stack */ intern_free_stack(); @@ -143,6 +190,7 @@ static void readfloat(double * dest, unsigned int code) #endif } +/* [len] is a number of floats */ static void readfloats(double * dest, mlsize_t len, unsigned int code) { mlsize_t i; @@ -287,7 +335,7 @@ static void intern_rec(value *dest) case OFreshOID: /* Refresh the object ID */ /* but do not do it for predefined exception slots */ - if (Int_val(Field((value)dest, 1)) >= 0) + if (Long_val(Field((value)dest, 1)) >= 0) caml_set_oo_id((value)dest); /* Pop item and iterate */ sp--; @@ -364,7 +412,7 @@ static void intern_rec(value *dest) break; case CODE_INT64: #ifdef ARCH_SIXTYFOUR - v = Val_long(read64s()); + v = Val_long((intnat) (read64u())); break; #else intern_cleanup(); @@ -385,21 +433,22 @@ static void intern_rec(value *dest) case CODE_SHARED32: ofs = read32u(); goto read_shared; +#ifdef ARCH_SIXTYFOUR + case CODE_SHARED64: + ofs = read64u(); + goto read_shared; +#endif case CODE_BLOCK32: header = (header_t) read32u(); tag = Tag_hd(header); size = Wosize_hd(header); goto read_block; - case CODE_BLOCK64: #ifdef ARCH_SIXTYFOUR - header = (header_t) read64s(); + case CODE_BLOCK64: + header = (header_t) read64u(); tag = Tag_hd(header); size = Wosize_hd(header); goto read_block; -#else - intern_cleanup(); - caml_failwith("input_value: data block too large"); - break; #endif case CODE_STRING8: len = read8u(); @@ -407,6 +456,11 @@ static void intern_rec(value *dest) case CODE_STRING32: len = read32u(); goto read_string; +#ifdef ARCH_SIXTYFOUR + case CODE_STRING64: + len = read64u(); + goto read_string; +#endif case CODE_DOUBLE_LITTLE: case CODE_DOUBLE_BIG: v = Val_hp(intern_dest); @@ -430,6 +484,12 @@ static void intern_rec(value *dest) case CODE_DOUBLE_ARRAY32_BIG: len = read32u(); goto read_double_array; +#ifdef ARCH_SIXTYFOUR + case CODE_DOUBLE_ARRAY64_LITTLE: + case CODE_DOUBLE_ARRAY64_BIG: + len = read64u(); + goto read_double_array; +#endif case CODE_CODEPOINTER: ofs = read32u(); readblock(digest, 16); @@ -469,6 +529,12 @@ static void intern_rec(value *dest) if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; *intern_dest = Make_header(size, Custom_tag, intern_color); Custom_ops_val(v) = ops; + + if (ops->finalize != NULL && Is_young(v)) { + /* Remember that the block has a finalizer. */ + add_to_custom_table (&caml_custom_table, v, 0, 1); + } + intern_dest += 1 + size; break; default: @@ -493,9 +559,8 @@ static void intern_alloc(mlsize_t whsize, mlsize_t num_objects) mlsize_t wosize; if (whsize == 0) { - intern_obj_table = NULL; - intern_extra_block = NULL; - intern_block = 0; + Assert (intern_extra_block == NULL && intern_block == 0 + && intern_obj_table == NULL); return; } wosize = Wosize_whsize(whsize); @@ -504,9 +569,13 @@ static void intern_alloc(mlsize_t whsize, mlsize_t num_objects) asize_t request = ((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log; intern_extra_block = caml_alloc_for_heap(request); - if (intern_extra_block == NULL) caml_raise_out_of_memory(); + if (intern_extra_block == NULL) { + intern_cleanup(); + caml_raise_out_of_memory(); + } intern_color = caml_allocation_color(intern_extra_block); intern_dest = (header_t *) intern_extra_block; + Assert (intern_block == 0); } else { /* this is a specialised version of caml_alloc from alloc.c */ if (wosize == 0){ @@ -514,21 +583,29 @@ static void intern_alloc(mlsize_t whsize, mlsize_t num_objects) }else if (wosize <= Max_young_wosize){ intern_block = caml_alloc_small (wosize, String_tag); }else{ - intern_block = caml_alloc_shr (wosize, String_tag); + intern_block = caml_alloc_shr_no_raise (wosize, String_tag); /* do not do the urgent_gc check here because it might darken intern_block into gray and break the Assert 3 lines down */ + if (intern_block == 0) { + intern_cleanup(); + caml_raise_out_of_memory(); + } } intern_header = Hd_val(intern_block); intern_color = Color_hd(intern_header); Assert (intern_color == Caml_white || intern_color == Caml_black); intern_dest = (header_t *) Hp_val(intern_block); - intern_extra_block = NULL; + Assert (intern_extra_block == NULL); } obj_counter = 0; - if (num_objects > 0) - intern_obj_table = (value *) caml_stat_alloc(num_objects * sizeof(value)); - else - intern_obj_table = NULL; + if (num_objects > 0) { + intern_obj_table = (value *) malloc(num_objects * sizeof(value)); + if (intern_obj_table == NULL) { + intern_cleanup(); + caml_raise_out_of_memory(); + } + } else + Assert(intern_obj_table == NULL); } static void intern_add_to_heap(mlsize_t whsize) @@ -536,10 +613,10 @@ static void intern_add_to_heap(mlsize_t whsize) /* Add new heap chunk to heap if needed */ if (intern_extra_block != NULL) { /* If heap chunk not filled totally, build free block at end */ - asize_t request = - ((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log; + asize_t request = Chunk_size (intern_extra_block); header_t * end_extra_block = (header_t *) intern_extra_block + Wsize_bsize(request); + Assert(intern_block == 0); Assert(intern_dest <= end_extra_block); if (intern_dest < end_extra_block){ caml_make_free_blocks ((value *) intern_dest, @@ -548,49 +625,105 @@ static void intern_add_to_heap(mlsize_t whsize) caml_allocated_words += Wsize_bsize ((char *) intern_dest - intern_extra_block); caml_add_to_heap(intern_extra_block); + intern_extra_block = NULL; // To prevent intern_cleanup freeing it + } else { + intern_block = 0; // To prevent intern_cleanup rewriting its header + } +} + +/* Parsing the header */ + +struct marshal_header { + uint32_t magic; + int header_len; + uintnat data_len; + uintnat num_objects; + uintnat whsize; +}; + +static void caml_parse_header(char * fun_name, + /*out*/ struct marshal_header * h) +{ + char errmsg[100]; + + h->magic = read32u(); + switch(h->magic) { + case Intext_magic_number_small: + h->header_len = 20; + h->data_len = read32u(); + h->num_objects = read32u(); +#ifdef ARCH_SIXTYFOUR + read32u(); + h->whsize = read32u(); +#else + h->whsize = read32u(); + read32u(); +#endif + break; + case Intext_magic_number_big: +#ifdef ARCH_SIXTYFOUR + h->header_len = 32; + read32u(); + h->data_len = read64u(); + h->num_objects = read64u(); + h->whsize = read64u(); +#else + errmsg[sizeof(errmsg) - 1] = 0; + snprintf(errmsg, sizeof(errmsg) - 1, + "%s: object too large to be read back on a 32-bit platform", + fun_name); + caml_failwith(errmsg); +#endif + break; + default: + errmsg[sizeof(errmsg) - 1] = 0; + snprintf(errmsg, sizeof(errmsg) - 1, + "%s: bad object", + fun_name); + caml_failwith(errmsg); } } +/* Reading from a channel */ + value caml_input_val(struct channel *chan) { - uint32 magic; - mlsize_t block_len, num_objects, whsize; + char header[32]; + struct marshal_header h; char * block; value res; if (! caml_channel_binary_mode(chan)) caml_failwith("input_value: not a binary channel"); - magic = caml_getword(chan); - if (magic != Intext_magic_number) caml_failwith("input_value: bad object"); - block_len = caml_getword(chan); - num_objects = caml_getword(chan); -#ifdef ARCH_SIXTYFOUR - caml_getword(chan); /* skip size_32 */ - whsize = caml_getword(chan); -#else - whsize = caml_getword(chan); - caml_getword(chan); /* skip size_64 */ -#endif + /* Read and parse the header */ + if (caml_really_getblock(chan, header, 20) == 0) + caml_failwith("input_value: truncated object"); + intern_src = (unsigned char *) header; + if (read32u() == Intext_magic_number_big) { + /* Finish reading the header */ + if (caml_really_getblock(chan, header + 20, 32 - 20) == 0) + caml_failwith("input_value: truncated object"); + } + intern_src = (unsigned char *) header; + caml_parse_header("input_value", &h); /* Read block from channel */ - block = caml_stat_alloc(block_len); + block = caml_stat_alloc(h.data_len); /* During [caml_really_getblock], concurrent [caml_input_val] operations can take place (via signal handlers or context switching in systhreads), and [intern_input] may change. So, wait until [caml_really_getblock] is over before using [intern_input] and the other global vars. */ - if (caml_really_getblock(chan, block, block_len) == 0) { + if (caml_really_getblock(chan, block, h.data_len) == 0) { caml_stat_free(block); caml_failwith("input_value: truncated object"); } - intern_input = (unsigned char *) block; - intern_input_malloced = 1; - intern_src = intern_input; - intern_alloc(whsize, num_objects); + /* Initialize global state */ + intern_init(block, block); + intern_alloc(h.whsize, h.num_objects); /* Fill it in */ intern_rec(&res); - intern_add_to_heap(whsize); + intern_add_to_heap(h.whsize); /* Free everything */ - caml_stat_free(intern_input); - if (intern_obj_table != NULL) caml_stat_free(intern_obj_table); + intern_cleanup(); return caml_check_urgent_gc(res); } @@ -606,30 +739,27 @@ CAMLprim value caml_input_value(value vchan) CAMLreturn (res); } +/* Reading from memory-resident blocks */ + CAMLexport value caml_input_val_from_string(value str, intnat ofs) { CAMLparam1 (str); - mlsize_t num_objects, whsize; CAMLlocal1 (obj); + struct marshal_header h; - intern_src = &Byte_u(str, ofs + 2*4); - intern_input_malloced = 0; - num_objects = read32u(); -#ifdef ARCH_SIXTYFOUR - intern_src += 4; /* skip size_32 */ - whsize = read32u(); -#else - whsize = read32u(); - intern_src += 4; /* skip size_64 */ -#endif + /* Initialize global state */ + intern_init(&Byte_u(str, ofs), NULL); + caml_parse_header("input_val_from_string", &h); + if (ofs + h.header_len + h.data_len > caml_string_length(str)) + caml_failwith("input_val_from_string: bad length"); /* Allocate result */ - intern_alloc(whsize, num_objects); - intern_src = &Byte_u(str, ofs + 5*4); /* If a GC occurred */ + intern_alloc(h.whsize, h.num_objects); + intern_src = &Byte_u(str, ofs + h.header_len); /* If a GC occurred */ /* Fill it in */ intern_rec(&obj); - intern_add_to_heap(whsize); + intern_add_to_heap(h.whsize); /* Free everything */ - if (intern_obj_table != NULL) caml_stat_free(intern_obj_table); + intern_cleanup(); CAMLreturn (caml_check_urgent_gc(obj)); } @@ -638,79 +768,77 @@ CAMLprim value caml_input_value_from_string(value str, value ofs) return caml_input_val_from_string(str, Long_val(ofs)); } -static value input_val_from_block(void) +static value input_val_from_block(struct marshal_header * h) { - mlsize_t num_objects, whsize; value obj; - - num_objects = read32u(); -#ifdef ARCH_SIXTYFOUR - intern_src += 4; /* skip size_32 */ - whsize = read32u(); -#else - whsize = read32u(); - intern_src += 4; /* skip size_64 */ -#endif /* Allocate result */ - intern_alloc(whsize, num_objects); + intern_alloc(h->whsize, h->num_objects); /* Fill it in */ intern_rec(&obj); - intern_add_to_heap(whsize); + intern_add_to_heap(h->whsize); /* Free internal data structures */ - if (intern_obj_table != NULL) caml_stat_free(intern_obj_table); + intern_cleanup(); return caml_check_urgent_gc(obj); } CAMLexport value caml_input_value_from_malloc(char * data, intnat ofs) { - uint32 magic; - value obj; + struct marshal_header h; - intern_input = (unsigned char *) data; - intern_src = intern_input + ofs; - intern_input_malloced = 1; - magic = read32u(); - if (magic != Intext_magic_number) - caml_failwith("input_value_from_malloc: bad object"); - intern_src += 4; /* Skip block_len */ - obj = input_val_from_block(); - /* Free the input */ - caml_stat_free(intern_input); - return obj; + intern_init(data + ofs, data); + + caml_parse_header("input_value_from_malloc", &h); + + return input_val_from_block(&h); } +/* [len] is a number of bytes */ CAMLexport value caml_input_value_from_block(char * data, intnat len) { - uint32 magic; - mlsize_t block_len; - value obj; + struct marshal_header h; - intern_input = (unsigned char *) data; - intern_src = intern_input; - intern_input_malloced = 0; - magic = read32u(); - if (magic != Intext_magic_number) - caml_failwith("input_value_from_block: bad object"); - block_len = read32u(); - if (5*4 + block_len > len) - caml_failwith("input_value_from_block: bad block length"); - obj = input_val_from_block(); - return obj; + /* Initialize global state */ + intern_init(data, NULL); + caml_parse_header("input_value_from_block", &h); + if (h.header_len + h.data_len > len) + caml_failwith("input_val_from_block: bad length"); + return input_val_from_block(&h); } +/* [ofs] is a [value] that represents a number of bytes + result is a [value] that represents a number of bytes + To handle both the small and the big format, + we assume 20 bytes are available at [buff + ofs], + and we return the data size + the length of the part of the header + that remains to be read. */ + CAMLprim value caml_marshal_data_size(value buff, value ofs) { - uint32 magic; - mlsize_t block_len; + uint32_t magic; + int header_len; + uintnat data_len; intern_src = &Byte_u(buff, Long_val(ofs)); - intern_input_malloced = 0; magic = read32u(); - if (magic != Intext_magic_number){ + switch(magic) { + case Intext_magic_number_small: + header_len = 20; + data_len = read32u(); + break; + case Intext_magic_number_big: +#ifdef ARCH_SIXTYFOUR + header_len = 32; + read32u(); + data_len = read64u(); +#else + caml_failwith("Marshal.data_size: " + "object too large to be read back on a 32-bit platform"); +#endif + break; + default: caml_failwith("Marshal.data_size: bad object"); } - block_len = read32u(); - return Val_long(block_len); + return Val_long((header_len - 20) + data_len); } /* Resolution of code pointers */ @@ -771,26 +899,26 @@ CAMLexport int caml_deserialize_sint_2(void) return read16s(); } -CAMLexport uint32 caml_deserialize_uint_4(void) +CAMLexport uint32_t caml_deserialize_uint_4(void) { return read32u(); } -CAMLexport int32 caml_deserialize_sint_4(void) +CAMLexport int32_t caml_deserialize_sint_4(void) { return read32s(); } -CAMLexport uint64 caml_deserialize_uint_8(void) +CAMLexport uint64_t caml_deserialize_uint_8(void) { - uint64 i; + uint64_t i; caml_deserialize_block_8(&i, 1); return i; } -CAMLexport int64 caml_deserialize_sint_8(void) +CAMLexport int64_t caml_deserialize_sint_8(void) { - int64 i; + int64_t i; caml_deserialize_block_8(&i, 1); return i; } @@ -811,7 +939,7 @@ CAMLexport double caml_deserialize_float_8(void) CAMLexport void caml_deserialize_block_1(void * data, intnat len) { - memmove(data, intern_src, len); + memcpy(data, intern_src, len); intern_src += len; } @@ -823,7 +951,7 @@ CAMLexport void caml_deserialize_block_2(void * data, intnat len) Reverse_16(q, p); intern_src = p; #else - memmove(data, intern_src, len * 2); + memcpy(data, intern_src, len * 2); intern_src += len * 2; #endif } @@ -836,7 +964,7 @@ CAMLexport void caml_deserialize_block_4(void * data, intnat len) Reverse_32(q, p); intern_src = p; #else - memmove(data, intern_src, len * 4); + memcpy(data, intern_src, len * 4); intern_src += len * 4; #endif } @@ -849,7 +977,7 @@ CAMLexport void caml_deserialize_block_8(void * data, intnat len) Reverse_64(q, p); intern_src = p; #else - memmove(data, intern_src, len * 8); + memcpy(data, intern_src, len * 8); intern_src += len * 8; #endif } @@ -857,7 +985,7 @@ CAMLexport void caml_deserialize_block_8(void * data, intnat len) CAMLexport void caml_deserialize_block_float_8(void * data, intnat len) { #if ARCH_FLOAT_ENDIANNESS == 0x01234567 - memmove(data, intern_src, len * 8); + memcpy(data, intern_src, len * 8); intern_src += len * 8; #elif ARCH_FLOAT_ENDIANNESS == 0x76543210 unsigned char * p, * q; diff --git a/byterun/interp.c b/byterun/interp.c index fd4740b2..f039b9a6 100644 --- a/byterun/interp.c +++ b/byterun/interp.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The bytecode interpreter */ #include @@ -29,6 +31,7 @@ #include "caml/prims.h" #include "caml/signals.h" #include "caml/stacks.h" +#include "caml/startup_aux.h" /* Registers for the abstract machine: pc the code pointer @@ -271,9 +274,9 @@ value caml_interprete(code_t prog, asize_t prog_size) #ifdef DEBUG caml_bcodcount++; if (caml_icount-- == 0) caml_stop_here (); - if (caml_trace_flag>1) printf("\n##%ld\n", caml_bcodcount); - if (caml_trace_flag) caml_disasm_instr(pc); - if (caml_trace_flag>1) { + if (caml_trace_level>1) printf("\n##%ld\n", caml_bcodcount); + if (caml_trace_level>0) caml_disasm_instr(pc); + if (caml_trace_level>1) { printf("env="); caml_trace_value_file(env,prog,prog_size,stdout); putchar('\n'); @@ -793,7 +796,7 @@ value caml_interprete(code_t prog, asize_t prog_size) if (accu == Val_false) pc += *pc; else pc++; Next; Instruct(SWITCH): { - uint32 sizes = *pc++; + uint32_t sizes = *pc++; if (Is_block(accu)) { intnat index = Tag_val(accu); Assert ((uintnat) index < (sizes >> 16)); diff --git a/byterun/ints.c b/byterun/ints.c index 4a732762..6141f2b9 100644 --- a/byterun/ints.c +++ b/byterun/ints.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -23,22 +25,26 @@ static char * parse_sign_and_base(char * p, /*out*/ int * base, + /*out*/ int * signedness, /*out*/ int * sign) { *sign = 1; if (*p == '-') { *sign = -1; p++; - } - *base = 10; + } else if (*p == '+') + p++; + *base = 10; *signedness = 1; if (*p == '0') { switch (p[1]) { case 'x': case 'X': - *base = 16; p += 2; break; + *base = 16; *signedness = 0; p += 2; break; case 'o': case 'O': - *base = 8; p += 2; break; + *base = 8; *signedness = 0; p += 2; break; case 'b': case 'B': - *base = 2; p += 2; break; + *base = 2; *signedness = 0; p += 2; break; + case 'u': case 'U': + *signedness = 0; p += 2; break; } } return p; @@ -56,42 +62,47 @@ static int parse_digit(char c) return -1; } -static intnat parse_intnat(value s, int nbits) +#define INT_ERRMSG "int_of_string" +#define INT32_ERRMSG "Int32.of_string" +#define INT64_ERRMSG "Int64.of_string" +#define INTNAT_ERRMSG "Nativeint.of_string" + +static intnat parse_intnat(value s, int nbits, const char *errmsg) { char * p; uintnat res, threshold; - int sign, base, d; + int sign, base, signedness, d; - p = parse_sign_and_base(String_val(s), &base, &sign); + p = parse_sign_and_base(String_val(s), &base, &signedness, &sign); threshold = ((uintnat) -1) / base; d = parse_digit(*p); - if (d < 0 || d >= base) caml_failwith("int_of_string"); + if (d < 0 || d >= base) caml_failwith(errmsg); for (p++, res = d; /*nothing*/; p++) { char c = *p; if (c == '_') continue; d = parse_digit(c); if (d < 0 || d >= base) break; /* Detect overflow in multiplication base * res */ - if (res > threshold) caml_failwith("int_of_string"); + if (res > threshold) caml_failwith(errmsg); res = base * res + d; /* Detect overflow in addition (base * res) + d */ - if (res < (uintnat) d) caml_failwith("int_of_string"); + if (res < (uintnat) d) caml_failwith(errmsg); } if (p != String_val(s) + caml_string_length(s)){ - caml_failwith("int_of_string"); + caml_failwith(errmsg); } - if (base == 10) { + if (signedness) { /* Signed representation expected, allow -2^(nbits-1) to 2^(nbits-1) - 1 */ if (sign >= 0) { - if (res >= (uintnat)1 << (nbits - 1)) caml_failwith("int_of_string"); + if (res >= (uintnat)1 << (nbits - 1)) caml_failwith(errmsg); } else { - if (res > (uintnat)1 << (nbits - 1)) caml_failwith("int_of_string"); + if (res > (uintnat)1 << (nbits - 1)) caml_failwith(errmsg); } } else { /* Unsigned representation expected, allow 0 to 2^nbits - 1 and tolerate -(2^nbits - 1) to 0 */ if (nbits < sizeof(uintnat) * 8 && res >= (uintnat)1 << nbits) - caml_failwith("int_of_string"); + caml_failwith(errmsg); } return sign < 0 ? -((intnat) res) : (intnat) res; } @@ -119,7 +130,7 @@ CAMLprim value caml_int_compare(value v1, value v2) CAMLprim value caml_int_of_string(value s) { - return Val_long(parse_intnat(s, 8 * sizeof(value) - 1)); + return Val_long(parse_intnat(s, 8 * sizeof(value) - 1, INT_ERRMSG)); } #define FORMAT_BUFFER_SIZE 32 @@ -172,8 +183,8 @@ CAMLprim value caml_format_int(value fmt, value arg) static int int32_cmp(value v1, value v2) { - int32 i1 = Int32_val(v1); - int32 i2 = Int32_val(v2); + int32_t i1 = Int32_val(v1); + int32_t i2 = Int32_val(v2); return (i1 > i2) - (i1 < i2); } @@ -182,16 +193,16 @@ static intnat int32_hash(value v) return Int32_val(v); } -static void int32_serialize(value v, uintnat * wsize_32, - uintnat * wsize_64) +static void int32_serialize(value v, uintnat * bsize_32, + uintnat * bsize_64) { caml_serialize_int_4(Int32_val(v)); - *wsize_32 = *wsize_64 = 4; + *bsize_32 = *bsize_64 = 4; } static uintnat int32_deserialize(void * dst) { - *((int32 *) dst) = caml_deserialize_sint_4(); + *((int32_t *) dst) = caml_deserialize_sint_4(); return 4; } @@ -205,7 +216,7 @@ CAMLexport struct custom_operations caml_int32_ops = { custom_compare_ext_default }; -CAMLexport value caml_copy_int32(int32 i) +CAMLexport value caml_copy_int32(int32_t i) { value res = caml_alloc_custom(&caml_int32_ops, 4, 0, 1); Int32_val(res) = i; @@ -226,8 +237,8 @@ CAMLprim value caml_int32_mul(value v1, value v2) CAMLprim value caml_int32_div(value v1, value v2) { - int32 dividend = Int32_val(v1); - int32 divisor = Int32_val(v2); + int32_t dividend = Int32_val(v1); + int32_t divisor = Int32_val(v2); if (divisor == 0) caml_raise_zero_divide(); /* PR#4740: on some processors, division crashes on overflow. Implement the same behavior as for type "int". */ @@ -237,8 +248,8 @@ CAMLprim value caml_int32_div(value v1, value v2) CAMLprim value caml_int32_mod(value v1, value v2) { - int32 dividend = Int32_val(v1); - int32 divisor = Int32_val(v2); + int32_t dividend = Int32_val(v1); + int32_t divisor = Int32_val(v2); if (divisor == 0) caml_raise_zero_divide(); /* PR#4740: on some processors, modulus crashes if division overflows. Implement the same behavior as for type "int". */ @@ -262,9 +273,9 @@ CAMLprim value caml_int32_shift_right(value v1, value v2) { return caml_copy_int32(Int32_val(v1) >> Int_val(v2)); } CAMLprim value caml_int32_shift_right_unsigned(value v1, value v2) -{ return caml_copy_int32((uint32)Int32_val(v1) >> Int_val(v2)); } +{ return caml_copy_int32((uint32_t)Int32_val(v1) >> Int_val(v2)); } -static int32 caml_swap32(int32 x) +static int32_t caml_swap32(int32_t x) { return (((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | @@ -284,18 +295,26 @@ CAMLprim value caml_int32_of_int(value v) CAMLprim value caml_int32_to_int(value v) { return Val_long(Int32_val(v)); } +int32_t caml_int32_of_float_unboxed(double x) +{ return x; } + CAMLprim value caml_int32_of_float(value v) -{ return caml_copy_int32((int32)(Double_val(v))); } +{ return caml_copy_int32((int32_t)(Double_val(v))); } + +double caml_int32_to_float_unboxed(int32_t x) +{ return x; } CAMLprim value caml_int32_to_float(value v) { return caml_copy_double((double)(Int32_val(v))); } +intnat caml_int32_compare_unboxed(int32_t i1, int32_t i2) +{ + return (i1 > i2) - (i1 < i2); +} + CAMLprim value caml_int32_compare(value v1, value v2) { - int32 i1 = Int32_val(v1); - int32 i2 = Int32_val(v2); - int res = (i1 > i2) - (i1 < i2); - return Val_int(res); + return Val_int(caml_int32_compare_unboxed(Int32_val(v1),Int32_val(v2))); } CAMLprim value caml_int32_format(value fmt, value arg) @@ -308,32 +327,42 @@ CAMLprim value caml_int32_format(value fmt, value arg) CAMLprim value caml_int32_of_string(value s) { - return caml_copy_int32(parse_intnat(s, 32)); + return caml_copy_int32(parse_intnat(s, 32, INT32_ERRMSG)); +} + +int32_t caml_int32_bits_of_float_unboxed(double d) +{ + union { float d; int32_t i; } u; + u.d = d; + return u.i; +} + +double caml_int32_float_of_bits_unboxed(int32_t i) +{ + union { float d; int32_t i; } u; + u.i = i; + return u.d; } CAMLprim value caml_int32_bits_of_float(value vd) { - union { float d; int32 i; } u; - u.d = Double_val(vd); - return caml_copy_int32(u.i); + return caml_copy_int32(caml_int32_bits_of_float_unboxed(Double_val(vd))); } CAMLprim value caml_int32_float_of_bits(value vi) { - union { float d; int32 i; } u; - u.i = Int32_val(vi); - return caml_copy_double(u.d); + return caml_copy_double(caml_int32_float_of_bits_unboxed(Int32_val(vi))); } /* 64-bit integers */ #ifdef ARCH_ALIGN_INT64 -CAMLexport int64 caml_Int64_val(value v) +CAMLexport int64_t caml_Int64_val(value v) { - union { int32 i[2]; int64 j; } buffer; - buffer.i[0] = ((int32 *) Data_custom_val(v))[0]; - buffer.i[1] = ((int32 *) Data_custom_val(v))[1]; + union { int32_t i[2]; int64_t j; } buffer; + buffer.i[0] = ((int32_t *) Data_custom_val(v))[0]; + buffer.i[1] = ((int32_t *) Data_custom_val(v))[1]; return buffer.j; } @@ -341,34 +370,34 @@ CAMLexport int64 caml_Int64_val(value v) static int int64_cmp(value v1, value v2) { - int64 i1 = Int64_val(v1); - int64 i2 = Int64_val(v2); + int64_t i1 = Int64_val(v1); + int64_t i2 = Int64_val(v2); return (i1 > i2) - (i1 < i2); } static intnat int64_hash(value v) { - int64 x = Int64_val(v); - uint32 lo = (uint32) x, hi = (uint32) (x >> 32); + int64_t x = Int64_val(v); + uint32_t lo = (uint32_t) x, hi = (uint32_t) (x >> 32); return hi ^ lo; } -static void int64_serialize(value v, uintnat * wsize_32, - uintnat * wsize_64) +static void int64_serialize(value v, uintnat * bsize_32, + uintnat * bsize_64) { caml_serialize_int_8(Int64_val(v)); - *wsize_32 = *wsize_64 = 8; + *bsize_32 = *bsize_64 = 8; } static uintnat int64_deserialize(void * dst) { #ifndef ARCH_ALIGN_INT64 - *((int64 *) dst) = caml_deserialize_sint_8(); + *((int64_t *) dst) = caml_deserialize_sint_8(); #else - union { int32 i[2]; int64 j; } buffer; + union { int32_t i[2]; int64_t j; } buffer; buffer.j = caml_deserialize_sint_8(); - ((int32 *) dst)[0] = buffer.i[0]; - ((int32 *) dst)[1] = buffer.i[1]; + ((int32_t *) dst)[0] = buffer.i[0]; + ((int32_t *) dst)[1] = buffer.i[1]; #endif return 8; } @@ -383,16 +412,16 @@ CAMLexport struct custom_operations caml_int64_ops = { custom_compare_ext_default }; -CAMLexport value caml_copy_int64(int64 i) +CAMLexport value caml_copy_int64(int64_t i) { value res = caml_alloc_custom(&caml_int64_ops, 8, 0, 1); #ifndef ARCH_ALIGN_INT64 Int64_val(res) = i; #else - union { int32 i[2]; int64 j; } buffer; + union { int32_t i[2]; int64_t j; } buffer; buffer.j = i; - ((int32 *) Data_custom_val(res))[0] = buffer.i[0]; - ((int32 *) Data_custom_val(res))[1] = buffer.i[1]; + ((int32_t *) Data_custom_val(res))[0] = buffer.i[0]; + ((int32_t *) Data_custom_val(res))[1] = buffer.i[1]; #endif return res; } @@ -413,23 +442,25 @@ CAMLprim value caml_int64_mul(value v1, value v2) CAMLprim value caml_int64_div(value v1, value v2) { - int64 dividend = Int64_val(v1); - int64 divisor = Int64_val(v2); + int64_t dividend = Int64_val(v1); + int64_t divisor = Int64_val(v2); if (divisor == 0) caml_raise_zero_divide(); /* PR#4740: on some processors, division crashes on overflow. Implement the same behavior as for type "int". */ - if (dividend == ((int64)1 << 63) && divisor == -1) return v1; + if (dividend == ((int64_t)1 << 63) && divisor == -1) return v1; return caml_copy_int64(Int64_val(v1) / divisor); } CAMLprim value caml_int64_mod(value v1, value v2) { - int64 dividend = Int64_val(v1); - int64 divisor = Int64_val(v2); + int64_t dividend = Int64_val(v1); + int64_t divisor = Int64_val(v2); if (divisor == 0) caml_raise_zero_divide(); /* PR#4740: on some processors, division crashes on overflow. Implement the same behavior as for type "int". */ - if (dividend == ((int64)1 << 63) && divisor == -1) return caml_copy_int64(0); + if (dividend == ((int64_t)1 << 63) && divisor == -1){ + return caml_copy_int64(0); + } return caml_copy_int64(Int64_val(v1) % divisor); } @@ -449,7 +480,7 @@ CAMLprim value caml_int64_shift_right(value v1, value v2) { return caml_copy_int64(Int64_val(v1) >> Int_val(v2)); } CAMLprim value caml_int64_shift_right_unsigned(value v1, value v2) -{ return caml_copy_int64((uint64) (Int64_val(v1)) >> Int_val(v2)); } +{ return caml_copy_int64((uint64_t) (Int64_val(v1)) >> Int_val(v2)); } #ifdef ARCH_SIXTYFOUR static value caml_swap64(value x) @@ -470,7 +501,7 @@ value caml_int64_direct_bswap(value v) CAMLprim value caml_int64_bswap(value v) { - int64 x = Int64_val(v); + int64_t x = Int64_val(v); return caml_copy_int64 (((x & 0x00000000000000FFULL) << 56) | ((x & 0x000000000000FF00ULL) << 40) | @@ -483,34 +514,43 @@ CAMLprim value caml_int64_bswap(value v) } CAMLprim value caml_int64_of_int(value v) -{ return caml_copy_int64((int64) (Long_val(v))); } +{ return caml_copy_int64((int64_t) (Long_val(v))); } CAMLprim value caml_int64_to_int(value v) { return Val_long((intnat) (Int64_val(v))); } +int64_t caml_int64_of_float_unboxed(double x) +{ return x; } + CAMLprim value caml_int64_of_float(value v) -{ return caml_copy_int64((int64) (Double_val(v))); } +{ return caml_copy_int64((int64_t) (Double_val(v))); } + +double caml_int64_to_float_unboxed(int64_t x) +{ return x; } CAMLprim value caml_int64_to_float(value v) { return caml_copy_double((double) (Int64_val(v))); } CAMLprim value caml_int64_of_int32(value v) -{ return caml_copy_int64((int64) (Int32_val(v))); } +{ return caml_copy_int64((int64_t) (Int32_val(v))); } CAMLprim value caml_int64_to_int32(value v) -{ return caml_copy_int32((int32) (Int64_val(v))); } +{ return caml_copy_int32((int32_t) (Int64_val(v))); } CAMLprim value caml_int64_of_nativeint(value v) -{ return caml_copy_int64((int64) (Nativeint_val(v))); } +{ return caml_copy_int64((int64_t) (Nativeint_val(v))); } CAMLprim value caml_int64_to_nativeint(value v) { return caml_copy_nativeint((intnat) (Int64_val(v))); } +intnat caml_int64_compare_unboxed(int64_t i1, int64_t i2) +{ + return (i1 > i2) - (i1 < i2); +} + CAMLprim value caml_int64_compare(value v1, value v2) { - int64 i1 = Int64_val(v1); - int64 i2 = Int64_val(v2); - return Val_int((i1 > i2) - (i1 < i2)); + return Val_int(caml_int64_compare_unboxed(Int64_val(v1),Int64_val(v2))); } CAMLprim value caml_int64_format(value fmt, value arg) @@ -524,13 +564,13 @@ CAMLprim value caml_int64_format(value fmt, value arg) CAMLprim value caml_int64_of_string(value s) { char * p; - uint64 res, threshold; - int sign, base, d; + uint64_t res, threshold; + int sign, base, signedness, d; - p = parse_sign_and_base(String_val(s), &base, &sign); - threshold = ((uint64) -1) / base; + p = parse_sign_and_base(String_val(s), &base, &signedness, &sign); + threshold = ((uint64_t) -1) / base; d = parse_digit(*p); - if (d < 0 || d >= base) caml_failwith("int_of_string"); + if (d < 0 || d >= base) caml_failwith(INT64_ERRMSG); res = d; for (p++; /*nothing*/; p++) { char c = *p; @@ -538,44 +578,54 @@ CAMLprim value caml_int64_of_string(value s) d = parse_digit(c); if (d < 0 || d >= base) break; /* Detect overflow in multiplication base * res */ - if (res > threshold) caml_failwith("int_of_string"); + if (res > threshold) caml_failwith(INT64_ERRMSG); res = base * res + d; /* Detect overflow in addition (base * res) + d */ - if (res < (uint64) d) caml_failwith("int_of_string"); + if (res < (uint64_t) d) caml_failwith(INT64_ERRMSG); } if (p != String_val(s) + caml_string_length(s)){ - caml_failwith("int_of_string"); + caml_failwith(INT64_ERRMSG); } - if (base == 10) { + if (signedness) { /* Signed representation expected, allow -2^63 to 2^63 - 1 only */ if (sign >= 0) { - if (res >= (uint64)1 << 63) caml_failwith("int_of_string"); + if (res >= (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG); } else { - if (res > (uint64)1 << 63) caml_failwith("int_of_string"); + if (res > (uint64_t)1 << 63) caml_failwith(INT64_ERRMSG); } } if (sign < 0) res = - res; return caml_copy_int64(res); } -CAMLprim value caml_int64_bits_of_float(value vd) +int64_t caml_int64_bits_of_float_unboxed(double d) { - union { double d; int64 i; int32 h[2]; } u; - u.d = Double_val(vd); + union { double d; int64_t i; int32_t h[2]; } u; + u.d = d; #if defined(__arm__) && !defined(__ARM_EABI__) - { int32 t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } + { int32_t t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } #endif - return caml_copy_int64(u.i); + return u.i; } -CAMLprim value caml_int64_float_of_bits(value vi) +double caml_int64_float_of_bits_unboxed(int64_t i) { - union { double d; int64 i; int32 h[2]; } u; - u.i = Int64_val(vi); + union { double d; int64_t i; int32_t h[2]; } u; + u.i = i; #if defined(__arm__) && !defined(__ARM_EABI__) - { int32 t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } + { int32_t t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; } #endif - return caml_copy_double(u.d); + return u.d; +} + +CAMLprim value caml_int64_bits_of_float(value vd) +{ + return caml_copy_int64(caml_int64_bits_of_float_unboxed(Double_val(vd))); +} + +CAMLprim value caml_int64_float_of_bits(value vi) +{ + return caml_copy_double(caml_int64_float_of_bits_unboxed(Int64_val(vi))); } /* Native integers */ @@ -599,14 +649,14 @@ static intnat nativeint_hash(value v) #endif } -static void nativeint_serialize(value v, uintnat * wsize_32, - uintnat * wsize_64) +static void nativeint_serialize(value v, uintnat * bsize_32, + uintnat * bsize_64) { intnat l = Nativeint_val(v); #ifdef ARCH_SIXTYFOUR if (l >= -((intnat)1 << 31) && l < ((intnat)1 << 31)) { caml_serialize_int_1(1); - caml_serialize_int_4((int32) l); + caml_serialize_int_4((int32_t) l); } else { caml_serialize_int_1(2); caml_serialize_int_8(l); @@ -615,8 +665,8 @@ static void nativeint_serialize(value v, uintnat * wsize_32, caml_serialize_int_1(1); caml_serialize_int_4(l); #endif - *wsize_32 = 4; - *wsize_64 = 8; + *bsize_32 = 4; + *bsize_64 = 8; } static uintnat nativeint_deserialize(void * dst) @@ -735,9 +785,15 @@ CAMLprim value caml_nativeint_of_int(value v) CAMLprim value caml_nativeint_to_int(value v) { return Val_long(Nativeint_val(v)); } +intnat caml_nativeint_of_float_unboxed(double x) +{ return x; } + CAMLprim value caml_nativeint_of_float(value v) { return caml_copy_nativeint((intnat)(Double_val(v))); } +double caml_nativeint_to_float_unboxed(intnat x) +{ return x; } + CAMLprim value caml_nativeint_to_float(value v) { return caml_copy_double((double)(Nativeint_val(v))); } @@ -747,12 +803,15 @@ CAMLprim value caml_nativeint_of_int32(value v) CAMLprim value caml_nativeint_to_int32(value v) { return caml_copy_int32(Nativeint_val(v)); } +intnat caml_nativeint_compare_unboxed(intnat i1, intnat i2) +{ + return (i1 > i2) - (i1 < i2); +} + CAMLprim value caml_nativeint_compare(value v1, value v2) { - intnat i1 = Nativeint_val(v1); - intnat i2 = Nativeint_val(v2); - int res = (i1 > i2) - (i1 < i2); - return Val_int(res); + return Val_int(caml_nativeint_compare_unboxed(Nativeint_val(v1), + Nativeint_val(v2))); } CAMLprim value caml_nativeint_format(value fmt, value arg) @@ -765,5 +824,5 @@ CAMLprim value caml_nativeint_format(value fmt, value arg) CAMLprim value caml_nativeint_of_string(value s) { - return caml_copy_nativeint(parse_intnat(s, 8 * sizeof(value))); + return caml_copy_nativeint(parse_intnat(s, 8 * sizeof(value), INTNAT_ERRMSG)); } diff --git a/byterun/io.c b/byterun/io.c index 11f941dc..b9f5af36 100644 --- a/byterun/io.c +++ b/byterun/io.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Buffered input/output. */ @@ -17,6 +19,7 @@ #include #include #include +#include #include #include "caml/config.h" #ifdef HAS_UNISTD @@ -32,6 +35,7 @@ #include "caml/memory.h" #include "caml/misc.h" #include "caml/mlvalues.h" +#include "caml/osdeps.h" #include "caml/signals.h" #include "caml/sys.h" @@ -75,6 +79,7 @@ CAMLexport struct channel * caml_open_descriptor_in(int fd) channel->flags = 0; channel->next = caml_all_opened_channels; channel->prev = NULL; + channel->name = NULL; if (caml_all_opened_channels != NULL) caml_all_opened_channels->prev = channel; caml_all_opened_channels = channel; @@ -109,6 +114,7 @@ CAMLexport void caml_close_channel(struct channel *channel) if (channel->refcount > 0) return; if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(channel); unlink_channel(channel); + caml_stat_free(channel->name); caml_stat_free(channel); } @@ -145,39 +151,6 @@ CAMLexport int caml_channel_binary_mode(struct channel *channel) /* Output */ -#ifndef EINTR -#define EINTR (-1) -#endif -#ifndef EAGAIN -#define EAGAIN (-1) -#endif -#ifndef EWOULDBLOCK -#define EWOULDBLOCK (-1) -#endif - -static int do_write(int fd, char *p, int n) -{ - int retcode; - -again: - caml_enter_blocking_section(); - retcode = write(fd, p, n); - caml_leave_blocking_section(); - if (retcode == -1) { - if (errno == EINTR) goto again; - if ((errno == EAGAIN || errno == EWOULDBLOCK) && n > 1) { - /* We couldn't do a partial write here, probably because - n <= PIPE_BUF and POSIX says that writes of less than - PIPE_BUF characters must be atomic. - We first try again with a partial write of 1 character. - If that fails too, we'll raise Sys_blocked_io below. */ - n = 1; goto again; - } - } - if (retcode == -1) caml_sys_io_error(NO_ARG); - return retcode; -} - /* Attempt to flush the buffer. This will make room in the buffer for at least one character. Returns true if the buffer is empty at the end of the flush, or false if some data remains in the buffer. @@ -188,8 +161,10 @@ CAMLexport int caml_flush_partial(struct channel *channel) int towrite, written; towrite = channel->curr - channel->buff; + CAMLassert (towrite >= 0); if (towrite > 0) { - written = do_write(channel->fd, channel->buff, towrite); + written = caml_write_fd(channel->fd, channel->flags, + channel->buff, towrite); channel->offset += written; if (written < towrite) memmove(channel->buff, channel->buff + written, towrite - written); @@ -207,7 +182,7 @@ CAMLexport void caml_flush(struct channel *channel) /* Output data */ -CAMLexport void caml_putword(struct channel *channel, uint32 w) +CAMLexport void caml_putword(struct channel *channel, uint32_t w) { if (! caml_channel_binary_mode(channel)) caml_failwith("output_binary_int: not a binary channel"); @@ -233,7 +208,8 @@ CAMLexport int caml_putblock(struct channel *channel, char *p, intnat len) fits to buffer and write the buffer */ memmove(channel->curr, p, free); towrite = channel->end - channel->buff; - written = do_write(channel->fd, channel->buff, towrite); + written = caml_write_fd(channel->fd, channel->flags, + channel->buff, towrite); if (written < towrite) memmove(channel->buff, channel->buff + written, towrite - written); channel->offset += written; @@ -275,27 +251,15 @@ CAMLexport file_offset caml_pos_out(struct channel *channel) /* caml_do_read is exported for Cash */ CAMLexport int caml_do_read(int fd, char *p, unsigned int n) { - int retcode; - - do { - caml_enter_blocking_section(); - retcode = read(fd, p, n); -#if defined(_WIN32) - if (retcode == -1 && errno == ENOMEM && n > 16384){ - retcode = read(fd, p, 16384); - } -#endif - caml_leave_blocking_section(); - } while (retcode == -1 && errno == EINTR); - if (retcode == -1) caml_sys_io_error(NO_ARG); - return retcode; + return caml_read_fd(fd, 0, p, n); } CAMLexport unsigned char caml_refill(struct channel *channel) { int n; - n = caml_do_read(channel->fd, channel->buff, channel->end - channel->buff); + n = caml_read_fd(channel->fd, channel->flags, + channel->buff, channel->end - channel->buff); if (n == 0) caml_raise_end_of_file(); channel->offset += n; channel->max = channel->buff + n; @@ -303,10 +267,10 @@ CAMLexport unsigned char caml_refill(struct channel *channel) return (unsigned char)(channel->buff[0]); } -CAMLexport uint32 caml_getword(struct channel *channel) +CAMLexport uint32_t caml_getword(struct channel *channel) { int i; - uint32 res; + uint32_t res; if (! caml_channel_binary_mode(channel)) caml_failwith("input_binary_int: not a binary channel"); @@ -332,7 +296,7 @@ CAMLexport int caml_getblock(struct channel *channel, char *p, intnat len) channel->curr += avail; return avail; } else { - nread = caml_do_read(channel->fd, channel->buff, + nread = caml_read_fd(channel->fd, channel->flags, channel->buff, channel->end - channel->buff); channel->offset += nread; channel->max = channel->buff + nread; @@ -402,7 +366,8 @@ CAMLexport intnat caml_input_scan_line(struct channel *channel) return -(channel->max - channel->curr); } /* Fill the buffer as much as possible */ - n = caml_do_read(channel->fd, channel->max, channel->end - channel->max); + n = caml_read_fd(channel->fd, channel->flags, + channel->max, channel->end - channel->max); if (n == 0) { /* End-of-file encountered. Return the number of characters in the buffer, with negative sign since we haven't encountered @@ -420,14 +385,42 @@ CAMLexport intnat caml_input_scan_line(struct channel *channel) /* OCaml entry points for the I/O functions. Wrap struct channel * objects into a heap-allocated object. Perform locking and unlocking around the I/O operations. */ + /* FIXME CAMLexport, but not in io.h exported for Cash ? */ CAMLexport void caml_finalize_channel(value vchan) { struct channel * chan = Channel(vchan); if (--chan->refcount > 0) return; if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(chan); - unlink_channel(chan); - caml_stat_free(chan); + + if (chan->fd != -1 && chan->name && caml_runtime_warnings_active()) + fprintf(stderr, + "[ocaml] channel opened on file '%s' dies without being closed\n", + chan->name + ); + + if (chan->max == NULL && chan->curr != chan->buff){ + /* + This is an unclosed out channel (chan->max == NULL) with a + non-empty buffer: keep it around so the OCaml [at_exit] function + gets a chance to flush it. We would want to simply flush the + channel now, but (i) flushing can raise exceptions, and (ii) it + is potentially a blocking operation. Both are forbidden in a + finalization function. + + Refs: + http://caml.inria.fr/mantis/view.php?id=6902 + https://github.com/ocaml/ocaml/pull/210 + */ + if (chan->name && caml_runtime_warnings_active()) + fprintf(stderr, + "[ocaml] (moreover, it has unflushed data)\n" + ); + } else { + unlink_channel(chan); + caml_stat_free(chan->name); + caml_stat_free(chan); + } } static int compare_channel(value vchan1, value vchan2) @@ -472,6 +465,17 @@ CAMLprim value caml_ml_open_descriptor_out(value fd) return caml_alloc_channel(caml_open_descriptor_out(Int_val(fd))); } +CAMLprim value caml_ml_set_channel_name(value vchannel, value vname) +{ + struct channel * channel = Channel(vchannel); + caml_stat_free(channel->name); + if (caml_string_length(vname) > 0) + channel->name = caml_strdup(String_val(vname)); + else + channel->name = NULL; + return Val_unit; +} + #define Pair_tag 0 CAMLprim value caml_ml_out_channels_list (value unit) @@ -559,6 +563,15 @@ CAMLprim value caml_ml_set_binary_mode(value vchannel, value mode) { #if defined(_WIN32) || defined(__CYGWIN__) struct channel * channel = Channel(vchannel); +#if defined(_WIN32) + /* The implementation of [caml_read_fd] and [caml_write_fd] in win32.c + doesn't support socket I/O with CRLF conversion. */ + if ((channel->flags & CHANNEL_FLAG_FROM_SOCKET) != 0 + && ! Bool_val(mode)) { + errno = EINVAL; + caml_sys_error(NO_ARG); + } +#endif if (setmode(channel->fd, Bool_val(mode) ? O_BINARY : O_TEXT) == -1) caml_sys_error(NO_ARG); #endif @@ -721,7 +734,7 @@ CAMLprim value caml_ml_input(value vchannel, value buff, value vstart, Lock(channel); /* We cannot call caml_getblock here because buff may move during - caml_do_read */ + caml_read_fd */ start = Long_val(vstart); len = Long_val(vlength); n = len >= INT_MAX ? INT_MAX : (int) len; @@ -734,7 +747,7 @@ CAMLprim value caml_ml_input(value vchannel, value buff, value vstart, channel->curr += avail; n = avail; } else { - nread = caml_do_read(channel->fd, channel->buff, + nread = caml_read_fd(channel->fd, channel->flags, channel->buff, channel->end - channel->buff); channel->offset += nread; channel->max = channel->buff + nread; diff --git a/byterun/lexing.c b/byterun/lexing.c index eac302e3..567b7a76 100644 --- a/byterun/lexing.c +++ b/byterun/lexing.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The table-driven automaton for lexers generated by camllex. */ diff --git a/byterun/main.c b/byterun/main.c index 1ad20280..2a017284 100644 --- a/byterun/main.c +++ b/byterun/main.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Main entry point (can be overridden by a user-provided main() function that calls caml_main() later). */ @@ -26,27 +28,6 @@ CAMLextern void caml_expand_command_line (int *, char ***); int main(int argc, char **argv) { -#ifdef DEBUG - caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0); -#if 0 - { - int i; - char *ocp; - char *cp; - - caml_gc_message (-1, "### command line:", 0); - for (i = 0; i < argc; i++){ - caml_gc_message (-1, " %s", argv[i]); - } - caml_gc_message (-1, "\n", 0); - ocp = getenv ("OCAMLRUNPARAM"); - caml_gc_message (-1, "### OCAMLRUNPARAM=%s\n", ocp == NULL ? "" : ocp); - cp = getenv ("CAMLRUNPARAM"); - caml_gc_message (-1, "### CAMLRUNPARAM=%s\n", cp == NULL ? "" : cp); - caml_gc_message (-1, "### working dir: %s\n", getcwd (NULL, 0)); - } -#endif -#endif #ifdef _WIN32 /* Expand wildcards and diversions in command line */ caml_expand_command_line(&argc, &argv); diff --git a/byterun/major_gc.c b/byterun/major_gc.c index 6a273b97..4e75012e 100644 --- a/byterun/major_gc.c +++ b/byterun/major_gc.c @@ -1,17 +1,20 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 +#include #include "caml/compact.h" #include "caml/custom.h" @@ -25,6 +28,7 @@ #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/roots.h" +#include "caml/signals.h" #include "caml/weak.h" #if defined (NATIVE_CODE) && defined (NO_NAKED_POINTERS) @@ -33,11 +37,18 @@ #undef NATIVE_CODE_AND_NO_NAKED_POINTERS #endif +#ifdef _MSC_VER +static inline double fmin(double a, double b) { + return (a < b) ? a : b; +} +#endif + uintnat caml_percent_free; uintnat caml_major_heap_increment; CAMLexport char *caml_heap_start; char *caml_gc_sweep_hp; -int caml_gc_phase; /* always Phase_mark, Phase_sweep, or Phase_idle */ +int caml_gc_phase; /* always Phase_mark, Pase_clean, + Phase_sweep, or Phase_idle */ static value *gray_vals; static value *gray_vals_cur, *gray_vals_end; static asize_t gray_vals_size; @@ -46,14 +57,59 @@ static int heap_is_pure; /* The heap is pure if the only gray objects uintnat caml_allocated_words; uintnat caml_dependent_size, caml_dependent_allocated; double caml_extra_heap_resources; -uintnat caml_fl_size_at_phase_change = 0; +uintnat caml_fl_wsz_at_phase_change = 0; extern char *caml_fl_merge; /* Defined in freelist.c. */ static char *markhp, *chunk, *limit; -int caml_gc_subphase; /* Subphase_{main,weak1,weak2,final} */ -static value *weak_prev; +int caml_gc_subphase; /* Subphase_{mark_roots,mark_main,mark_final} */ + +/** + Ephemerons: + During mark phase the list caml_ephe_list_head of ephemerons + is iterated by different pointers that follow the invariants: + caml_ephe_list_head ->* ephes_checked_if_pure ->* ephes_to_check ->* null + | | | + (1) (2) (3) + + At the start of mark phase, (1) and (2) are empty. + + In mark phase: + - the ephemerons in (1) have a data alive or none + (nb: new ephemerons are added in this part by weak.c) + - the ephemerons in (2) have at least a white key or are white + if ephe_list_pure is true, otherwise they are in an unknown state and + must be checked again. + - the ephemerons in (3) are in an unknown state and must be checked + + At the end of mark phase, (3) is empty and ephe_list_pure is true. + The ephemeron in (1) and (2) will be cleaned (white keys and datas + replaced by none or the ephemeron is removed from the list if it is white) + in clean phase. + + In clean phase: + caml_ephe_list_head ->* ephes_to_check ->* null + | | + (1) (3) + + In clean phase, (2) is not used, ephes_to_check is initialized at + caml_ephe_list_head: + - the ephemerons in (1) are clean. + - the ephemerons in (3) should be cleaned or removed if white. + + */ +static int ephe_list_pure; +/** The ephemerons is pure if since the start of its iteration + no value have been darken. */ +static value *ephes_checked_if_pure; +static value *ephes_to_check; + +int caml_major_window = 1; +double caml_major_ring[Max_major_window] = { 0. }; +int caml_major_ring_index = 0; +double caml_major_work_credit = 0.0; +double caml_gc_clock = 0.0; #ifdef DEBUG static unsigned long major_gc_counter = 0; @@ -66,7 +122,7 @@ static void realloc_gray_vals (void) value *new; Assert (gray_vals_cur == gray_vals_end); - if (gray_vals_size < caml_stat_heap_size / 128){ + if (gray_vals_size < caml_stat_heap_wsz / 32){ caml_gc_message (0x08, "Growing gray_vals to %" ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", (intnat) gray_vals_size * sizeof (value) / 512); @@ -91,7 +147,7 @@ static void realloc_gray_vals (void) void caml_darken (value v, value *p /* not used */) { #ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - if (Is_block (v) && Wosize_val (v) > 0) { + if (Is_block (v) && !Is_young (v) && Wosize_val (v) > 0) { #else if (Is_block (v) && Is_in_heap (v)) { #endif @@ -113,6 +169,7 @@ void caml_darken (value v, value *p /* not used */) #endif CAMLassert (!Is_blue_hd (h)); if (Is_white_hd (h)){ + ephe_list_pure = 0; if (t < No_scan_tag){ Hd_val (v) = Grayhd_hd (h); *gray_vals_cur++ = v; @@ -129,85 +186,247 @@ static void start_cycle (void) Assert (caml_gc_phase == Phase_idle); Assert (gray_vals_cur == gray_vals); caml_gc_message (0x01, "Starting new major GC cycle\n", 0); - caml_darken_all_roots(); + caml_darken_all_roots_start (); caml_gc_phase = Phase_mark; - caml_gc_subphase = Subphase_main; + caml_gc_subphase = Subphase_mark_roots; markhp = NULL; + ephe_list_pure = 1; + ephes_checked_if_pure = &caml_ephe_list_head; + ephes_to_check = &caml_ephe_list_head; #ifdef DEBUG ++ major_gc_counter; caml_heap_check (); #endif } -static void mark_slice (intnat work) +/* We may stop the slice inside values, in order to avoid large latencies + on large arrays. In this case, [current_value] is the partially-marked + value and [current_index] is the index of the next field to be marked. +*/ +static value current_value = 0; +static mlsize_t current_index = 0; + +/* For instrumentation */ +#ifdef CAML_INSTR +#define INSTR(x) x +#else +#define INSTR(x) /**/ +#endif + +static void init_sweep_phase(void) +{ + /* Phase_clean is done. */ + /* Initialise the sweep phase. */ + caml_gc_sweep_hp = caml_heap_start; + caml_fl_init_merge (); + caml_gc_phase = Phase_sweep; + chunk = caml_heap_start; + caml_gc_sweep_hp = chunk; + limit = chunk + Chunk_size (chunk); + caml_fl_wsz_at_phase_change = caml_fl_cur_wsz; + if (caml_major_gc_hook) (*caml_major_gc_hook)(); +} + +/* auxillary function of mark_slice */ +static inline value* mark_slice_darken(value *gray_vals_ptr, value v, int i, + int in_ephemeron, int *slice_pointers) +{ + value child; + header_t chd; + + child = Field (v, i); + +#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS + if (Is_block (child) + && ! Is_young (child) + && Wosize_val (child) > 0 /* Atoms never need to be marked. */ + /* Closure blocks contain code pointers at offsets that cannot + be reliably determined, so we always use the page table when + marking such values. */ + && (!(Tag_val (v) == Closure_tag || Tag_val (v) == Infix_tag) || + Is_in_heap (child))) { +#else + if (Is_block (child) && Is_in_heap (child)) { +#endif + INSTR (++ *slice_pointers;) + chd = Hd_val (child); + if (Tag_hd (chd) == Forward_tag){ + value f = Forward_val (child); + if ((in_ephemeron && Is_long(f)) || + (Is_block (f) + && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag))){ + /* Do not short-circuit the pointer. */ + }else{ + /* The variable child is not changed because it must be mark alive */ + Field (v, i) = f; + if (Is_block (f) && Is_young (f) && !Is_young (child)){ + if(in_ephemeron){ + add_to_ephe_ref_table (&caml_ephe_ref_table, v, i); + }else{ + add_to_ref_table (&caml_ref_table, &Field (v, i)); + } + } + } + } + else if (Tag_hd(chd) == Infix_tag) { + child -= Infix_offset_val(child); + chd = Hd_val(child); + } +#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS + /* See [caml_darken] for a description of this assertion. */ + CAMLassert (Is_in_heap (child) || Is_black_hd (chd)); +#endif + if (Is_white_hd (chd)){ + ephe_list_pure = 0; + Hd_val (child) = Grayhd_hd (chd); + *gray_vals_ptr++ = child; + if (gray_vals_ptr >= gray_vals_end) { + gray_vals_cur = gray_vals_ptr; + realloc_gray_vals (); + gray_vals_ptr = gray_vals_cur; + } + } + } + + return gray_vals_ptr; +} + +static value* mark_ephe_aux (value *gray_vals_ptr, intnat *work, + int *slice_pointers) { - value *gray_vals_ptr; /* Local copy of gray_vals_cur */ - value v, child; + value v, data, key; header_t hd; mlsize_t size, i; -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - int marking_closure = 0; + + v = *ephes_to_check; + hd = Hd_val(v); + Assert(Tag_val (v) == Abstract_tag); + data = Field(v,CAML_EPHE_DATA_OFFSET); + if ( data != caml_ephe_none && + Is_block (data) && Is_in_heap (data) && Is_white_val (data)){ + + int alive_data = 1; + + /* The liveness of the ephemeron is one of the condition */ + if (Is_white_hd (hd)) alive_data = 0; + + /* The liveness of the keys not caml_ephe_none is the other condition */ + size = Wosize_hd (hd); + for (i = CAML_EPHE_FIRST_KEY; alive_data && i < size; i++){ + key = Field (v, i); + ephemeron_again: + if (key != caml_ephe_none && + Is_block (key) && Is_in_heap (key)){ + if (Tag_val (key) == Forward_tag){ + value f = Forward_val (key); + if (Is_long (f) || + (Is_block (f) && + (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag))){ + /* Do not short-circuit the pointer. */ + }else{ + Field (v, i) = key = f; + goto ephemeron_again; + } + } + if (Is_white_val (key)){ + alive_data = 0; + } + } + } + *work -= Whsize_wosize(i); + + if (alive_data){ + gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v, + CAML_EPHE_DATA_OFFSET, + /*in_ephemeron=*/1, + slice_pointers); + } else { /* not triggered move to the next one */ + ephes_to_check = &Field(v,CAML_EPHE_LINK_OFFSET); + return gray_vals_ptr; + } + } else { /* a simily weak pointer or an already alive data */ + *work -= 1; + } + + /* all keys black or data none or black + move the ephemerons from (3) to the end of (1) */ + if ( ephes_checked_if_pure == ephes_to_check ) { + /* corner case and optim */ + ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); + ephes_to_check = ephes_checked_if_pure; + } else { + /* - remove v from the list (3) */ + *ephes_to_check = Field(v,CAML_EPHE_LINK_OFFSET); + /* - insert it at the end of (1) */ + Field(v,CAML_EPHE_LINK_OFFSET) = *ephes_checked_if_pure; + *ephes_checked_if_pure = v; + ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); + } + return gray_vals_ptr; +} + + + +static void mark_slice (intnat work) +{ + value *gray_vals_ptr; /* Local copy of [gray_vals_cur] */ + value v; + header_t hd; + mlsize_t size, i, start, end; /* [start] is a local copy of [current_index] */ +#ifdef CAML_INSTR + int slice_fields = 0; #endif + int slice_pointers = 0; /** gcc removes it when not in CAML_INSTR */ caml_gc_message (0x40, "Marking %ld words\n", work); caml_gc_message (0x40, "Subphase = %ld\n", caml_gc_subphase); gray_vals_ptr = gray_vals_cur; + v = current_value; + start = current_index; while (work > 0){ - if (gray_vals_ptr > gray_vals){ + if (v == 0 && gray_vals_ptr > gray_vals){ + CAMLassert (start == 0); v = *--gray_vals_ptr; + CAMLassert (Is_gray_val (v)); + } + if (v != 0){ hd = Hd_val(v); -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - marking_closure = - (Tag_hd (hd) == Closure_tag || Tag_hd (hd) == Infix_tag); -#endif Assert (Is_gray_hd (hd)); - Hd_val (v) = Blackhd_hd (hd); size = Wosize_hd (hd); + end = start + work; if (Tag_hd (hd) < No_scan_tag){ - for (i = 0; i < size; i++){ - child = Field (v, i); -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - if (Is_block (child) - && Wosize_val (child) > 0 /* Atoms never need to be marked. */ - /* Closure blocks contain code pointers at offsets that cannot - be reliably determined, so we always use the page table when - marking such values. */ - && (!marking_closure || Is_in_heap (child))) { -#else - if (Is_block (child) && Is_in_heap (child)) { -#endif - hd = Hd_val (child); - if (Tag_hd (hd) == Forward_tag){ - value f = Forward_val (child); - if (Is_block (f) - && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag)){ - /* Do not short-circuit the pointer. */ - }else{ - Field (v, i) = f; - } - } - else if (Tag_hd(hd) == Infix_tag) { - child -= Infix_offset_val(child); - hd = Hd_val(child); - } -#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS - /* See [caml_darken] for a description of this assertion. */ - CAMLassert (Is_in_heap (child) || Is_black_hd (hd)); -#endif - if (Is_white_hd (hd)){ - Hd_val (child) = Grayhd_hd (hd); - *gray_vals_ptr++ = child; - if (gray_vals_ptr >= gray_vals_end) { - gray_vals_cur = gray_vals_ptr; - realloc_gray_vals (); - gray_vals_ptr = gray_vals_cur; - } - } - } + start = size < start ? size : start; + end = size < end ? size : end; + CAMLassert (end > start); + INSTR (slice_fields += end - start;) + INSTR (if (size > end) + CAML_INSTR_INT ("major/mark/slice/remain", size - end);) + for (i = start; i < end; i++){ + gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v,i, + /*in_ephemeron=*/ 0, + &slice_pointers); + } + if (end < size){ + work = 0; + start = end; + /* [v] doesn't change. */ + CAMLassert (Is_gray_val (v)); + }else{ + CAMLassert (end == size); + Hd_val (v) = Blackhd_hd (hd); + work -= Whsize_wosize(end - start); + start = 0; + v = 0; } + }else{ + /* The block doesn't contain any pointers. */ + CAMLassert (start == 0); + Hd_val (v) = Blackhd_hd (hd); + work -= Whsize_wosize(size); + v = 0; } - work -= Whsize_wosize(size); }else if (markhp != NULL){ if (markhp == limit){ chunk = Chunk_next (chunk); @@ -220,7 +439,8 @@ static void mark_slice (intnat work) }else{ if (Is_gray_val (Val_hp (markhp))){ Assert (gray_vals_ptr == gray_vals); - *gray_vals_ptr++ = Val_hp (markhp); + CAMLassert (v == 0 && start == 0); + v = Val_hp (markhp); } markhp += Bhsize_hp (markhp); } @@ -229,91 +449,49 @@ static void mark_slice (intnat work) chunk = caml_heap_start; markhp = chunk; limit = chunk + Chunk_size (chunk); + } else if (caml_gc_subphase == Subphase_mark_roots) { + gray_vals_cur = gray_vals_ptr; + work = caml_darken_all_roots_slice (work); + gray_vals_ptr = gray_vals_cur; + if (work > 0){ + caml_gc_subphase = Subphase_mark_main; + } + } else if (*ephes_to_check != (value) NULL) { + /* Continue to scan the list of ephe */ + gray_vals_ptr = mark_ephe_aux(gray_vals_ptr,&work,&slice_pointers); + } else if (!ephe_list_pure){ + /* We must scan again the list because some value have been darken */ + ephe_list_pure = 1; + ephes_to_check = ephes_checked_if_pure; }else{ switch (caml_gc_subphase){ - case Subphase_main: { - /* The main marking phase is over. Start removing weak pointers to - dead values. */ - caml_gc_subphase = Subphase_weak1; - weak_prev = &caml_weak_list_head; - } - break; - case Subphase_weak1: { - value cur, curfield; - mlsize_t sz, i; - header_t hd; - - cur = *weak_prev; - if (cur != (value) NULL){ - hd = Hd_val (cur); - sz = Wosize_hd (hd); - for (i = 1; i < sz; i++){ - curfield = Field (cur, i); - weak_again: - if (curfield != caml_weak_none - && Is_block (curfield) && Is_in_heap (curfield)){ - if (Tag_val (curfield) == Forward_tag){ - value f = Forward_val (curfield); - if (Is_block (f)) { - if (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag){ - /* Do not short-circuit the pointer. */ - }else{ - Field (cur, i) = curfield = f; - goto weak_again; - } - } - } - if (Is_white_val (curfield)){ - Field (cur, i) = caml_weak_none; - } - } - } - weak_prev = &Field (cur, 0); - work -= Whsize_hd (hd); - }else{ - /* Subphase_weak1 is done. - Handle finalised values and start removing dead weak arrays. */ + case Subphase_mark_main: { + /* Subphase_mark_main is done. + Mark finalised values. */ gray_vals_cur = gray_vals_ptr; caml_final_update (); gray_vals_ptr = gray_vals_cur; - caml_gc_subphase = Subphase_weak2; - weak_prev = &caml_weak_list_head; - } - } - break; - case Subphase_weak2: { - value cur; - header_t hd; - - cur = *weak_prev; - if (cur != (value) NULL){ - hd = Hd_val (cur); - if (Color_hd (hd) == Caml_white){ - /* The whole array is dead, remove it from the list. */ - *weak_prev = Field (cur, 0); - }else{ - weak_prev = &Field (cur, 0); + if (gray_vals_ptr > gray_vals){ + v = *--gray_vals_ptr; + CAMLassert (start == 0); } - work -= 1; - }else{ - /* Subphase_weak2 is done. Go to Subphase_final. */ - caml_gc_subphase = Subphase_final; - } + /* Complete the marking */ + ephes_to_check = ephes_checked_if_pure; + caml_gc_subphase = Subphase_mark_final; } break; - case Subphase_final: { - /* Initialise the sweep phase. */ - gray_vals_cur = gray_vals_ptr; - caml_gc_sweep_hp = caml_heap_start; - caml_fl_init_merge (); - caml_gc_phase = Phase_sweep; - chunk = caml_heap_start; - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - work = 0; - caml_fl_size_at_phase_change = caml_fl_cur_size; - if (caml_major_gc_hook) (*caml_major_gc_hook)(); + case Subphase_mark_final: { + if (caml_ephe_list_head != (value) NULL){ + /* Initialise the clean phase. */ + caml_gc_phase = Phase_clean; + ephes_to_check = &caml_ephe_list_head; + work = 0; + } else { + /* Initialise the sweep phase, + shortcut the unneeded clean phase. */ + init_sweep_phase(); + work = 0; + } } break; default: Assert (0); @@ -321,6 +499,37 @@ static void mark_slice (intnat work) } } gray_vals_cur = gray_vals_ptr; + current_value = v; + current_index = start; + INSTR (CAML_INSTR_INT ("major/mark/slice/fields#", slice_fields);) + INSTR (CAML_INSTR_INT ("major/mark/slice/pointers#", slice_pointers);) +} + +/* Clean ephemerons */ +static void clean_slice (intnat work) +{ + value v; + + caml_gc_message (0x40, "Cleaning %ld words\n", work); + while (work > 0){ + v = *ephes_to_check; + if (v != (value) NULL){ + if (Is_white_val (v)){ + /* The whole array is dead, remove it from the list. */ + *ephes_to_check = Field (v, CAML_EPHE_LINK_OFFSET); + work -= 1; + }else{ + caml_ephe_clean(v); + ephes_to_check = &Field (v, CAML_EPHE_LINK_OFFSET); + work -= Whsize_val (v); + } + }else{ /* End of list reached */ + /* Phase_clean is done. */ + /* Initialise the sweep phase. */ + init_sweep_phase(); + work = 0; + } + } } static void sweep_slice (intnat work) @@ -341,7 +550,7 @@ static void sweep_slice (intnat work) void (*final_fun)(value) = Custom_ops_val(Val_hp(hp))->finalize; if (final_fun != NULL) final_fun(Val_hp(hp)); } - caml_gc_sweep_hp = caml_fl_merge_block (Bp_hp (hp)); + caml_gc_sweep_hp = (char *) caml_fl_merge_block (Val_hp (hp)); break; case Caml_blue: /* Only the blocks of the free-list are blue. See [freelist.c]. */ @@ -360,6 +569,7 @@ static void sweep_slice (intnat work) ++ caml_stat_major_collections; work = 0; caml_gc_phase = Phase_idle; + caml_request_minor_gc (); }else{ caml_gc_sweep_hp = chunk; limit = chunk + Chunk_size (chunk); @@ -368,17 +578,40 @@ static void sweep_slice (intnat work) } } -/* The main entry point for the GC. Called after each minor GC. - [howmuch] is the amount of work to do, 0 to let the GC compute it. - Return the computed amount of work to do. +#ifdef CAML_INSTR +static char *mark_slice_name[] = { + /* 0 */ NULL, + /* 1 */ NULL, + /* 2 */ NULL, + /* 3 */ NULL, + /* 4 */ NULL, + /* 5 */ NULL, + /* 6 */ NULL, + /* 7 */ NULL, + /* 8 */ NULL, + /* 9 */ NULL, + /* 10 */ "major/mark_roots", + /* 11 */ "major/mark_main", + /* 12 */ "major/mark_weak1", + /* 13 */ "major/mark_weak2", + /* 14 */ "major/mark_final", +}; +#endif + +/* The main entry point for the major GC. Called about once for each + minor GC. [howmuch] is the amount of work to do: + -1 if the GC is triggered automatically + 0 to let the GC compute the amount of work + [n] to make the GC do enough work to (on average) free [n] words */ -intnat caml_major_collection_slice (intnat howmuch) +void caml_major_collection_slice (intnat howmuch) { - double p, dp; + double p, dp, filt_p, spend; intnat computed_work; + int i; /* Free memory at the start of the GC cycle (garbage + free list) (assumed): - FM = caml_stat_heap_size * caml_percent_free + FM = caml_stat_heap_wsz * caml_percent_free / (100 + caml_percent_free) Assuming steady state and enforcing a constant allocation rate, then @@ -390,42 +623,54 @@ intnat caml_major_collection_slice (intnat howmuch) Proportion of G consumed since the previous slice: PH = caml_allocated_words / G = caml_allocated_words * 3 * (100 + caml_percent_free) - / (2 * caml_stat_heap_size * caml_percent_free) + / (2 * caml_stat_heap_wsz * caml_percent_free) Proportion of extra-heap resources consumed since the previous slice: PE = caml_extra_heap_resources Proportion of total work to do in this slice: P = max (PH, PE) + + Here, we insert a time-based filter on the P variable to avoid large + latency spikes in the GC, so the P below is a smoothed-out version of + the P above. + Amount of marking work for the GC cycle: - MW = caml_stat_heap_size * 100 / (100 + caml_percent_free) + MW = caml_stat_heap_wsz * 100 / (100 + caml_percent_free) + + caml_incremental_roots_count Amount of sweeping work for the GC cycle: - SW = caml_stat_heap_size + SW = caml_stat_heap_wsz In order to finish marking with a non-empty free list, we will use 40% of the time for marking, and 60% for sweeping. - If TW is the total work for this cycle, - MW = 40/100 * TW - SW = 60/100 * TW + Let MT be the time spent marking, ST the time spent sweeping, and TT + the total time for this cycle. We have: + MT = 40/100 * TT + ST = 60/100 * TT + + Amount of time to spend on this slice: + T = P * TT = P * MT / (40/100) = P * ST / (60/100) - Amount of work to do for this slice: - W = P * TW + Since we must do MW work in MT time or SW work in ST time, the amount + of work for this slice is: + MS = P * MW / (40/100) if marking + SS = P * SW / (60/100) if sweeping Amount of marking work for a marking slice: MS = P * MW / (40/100) - MS = P * caml_stat_heap_size * 250 / (100 + caml_percent_free) + MS = P * (caml_stat_heap_wsz * 250 / (100 + caml_percent_free) + + 2.5 * caml_incremental_roots_count) Amount of sweeping work for a sweeping slice: SS = P * SW / (60/100) - SS = P * caml_stat_heap_size * 5 / 3 + SS = P * caml_stat_heap_wsz * 5 / 3 This slice will either mark MS words or sweep SS words. */ if (caml_major_slice_begin_hook != NULL) (*caml_major_slice_begin_hook) (); - - if (caml_gc_phase == Phase_idle) start_cycle (); + CAML_INSTR_SETUP (tmr, "major"); p = (double) caml_allocated_words * 3.0 * (100 + caml_percent_free) - / Wsize_bsize (caml_stat_heap_size) / caml_percent_free / 2.0; + / caml_stat_heap_wsz / caml_percent_free / 2.0; if (caml_dependent_size > 0){ dp = (double) caml_dependent_allocated * (100 + caml_percent_free) / caml_dependent_size / caml_percent_free; @@ -434,56 +679,142 @@ intnat caml_major_collection_slice (intnat howmuch) } if (p < dp) p = dp; if (p < caml_extra_heap_resources) p = caml_extra_heap_resources; + if (p > 0.3) p = 0.3; + CAML_INSTR_INT ("major/work/extra#", + (uintnat) (caml_extra_heap_resources * 1000000)); + caml_gc_message (0x40, "ordered work = %ld words\n", howmuch); caml_gc_message (0x40, "allocated_words = %" ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocated_words); caml_gc_message (0x40, "extra_heap_resources = %" ARCH_INTNAT_PRINTF_FORMAT "uu\n", (uintnat) (caml_extra_heap_resources * 1000000)); - caml_gc_message (0x40, "amount of work to do = %" - ARCH_INTNAT_PRINTF_FORMAT "uu\n", - (uintnat) (p * 1000000)); + caml_gc_message (0x40, "raw work-to-do = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p * 1000000)); - if (caml_gc_phase == Phase_mark){ - computed_work = (intnat) (p * Wsize_bsize (caml_stat_heap_size) * 250 - / (100 + caml_percent_free)); + for (i = 0; i < caml_major_window; i++){ + caml_major_ring[i] += p / caml_major_window; + } + + if (caml_gc_clock >= 1.0){ + caml_gc_clock -= 1.0; + ++caml_major_ring_index; + if (caml_major_ring_index >= caml_major_window){ + caml_major_ring_index = 0; + } + } + if (howmuch == -1){ + /* auto-triggered GC slice: spend work credit on the current bucket, + then do the remaining work, if any */ + /* Note that the minor GC guarantees that the major slice is called in + automatic mode (with [howmuch] = -1) at least once per clock tick. + This means we never leave a non-empty bucket behind. */ + spend = fmin (caml_major_work_credit, + caml_major_ring[caml_major_ring_index]); + caml_major_work_credit -= spend; + filt_p = caml_major_ring[caml_major_ring_index] - spend; + caml_major_ring[caml_major_ring_index] = 0.0; }else{ - computed_work = (intnat) (p * Wsize_bsize (caml_stat_heap_size) * 5 / 3); + /* forced GC slice: do work and add it to the credit */ + if (howmuch == 0){ + /* automatic setting: size of next bucket + we do not use the current bucket, as it may be empty */ + int i = caml_major_ring_index + 1; + if (i >= caml_major_window) i = 0; + filt_p = caml_major_ring[i]; + }else{ + /* manual setting */ + filt_p = (double) howmuch * 3.0 * (100 + caml_percent_free) + / caml_stat_heap_wsz / caml_percent_free / 2.0; + } + caml_major_work_credit += filt_p; + } + + p = filt_p; + + caml_gc_message (0x40, "filtered work-to-do = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p * 1000000)); + + if (caml_gc_phase == Phase_idle){ + if (caml_young_ptr == caml_young_alloc_end){ + /* We can only start a major GC cycle if the minor allocation arena + is empty, otherwise we'd have to treat it as a set of roots. */ + start_cycle (); + CAML_INSTR_TIME (tmr, "major/roots"); + } + p = 0; + goto finished; + } + + if (p < 0){ + p = 0; + goto finished; + } + + if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean){ + computed_work = (intnat) (p * ((double) caml_stat_heap_wsz * 250 + / (100 + caml_percent_free) + + caml_incremental_roots_count)); + }else{ + computed_work = (intnat) (p * caml_stat_heap_wsz * 5 / 3); } - caml_gc_message (0x40, "ordered work = %ld words\n", howmuch); caml_gc_message (0x40, "computed work = %ld words\n", computed_work); - if (howmuch == 0) howmuch = computed_work; if (caml_gc_phase == Phase_mark){ - mark_slice (howmuch); + CAML_INSTR_INT ("major/work/mark#", computed_work); + mark_slice (computed_work); + CAML_INSTR_TIME (tmr, mark_slice_name[caml_gc_subphase]); caml_gc_message (0x02, "!", 0); + }else if (caml_gc_phase == Phase_clean){ + clean_slice (computed_work); + caml_gc_message (0x02, "%%", 0); }else{ Assert (caml_gc_phase == Phase_sweep); - sweep_slice (howmuch); + CAML_INSTR_INT ("major/work/sweep#", computed_work); + sweep_slice (computed_work); + CAML_INSTR_TIME (tmr, "major/sweep"); caml_gc_message (0x02, "$", 0); } - if (caml_gc_phase == Phase_idle) caml_compact_heap_maybe (); + if (caml_gc_phase == Phase_idle){ + caml_compact_heap_maybe (); + CAML_INSTR_TIME (tmr, "major/check_and_compact"); + } + + finished: + caml_gc_message (0x40, "work-done = %" + ARCH_INTNAT_PRINTF_FORMAT "du\n", + (intnat) (p * 1000000)); + + /* if some of the work was not done, take it back from the credit + or spread it over the buckets. */ + p = filt_p - p; + spend = fmin (p, caml_major_work_credit); + caml_major_work_credit -= spend; + if (p > spend){ + p -= spend; + p /= caml_major_window; + for (i = 0; i < caml_major_window; i++) caml_major_ring[i] += p; + } caml_stat_major_words += caml_allocated_words; caml_allocated_words = 0; caml_dependent_allocated = 0; caml_extra_heap_resources = 0.0; if (caml_major_slice_end_hook != NULL) (*caml_major_slice_end_hook) (); - return computed_work; } -/* The minor heap must be empty when this function is called; - the minor heap is empty when this function returns. -*/ -/* This does not call caml_compact_heap_maybe because the estimations of +/* This does not call [caml_compact_heap_maybe] because the estimates of free and live memory are only valid for a cycle done incrementally. - Besides, this function is called by caml_compact_heap_maybe. + Besides, this function itself is called by [caml_compact_heap_maybe]. */ void caml_finish_major_cycle (void) { if (caml_gc_phase == Phase_idle) start_cycle (); while (caml_gc_phase == Phase_mark) mark_slice (LONG_MAX); + while (caml_gc_phase == Phase_clean) clean_slice (LONG_MAX); Assert (caml_gc_phase == Phase_sweep); while (caml_gc_phase == Phase_sweep) sweep_slice (LONG_MAX); Assert (caml_gc_phase == Phase_idle); @@ -491,64 +822,57 @@ void caml_finish_major_cycle (void) caml_allocated_words = 0; } -/* Make sure the request is at least Heap_chunk_min and round it up - to a multiple of the page size. -*/ -static asize_t clip_heap_chunk_size (asize_t request) -{ - if (request < Bsize_wsize (Heap_chunk_min)){ - request = Bsize_wsize (Heap_chunk_min); - } - return ((request + Page_size - 1) >> Page_log) << Page_log; -} - -/* Compute the heap increment, make sure the request is at least that big, - then call clip_heap_chunk_size, then make sure the result is >= request. +/* Call this function to make sure [bsz] is greater than or equal + to both [Heap_chunk_min] and the current heap increment. */ -asize_t caml_round_heap_chunk_size (asize_t request) +asize_t caml_clip_heap_chunk_wsz (asize_t wsz) { - asize_t result = request; + asize_t result = wsz; uintnat incr; - /* Compute the heap increment as a byte size. */ + /* Compute the heap increment as a word size. */ if (caml_major_heap_increment > 1000){ - incr = Bsize_wsize (caml_major_heap_increment); + incr = caml_major_heap_increment; }else{ - incr = caml_stat_heap_size / 100 * caml_major_heap_increment; + incr = caml_stat_heap_wsz / 100 * caml_major_heap_increment; } if (result < incr){ result = incr; } - result = clip_heap_chunk_size (result); - - if (result < request){ - caml_raise_out_of_memory (); - return 0; /* not reached */ + if (result < Heap_chunk_min){ + result = Heap_chunk_min; } return result; } +/* [heap_size] is a number of bytes */ void caml_init_major_heap (asize_t heap_size) { - caml_stat_heap_size = clip_heap_chunk_size (heap_size); - caml_stat_top_heap_size = caml_stat_heap_size; - Assert (caml_stat_heap_size % Page_size == 0); - caml_heap_start = (char *) caml_alloc_for_heap (caml_stat_heap_size); + int i; + + caml_stat_heap_wsz = caml_clip_heap_chunk_wsz (Wsize_bsize (heap_size)); + caml_stat_top_heap_wsz = caml_stat_heap_wsz; + Assert (Bsize_wsize (caml_stat_heap_wsz) % Page_size == 0); + caml_heap_start = + (char *) caml_alloc_for_heap (Bsize_wsize (caml_stat_heap_wsz)); if (caml_heap_start == NULL) - caml_fatal_error ("Fatal error: not enough memory for the initial heap.\n"); + caml_fatal_error ("Fatal error: cannot allocate initial major heap.\n"); Chunk_next (caml_heap_start) = NULL; + caml_stat_heap_wsz = Wsize_bsize (Chunk_size (caml_heap_start)); caml_stat_heap_chunks = 1; + caml_stat_top_heap_wsz = caml_stat_heap_wsz; if (caml_page_table_add(In_heap, caml_heap_start, - caml_heap_start + caml_stat_heap_size) != 0) { - caml_fatal_error ("Fatal error: not enough memory " - "for the initial page table.\n"); + caml_heap_start + Bsize_wsize (caml_stat_heap_wsz)) + != 0) { + caml_fatal_error ("Fatal error: cannot allocate " + "initial page table.\n"); } caml_fl_init_merge (); caml_make_free_blocks ((value *) caml_heap_start, - Wsize_bsize (caml_stat_heap_size), 1, Caml_white); + caml_stat_heap_wsz, 1, Caml_white); caml_gc_phase = Phase_idle; gray_vals_size = 2048; gray_vals = (value *) malloc (gray_vals_size * sizeof (value)); @@ -559,4 +883,21 @@ void caml_init_major_heap (asize_t heap_size) heap_is_pure = 1; caml_allocated_words = 0; caml_extra_heap_resources = 0.0; + for (i = 0; i < Max_major_window; i++) caml_major_ring[i] = 0.0; +} + +void caml_set_major_window (int w){ + uintnat total = 0; + int i; + if (w == caml_major_window) return; + CAMLassert (w <= Max_major_window); + /* Collect the current work-to-do from the buckets. */ + for (i = 0; i < caml_major_window; i++){ + total += caml_major_ring[i]; + } + /* Redistribute to the new buckets. */ + for (i = 0; i < w; i++){ + caml_major_ring[i] = total / w; + } + caml_major_window = w; } diff --git a/byterun/md5.c b/byterun/md5.c index 5d748c1a..3d5ae496 100644 --- a/byterun/md5.c +++ b/byterun/md5.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "caml/alloc.h" @@ -101,11 +103,11 @@ CAMLexport void caml_md5_block(unsigned char digest[16], #else static void byteReverse(unsigned char * buf, unsigned longs) { - uint32 t; + uint32_t t; do { - t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | ((unsigned) buf[1] << 8 | buf[0]); - *(uint32 *) buf = t; + *(uint32_t *) buf = t; buf += 4; } while (--longs); } @@ -133,12 +135,12 @@ CAMLexport void caml_MD5Init(struct MD5Context *ctx) CAMLexport void caml_MD5Update(struct MD5Context *ctx, unsigned char *buf, uintnat len) { - uint32 t; + uint32_t t; /* Update bitcount */ t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; @@ -156,7 +158,7 @@ CAMLexport void caml_MD5Update(struct MD5Context *ctx, unsigned char *buf, } memcpy(p, buf, t); byteReverse(ctx->in, 16); - caml_MD5Transform(ctx->buf, (uint32 *) ctx->in); + caml_MD5Transform(ctx->buf, (uint32_t *) ctx->in); buf += t; len -= t; } @@ -165,7 +167,7 @@ CAMLexport void caml_MD5Update(struct MD5Context *ctx, unsigned char *buf, while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); - caml_MD5Transform(ctx->buf, (uint32 *) ctx->in); + caml_MD5Transform(ctx->buf, (uint32_t *) ctx->in); buf += 64; len -= 64; } @@ -200,7 +202,7 @@ CAMLexport void caml_MD5Final(unsigned char *digest, struct MD5Context *ctx) /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); - caml_MD5Transform(ctx->buf, (uint32 *) ctx->in); + caml_MD5Transform(ctx->buf, (uint32_t *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -211,10 +213,10 @@ CAMLexport void caml_MD5Final(unsigned char *digest, struct MD5Context *ctx) byteReverse(ctx->in, 14); /* Append length in bits and transform */ - ((uint32 *) ctx->in)[14] = ctx->bits[0]; - ((uint32 *) ctx->in)[15] = ctx->bits[1]; + ((uint32_t *) ctx->in)[14] = ctx->bits[0]; + ((uint32_t *) ctx->in)[15] = ctx->bits[1]; - caml_MD5Transform(ctx->buf, (uint32 *) ctx->in); + caml_MD5Transform(ctx->buf, (uint32_t *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ @@ -237,9 +239,9 @@ CAMLexport void caml_MD5Final(unsigned char *digest, struct MD5Context *ctx) * reflect the addition of 16 longwords of new data. caml_MD5Update blocks * the data and converts bytes into longwords for this routine. */ -CAMLexport void caml_MD5Transform(uint32 *buf, uint32 *in) +CAMLexport void caml_MD5Transform(uint32_t *buf, uint32_t *in) { - register uint32 a, b, c, d; + register uint32_t a, b, c, d; a = buf[0]; b = buf[1]; diff --git a/byterun/memory.c b/byterun/memory.c index 4eb63b40..4b52b820 100644 --- a/byterun/memory.c +++ b/byterun/memory.c @@ -1,19 +1,22 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include "caml/address_class.h" +#include "caml/config.h" #include "caml/fail.h" #include "caml/freelist.h" #include "caml/gc.h" @@ -26,6 +29,18 @@ #include "caml/mlvalues.h" #include "caml/signals.h" +int caml_huge_fallback_count = 0; +/* Number of times that mmapping big pages fails and we fell back to small + pages. This counter is available to the program through + [Gc.huge_fallback_count]. +*/ + +uintnat caml_use_huge_pages = 0; +/* True iff the program allocates heap chunks by mmapping huge pages. + This is set when parsing [OCAMLRUNPARAM] and must stay constant + after that. +*/ + extern uintnat caml_percent_free; /* major_gc.c */ /* Page table management */ @@ -217,25 +232,56 @@ int caml_page_table_remove(int kind, void * start, void * end) return 0; } + +/* Initialize the [alloc_for_heap] system. + This function must be called exactly once, and it must be called + before the first call to [alloc_for_heap]. + It returns 0 on success and -1 on failure. +*/ +int caml_init_alloc_for_heap (void) +{ + return 0; +} + /* Allocate a block of the requested size, to be passed to [caml_add_to_heap] later. - [request] must be a multiple of [Page_size]. - [caml_alloc_for_heap] returns NULL if the request cannot be satisfied. - The returned pointer is a hp, but the header must be initialized by - the caller. + [request] will be rounded up to some implementation-dependent size. + The caller must use [Chunk_size] on the result to recover the actual + size. + Return NULL if the request cannot be satisfied. The returned pointer + is a hp, but the header (and the contents) must be initialized by the + caller. */ char *caml_alloc_for_heap (asize_t request) { - char *mem; - void *block; - Assert (request % Page_size == 0); - mem = caml_aligned_malloc (request + sizeof (heap_chunk_head), - sizeof (heap_chunk_head), &block); - if (mem == NULL) return NULL; - mem += sizeof (heap_chunk_head); - Chunk_size (mem) = request; - Chunk_block (mem) = block; - return mem; + if (caml_use_huge_pages){ +#ifdef HAS_HUGE_PAGES + uintnat size = Round_mmap_size (sizeof (heap_chunk_head) + request); + void *block; + char *mem; + block = mmap (NULL, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0); + if (block == MAP_FAILED) return NULL; + mem = (char *) block + sizeof (heap_chunk_head); + Chunk_size (mem) = size - sizeof (heap_chunk_head); + Chunk_block (mem) = block; + return mem; +#else + return NULL; +#endif + }else{ + char *mem; + void *block; + + request = ((request + Page_size - 1) >> Page_log) << Page_log; + mem = caml_aligned_malloc (request + sizeof (heap_chunk_head), + sizeof (heap_chunk_head), &block); + if (mem == NULL) return NULL; + mem += sizeof (heap_chunk_head); + Chunk_size (mem) = request; + Chunk_block (mem) = block; + return mem; + } } /* Use this function to free a block allocated with [caml_alloc_for_heap] @@ -243,7 +289,15 @@ char *caml_alloc_for_heap (asize_t request) */ void caml_free_for_heap (char *mem) { - free (Chunk_block (mem)); + if (caml_use_huge_pages){ +#ifdef HAS_HUGE_PAGES + munmap (Chunk_block (mem), Chunk_size (mem) + sizeof (heap_chunk_head)); +#else + CAMLassert (0); +#endif + }else{ + free (Chunk_block (mem)); + } } /* Take a chunk of memory as argument, which must be the result of a @@ -259,13 +313,12 @@ void caml_free_for_heap (char *mem) */ int caml_add_to_heap (char *m) { - Assert (Chunk_size (m) % Page_size == 0); #ifdef DEBUG /* Should check the contents of the block. */ -#endif /* debug */ +#endif /* DEBUG */ caml_gc_message (0x04, "Growing heap to %luk bytes\n", - (caml_stat_heap_size + Chunk_size (m)) / 1024); + (Bsize_wsize (caml_stat_heap_wsz) + Chunk_size (m)) / 1024); /* Register block in page table */ if (caml_page_table_add(In_heap, m, m + Chunk_size(m)) != 0) @@ -286,9 +339,9 @@ int caml_add_to_heap (char *m) ++ caml_stat_heap_chunks; } - caml_stat_heap_size += Chunk_size (m); - if (caml_stat_heap_size > caml_stat_top_heap_size){ - caml_stat_top_heap_size = caml_stat_heap_size; + caml_stat_heap_wsz += Wsize_bsize (Chunk_size (m)); + if (caml_stat_heap_wsz > caml_stat_top_heap_wsz){ + caml_stat_top_heap_wsz = caml_stat_heap_wsz; } return 0; } @@ -299,52 +352,54 @@ int caml_add_to_heap (char *m) field 0); the last block of the chain is pointed by field 1 of the first. There may be a fragment after the last block. The caller must insert the blocks into the free list. - The request must be less than or equal to Max_wosize. + [request] is a number of words and must be less than or equal + to [Max_wosize]. Return NULL when out of memory. */ -static char *expand_heap (mlsize_t request) +static value *expand_heap (mlsize_t request) { - char *mem, *hp, *prev; + /* these point to headers, but we do arithmetic on them, hence [value *]. */ + value *mem, *hp, *prev; asize_t over_request, malloc_request, remain; Assert (request <= Max_wosize); over_request = request + request / 100 * caml_percent_free; - malloc_request = caml_round_heap_chunk_size (Bhsize_wosize (over_request)); - mem = caml_alloc_for_heap (malloc_request); + malloc_request = caml_clip_heap_chunk_wsz (over_request); + mem = (value *) caml_alloc_for_heap (Bsize_wsize (malloc_request)); if (mem == NULL){ caml_gc_message (0x04, "No room for growing heap\n", 0); return NULL; } - remain = malloc_request; + remain = Wsize_bsize (Chunk_size (mem)); prev = hp = mem; /* FIXME find a way to do this with a call to caml_make_free_blocks */ - while (Wosize_bhsize (remain) > Max_wosize){ + while (Wosize_whsize (remain) > Max_wosize){ Hd_hp (hp) = Make_header (Max_wosize, 0, Caml_blue); #ifdef DEBUG - caml_set_fields (Bp_hp (hp), 0, Debug_free_major); + caml_set_fields (Val_hp (hp), 0, Debug_free_major); #endif - hp += Bhsize_wosize (Max_wosize); - remain -= Bhsize_wosize (Max_wosize); - Field (Op_hp (mem), 1) = Field (Op_hp (prev), 0) = (value) Op_hp (hp); + hp += Whsize_wosize (Max_wosize); + remain -= Whsize_wosize (Max_wosize); + Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); prev = hp; } if (remain > 1){ - Hd_hp (hp) = Make_header (Wosize_bhsize (remain), 0, Caml_blue); + Hd_hp (hp) = Make_header (Wosize_whsize (remain), 0, Caml_blue); #ifdef DEBUG - caml_set_fields (Bp_hp (hp), 0, Debug_free_major); + caml_set_fields (Val_hp (hp), 0, Debug_free_major); #endif - Field (Op_hp (mem), 1) = Field (Op_hp (prev), 0) = (value) Op_hp (hp); - Field (Op_hp (hp), 0) = (value) NULL; + Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); + Field (Val_hp (hp), 0) = (value) NULL; }else{ - Field (Op_hp (prev), 0) = (value) NULL; + Field (Val_hp (prev), 0) = (value) NULL; if (remain == 1) Hd_hp (hp) = Make_header (0, 0, Caml_white); } Assert (Wosize_hp (mem) >= request); - if (caml_add_to_heap (mem) != 0){ - caml_free_for_heap (mem); + if (caml_add_to_heap ((char *) mem) != 0){ + caml_free_for_heap ((char *) mem); return NULL; } - return Bp_hp (mem); + return Op_hp (mem); } /* Remove the heap chunk [chunk] from the heap and give the memory back @@ -359,12 +414,13 @@ void caml_shrink_heap (char *chunk) want to shift the page table, it's too messy (see above). It will never happen anyway, because of the way compaction works. (see compact.c) + XXX FIXME this has become false with the fix to PR#5389 (see compact.c) */ if (chunk == caml_heap_start) return; - caml_stat_heap_size -= Chunk_size (chunk); - caml_gc_message (0x04, "Shrinking heap to %luk bytes\n", - (unsigned long) caml_stat_heap_size / 1024); + caml_stat_heap_wsz -= Wsize_bsize (Chunk_size (chunk)); + caml_gc_message (0x04, "Shrinking heap to %luk words\n", + (unsigned long) caml_stat_heap_wsz / 1024); #ifdef DEBUG { @@ -391,7 +447,7 @@ void caml_shrink_heap (char *chunk) color_t caml_allocation_color (void *hp) { - if (caml_gc_phase == Phase_mark + if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){ return Caml_black; }else{ @@ -402,28 +458,37 @@ color_t caml_allocation_color (void *hp) } } -CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) +static inline value caml_alloc_shr_aux (mlsize_t wosize, tag_t tag, + int raise_oom) { - char *hp, *new_block; - - if (wosize > Max_wosize) caml_raise_out_of_memory (); + header_t *hp; + value *new_block; + + if (wosize > Max_wosize) { + if (raise_oom) + caml_raise_out_of_memory (); + else + return 0; + } hp = caml_fl_allocate (wosize); if (hp == NULL){ new_block = expand_heap (wosize); if (new_block == NULL) { - if (caml_in_minor_collection) + if (!raise_oom) + return 0; + else if (caml_in_minor_collection) caml_fatal_error ("Fatal error: out of memory.\n"); else caml_raise_out_of_memory (); } - caml_fl_add_blocks (new_block); + caml_fl_add_blocks ((value) new_block); hp = caml_fl_allocate (wosize); } Assert (Is_in_heap (Val_hp (hp))); /* Inline expansion of caml_allocation_color. */ - if (caml_gc_phase == Phase_mark + if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean || (caml_gc_phase == Phase_sweep && (addr)hp >= (addr)caml_gc_sweep_hp)){ Hd_hp (hp) = Make_header (wosize, tag, Caml_black); }else{ @@ -434,8 +499,9 @@ CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) } Assert (Hd_hp (hp) == Make_header (wosize, tag, caml_allocation_color (hp))); caml_allocated_words += Whsize_wosize (wosize); - if (caml_allocated_words > Wsize_bsize (caml_minor_heap_size)){ - caml_urge_major_slice (); + if (caml_allocated_words > caml_minor_heap_wsz){ + CAML_INSTR_INT ("request_major/alloc_shr@", 1); + caml_request_major_slice (); } #ifdef DEBUG { @@ -448,6 +514,16 @@ CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) return Val_hp (hp); } +CAMLexport value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t tag) +{ + return caml_alloc_shr_aux(wosize, tag, 0); +} + +CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) +{ + return caml_alloc_shr_aux(wosize, tag, 1); +} + /* Dependent memory is all memory blocks allocated out of the heap that depend on the GC (and finalizers) for deallocation. For the GC to take dependent memory into account when computing @@ -486,13 +562,15 @@ CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max) if (res > max) res = max; caml_extra_heap_resources += (double) res / (double) max; if (caml_extra_heap_resources > 1.0){ + CAML_INSTR_INT ("request_major/adjust_gc_speed_1@", 1); caml_extra_heap_resources = 1.0; - caml_urge_major_slice (); + caml_request_major_slice (); } if (caml_extra_heap_resources - > (double) Wsize_bsize (caml_minor_heap_size) / 2.0 - / (double) Wsize_bsize (caml_stat_heap_size)) { - caml_urge_major_slice (); + > (double) caml_minor_heap_wsz / 2.0 + / (double) caml_stat_heap_wsz) { + CAML_INSTR_INT ("request_major/adjust_gc_speed_2@", 1); + caml_request_major_slice (); } } @@ -509,10 +587,7 @@ CAMLexport CAMLweakdef void caml_initialize (value *fp, value val) CAMLassert(Is_in_heap(fp)); *fp = val; if (Is_block (val) && Is_young (val)) { - if (caml_ref_table.ptr >= caml_ref_table.limit){ - caml_realloc_ref_table (&caml_ref_table); - } - *caml_ref_table.ptr++ = fp; + add_to_ref_table (&caml_ref_table, fp); } } @@ -560,16 +635,12 @@ CAMLexport CAMLweakdef void caml_modify (value *fp, value val) } /* Check for condition 1. */ if (Is_block(val) && Is_young(val)) { - /* Add [fp] to remembered set */ - if (caml_ref_table.ptr >= caml_ref_table.limit){ - CAMLassert (caml_ref_table.ptr == caml_ref_table.limit); - caml_realloc_ref_table (&caml_ref_table); - } - *caml_ref_table.ptr++ = fp; + add_to_ref_table (&caml_ref_table, fp); } } } +/* [sz] is a number of bytes */ CAMLexport void * caml_stat_alloc (asize_t sz) { void * result = malloc (sz); @@ -587,6 +658,7 @@ CAMLexport void caml_stat_free (void * blk) free (blk); } +/* [sz] is a number of bytes */ CAMLexport void * caml_stat_resize (void * blk, asize_t sz) { void * result = realloc (blk, sz); diff --git a/byterun/meta.c b/byterun/meta.c index edec4079..14205f1f 100644 --- a/byterun/meta.c +++ b/byterun/meta.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Primitives for the toplevel */ @@ -47,7 +49,14 @@ CAMLprim value caml_get_section_table(value unit) CAMLprim value caml_reify_bytecode(value prog, value len) { + struct code_fragment * cf = caml_stat_alloc(sizeof(struct code_fragment)); value clos; + + cf->code_start = (char *) prog; + cf->code_end = (char *) prog + Long_val(len); + cf->digest_computed = 0; + caml_ext_table_add(&caml_code_fragments_table, cf); + #ifdef ARCH_BIG_ENDIAN caml_fixup_endianness((code_t) prog, (asize_t) Long_val(len)); #endif @@ -60,6 +69,38 @@ CAMLprim value caml_reify_bytecode(value prog, value len) return clos; } +/* signal to the interpreter machinery that a bytecode is no more + needed (before freeing it) - this might be useful for a JIT + implementation */ + +CAMLprim value caml_static_release_bytecode(value prog, value len) +{ + struct code_fragment * cf = NULL, * cfi; + int i; + for (i = 0; i < caml_code_fragments_table.size; i++) { + cfi = (struct code_fragment *) caml_code_fragments_table.contents[i]; + if (cfi->code_start == (char *) prog && + cfi->code_end == (char *) prog + Long_val(len)) { + cf = cfi; + break; + } + } + + if (!cf) { + /* [cf] Not matched with a caml_reify_bytecode call; impossible. */ + Assert (0); + } else { + caml_ext_table_remove(&caml_code_fragments_table, cf); + } + +#ifndef NATIVE_CODE + caml_release_bytecode((code_t) prog, (asize_t) Long_val(len)); +#else + caml_failwith("Meta.static_release_bytecode impossible with native code"); +#endif + return Val_unit; +} + CAMLprim value caml_register_code_fragment(value prog, value len, value digest) { struct code_fragment * cf = caml_stat_alloc(sizeof(struct code_fragment)); @@ -171,6 +212,12 @@ value caml_reify_bytecode(value prog, value len) return Val_unit; /* not reached */ } +value caml_static_release_bytecode(value prog, value len) +{ + caml_invalid_argument("Meta.static_release_bytecode"); + return Val_unit; /* not reached */ +} + value * caml_stack_low; value * caml_stack_high; value * caml_stack_threshold; diff --git a/byterun/minor_gc.c b/byterun/minor_gc.c index 8eb087c7..727fdb01 100644 --- a/byterun/minor_gc.c +++ b/byterun/minor_gc.c @@ -1,17 +1,20 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 +#include "caml/custom.h" #include "caml/config.h" #include "caml/fail.h" #include "caml/finalise.h" @@ -26,38 +29,90 @@ #include "caml/signals.h" #include "caml/weak.h" -asize_t caml_minor_heap_size; +/* Pointers into the minor heap. + [caml_young_base] + The [malloc] block that contains the heap. + [caml_young_start] ... [caml_young_end] + The whole range of the minor heap: all young blocks are inside + this interval. + [caml_young_alloc_start]...[caml_young_alloc_end] + The allocation arena: newly-allocated blocks are carved from + this interval. + [caml_young_alloc_mid] is the mid-point of this interval. + [caml_young_ptr], [caml_young_trigger], [caml_young_limit] + These pointers are all inside the allocation arena. + - [caml_young_ptr] is where the next allocation will take place. + - [caml_young_trigger] is how far we can allocate before triggering + [caml_gc_dispatch]. Currently, it is either [caml_young_alloc_start] + or the mid-point of the allocation arena. + - [caml_young_limit] is the pointer that is compared to + [caml_young_ptr] for allocation. It is either + [caml_young_alloc_end] if a signal is pending and we are in + native code, or [caml_young_trigger]. +*/ + +struct generic_table CAML_TABLE_STRUCT(char); + +asize_t caml_minor_heap_wsz; static void *caml_young_base = NULL; -CAMLexport char *caml_young_start = NULL, *caml_young_end = NULL; -CAMLexport char *caml_young_ptr = NULL, *caml_young_limit = NULL; +CAMLexport value *caml_young_start = NULL, *caml_young_end = NULL; +CAMLexport value *caml_young_alloc_start = NULL, + *caml_young_alloc_mid = NULL, + *caml_young_alloc_end = NULL; +CAMLexport value *caml_young_ptr = NULL, *caml_young_limit = NULL; +CAMLexport value *caml_young_trigger = NULL; CAMLexport struct caml_ref_table - caml_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}, - caml_weak_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; + caml_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; -int caml_in_minor_collection = 0; +CAMLexport struct caml_ephe_ref_table + caml_ephe_ref_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; -#ifdef DEBUG -static unsigned long minor_gc_counter = 0; -#endif +CAMLexport struct caml_custom_table + caml_custom_table = { NULL, NULL, NULL, NULL, NULL, 0, 0}; +/* Table of custom blocks in the minor heap that contain finalizers + or GC speed parameters. */ -void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv) +int caml_in_minor_collection = 0; + +/* [sz] and [rsv] are numbers of entries */ +static void alloc_generic_table (struct generic_table *tbl, asize_t sz, + asize_t rsv, asize_t element_size) { - value **new_table; + void *new_table; tbl->size = sz; tbl->reserve = rsv; - new_table = (value **) caml_stat_alloc ((tbl->size + tbl->reserve) - * sizeof (value *)); + new_table = (void *) caml_stat_alloc ((tbl->size + tbl->reserve) + * element_size); if (tbl->base != NULL) caml_stat_free (tbl->base); tbl->base = new_table; tbl->ptr = tbl->base; - tbl->threshold = tbl->base + tbl->size; + tbl->threshold = tbl->base + tbl->size * element_size; tbl->limit = tbl->threshold; - tbl->end = tbl->base + tbl->size + tbl->reserve; + tbl->end = tbl->base + (tbl->size + tbl->reserve) * element_size; } -static void reset_table (struct caml_ref_table *tbl) +void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv) +{ + alloc_generic_table ((struct generic_table *) tbl, sz, rsv, sizeof (value *)); +} + +void caml_alloc_ephe_table (struct caml_ephe_ref_table *tbl, asize_t sz, + asize_t rsv) +{ + alloc_generic_table ((struct generic_table *) tbl, sz, rsv, + sizeof (struct caml_ephe_ref_elt)); +} + +void caml_alloc_custom_table (struct caml_custom_table *tbl, asize_t sz, + asize_t rsv) +{ + alloc_generic_table ((struct generic_table *) tbl, sz, rsv, + sizeof (struct caml_custom_elt)); +} + +static void reset_table (struct generic_table *tbl) { tbl->size = 0; tbl->reserve = 0; @@ -65,26 +120,31 @@ static void reset_table (struct caml_ref_table *tbl) tbl->base = tbl->ptr = tbl->threshold = tbl->limit = tbl->end = NULL; } -static void clear_table (struct caml_ref_table *tbl) +static void clear_table (struct generic_table *tbl) { tbl->ptr = tbl->base; tbl->limit = tbl->threshold; } -/* size in bytes */ -void caml_set_minor_heap_size (asize_t size) +void caml_set_minor_heap_size (asize_t bsz) { char *new_heap; void *new_heap_base; - Assert (size >= Bsize_wsize(Minor_heap_min)); - Assert (size <= Bsize_wsize(Minor_heap_max)); - Assert (size % sizeof (value) == 0); - if (caml_young_ptr != caml_young_end) caml_minor_collection (); - Assert (caml_young_ptr == caml_young_end); - new_heap = caml_aligned_malloc(size, 0, &new_heap_base); + Assert (bsz >= Bsize_wsize(Minor_heap_min)); + Assert (bsz <= Bsize_wsize(Minor_heap_max)); + Assert (bsz % sizeof (value) == 0); + if (caml_young_ptr != caml_young_alloc_end){ + CAML_INSTR_INT ("force_minor/set_minor_heap_size@", 1); + caml_requested_minor_gc = 0; + caml_young_trigger = caml_young_alloc_mid; + caml_young_limit = caml_young_trigger; + caml_empty_minor_heap (); + } + CAMLassert (caml_young_ptr == caml_young_alloc_end); + new_heap = caml_aligned_malloc(bsz, 0, &new_heap_base); if (new_heap == NULL) caml_raise_out_of_memory(); - if (caml_page_table_add(In_young, new_heap, new_heap + size) != 0) + if (caml_page_table_add(In_young, new_heap, new_heap + bsz) != 0) caml_raise_out_of_memory(); if (caml_young_start != NULL){ @@ -92,14 +152,19 @@ void caml_set_minor_heap_size (asize_t size) free (caml_young_base); } caml_young_base = new_heap_base; - caml_young_start = new_heap; - caml_young_end = new_heap + size; - caml_young_limit = caml_young_start; - caml_young_ptr = caml_young_end; - caml_minor_heap_size = size; - - reset_table (&caml_ref_table); - reset_table (&caml_weak_ref_table); + caml_young_start = (value *) new_heap; + caml_young_end = (value *) (new_heap + bsz); + caml_young_alloc_start = caml_young_start; + caml_young_alloc_mid = caml_young_alloc_start + Wsize_bsize (bsz) / 2; + caml_young_alloc_end = caml_young_end; + caml_young_trigger = caml_young_alloc_start; + caml_young_limit = caml_young_trigger; + caml_young_ptr = caml_young_alloc_end; + caml_minor_heap_wsz = Wsize_bsize (bsz); + + reset_table ((struct generic_table *) &caml_ref_table); + reset_table ((struct generic_table *) &caml_ephe_ref_table); + reset_table ((struct generic_table *) &caml_custom_table); } static value oldify_todo_list = 0; @@ -116,7 +181,7 @@ void caml_oldify_one (value v, value *p) tail_call: if (Is_block (v) && Is_young (v)){ - Assert (Hp_val (v) >= caml_young_ptr); + Assert ((value *) Hp_val (v) >= caml_young_ptr); hd = Hd_val (v); if (hd == 0){ /* If already forwarded */ *p = Field (v, 0); /* then forward pointer is first field. */ @@ -190,6 +255,21 @@ void caml_oldify_one (value v, value *p) } } +/* Test if the ephemeron is alive, everything outside minor heap is alive */ +static inline int ephe_check_alive_data(struct caml_ephe_ref_elt *re){ + mlsize_t i; + value child; + for (i = CAML_EPHE_FIRST_KEY; i < Wosize_val(re->ephe); i++){ + child = Field (re->ephe, i); + if(child != caml_ephe_none + && Is_block (child) && Is_young (child) + && Hd_val (child) != 0){ /* Value not copied to major heap */ + return 0; + } + } + return 1; +} + /* Finish the work that was put off by [caml_oldify_one]. Note that [caml_oldify_one] itself is called by oldify_mopup, so we have to be careful to remove the first entry from the list before @@ -198,6 +278,8 @@ void caml_oldify_mopup (void) { value v, new_v, f; mlsize_t i; + struct caml_ephe_ref_elt *re; + int redo = 0; while (oldify_todo_list != 0){ v = oldify_todo_list; /* Get the head. */ @@ -218,6 +300,28 @@ void caml_oldify_mopup (void) } } } + + /* Oldify the data in the minor heap of alive ephemeron + During minor collection keys outside the minor heap are considered alive */ + for (re = caml_ephe_ref_table.base; + re < caml_ephe_ref_table.ptr; re++){ + /* look only at ephemeron with data in the minor heap */ + if (re->offset == 1){ + value *data = &Field(re->ephe,1); + if (*data != caml_ephe_none && Is_block (*data) && Is_young (*data)){ + if (Hd_val (*data) == 0){ /* Value copied to major heap */ + *data = Field (*data, 0); + } else { + if (ephe_check_alive_data(re)){ + caml_oldify_one(*data,data); + redo = 1; /* oldify_todo_list can still be 0 */ + } + } + } + } + } + + if (redo) caml_oldify_mopup (); } /* Make sure the minor heap is empty by performing a minor collection @@ -226,38 +330,68 @@ void caml_oldify_mopup (void) void caml_empty_minor_heap (void) { value **r; + struct caml_custom_elt *elt; uintnat prev_alloc_words; + struct caml_ephe_ref_elt *re; - if (caml_young_ptr != caml_young_end){ + if (caml_young_ptr != caml_young_alloc_end){ if (caml_minor_gc_begin_hook != NULL) (*caml_minor_gc_begin_hook) (); + CAML_INSTR_SETUP (tmr, "minor"); prev_alloc_words = caml_allocated_words; caml_in_minor_collection = 1; caml_gc_message (0x02, "<", 0); caml_oldify_local_roots(); + CAML_INSTR_TIME (tmr, "minor/local_roots"); for (r = caml_ref_table.base; r < caml_ref_table.ptr; r++){ caml_oldify_one (**r, *r); } + CAML_INSTR_TIME (tmr, "minor/ref_table"); caml_oldify_mopup (); - for (r = caml_weak_ref_table.base; r < caml_weak_ref_table.ptr; r++){ - if (Is_block (**r) && Is_young (**r)){ - if (Hd_val (**r) == 0){ - **r = Field (**r, 0); - }else{ - **r = caml_weak_none; + CAML_INSTR_TIME (tmr, "minor/copy"); + /* Update the ephemerons */ + for (re = caml_ephe_ref_table.base; + re < caml_ephe_ref_table.ptr; re++){ + if(re->offset < Wosize_val(re->ephe)){ + /* If it is not the case, the ephemeron has been truncated */ + value *key = &Field(re->ephe,re->offset); + if (*key != caml_ephe_none && Is_block (*key) && Is_young (*key)){ + if (Hd_val (*key) == 0){ /* Value copied to major heap */ + *key = Field (*key, 0); + }else{ /* Value not copied so it's dead */ + Assert(!ephe_check_alive_data(re)); + *key = caml_ephe_none; + Field(re->ephe,1) = caml_ephe_none; + } } } } - if (caml_young_ptr < caml_young_start) caml_young_ptr = caml_young_start; - caml_stat_minor_words += Wsize_bsize (caml_young_end - caml_young_ptr); - caml_young_ptr = caml_young_end; - caml_young_limit = caml_young_start; - clear_table (&caml_ref_table); - clear_table (&caml_weak_ref_table); + /* Run custom block finalisation of dead minor values */ + for (elt = caml_custom_table.base; elt < caml_custom_table.ptr; elt++){ + value v = elt->block; + if (Hd_val (v) == 0){ + /* Block was copied to the major heap: adjust GC speed numbers. */ + caml_adjust_gc_speed(elt->mem, elt->max); + }else{ + /* Block will be freed: call finalization function, if any. */ + void (*final_fun)(value) = Custom_ops_val(v)->finalize; + if (final_fun != NULL) final_fun(v); + } + } + CAML_INSTR_TIME (tmr, "minor/update_weak"); + caml_stat_minor_words += caml_young_alloc_end - caml_young_ptr; + caml_gc_clock += (double) (caml_young_alloc_end - caml_young_ptr) + / caml_minor_heap_wsz; + caml_young_ptr = caml_young_alloc_end; + clear_table ((struct generic_table *) &caml_ref_table); + clear_table ((struct generic_table *) &caml_ephe_ref_table); + clear_table ((struct generic_table *) &caml_custom_table); caml_gc_message (0x02, ">", 0); caml_in_minor_collection = 0; + caml_final_empty_young (); + CAML_INSTR_TIME (tmr, "minor/finalized"); caml_stat_promoted_words += caml_allocated_words - prev_alloc_words; + CAML_INSTR_INT ("minor/promoted#", caml_allocated_words - prev_alloc_words); ++ caml_stat_minor_collections; - caml_final_empty_young (); if (caml_minor_gc_end_hook != NULL) (*caml_minor_gc_end_hook) (); }else{ caml_final_empty_young (); @@ -265,65 +399,147 @@ void caml_empty_minor_heap (void) #ifdef DEBUG { value *p; - for (p = (value *) caml_young_start; p < (value *) caml_young_end; ++p){ + for (p = caml_young_alloc_start; p < caml_young_alloc_end; ++p){ *p = Debug_free_minor; } - ++ minor_gc_counter; } #endif } -/* Do a minor collection and a slice of major collection, call finalisation +#ifdef CAML_INSTR +extern uintnat caml_instr_alloc_jump; +#endif + +/* Do a minor collection or a slice of major collection, call finalisation functions, etc. - Leave the minor heap empty. + Leave enough room in the minor heap to allocate at least one object. */ -CAMLexport void caml_minor_collection (void) +CAMLexport void caml_gc_dispatch (void) { - caml_empty_minor_heap (); - - caml_major_collection_slice (0); - caml_force_major_slice = 0; + value *trigger = caml_young_trigger; /* save old value of trigger */ +#ifdef CAML_INSTR + CAML_INSTR_SETUP(tmr, "dispatch"); + CAML_INSTR_TIME (tmr, "overhead"); + CAML_INSTR_INT ("alloc/jump#", caml_instr_alloc_jump); + caml_instr_alloc_jump = 0; +#endif - caml_final_do_calls (); + if (trigger == caml_young_alloc_start || caml_requested_minor_gc){ + /* The minor heap is full, we must do a minor collection. */ + /* reset the pointers first because the end hooks might allocate */ + caml_requested_minor_gc = 0; + caml_young_trigger = caml_young_alloc_mid; + caml_young_limit = caml_young_trigger; + caml_empty_minor_heap (); + /* The minor heap is empty, we can start a major collection. */ + if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1); + CAML_INSTR_TIME (tmr, "dispatch/minor"); + + caml_final_do_calls (); + CAML_INSTR_TIME (tmr, "dispatch/finalizers"); + + while (caml_young_ptr - caml_young_alloc_start < Max_young_whsize){ + /* The finalizers or the hooks have filled up the minor heap, we must + repeat the minor collection. */ + caml_requested_minor_gc = 0; + caml_young_trigger = caml_young_alloc_mid; + caml_young_limit = caml_young_trigger; + caml_empty_minor_heap (); + /* The minor heap is empty, we can start a major collection. */ + if (caml_gc_phase == Phase_idle) caml_major_collection_slice (-1); + CAML_INSTR_TIME (tmr, "dispatch/finalizers_minor"); + } + } + if (trigger != caml_young_alloc_start || caml_requested_major_slice){ + /* The minor heap is half-full, do a major GC slice. */ + caml_requested_major_slice = 0; + caml_young_trigger = caml_young_alloc_start; + caml_young_limit = caml_young_trigger; + caml_major_collection_slice (-1); + CAML_INSTR_TIME (tmr, "dispatch/major"); + } +} - caml_empty_minor_heap (); +/* For backward compatibility with Lablgtk: do a minor collection to + ensure that the minor heap is empty. +*/ +CAMLexport void caml_minor_collection (void) +{ + caml_requested_minor_gc = 1; + caml_gc_dispatch (); } CAMLexport value caml_check_urgent_gc (value extra_root) { CAMLparam1 (extra_root); - if (caml_force_major_slice) caml_minor_collection(); + if (caml_requested_major_slice || caml_requested_minor_gc){ + CAML_INSTR_INT ("force_minor/check_urgent_gc@", 1); + caml_gc_dispatch(); + } CAMLreturn (extra_root); } -void caml_realloc_ref_table (struct caml_ref_table *tbl) -{ Assert (tbl->ptr == tbl->limit); +static void realloc_generic_table +(struct generic_table *tbl, asize_t element_size, + char * msg_intr_int, char *msg_threshold, char *msg_growing, char *msg_error) +{ + Assert (tbl->ptr == tbl->limit); Assert (tbl->limit <= tbl->end); Assert (tbl->limit >= tbl->threshold); if (tbl->base == NULL){ - caml_alloc_table (tbl, caml_minor_heap_size / sizeof (value) / 8, 256); + alloc_generic_table (tbl, caml_minor_heap_wsz / 8, 256, + element_size); }else if (tbl->limit == tbl->threshold){ - caml_gc_message (0x08, "ref_table threshold crossed\n", 0); + CAML_INSTR_INT (msg_intr_int, 1); + caml_gc_message (0x08, msg_threshold, 0); tbl->limit = tbl->end; - caml_urge_major_slice (); - }else{ /* This will almost never happen with the bytecode interpreter. */ + caml_request_minor_gc (); + }else{ asize_t sz; asize_t cur_ptr = tbl->ptr - tbl->base; - Assert (caml_force_major_slice); + CAMLassert (caml_requested_minor_gc); tbl->size *= 2; - sz = (tbl->size + tbl->reserve) * sizeof (value *); - caml_gc_message (0x08, "Growing ref_table to %" - ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", - (intnat) sz/1024); - tbl->base = (value **) realloc ((char *) tbl->base, sz); + sz = (tbl->size + tbl->reserve) * element_size; + caml_gc_message (0x08, msg_growing, (intnat) sz/1024); + tbl->base = (void *) realloc ((char *) tbl->base, sz); if (tbl->base == NULL){ - caml_fatal_error ("Fatal error: ref_table overflow\n"); + caml_fatal_error (msg_error); } - tbl->end = tbl->base + tbl->size + tbl->reserve; - tbl->threshold = tbl->base + tbl->size; + tbl->end = tbl->base + (tbl->size + tbl->reserve) * element_size; + tbl->threshold = tbl->base + tbl->size * element_size; tbl->ptr = tbl->base + cur_ptr; tbl->limit = tbl->end; } } + +void caml_realloc_ref_table (struct caml_ref_table *tbl) +{ + realloc_generic_table + ((struct generic_table *) tbl, sizeof (value *), + "request_minor/realloc_ref_table@", + "ref_table threshold crossed\n", + "Growing ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", + "Fatal error: ref_table overflow\n"); +} + +void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *tbl) +{ + realloc_generic_table + ((struct generic_table *) tbl, sizeof (struct caml_ephe_ref_elt), + "request_minor/realloc_ephe_ref_table@", + "ephe_ref_table threshold crossed\n", + "Growing ephe_ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", + "Fatal error: ephe_ref_table overflow\n"); +} + +void caml_realloc_custom_table (struct caml_custom_table *tbl) +{ + realloc_generic_table + ((struct generic_table *) tbl, sizeof (struct caml_custom_elt), + "request_minor/realloc_custom_table@", + "custom_table threshold crossed\n", + "Growing custom_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", + "Fatal error: custom_table overflow\n"); +} diff --git a/byterun/misc.c b/byterun/misc.c index a951ee2b..9c6ded0d 100644 --- a/byterun/misc.c +++ b/byterun/misc.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -17,6 +19,7 @@ #include "caml/config.h" #include "caml/misc.h" #include "caml/memory.h" +#include "caml/version.h" caml_timing_hook caml_major_slice_begin_hook = NULL; caml_timing_hook caml_major_slice_end_hook = NULL; @@ -33,14 +36,13 @@ int caml_failed_assert (char * expr, char * file, int line) file, line, expr); fflush (stderr); exit (100); - return 1; /* not reached */ } -void caml_set_fields (char *bp, unsigned long start, unsigned long filler) +void caml_set_fields (value v, unsigned long start, unsigned long filler) { mlsize_t i; - for (i = start; i < Wosize_bp (bp); i++){ - Field (Val_bp (bp), i) = (value) filler; + for (i = start; i < Wosize_val (v); i++){ + Field (v, i) = (value) filler; } } @@ -50,7 +52,7 @@ uintnat caml_verb_gc = 0; void caml_gc_message (int level, char *msg, uintnat arg) { - if (level < 0 || (caml_verb_gc & level) != 0){ + if ((caml_verb_gc & level) != 0){ fprintf (stderr, msg, arg); fflush (stderr); } @@ -76,6 +78,7 @@ CAMLexport void caml_fatal_error_arg2 (char *fmt1, char *arg1, exit(2); } +/* [size] and [modulo] are numbers of bytes */ char *caml_aligned_malloc (asize_t size, int modulo, void **block) { char *raw_mem; @@ -123,6 +126,19 @@ int caml_ext_table_add(struct ext_table * tbl, void * data) return res; } +void caml_ext_table_remove(struct ext_table * tbl, void * data) +{ + int i; + for (i = 0; i < tbl->size; i++) { + if (tbl->contents[i] == data) { + caml_stat_free(tbl->contents[i]); + memmove(&tbl->contents[i], &tbl->contents[i + 1], + (tbl->size - i - 1) * sizeof(void *)); + tbl->size--; + } + } +} + void caml_ext_table_free(struct ext_table * tbl, int free_entries) { int i; @@ -166,3 +182,97 @@ CAMLexport char * caml_strconcat(int n, ...) *p = 0; return res; } + +/* Runtime warnings */ + +uintnat caml_runtime_warnings = 0; +static int caml_runtime_warnings_first = 1; + +int caml_runtime_warnings_active(void) +{ + if (!caml_runtime_warnings) return 0; + if (caml_runtime_warnings_first) { + fprintf(stderr, "[ocaml] (use Sys.enable_runtime_warnings to control " + "these warnings)\n"); + caml_runtime_warnings_first = 0; + } + return 1; +} + +#ifdef CAML_INSTR +/* Timers for profiling GC and allocation (experimental, Linux-only) */ + +#include +#include +#include + +struct CAML_INSTR_BLOCK *CAML_INSTR_LOG = NULL; +intnat CAML_INSTR_STARTTIME, CAML_INSTR_STOPTIME; + +#define Get_time(p,i) ((p)->ts[(i)].tv_nsec + 1000000000 * (p)->ts[(i)].tv_sec) + +void CAML_INSTR_INIT (void) +{ + char *s; + + CAML_INSTR_STARTTIME = 0; + s = getenv ("OCAML_INSTR_START"); + if (s != NULL) CAML_INSTR_STARTTIME = atol (s); + CAML_INSTR_STOPTIME = LONG_MAX; + s = getenv ("OCAML_INSTR_STOP"); + if (s != NULL) CAML_INSTR_STOPTIME = atol (s); +} + +void CAML_INSTR_ATEXIT (void) +{ + int i; + struct CAML_INSTR_BLOCK *p, *prev, *next; + FILE *f = NULL; + char *fname; + + fname = getenv ("OCAML_INSTR_FILE"); + if (fname != NULL){ + char *mode = "a"; + char buf [1000]; + char *name = fname; + + if (name[0] == '@'){ + snprintf (buf, sizeof(buf), "%s.%d", name + 1, getpid ()); + name = buf; + } + if (name[0] == '+'){ + mode = "a"; + name = name + 1; + }else if (name [0] == '>' || name[0] == '-'){ + mode = "w"; + name = name + 1; + } + f = fopen (name, mode); + } + + if (f != NULL){ + /* reverse the list */ + prev = NULL; + p = CAML_INSTR_LOG; + while (p != NULL){ + next = p->next; + p->next = prev; + prev = p; + p = next; + } + CAML_INSTR_LOG = prev; + fprintf (f, "==== OCAML INSTRUMENTATION DATA %s\n", OCAML_VERSION_STRING); + for (p = CAML_INSTR_LOG; p != NULL; p = p->next){ + for (i = 0; i < p->index; i++){ + fprintf (f, "@@ %19ld %19ld %s\n", + Get_time (p, i), Get_time(p, i+1), p->tag[i+1]); + } + if (p->tag[0][0] != '\000'){ + fprintf (f, "@@ %19ld %19ld %s\n", + Get_time (p, 0), Get_time(p, p->index), p->tag[0]); + } + } + fclose (f); + } +} +#endif /* CAML_INSTR */ diff --git a/byterun/obj.c b/byterun/obj.c index ce7ffcd0..5f1efdd4 100644 --- a/byterun/obj.c +++ b/byterun/obj.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Operations on objects */ @@ -25,6 +27,7 @@ #include "caml/mlvalues.h" #include "caml/prims.h" +/* [size] is a value encoding a number of bytes */ CAMLprim value caml_static_alloc(value size) { return (value) caml_stat_alloc((asize_t) Long_val(size)); @@ -36,21 +39,6 @@ CAMLprim value caml_static_free(value blk) return Val_unit; } -/* signal to the interpreter machinery that a bytecode is no more - needed (before freeing it) - this might be useful for a JIT - implementation */ - -CAMLprim value caml_static_release_bytecode(value blk, value size) -{ -#ifndef NATIVE_CODE - caml_release_bytecode((code_t) blk, (asize_t) Long_val(size)); -#else - caml_failwith("Meta.static_release_bytecode impossible with native code"); -#endif - return Val_unit; -} - - CAMLprim value caml_static_resize(value blk, value new_size) { return (value) caml_stat_resize((char *) blk, (asize_t) Long_val(new_size)); @@ -80,6 +68,7 @@ CAMLprim value caml_obj_set_tag (value arg, value new_tag) return Val_unit; } +/* [size] is a value encoding a number of blocks */ CAMLprim value caml_obj_block(value tag, value size) { value res; @@ -124,9 +113,15 @@ CAMLprim value caml_obj_dup(value arg) to 0 or greater than the current size. algorithm: - Change the length field of the header. Make up a white object + Change the length field of the header. Make up a black object with the leftover part of the object: this is needed in the major - heap and harmless in the minor heap. + heap and harmless in the minor heap. The object cannot be white + because there may still be references to it in the ref table. By + using a black object we ensure that the ref table will be emptied + before the block is reallocated (since there must be a minor + collection within each major cycle). + + [newsize] is a value encoding a number of words. */ CAMLprim value caml_obj_truncate (value v, value newsize) { @@ -158,7 +153,7 @@ CAMLprim value caml_obj_truncate (value v, value newsize) look like a pointer because there may be some references to it in ref_table. */ Field (v, new_wosize) = - Make_header (Wosize_whsize (wosize-new_wosize), 1, Caml_white); + Make_header (Wosize_whsize (wosize-new_wosize), Abstract_tag, Caml_black); Hd_val (v) = Make_header (new_wosize, tag, color); return Val_unit; } @@ -256,6 +251,12 @@ CAMLprim value caml_set_oo_id (value obj) { return obj; } +CAMLprim value caml_fresh_oo_id (value v) { + v = oo_last_id; + oo_last_id += 2; + return v; +} + CAMLprim value caml_int_as_pointer (value n) { return n - 1; } diff --git a/byterun/parsing.c b/byterun/parsing.c index bd51a41e..89ca4c5e 100644 --- a/byterun/parsing.c +++ b/byterun/parsing.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The PDA automaton for parsers generated by camlyacc */ diff --git a/byterun/printexc.c b/byterun/printexc.c index 7647b3a1..ee7a591d 100644 --- a/byterun/printexc.c +++ b/byterun/printexc.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Print an uncaught exception and abort */ diff --git a/byterun/roots.c b/byterun/roots.c index f812cd75..a1cba5e3 100644 --- a/byterun/roots.c +++ b/byterun/roots.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* To walk the memory roots for garbage collection */ @@ -27,7 +29,7 @@ CAMLexport struct caml__roots_block *caml_local_roots = NULL; CAMLexport void (*caml_scan_roots_hook) (scanning_action f) = NULL; -/* FIXME should rename to [caml_oldify_young_roots] and synchronise with +/* FIXME should rename to [caml_oldify_minor_roots] and synchronise with asmrun/roots.c */ /* Call [caml_oldify_one] on (at least) all the roots that point to the minor heap. */ @@ -60,23 +62,38 @@ void caml_oldify_local_roots (void) /* Call [caml_darken] on all roots */ -void caml_darken_all_roots (void) +void caml_darken_all_roots_start (void) { - caml_do_roots (caml_darken); + caml_do_roots (caml_darken, 1); } -void caml_do_roots (scanning_action f) +uintnat caml_incremental_roots_count = 1; + +intnat caml_darken_all_roots_slice (intnat work) +{ + return work; +} + +/* Note, in byte-code there is only one global root, so [do_globals] is + ignored and [caml_darken_all_roots_slice] does nothing. */ +void caml_do_roots (scanning_action f, int do_globals) { + CAML_INSTR_SETUP (tmr, "major_roots"); /* Global variables */ f(caml_global_data, &caml_global_data); + CAML_INSTR_TIME (tmr, "major_roots/global"); /* The stack and the local C roots */ caml_do_local_roots(f, caml_extern_sp, caml_stack_high, caml_local_roots); + CAML_INSTR_TIME (tmr, "major_roots/local"); /* Global C roots */ caml_scan_global_roots(f); + CAML_INSTR_TIME (tmr, "major_roots/C"); /* Finalised values */ caml_final_do_strong_roots (f); + CAML_INSTR_TIME (tmr, "major_roots/finalised"); /* Hook */ if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f); + CAML_INSTR_TIME (tmr, "major_roots/hook"); } CAMLexport void caml_do_local_roots (scanning_action f, value *stack_low, diff --git a/byterun/signals.c b/byterun/signals.c index 3d642f19..5c4e2614 100644 --- a/byterun/signals.c +++ b/byterun/signals.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Signal handling, code common to the bytecode and native systems */ @@ -67,7 +69,7 @@ void caml_record_signal(int signal_number) #ifndef NATIVE_CODE caml_something_to_do = 1; #else - caml_young_limit = caml_young_end; + caml_young_limit = caml_young_alloc_end; #endif } @@ -157,15 +159,16 @@ void caml_execute_signal(int signal_number, int in_signal_handler) /* Arrange for a garbage collection to be performed as soon as possible */ -int volatile caml_force_major_slice = 0; +int volatile caml_requested_major_slice = 0; +int volatile caml_requested_minor_gc = 0; -void caml_urge_major_slice (void) +void caml_request_major_slice (void) { - caml_force_major_slice = 1; + caml_requested_major_slice = 1; #ifndef NATIVE_CODE caml_something_to_do = 1; #else - caml_young_limit = caml_young_end; + caml_young_limit = caml_young_alloc_end; /* This is only moderately effective on ports that cache [caml_young_limit] in a register, since [caml_modify] is called directly, not through [caml_c_call], so it may take a while before the register is reloaded @@ -173,6 +176,17 @@ void caml_urge_major_slice (void) #endif } +void caml_request_minor_gc (void) +{ + caml_requested_minor_gc = 1; +#ifndef NATIVE_CODE + caml_something_to_do = 1; +#else + caml_young_limit = caml_young_alloc_end; + /* Same remark as above in [caml_request_major_slice]. */ +#endif +} + /* OS-independent numbering of signals */ #ifndef SIGABRT @@ -238,11 +252,33 @@ void caml_urge_major_slice (void) #ifndef SIGPROF #define SIGPROF -1 #endif +#ifndef SIGBUS +#define SIGBUS -1 +#endif +#ifndef SIGPOLL +#define SIGPOLL -1 +#endif +#ifndef SIGSYS +#define SIGSYS -1 +#endif +#ifndef SIGTRAP +#define SIGTRAP -1 +#endif +#ifndef SIGURG +#define SIGURG -1 +#endif +#ifndef SIGXCPU +#define SIGXCPU -1 +#endif +#ifndef SIGXFSZ +#define SIGXFSZ -1 +#endif static int posix_signals[] = { SIGABRT, SIGALRM, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGKILL, SIGPIPE, SIGQUIT, SIGSEGV, SIGTERM, SIGUSR1, SIGUSR2, SIGCHLD, SIGCONT, - SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGVTALRM, SIGPROF + SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGVTALRM, SIGPROF, SIGBUS, + SIGPOLL, SIGSYS, SIGTRAP, SIGURG, SIGXCPU, SIGXFSZ }; CAMLexport int caml_convert_signal_number(int signo) diff --git a/byterun/signals_byt.c b/byterun/signals_byt.c index e9c6c662..38aebfd0 100644 --- a/byterun/signals_byt.c +++ b/byterun/signals_byt.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 2007 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 2007 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. */ +/* */ +/**************************************************************************/ /* Signal handling, code specific to the bytecode interpreter */ @@ -38,8 +40,7 @@ void caml_process_event(void) { void (*async_action)(void); - if (caml_force_major_slice) caml_minor_collection (); - /* FIXME should be [caml_check_urgent_gc] */ + caml_check_urgent_gc (Val_unit); caml_process_pending_signals(); async_action = caml_async_action_hook; if (async_action != NULL) { diff --git a/byterun/stacks.c b/byterun/stacks.c index 94bff0b9..cb96d2d7 100644 --- a/byterun/stacks.c +++ b/byterun/stacks.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* To initialize and resize the stacks */ diff --git a/byterun/startup.c b/byterun/startup.c index fb6e7778..0d2c1945 100644 --- a/byterun/startup.c +++ b/byterun/startup.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Start-up code */ @@ -51,6 +53,7 @@ #include "caml/stacks.h" #include "caml/sys.h" #include "caml/startup.h" +#include "caml/startup_aux.h" #include "caml/version.h" #ifndef O_BINARY @@ -61,25 +64,9 @@ #define SEEK_END 2 #endif -extern int caml_parser_trace; - -CAMLexport header_t caml_atom_table[256]; - -/* Initialize the atom table */ - -static void init_atoms(void) -{ - int i; - for(i = 0; i < 256; i++) caml_atom_table[i] = Make_header(0, i, Caml_white); - if (caml_page_table_add(In_static_data, - caml_atom_table, caml_atom_table + 256) != 0) { - caml_fatal_error("Fatal error: not enough memory for initial page table"); - } -} - /* Read the trailer of a bytecode file */ -static void fixup_endianness_trailer(uint32 * p) +static void fixup_endianness_trailer(uint32_t * p) { #ifndef ARCH_BIG_ENDIAN Reverse_32(p, p); @@ -153,7 +140,8 @@ void caml_read_section_descriptors(int fd, struct exec_trailer *trail) Return the length of the section data in bytes, or -1 if no section found with that name. */ -int32 caml_seek_optional_section(int fd, struct exec_trailer *trail, char *name) +int32_t caml_seek_optional_section(int fd, struct exec_trailer *trail, + char *name) { long ofs; int i; @@ -172,9 +160,9 @@ int32 caml_seek_optional_section(int fd, struct exec_trailer *trail, char *name) /* Position fd at the beginning of the section having the given name. Return the length of the section data in bytes. */ -int32 caml_seek_section(int fd, struct exec_trailer *trail, char *name) +int32_t caml_seek_section(int fd, struct exec_trailer *trail, char *name) { - int32 len = caml_seek_optional_section(fd, trail, name); + int32_t len = caml_seek_optional_section(fd, trail, name); if (len == -1) caml_fatal_error_arg("Fatal_error: section `%s' is missing\n", name); return len; @@ -185,7 +173,7 @@ int32 caml_seek_section(int fd, struct exec_trailer *trail, char *name) static char * read_section(int fd, struct exec_trailer *trail, char *name) { - int32 len; + int32_t len; char * data; len = caml_seek_optional_section(fd, trail, name); @@ -222,15 +210,6 @@ Algorithm: */ -/* Configuration parameters and flags */ - -static uintnat percent_free_init = Percent_free_def; -static uintnat max_percent_free_init = Max_percent_free_def; -static uintnat minor_heap_init = Minor_heap_def; -static uintnat heap_chunk_init = Heap_chunk_def; -static uintnat heap_size_init = Init_heap_def; -static uintnat max_stack_init = Max_stack_def; - /* Parse options on the command line */ static int parse_command_line(char **argv) @@ -239,11 +218,9 @@ static int parse_command_line(char **argv) for(i = 1; argv[i] != NULL && argv[i][0] == '-'; i++) { switch(argv[i][1]) { -#ifdef DEBUG case 't': - caml_trace_flag++; + ++ caml_trace_level; /* ignored unless DEBUG mode */ break; -#endif case 'v': if (!strcmp (argv[i], "-version")){ printf ("The OCaml runtime, version " OCAML_VERSION_STRING "\n"); @@ -276,57 +253,6 @@ static int parse_command_line(char **argv) return i; } -/* Parse the OCAMLRUNPARAM variable */ -/* The option letter for each runtime option is the first letter of the - last word of the ML name of the option (see [stdlib/gc.mli]). - Except for l (maximum stack size) and h (initial heap size). -*/ - -/* If you change these functions, see also their copy in asmrun/startup.c */ - -static void scanmult (char *opt, uintnat *var) -{ - char mult = ' '; - unsigned int val; - sscanf (opt, "=%u%c", &val, &mult); - sscanf (opt, "=0x%x%c", &val, &mult); - switch (mult) { - case 'k': *var = (uintnat) val * 1024; break; - case 'M': *var = (uintnat) val * 1024 * 1024; break; - case 'G': *var = (uintnat) val * 1024 * 1024 * 1024; break; - default: *var = (uintnat) val; break; - } -} - -static void parse_camlrunparam(void) -{ - char *opt = getenv ("OCAMLRUNPARAM"); - uintnat p; - - if (opt == NULL) opt = getenv ("CAMLRUNPARAM"); - - if (opt != NULL){ - while (*opt != '\0'){ - switch (*opt++){ - case 'a': scanmult (opt, &p); caml_set_allocation_policy (p); break; - case 'b': caml_record_backtrace(Val_true); break; - case 'h': scanmult (opt, &heap_size_init); break; - case 'i': scanmult (opt, &heap_chunk_init); break; - case 'l': scanmult (opt, &max_stack_init); break; - case 'o': scanmult (opt, &percent_free_init); break; - case 'O': scanmult (opt, &max_percent_free_init); break; - case 'p': caml_parser_trace = 1; break; - /* case 'R': see stdlib/hashtbl.mli */ - case 's': scanmult (opt, &minor_heap_init); break; -#ifdef DEBUG - case 't': caml_trace_flag = 1; break; -#endif - case 'v': scanmult (opt, &caml_verb_gc); break; - } - } - } -} - extern void caml_init_ieee_floats (void); #ifdef _WIN32 @@ -363,9 +289,13 @@ CAMLexport void caml_main(char **argv) caml_external_raise = NULL; /* Determine options and position of bytecode file */ #ifdef DEBUG - caml_verb_gc = 0xBF; + caml_verb_gc = 0x3F; #endif - parse_camlrunparam(); + caml_parse_ocamlrunparam(); +#ifdef DEBUG + caml_gc_message (-1, "### OCaml runtime: debug mode ###\n", 0); +#endif + pos = 0; /* First, try argv[0] (when ocamlrun is called by a bytecode program) */ @@ -400,10 +330,12 @@ CAMLexport void caml_main(char **argv) /* Read the table of contents (section descriptors) */ caml_read_section_descriptors(fd, &trail); /* Initialize the abstract machine */ - caml_init_gc (minor_heap_init, heap_size_init, heap_chunk_init, - percent_free_init, max_percent_free_init); - caml_init_stack (max_stack_init); - init_atoms(); + caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, + caml_init_heap_chunk_sz, caml_init_percent_free, + caml_init_max_percent_free, caml_init_major_window); + caml_init_stack (caml_init_max_stack_wsz); + caml_init_atom_table(); + caml_init_backtrace(); /* Initialize the interpreter */ caml_interprete(NULL, 0); /* Initialize the debugger, if needed */ @@ -411,6 +343,7 @@ CAMLexport void caml_main(char **argv) /* Load the code */ caml_code_size = caml_seek_section(fd, &trail, "CODE"); caml_load_code(fd, caml_code_size); + caml_init_debug_info(); /* Build the table of primitives */ shared_lib_path = read_section(fd, &trail, "DLPT"); shared_libs = read_section(fd, &trail, "DLLS"); @@ -475,16 +408,18 @@ CAMLexport void caml_startup_code( if (cds_file != NULL) { caml_cds_file = caml_strdup(cds_file); } - parse_camlrunparam(); + caml_parse_ocamlrunparam(); exe_name = argv[0]; if (caml_executable_name(proc_self_exe, sizeof(proc_self_exe)) == 0) exe_name = proc_self_exe; caml_external_raise = NULL; /* Initialize the abstract machine */ - caml_init_gc (minor_heap_init, heap_size_init, heap_chunk_init, - percent_free_init, max_percent_free_init); - caml_init_stack (max_stack_init); - init_atoms(); + caml_init_gc (caml_init_minor_heap_wsz, caml_init_heap_wsz, + caml_init_heap_chunk_sz, caml_init_percent_free, + caml_init_max_percent_free, caml_init_major_window); + caml_init_stack (caml_init_max_stack_wsz); + caml_init_atom_table(); + caml_init_backtrace(); /* Initialize the interpreter */ caml_interprete(NULL, 0); /* Initialize the debugger, if needed */ @@ -493,6 +428,7 @@ CAMLexport void caml_startup_code( caml_start_code = code; caml_code_size = code_size; caml_init_code_fragments(); + caml_init_debug_info(); if (caml_debugger_in_use) { int len, i; len = code_size / sizeof(opcode_t); diff --git a/byterun/startup_aux.c b/byterun/startup_aux.c new file mode 100644 index 00000000..714e486a --- /dev/null +++ b/byterun/startup_aux.c @@ -0,0 +1,97 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ + +/* Some runtime initialization functions that are common to bytecode + and native code. */ + +#include +#include "caml/backtrace.h" +#include "caml/memory.h" +#include "caml/startup_aux.h" + + +/* Initialize the atom table */ + +CAMLexport header_t caml_atom_table[256]; +void caml_init_atom_table(void) +{ + int i; + for(i = 0; i < 256; i++) caml_atom_table[i] = Make_header(0, i, Caml_white); + if (caml_page_table_add(In_static_data, + caml_atom_table, caml_atom_table + 256) != 0) { + caml_fatal_error("Fatal error: not enough memory for initial page table"); + } +} + + +/* Parse the OCAMLRUNPARAM environment variable. */ + +uintnat caml_init_percent_free = Percent_free_def; +uintnat caml_init_max_percent_free = Max_percent_free_def; +uintnat caml_init_minor_heap_wsz = Minor_heap_def; +uintnat caml_init_heap_chunk_sz = Heap_chunk_def; +uintnat caml_init_heap_wsz = Init_heap_def; +uintnat caml_init_max_stack_wsz = Max_stack_def; +uintnat caml_init_major_window = Major_window_def; +extern int caml_parser_trace; +uintnat caml_trace_level = 0; + + +static void scanmult (char *opt, uintnat *var) +{ + char mult = ' '; + unsigned int val = 1; + sscanf (opt, "=%u%c", &val, &mult); + sscanf (opt, "=0x%x%c", &val, &mult); + switch (mult) { + case 'k': *var = (uintnat) val * 1024; break; + case 'M': *var = (uintnat) val * (1024 * 1024); break; + case 'G': *var = (uintnat) val * (1024 * 1024 * 1024); break; + default: *var = (uintnat) val; break; + } +} + +void caml_parse_ocamlrunparam(void) +{ + char *opt = getenv ("OCAMLRUNPARAM"); + uintnat p; + + if (opt == NULL) opt = getenv ("CAMLRUNPARAM"); + + if (opt != NULL){ + while (*opt != '\0'){ + switch (*opt++){ + case 'a': scanmult (opt, &p); caml_set_allocation_policy (p); break; + case 'b': scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); break; + case 'h': scanmult (opt, &caml_init_heap_wsz); break; + case 'H': scanmult (opt, &caml_use_huge_pages); break; + case 'i': scanmult (opt, &caml_init_heap_chunk_sz); break; + case 'l': scanmult (opt, &caml_init_max_stack_wsz); break; + case 'o': scanmult (opt, &caml_init_percent_free); break; + case 'O': scanmult (opt, &caml_init_max_percent_free); break; + case 'p': scanmult (opt, &p); caml_parser_trace = p; break; + case 'R': break; /* see stdlib/hashtbl.mli */ + case 's': scanmult (opt, &caml_init_minor_heap_wsz); break; + case 't': scanmult (opt, &caml_trace_level); break; + case 'v': scanmult (opt, &caml_verb_gc); break; + case 'w': scanmult (opt, &caml_init_major_window); break; + case 'W': scanmult (opt, &caml_runtime_warnings); break; + } + while (*opt != '\0'){ + if (*opt++ == ',') break; + } + } + } +} diff --git a/byterun/str.c b/byterun/str.c index a72b34c4..d8d9a74e 100644 --- a/byterun/str.c +++ b/byterun/str.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Operations on strings */ @@ -21,10 +23,8 @@ #include "caml/fail.h" #include "caml/mlvalues.h" #include "caml/misc.h" -#ifdef HAS_LOCALE -#include -#endif +/* returns a number of bytes (chars) */ CAMLexport mlsize_t caml_string_length(value s) { mlsize_t temp; @@ -33,6 +33,7 @@ CAMLexport mlsize_t caml_string_length(value s) return temp - Byte (s, temp); } +/* returns a value that represents a number of bytes (chars) */ CAMLprim value caml_ml_string_length(value s) { mlsize_t temp; @@ -41,6 +42,12 @@ CAMLprim value caml_ml_string_length(value s) return Val_long(temp - Byte (s, temp)); } +CAMLexport int caml_string_is_c_safe (value s) +{ + return strlen(String_val(s)) == caml_string_length(s); +} + +/* [len] is a value that represents a number of bytes (chars) */ CAMLprim value caml_create_string(value len) { mlsize_t size = Long_val(len); @@ -101,7 +108,7 @@ CAMLprim value caml_string_get32(value str, value index) CAMLprim value caml_string_get64(value str, value index) { - uint64 res; + uint64_t res; unsigned char b1, b2, b3, b4, b5, b6, b7, b8; intnat idx = Long_val(index); if (idx < 0 || idx + 7 >= caml_string_length(str)) caml_array_bound_error(); @@ -114,15 +121,15 @@ CAMLprim value caml_string_get64(value str, value index) b7 = Byte_u(str, idx + 6); b8 = Byte_u(str, idx + 7); #ifdef ARCH_BIG_ENDIAN - res = (uint64) b1 << 56 | (uint64) b2 << 48 - | (uint64) b3 << 40 | (uint64) b4 << 32 - | (uint64) b5 << 24 | (uint64) b6 << 16 - | (uint64) b7 << 8 | (uint64) b8; + res = (uint64_t) b1 << 56 | (uint64_t) b2 << 48 + | (uint64_t) b3 << 40 | (uint64_t) b4 << 32 + | (uint64_t) b5 << 24 | (uint64_t) b6 << 16 + | (uint64_t) b7 << 8 | (uint64_t) b8; #else - res = (uint64) b8 << 56 | (uint64) b7 << 48 - | (uint64) b6 << 40 | (uint64) b5 << 32 - | (uint64) b4 << 24 | (uint64) b3 << 16 - | (uint64) b2 << 8 | (uint64) b1; + res = (uint64_t) b8 << 56 | (uint64_t) b7 << 48 + | (uint64_t) b6 << 40 | (uint64_t) b5 << 32 + | (uint64_t) b4 << 24 | (uint64_t) b3 << 16 + | (uint64_t) b2 << 8 | (uint64_t) b1; #endif return caml_copy_int64(res); } @@ -174,7 +181,7 @@ CAMLprim value caml_string_set32(value str, value index, value newval) CAMLprim value caml_string_set64(value str, value index, value newval) { unsigned char b1, b2, b3, b4, b5, b6, b7, b8; - int64 val; + int64_t val; intnat idx = Long_val(index); if (idx < 0 || idx + 7 >= caml_string_length(str)) caml_array_bound_error(); val = Int64_val(newval); @@ -266,7 +273,7 @@ CAMLprim value caml_string_greaterequal(value s1, value s2) CAMLprim value caml_blit_string(value s1, value ofs1, value s2, value ofs2, value n) { - memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Int_val(n)); + memmove(&Byte(s2, Long_val(ofs2)), &Byte(s1, Long_val(ofs1)), Long_val(n)); return Val_unit; } @@ -276,24 +283,9 @@ CAMLprim value caml_fill_string(value s, value offset, value len, value init) return Val_unit; } -CAMLprim value caml_is_printable(value chr) -{ - int c; - -#ifdef HAS_LOCALE - static int locale_is_set = 0; - if (! locale_is_set) { - setlocale(LC_CTYPE, ""); - locale_is_set = 1; - } -#endif - c = Int_val(chr); - return Val_bool(isprint(c)); -} - CAMLprim value caml_bitvect_test(value bv, value n) { - int pos = Int_val(n); + intnat pos = Long_val(n); return Val_int(Byte_u(bv, pos >> 3) & (1 << (pos & 7))); } @@ -304,7 +296,7 @@ CAMLexport value caml_alloc_sprintf(const char * format, ...) int n; value res; -#ifndef _WIN32 +#if !defined(_WIN32) || defined(_UCRT) /* C99-compliant implementation */ va_start(args, format); /* "vsnprintf(dest, sz, format, args)" writes at most "sz" characters diff --git a/byterun/sys.c b/byterun/sys.c index 292f664b..0fbc382e 100644 --- a/byterun/sys.c +++ b/byterun/sys.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Basic system calls */ @@ -22,7 +24,9 @@ #include #include #include -#if !_WIN32 +#if _WIN32 +#include /* for isatty */ +#else #include #endif #include "caml/config.h" @@ -42,7 +46,10 @@ #include "caml/alloc.h" #include "caml/debugger.h" #include "caml/fail.h" +#include "caml/gc_ctrl.h" #include "caml/instruct.h" +#include "caml/io.h" +#include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/osdeps.h" #include "caml/signals.h" @@ -91,11 +98,47 @@ CAMLexport void caml_sys_io_error(value arg) } } +/* Check that [name] can safely be used as a file path */ + +static void caml_sys_check_path(value name) +{ + if (! caml_string_is_c_safe(name)) { + errno = ENOENT; + caml_sys_error(name); + } +} + CAMLprim value caml_sys_exit(value retcode) { + if ((caml_verb_gc & 0x400) != 0) { + /* cf caml_gc_counters */ + double minwords = caml_stat_minor_words + + (double) (caml_young_end - caml_young_ptr); + double prowords = caml_stat_promoted_words; + double majwords = caml_stat_major_words + (double) caml_allocated_words; + double allocated_words = minwords + majwords - prowords; + intnat mincoll = caml_stat_minor_collections; + intnat majcoll = caml_stat_major_collections; + intnat heap_words = caml_stat_heap_wsz; + intnat heap_chunks = caml_stat_heap_chunks; + intnat top_heap_words = caml_stat_top_heap_wsz; + intnat cpct = caml_stat_compactions; + caml_gc_message(0x400, "allocated_words: %ld\n", (long)allocated_words); + caml_gc_message(0x400, "minor_words: %ld\n", (long) minwords); + caml_gc_message(0x400, "promoted_words: %ld\n", (long) prowords); + caml_gc_message(0x400, "major_words: %ld\n", (long) majwords); + caml_gc_message(0x400, "minor_collections: %d\n", mincoll); + caml_gc_message(0x400, "major_collections: %d\n", majcoll); + caml_gc_message(0x400, "heap_words: %d\n", heap_words); + caml_gc_message(0x400, "heap_chunks: %d\n", heap_chunks); + caml_gc_message(0x400, "top_heap_words: %d\n", top_heap_words); + caml_gc_message(0x400, "compactions: %d\n", cpct); + } + #ifndef NATIVE_CODE caml_debugger(PROGRAM_EXIT); #endif + CAML_INSTR_ATEXIT (); exit(Int_val(retcode)); return Val_unit; } @@ -125,6 +168,7 @@ CAMLprim value caml_sys_open(value path, value vflags, value vperm) int fd, flags, perm; char * p; + caml_sys_check_path(path); p = caml_strdup(String_val(path)); flags = caml_convert_flag_list(vflags, sys_open_flags); perm = Int_val(vperm); @@ -160,6 +204,7 @@ CAMLprim value caml_sys_file_exists(value name) char * p; int ret; + if (! caml_string_is_c_safe(name)) return Val_false; p = caml_strdup(String_val(name)); caml_enter_blocking_section(); #ifdef _WIN32 @@ -184,6 +229,7 @@ CAMLprim value caml_sys_is_directory(value name) char * p; int ret; + caml_sys_check_path(name); p = caml_strdup(String_val(name)); caml_enter_blocking_section(); #ifdef _WIN32 @@ -207,6 +253,7 @@ CAMLprim value caml_sys_remove(value name) CAMLparam1(name); char * p; int ret; + caml_sys_check_path(name); p = caml_strdup(String_val(name)); caml_enter_blocking_section(); ret = unlink(p); @@ -221,6 +268,8 @@ CAMLprim value caml_sys_rename(value oldname, value newname) char * p_old; char * p_new; int ret; + caml_sys_check_path(oldname); + caml_sys_check_path(newname); p_old = caml_strdup(String_val(oldname)); p_new = caml_strdup(String_val(newname)); caml_enter_blocking_section(); @@ -238,6 +287,7 @@ CAMLprim value caml_sys_chdir(value dirname) CAMLparam1(dirname); char * p; int ret; + caml_sys_check_path(dirname); p = caml_strdup(String_val(dirname)); caml_enter_blocking_section(); ret = chdir(p); @@ -262,6 +312,7 @@ CAMLprim value caml_sys_getenv(value var) { char * res; + if (! caml_string_is_c_safe(var)) caml_raise_not_found(); res = getenv(String_val(var)); if (res == 0) caml_raise_not_found(); return caml_copy_string(res); @@ -305,6 +356,10 @@ CAMLprim value caml_sys_system_command(value command) int status, retcode; char *buf; + if (! caml_string_is_c_safe (command)) { + errno = EINVAL; + caml_sys_error(command); + } buf = caml_strdup(String_val(command)); caml_enter_blocking_section (); status = system(buf); @@ -318,14 +373,14 @@ CAMLprim value caml_sys_system_command(value command) CAMLreturn (Val_int(retcode)); } -CAMLprim value caml_sys_time(value unit) +double caml_sys_time_unboxed(value unit) { #ifdef HAS_GETRUSAGE struct rusage ru; getrusage (RUSAGE_SELF, &ru); - return caml_copy_double (ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 - + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6); + return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1e6 + + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1e6; #else #ifdef HAS_TIMES #ifndef CLK_TCK @@ -337,14 +392,19 @@ CAMLprim value caml_sys_time(value unit) #endif struct tms t; times(&t); - return caml_copy_double((double)(t.tms_utime + t.tms_stime) / CLK_TCK); + return (double)(t.tms_utime + t.tms_stime) / CLK_TCK; #else /* clock() is standard ANSI C */ - return caml_copy_double((double)clock() / CLOCKS_PER_SEC); + return (double)clock() / CLOCKS_PER_SEC; #endif #endif } +CAMLprim value caml_sys_time(value unit) +{ + return caml_copy_double(caml_sys_time_unboxed(unit)); +} + #ifdef _WIN32 extern int caml_win32_random_seed (intnat data[16]); #endif @@ -400,24 +460,37 @@ CAMLprim value caml_sys_const_big_endian(value unit) #endif } +/* returns a value that represents a number of bits */ CAMLprim value caml_sys_const_word_size(value unit) { return Val_long(8 * sizeof(value)); } +/* returns a value that represents a number of bits */ +CAMLprim value caml_sys_const_int_size(value unit) +{ + return Val_long(8 * sizeof(value) - 1) ; +} + +/* returns a value that represents a number of words */ +CAMLprim value caml_sys_const_max_wosize(value unit) +{ + return Val_long(Max_wosize) ; +} + CAMLprim value caml_sys_const_ostype_unix(value unit) { - return Val_long(0 == strcmp(OCAML_OS_TYPE,"Unix")); + return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Unix")); } CAMLprim value caml_sys_const_ostype_win32(value unit) { - return Val_long(0 == strcmp(OCAML_OS_TYPE,"Win32")); + return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Win32")); } CAMLprim value caml_sys_const_ostype_cygwin(value unit) { - return Val_long(0 == strcmp(OCAML_OS_TYPE,"Cygwin")); + return Val_bool(0 == strcmp(OCAML_OS_TYPE,"Cygwin")); } CAMLprim value caml_sys_get_config(value unit) @@ -445,6 +518,7 @@ CAMLprim value caml_sys_read_directory(value path) char * p; int ret; + caml_sys_check_path(path); caml_ext_table_init(&tbl, 50); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); @@ -460,3 +534,21 @@ CAMLprim value caml_sys_read_directory(value path) caml_ext_table_free(&tbl, 1); CAMLreturn(result); } + +/* Return true if the value is a filedescriptor (int) that is + * (presumably) open on an interactive terminal */ +CAMLprim value caml_sys_isatty(value chan) +{ + int fd; + value ret; + + fd = (Channel(chan))->fd; +#ifdef _WIN32 + ret = Val_bool(_isatty(fd)); + /* https://msdn.microsoft.com/en-us/library/f4s0ddew.aspx */ +#else + ret = Val_bool(isatty(fd)); +#endif + + return ret; +} diff --git a/byterun/terminfo.c b/byterun/terminfo.c index 1d0fdc42..41257328 100644 --- a/byterun/terminfo.c +++ b/byterun/terminfo.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Read and output terminal commands */ diff --git a/byterun/unix.c b/byterun/unix.c index 38ddee00..d3627733 100644 --- a/byterun/unix.c +++ b/byterun/unix.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ /* Unix-specific stuff */ @@ -21,6 +23,7 @@ #include #include #include +#include #include #include "caml/config.h" #ifdef SUPPORT_DYNAMIC_LINKING @@ -38,14 +41,62 @@ #else #include #endif +#include "caml/fail.h" #include "caml/memory.h" #include "caml/misc.h" #include "caml/osdeps.h" +#include "caml/signals.h" +#include "caml/sys.h" #ifndef S_ISREG #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif +#ifndef EINTR +#define EINTR (-1) +#endif +#ifndef EAGAIN +#define EAGAIN (-1) +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK (-1) +#endif + +int caml_read_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + do { + caml_enter_blocking_section(); + retcode = read(fd, buf, n); + caml_leave_blocking_section(); + } while (retcode == -1 && errno == EINTR); + if (retcode == -1) caml_sys_io_error(NO_ARG); + return retcode; +} + +int caml_write_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + again: + caml_enter_blocking_section(); + retcode = write(fd, buf, n); + caml_leave_blocking_section(); + if (retcode == -1) { + if (errno == EINTR) goto again; + if ((errno == EAGAIN || errno == EWOULDBLOCK) && n > 1) { + /* We couldn't do a partial write here, probably because + n <= PIPE_BUF and POSIX says that writes of less than + PIPE_BUF characters must be atomic. + We first try again with a partial write of 1 character. + If that fails too, we'll return an error code. */ + n = 1; goto again; + } + } + if (retcode == -1) caml_sys_io_error(NO_ARG); + CAMLassert (retcode > 0); + return retcode; +} + char * caml_decompose_path(struct ext_table * tbl, char * path) { char * p, * q; diff --git a/byterun/weak.c b/byterun/weak.c index 65da99dc..39806ced 100644 --- a/byterun/weak.c +++ b/byterun/weak.c @@ -1,17 +1,19 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ - -/* Operations on weak arrays */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 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. */ +/* */ +/**************************************************************************/ + +/* Operations on weak arrays and ephemerons (named ephe here)*/ #include @@ -20,29 +22,123 @@ #include "caml/major_gc.h" #include "caml/memory.h" #include "caml/mlvalues.h" +#include "caml/weak.h" -value caml_weak_list_head = 0; +value caml_ephe_list_head = 0; -static value weak_dummy = 0; -value caml_weak_none = (value) &weak_dummy; +static value ephe_dummy = 0; +value caml_ephe_none = (value) &ephe_dummy; -CAMLprim value caml_weak_create (value len) +#if defined (NATIVE_CODE) && defined (NO_NAKED_POINTERS) +/** The minor heap is considered alive. + Outside minor and major heap, x must be black. +*/ +static inline int Is_Dead_during_clean(value x){ + Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_clean); + return Is_block (x) && !Is_young (x) && Is_white_val(x); +} +/** The minor heap doesn't have to be marked, outside they should + already be black +*/ +static inline int Must_be_Marked_during_mark(value x){ + Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_mark); + return Is_block (x) && !Is_young (x); +} +#else +static inline int Is_Dead_during_clean(value x){ + Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_clean); + return Is_block (x) && Is_in_heap (x) && Is_white_val(x); +} +static inline int Must_be_Marked_during_mark(value x){ + Assert (x != caml_ephe_none); Assert (caml_gc_phase == Phase_mark); + return Is_block (x) && Is_in_heap (x); +} +#endif + + +/* [len] is a value that represents a number of words (fields) */ +CAMLprim value caml_ephe_create (value len) { mlsize_t size, i; value res; - size = Long_val (len) + 1; + size = Long_val (len) + 1 /* weak_list */ + 1 /* the value */; if (size <= 0 || size > Max_wosize) caml_invalid_argument ("Weak.create"); res = caml_alloc_shr (size, Abstract_tag); - for (i = 1; i < size; i++) Field (res, i) = caml_weak_none; - Field (res, 0) = caml_weak_list_head; - caml_weak_list_head = res; + for (i = 1; i < size; i++) Field (res, i) = caml_ephe_none; + Field (res, CAML_EPHE_LINK_OFFSET) = caml_ephe_list_head; + caml_ephe_list_head = res; return res; } +CAMLprim value caml_weak_create (value len) +{ + return caml_ephe_create(len); +} + +/** + Specificity of the cleaning phase (Phase_clean): + + The dead keys must be removed from the ephemerons and data removed + when one the keys is dead. Here we call it cleaning the ephemerons. + A specific phase of the GC is dedicated to this, Phase_clean. This + phase is just after the mark phase, so the white values are dead + values. It iterates the function caml_ephe_clean through all the + ephemerons. + + However the GC is incremental and ocaml code can run on the middle + of this cleaning phase. In order to respect the semantic of the + ephemerons concerning dead values, the getter and setter must work + as if the cleaning of all the ephemerons have been done at once. + + - key getter: Even if a dead key have not yet been replaced by + caml_ephe_none, getting it should return none. + - key setter: If we replace a dead key we need to set the data to + caml_ephe_none and clean the ephemeron. + + This two cases are dealt by a call to do_check_key_clean that + trigger the cleaning of the ephemerons when the accessed key is + dead. This test is fast. + + In the case of value getter and value setter, there is no fast + test because the removing of the data depend of the deadliness of the keys. + We must always try to clean the ephemerons. + + */ + #define None_val (Val_int(0)) #define Some_tag 0 +/* If we are in Phase_clean we need to check if the key + that is going to disappear is dead and so should trigger a cleaning + */ +static void do_check_key_clean(value ar, mlsize_t offset){ + Assert ( offset >= 2); + if (caml_gc_phase == Phase_clean){ + value elt = Field (ar, offset); + if (elt != caml_ephe_none && Is_Dead_during_clean(elt)){ + Field(ar,offset) = caml_ephe_none; + Field(ar,CAML_EPHE_DATA_OFFSET) = caml_ephe_none; + }; + }; +} + +/* If we are in Phase_clean we need to do as if the key is empty when + it will be cleaned during this phase */ +static inline int is_ephe_key_none(value ar, mlsize_t offset){ + value elt = Field (ar, offset); + if (elt == caml_ephe_none){ + return 1; + }else if (caml_gc_phase == Phase_clean && Is_Dead_during_clean(elt)){ + Field(ar,offset) = caml_ephe_none; + Field(ar,CAML_EPHE_DATA_OFFSET) = caml_ephe_none; + return 1; + } else { + return 0; + } +} + + static void do_set (value ar, mlsize_t offset, value v) { if (Is_block (v) && Is_young (v)){ @@ -50,50 +146,119 @@ static void do_set (value ar, mlsize_t offset, value v) value old = Field (ar, offset); Field (ar, offset) = v; if (!(Is_block (old) && Is_young (old))){ - if (caml_weak_ref_table.ptr >= caml_weak_ref_table.limit){ - CAMLassert (caml_weak_ref_table.ptr == caml_weak_ref_table.limit); - caml_realloc_ref_table (&caml_weak_ref_table); - } - *caml_weak_ref_table.ptr++ = &Field (ar, offset); + add_to_ephe_ref_table (&caml_ephe_ref_table, ar, offset); } }else{ Field (ar, offset) = v; } } -CAMLprim value caml_weak_set (value ar, value n, value el) +CAMLprim value caml_ephe_set_key (value ar, value n, value el) { - mlsize_t offset = Long_val (n) + 1; + mlsize_t offset = Long_val (n) + 2; Assert (Is_in_heap (ar)); - if (offset < 1 || offset >= Wosize_val (ar)){ + if (offset < 2 || offset >= Wosize_val (ar)){ + caml_invalid_argument ("Weak.set"); + } + do_check_key_clean(ar,offset); + do_set (ar, offset, el); + return Val_unit; +} + +CAMLprim value caml_ephe_unset_key (value ar, value n) +{ + mlsize_t offset = Long_val (n) + 2; + Assert (Is_in_heap (ar)); + if (offset < 2 || offset >= Wosize_val (ar)){ + caml_invalid_argument ("Weak.set"); + } + do_check_key_clean(ar,offset); + Field (ar, offset) = caml_ephe_none; + return Val_unit; +} + +value caml_ephe_set_key_option (value ar, value n, value el) +{ + mlsize_t offset = Long_val (n) + 2; + Assert (Is_in_heap (ar)); + if (offset < 2 || offset >= Wosize_val (ar)){ caml_invalid_argument ("Weak.set"); } + do_check_key_clean(ar,offset); if (el != None_val && Is_block (el)){ Assert (Wosize_val (el) == 1); do_set (ar, offset, Field (el, 0)); }else{ - Field (ar, offset) = caml_weak_none; + Field (ar, offset) = caml_ephe_none; } return Val_unit; } +CAMLprim value caml_weak_set (value ar, value n, value el){ + return caml_ephe_set_key_option(ar,n,el); +} + +CAMLprim value caml_ephe_set_data (value ar, value el) +{ + Assert (Is_in_heap (ar)); + if (caml_gc_phase == Phase_clean){ + /* During this phase since we don't know which ephemeron have been + cleaned we always need to check it. */ + caml_ephe_clean(ar); + }; + do_set (ar, 1, el); + return Val_unit; +} + +CAMLprim value caml_ephe_unset_data (value ar) +{ + Assert (Is_in_heap (ar)); + Field (ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; + return Val_unit; +} + + #define Setup_for_gc #define Restore_after_gc -CAMLprim value caml_weak_get (value ar, value n) +CAMLprim value caml_ephe_get_key (value ar, value n) { CAMLparam2 (ar, n); - mlsize_t offset = Long_val (n) + 1; + mlsize_t offset = Long_val (n) + 2; CAMLlocal2 (res, elt); Assert (Is_in_heap (ar)); - if (offset < 1 || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.get"); + if (offset < 2 || offset >= Wosize_val (ar)){ + caml_invalid_argument ("Weak.get_key"); } - if (Field (ar, offset) == caml_weak_none){ + if (is_ephe_key_none(ar, offset)){ res = None_val; }else{ elt = Field (ar, offset); - if (caml_gc_phase == Phase_mark && Is_block (elt) && Is_in_heap (elt)){ + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ + caml_darken (elt, NULL); + } + res = caml_alloc_small (1, Some_tag); + Field (res, 0) = elt; + } + CAMLreturn (res); +} + +CAMLprim value caml_weak_get (value ar, value n){ + return caml_ephe_get_key(ar, n); +} + +CAMLprim value caml_ephe_get_data (value ar) +{ + CAMLparam1 (ar); + mlsize_t offset = 1; + CAMLlocal2 (res, elt); + Assert (Is_in_heap (ar)); + elt = Field (ar, offset); + if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); + if (elt == caml_ephe_none){ + res = None_val; + }else{ + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ caml_darken (elt, NULL); } res = caml_alloc_small (1, Some_tag); @@ -105,29 +270,29 @@ CAMLprim value caml_weak_get (value ar, value n) #undef Setup_for_gc #undef Restore_after_gc -CAMLprim value caml_weak_get_copy (value ar, value n) +CAMLprim value caml_ephe_get_key_copy (value ar, value n) { CAMLparam2 (ar, n); - mlsize_t offset = Long_val (n) + 1; + mlsize_t offset = Long_val (n) + 2; CAMLlocal2 (res, elt); value v; /* Caution: this is NOT a local root. */ Assert (Is_in_heap (ar)); if (offset < 1 || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.get"); + caml_invalid_argument ("Weak.get_copy"); } + if (is_ephe_key_none(ar, offset)) CAMLreturn (None_val); v = Field (ar, offset); - if (v == caml_weak_none) CAMLreturn (None_val); if (Is_block (v) && Is_in_heap_or_young(v)) { 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); - if (v == caml_weak_none) CAMLreturn (None_val); + if (is_ephe_key_none(ar, offset)) CAMLreturn (None_val); if (Tag_val (v) < No_scan_tag){ mlsize_t i; for (i = 0; i < Wosize_val (v); i++){ value f = Field (v, i); - if (caml_gc_phase == Phase_mark && Is_block (f) && Is_in_heap (f)){ + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(f)){ caml_darken (f, NULL); } Modify (&Field (elt, i), f); @@ -144,21 +309,74 @@ CAMLprim value caml_weak_get_copy (value ar, value n) CAMLreturn (res); } -CAMLprim value caml_weak_check (value ar, value n) +CAMLprim value caml_weak_get_copy (value ar, value n){ + return caml_ephe_get_key_copy(ar,n); +} + +CAMLprim value caml_ephe_get_data_copy (value ar) { - mlsize_t offset = Long_val (n) + 1; + CAMLparam1 (ar); + mlsize_t offset = 1; + CAMLlocal2 (res, elt); + value v; /* Caution: this is NOT a local root. */ Assert (Is_in_heap (ar)); - if (offset < 1 || offset >= Wosize_val (ar)){ - caml_invalid_argument ("Weak.get"); + + 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)) { + 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); + if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar); + if (v == caml_ephe_none) CAMLreturn (None_val); + if (Tag_val (v) < No_scan_tag){ + mlsize_t i; + for (i = 0; i < Wosize_val (v); i++){ + value f = Field (v, i); + if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(f)){ + caml_darken (f, NULL); + } + Modify (&Field (elt, i), f); + } + }else{ + memmove (Bp_val (elt), Bp_val (v), Bosize_val (v)); + } + }else{ + elt = v; } - return Val_bool (Field (ar, offset) != caml_weak_none); + res = caml_alloc_small (1, Some_tag); + Field (res, 0) = elt; + + CAMLreturn (res); } -CAMLprim value caml_weak_blit (value ars, value ofs, +CAMLprim value caml_ephe_check_key (value ar, value n) +{ + mlsize_t offset = Long_val (n) + 2; + Assert (Is_in_heap (ar)); + if (offset < 2 || offset >= Wosize_val (ar)){ + caml_invalid_argument ("Weak.check"); + } + return Val_bool (!is_ephe_key_none(ar, offset)); +} + +CAMLprim value caml_weak_check (value ar, value n) +{ + return caml_ephe_check_key(ar,n); +} + +CAMLprim value caml_ephe_check_data (value ar) +{ + if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); + return Val_bool (Field (ar, CAML_EPHE_DATA_OFFSET) != caml_ephe_none); +} + +CAMLprim value caml_ephe_blit_key (value ars, value ofs, value ard, value ofd, value len) { - mlsize_t offset_s = Long_val (ofs) + 1; - mlsize_t offset_d = Long_val (ofd) + 1; + mlsize_t offset_s = Long_val (ofs) + 2; + mlsize_t offset_d = Long_val (ofd) + 2; mlsize_t length = Long_val (len); long i; Assert (Is_in_heap (ars)); @@ -169,14 +387,9 @@ CAMLprim value caml_weak_blit (value ars, value ofs, if (offset_d < 1 || offset_d + length > Wosize_val (ard)){ caml_invalid_argument ("Weak.blit"); } - if (caml_gc_phase == Phase_mark && caml_gc_subphase == Subphase_weak1){ - for (i = 0; i < length; i++){ - value v = Field (ars, offset_s + i); - if (v != caml_weak_none && Is_block (v) && Is_in_heap (v) - && Is_white_val (v)){ - Field (ars, offset_s + i) = caml_weak_none; - } - } + if (caml_gc_phase == Phase_clean){ + caml_ephe_clean(ars); + caml_ephe_clean(ard); } if (offset_d < offset_s){ for (i = 0; i < length; i++){ @@ -189,3 +402,19 @@ CAMLprim value caml_weak_blit (value ars, value ofs, } return Val_unit; } + +CAMLprim value caml_ephe_blit_data (value ars, value ard) +{ + if(caml_gc_phase == Phase_clean) { + caml_ephe_clean(ars); + caml_ephe_clean(ard); + }; + do_set (ard, CAML_EPHE_DATA_OFFSET, Field (ars, CAML_EPHE_DATA_OFFSET)); + return Val_unit; +} + +CAMLprim value caml_weak_blit (value ars, value ofs, + value ard, value ofd, value len) +{ + return caml_ephe_blit_key (ars, ofs, ard, ofd, len); +} diff --git a/byterun/win32.c b/byterun/win32.c index f26caf8f..c7865e66 100644 --- a/byterun/win32.c +++ b/byterun/win32.c @@ -1,19 +1,24 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Win32-specific stuff */ -#include +#define WIN32_LEAN_AND_MEAN +#include +#include +#include #include #include #include @@ -25,20 +30,87 @@ #include #include #include +#include "caml/alloc.h" #include "caml/address_class.h" #include "caml/fail.h" +#include "caml/io.h" #include "caml/memory.h" #include "caml/misc.h" #include "caml/osdeps.h" #include "caml/signals.h" #include "caml/sys.h" +#include "caml/config.h" +#ifdef SUPPORT_DYNAMIC_LINKING #include +#endif #ifndef S_ISREG #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif +CAMLnoreturn_start +static void caml_win32_sys_error (int errnum) +CAMLnoreturn_end; + +static void caml_win32_sys_error(int errnum) +{ + char buffer[512]; + value msg; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errnum, + 0, + buffer, + sizeof(buffer), + NULL)) { + msg = caml_copy_string(buffer); + } else { + msg = caml_alloc_sprintf("unknown error #%d", errnum); + } + caml_raise_sys_error(msg); +} + +int caml_read_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + if ((flags & CHANNEL_FLAG_FROM_SOCKET) == 0) { + caml_enter_blocking_section(); + retcode = read(fd, buf, n); + /* Large reads from console can fail with ENOMEM. Reduce requested size + and try again. */ + if (retcode == -1 && errno == ENOMEM && n > 16384) { + retcode = read(fd, buf, 16384); + } + caml_leave_blocking_section(); + if (retcode == -1) caml_sys_io_error(NO_ARG); + } else { + caml_enter_blocking_section(); + retcode = recv((SOCKET) _get_osfhandle(fd), buf, n, 0); + caml_leave_blocking_section(); + if (retcode == -1) caml_win32_sys_error(WSAGetLastError()); + } + return retcode; +} + +int caml_write_fd(int fd, int flags, void * buf, int n) +{ + int retcode; + if ((flags & CHANNEL_FLAG_FROM_SOCKET) == 0) { + caml_enter_blocking_section(); + retcode = write(fd, buf, n); + caml_leave_blocking_section(); + if (retcode == -1) caml_sys_io_error(NO_ARG); + } else { + caml_enter_blocking_section(); + retcode = send((SOCKET) _get_osfhandle(fd), buf, n, 0); + caml_leave_blocking_section(); + if (retcode == -1) caml_win32_sys_error(WSAGetLastError()); + } + CAMLassert (retcode > 0); + return retcode; +} + char * caml_decompose_path(struct ext_table * tbl, char * path) { char * p, * q; @@ -122,6 +194,8 @@ char * caml_search_dll_in_path(struct ext_table * path, char * name) return res; } +#ifdef SUPPORT_DYNAMIC_LINKING + void * caml_dlopen(char * libname, int for_execution, int global) { void *handle; @@ -155,6 +229,34 @@ char * caml_dlerror(void) return flexdll_dlerror(); } +#else + +void * caml_dlopen(char * libname, int for_execution, int global) +{ + return NULL; +} + +void caml_dlclose(void * handle) +{ +} + +void * caml_dlsym(void * handle, char * name) +{ + return NULL; +} + +void * caml_globalsym(char * name) +{ + return NULL; +} + +char * caml_dlerror(void) +{ + return "dynamic loading not supported on this platform"; +} + +#endif + /* Proper emulation of signal(), including ctrl-C and ctrl-break */ typedef void (*sighandler)(int sig); @@ -319,7 +421,7 @@ void caml_signal_thread(void * lpParam) char *endptr; HANDLE h; /* Get an hexa-code raw handle through the environment */ - h = (HANDLE) strtol(getenv("CAMLSIGPIPE"), &endptr, 16); + h = (HANDLE) (uintptr_t) strtol(getenv("CAMLSIGPIPE"), &endptr, 16); while (1) { DWORD numread; BOOL ret; @@ -510,6 +612,7 @@ int caml_executable_name(char * name, int name_len) /* snprintf emulation */ +#if defined(_WIN32) && !defined(_UCRT) int caml_snprintf(char * buf, size_t size, const char * format, ...) { int len; @@ -534,3 +637,4 @@ int caml_snprintf(char * buf, size_t size, const char * format, ...) va_end(args); return len; } +#endif diff --git a/compilerlibs/.gitignore b/compilerlibs/.gitignore new file mode 100644 index 00000000..c1eda49d --- /dev/null +++ b/compilerlibs/.gitignore @@ -0,0 +1,7 @@ +# This .gitignore is here to force git to create the compilerlibs directory +# because git doesn't create empty directories. +# The lines tell git to ignore everything in this directory except +# the .gitignore file itself. + +* +!.gitignore diff --git a/config/.ignore b/config/.ignore deleted file mode 100644 index 259ce3f6..00000000 --- a/config/.ignore +++ /dev/null @@ -1,3 +0,0 @@ -m.h -s.h -Makefile diff --git a/config/Makefile-templ b/config/Makefile-templ index b9142c66..6b8231eb 100644 --- a/config/Makefile-templ +++ b/config/Makefile-templ @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** ### Compile-time configuration @@ -72,10 +74,6 @@ SHARPBANGSCRIPTS=true # Under FreeBSD: #CPP=cpp -P -### Magic declarations for ocamlbuild -- leave unchanged -#ml let syslib x = "-l"^x;; -#ml let mklib out files opts = Printf.sprintf "ar rc %s %s %s; ranlib %s" out opts files out;; - ### How to invoke ranlib RANLIB=ranlib RANLIBCMD=ranlib diff --git a/config/Makefile.mingw b/config/Makefile.mingw index 5b4658f7..527e9915 100644 --- a/config/Makefile.mingw +++ b/config/Makefile.mingw @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Configuration for Windows, Mingw compiler @@ -20,9 +22,6 @@ PREFIX=C:/ocamlmgw ### Remove this to disable compiling ocamldebug WITH_DEBUGGER=ocamldebugger -### Remove this to disable compiling ocamlbuild -WITH_OCAMLBUILD=ocamlbuild - ### Remove this to disable compiling ocamldoc WITH_OCAMLDOC=ocamldoc @@ -86,6 +85,7 @@ RUNTIMED=noruntimed ASM_CFI_SUPPORTED=false UNIXLIB=win32unix GRAPHLIB=win32graph +FLAMBDA=false ########## Configuration for the bytecode compiler @@ -109,16 +109,33 @@ NATIVECCLIBS=-lws2_32 CPP=$(BYTECC) -E ### Flexlink -FLEXLINK=flexlink -chain mingw -stack 16777216 -link -static-libgcc -FLEXDIR:=$(shell $(FLEXLINK) -where) +FLEXLINK_CMD=flexlink +FLEXDLL_CHAIN=mingw +# FLEXLINK_FLAGS must be safe to insert in an OCaml string +# (see ocamlmklibconfig.ml in tools/Makefile.nt) +FLEXLINK_FLAGS=-chain $(FLEXDLL_CHAIN) -stack 16777216 -link -static-libgcc +FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) +FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) +ifeq ($(FLEXDIR),) +IFLEXDIR=-I"../flexdll" +else IFLEXDIR=-I"$(FLEXDIR)" +endif +# MKDLL, MKEXE and MKMAINDLL must ultimately be equivalent to +# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] +# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe MKMAINDLL=$(FLEXLINK) -maindll +### Native command to build ocamlrun.exe without flexlink +MKEXE_BOOT=$(BYTECC) -o $(1) $(2) + ### How to build a static library MKLIB=rm -f $(1); $(TOOLPREF)ar rc $(1) $(2); $(RANLIB) $(1) -#ml let mklib out files opts = Printf.sprintf "rm -f %s && %sar rcs %s %s %s" out toolpref opts out files;; +#ml let mklib out files opts = +#ml Printf.sprintf "rm -f %s && %sar rcs %s %s %s" +#ml out toolpref opts out files;; ### Canonicalize the name of a system library SYSLIB=-l$(1) @@ -173,5 +190,5 @@ OTOPDIR=$(WINTOPDIR) CTOPDIR=$(TOPDIR) CYGPATH=cygpath -m DIFF=diff -q --strip-trailing-cr -CANKILL=false SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" +MAX_TESTSUITE_DIR_RETRIES=1 diff --git a/config/Makefile.mingw64 b/config/Makefile.mingw64 index 19a9b943..79ff7943 100644 --- a/config/Makefile.mingw64 +++ b/config/Makefile.mingw64 @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Configuration for Windows, Mingw compiler @@ -20,9 +22,6 @@ PREFIX=C:/ocamlmgw64 ### Remove this to disable compiling ocamldebug WITH_DEBUGGER=ocamldebugger -### Remove this to disable compiling ocamlbuild -WITH_OCAMLBUILD=ocamlbuild - ### Remove this to disable compiling ocamldoc WITH_OCAMLDOC=ocamldoc @@ -86,6 +85,7 @@ RUNTIMED=noruntimed ASM_CFI_SUPPORTED=false UNIXLIB=win32unix GRAPHLIB=win32graph +FLAMBDA=false ########## Configuration for the bytecode compiler @@ -109,16 +109,33 @@ NATIVECCLIBS=-lws2_32 CPP=$(BYTECC) -E ### Flexlink -FLEXLINK=flexlink -chain mingw64 -stack 33554432 -FLEXDIR:=$(shell $(FLEXLINK) -where) +FLEXLINK_CMD=flexlink +FLEXDLL_CHAIN=mingw64 +# FLEXLINK_FLAGS must be safe to insert in an OCaml string +# (see ocamlmklibconfig.ml in tools/Makefile.nt) +FLEXLINK_FLAGS=-chain $(FLEXDLL_CHAIN) -stack 33554432 +FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) +FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) +ifeq ($(FLEXDIR),) +IFLEXDIR=-I"../flexdll" +else IFLEXDIR=-I"$(FLEXDIR)" +endif +# MKDLL, MKEXE and MKMAINDLL must ultimately be equivalent to +# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] +# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe MKMAINDLL=$(FLEXLINK) -maindll +### Native command to build ocamlrun.exe without flexlink +MKEXE_BOOT=$(BYTECC) -o $(1) $(2) + ### How to build a static library MKLIB=rm -f $(1); $(TOOLPREF)ar rc $(1) $(2); $(RANLIB) $(1) -#ml let mklib out files opts = Printf.sprintf "rm -f %s && %sar rcs %s %s %s" out toolpref opts out files;; +#ml let mklib out files opts = +#ml Printf.sprintf "rm -f %s && %sar rcs %s %s %s" +#ml out toolpref opts out files;; ### Canonicalize the name of a system library SYSLIB=-l$(1) @@ -173,5 +190,5 @@ OTOPDIR=$(WINTOPDIR) CTOPDIR=$(TOPDIR) CYGPATH=cygpath -m DIFF=diff -q --strip-trailing-cr -CANKILL=false SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" +MAX_TESTSUITE_DIR_RETRIES=1 diff --git a/config/Makefile.msvc b/config/Makefile.msvc index e0145102..20ddaf95 100644 --- a/config/Makefile.msvc +++ b/config/Makefile.msvc @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Configuration for Windows, Visual C++ compiler @@ -77,6 +79,7 @@ RUNTIMED=noruntimed ASM_CFI_SUPPORTED=false UNIXLIB=win32unix GRAPHLIB=win32graph +FLAMBDA=false ########## Configuration for the bytecode compiler @@ -84,13 +87,13 @@ GRAPHLIB=win32graph BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE ### Additional compile-time options for $(BYTECC). (For static linking.) -BYTECCCOMPOPTS=-Ox -MD +BYTECCCOMPOPTS=-O2 -Gy- -MD ### Additional link-time options for $(BYTECC). (For static linking.) BYTECCLINKOPTS= ### Additional compile-time options for $(BYTECC). (For building a DLL.) -DLLCCCOMPOPTS=-Ox -MD +DLLCCCOMPOPTS=-O2 -Gy- -MD ### Libraries needed BYTECCLIBS=advapi32.lib ws2_32.lib @@ -100,16 +103,36 @@ NATIVECCLIBS=advapi32.lib ws2_32.lib CPP=cl -nologo -EP ### Flexlink -FLEXLINK=flexlink -merge-manifest -stack 16777216 -FLEXDIR:=$(shell $(FLEXLINK) -where) +FLEXLINK_CMD=flexlink +FLEXDLL_CHAIN=msvc +# FLEXLINK_FLAGS must be safe to insert in an OCaml string +# (see ocamlmklibconfig.ml in tools/Makefile.nt) +FLEXLINK_FLAGS=-merge-manifest -stack 16777216 +FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) +FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) +ifeq ($(FLEXDIR),) +IFLEXDIR=-I"../flexdll" +else IFLEXDIR=-I"$(FLEXDIR)" +endif +# MKDLL, MKEXE and MKMAINDLL must ultimately be equivalent to +# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] +# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe MKMAINDLL=$(FLEXLINK) -maindll +### Native command to build ocamlrun.exe without flexlink +MERGEMANIFESTEXE=test ! -f $(1).manifest \ + || mt -nologo -outputresource:$(1) -manifest $(1).manifest \ + && rm -f $(1).manifest +MKEXE_BOOT=$(BYTECC) /Fe$(1) $(2) /link /subsystem:console \ + && ($(MERGEMANIFESTEXE)) + ### How to build a static library MKLIB=link -lib -nologo -out:$(1) $(2) -#ml let mklib out files opts = Printf.sprintf "link -lib -nologo -out:%s %s %s" out opts files;; +#ml let mklib out files opts = +#ml Printf.sprintf "link -lib -nologo -out:%s %s %s" out opts files;; MKSHAREDLIBRPATH= ### Canonicalize the name of a system library @@ -138,7 +161,7 @@ SYSTEM=win32 NATIVECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE ### Additional compile-time options for $(NATIVECC). -NATIVECCCOMPOPTS=-Ox -MD +NATIVECCCOMPOPTS=-O2 -Gy- -MD ### Additional link-time options for $(NATIVECC) NATIVECCLINKOPTS= @@ -149,9 +172,6 @@ PACKLD=link -lib -nologo -out:# there must be no space after this '-out:' ### Clear this to disable compiling ocamldebug WITH_DEBUGGER=ocamldebugger -### Clear this to disable compiling ocamlbuild -WITH_OCAMLBUILD=ocamlbuild - ### Clear this to disable compiling ocamldoc WITH_OCAMLDOC=ocamldoc @@ -174,7 +194,7 @@ OTOPDIR=$(WINTOPDIR) CTOPDIR=$(WINTOPDIR) CYGPATH=cygpath -m DIFF=diff -q --strip-trailing-cr -CANKILL=false FIND=/usr/bin/find SORT=/usr/bin/sort SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" +MAX_TESTSUITE_DIR_RETRIES=1 diff --git a/config/Makefile.msvc64 b/config/Makefile.msvc64 index 783ce953..0758aa7c 100644 --- a/config/Makefile.msvc64 +++ b/config/Makefile.msvc64 @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Configuration for Windows, Visual C++ compiler @@ -76,6 +78,7 @@ RUNTIMED=noruntimed ASM_CFI_SUPPORTED=false UNIXLIB=win32unix GRAPHLIB=win32graph +FLAMBDA=false ########## Configuration for the bytecode compiler @@ -83,7 +86,7 @@ GRAPHLIB=win32graph BYTECC=cl -nologo -D_CRT_SECURE_NO_DEPRECATE ### Additional compile-time options for $(BYTECC). (For static linking.) -BYTECCCOMPOPTS=-Ox -MD +BYTECCCOMPOPTS=-O2 -Gy- -MD ### Additional compile-time options for $(BYTECC). (For debug version.) BYTECCDBGCOMPOPTS=-DDEBUG -Zi -W3 -Wp64 @@ -92,7 +95,7 @@ BYTECCDBGCOMPOPTS=-DDEBUG -Zi -W3 -Wp64 BYTECCLINKOPTS= ### Additional compile-time options for $(BYTECC). (For building a DLL.) -DLLCCCOMPOPTS=-Ox -MD +DLLCCCOMPOPTS=-O2 -Gy- -MD ### Libraries needed #EXTRALIBS=bufferoverflowu.lib # for the old PSDK compiler only @@ -104,16 +107,37 @@ NATIVECCLIBS=advapi32.lib ws2_32.lib $(EXTRALIBS) CPP=cl -nologo -EP ### Flexlink -FLEXLINK=flexlink -x64 -merge-manifest -stack 33554432 -FLEXDIR:=$(shell $(FLEXLINK) -where) +FLEXLINK_CMD=flexlink +FLEXDLL_CHAIN=msvc64 +# FLEXLINK_FLAGS must be safe to insert in an OCaml string +# (see ocamlmklibconfig.ml in tools/Makefile.nt) +FLEXLINK_FLAGS=-x64 -merge-manifest -stack 33554432 +FLEXLINK=$(FLEXLINK_CMD) $(FLEXLINK_FLAGS) +FLEXDIR:=$(shell $(FLEXLINK) -where 2>/dev/null) +ifeq ($(FLEXDIR),) +IFLEXDIR=-I"../flexdll" +else IFLEXDIR=-I"$(FLEXDIR)" +endif +# MKDLL, MKEXE and MKMAINDLL must ultimately be equivalent to +# $(FLEXLINK_CMD) $(FLEXLINK_FLAGS) [-exe|-maindll] +# or OCAML_FLEXLINK overriding will not work (see utils/config.mlp) MKDLL=$(FLEXLINK) MKEXE=$(FLEXLINK) -exe MKMAINDLL=$(FLEXLINK) -maindll +### Native command to build ocamlrun.exe without flexlink +MERGEMANIFESTEXE=test ! -f $(1).manifest \ + || mt -nologo -outputresource:$(1) -manifest $(1).manifest \ + && rm -f $(1).manifest +MKEXE_BOOT=$(BYTECC) /Fe$(1) $(2) /link /subsystem:console \ + && ($(MERGEMANIFESTEXE)) + ### How to build a static library MKLIB=link -lib -nologo -machine:AMD64 /out:$(1) $(2) -#ml let mklib out files opts = Printf.sprintf "link -lib -nologo -machine:AMD64 -out:%s %s %s" out opts files;; +#ml let mklib out files opts = +#ml Printf.sprintf "link -lib -nologo -machine:AMD64 -out:%s %s %s" +#ml out opts files;; MKSHAREDLIBRPATH= ### Canonicalize the name of a system library @@ -142,7 +166,7 @@ SYSTEM=win64 NATIVECC=cl -nologo ### Additional compile-time options for $(NATIVECC). -NATIVECCCOMPOPTS=-Ox -MD +NATIVECCCOMPOPTS=-O2 -Gy- -MD ### Additional link-time options for $(NATIVECC) NATIVECCLINKOPTS= @@ -153,9 +177,6 @@ PACKLD=link -lib -nologo -machine:AMD64 -out:# must have no space after '-out:' ### Clear this to disable compiling ocamldebug WITH_DEBUGGER=ocamldebugger -### Clear this to disable compiling ocamlbuild -WITH_OCAMLBUILD=ocamlbuild - ### Clear this to disable compiling ocamldoc WITH_OCAMLDOC=ocamldoc @@ -178,7 +199,7 @@ OTOPDIR=$(WINTOPDIR) CTOPDIR=$(WINTOPDIR) CYGPATH=cygpath -m DIFF=diff -q --strip-trailing-cr -CANKILL=false FIND=/usr/bin/find SORT=/usr/bin/sort SET_LD_PATH=PATH="$(PATH):$(LD_PATH)" +MAX_TESTSUITE_DIR_RETRIES=1 diff --git a/config/auto-aux/.ignore b/config/auto-aux/.ignore deleted file mode 100644 index cb1ca8a9..00000000 --- a/config/auto-aux/.ignore +++ /dev/null @@ -1 +0,0 @@ -camlp4_config.ml diff --git a/config/auto-aux/align.c b/config/auto-aux/align.c index 579db9c6..c5f5f3f0 100644 --- a/config/auto-aux/align.c +++ b/config/auto-aux/align.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/config/auto-aux/ansi.c b/config/auto-aux/ansi.c index 01d46252..65d82400 100644 --- a/config/auto-aux/ansi.c +++ b/config/auto-aux/ansi.c @@ -1,21 +1,27 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 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. */ +/* */ +/**************************************************************************/ int main() { #ifdef __STDC__ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L return 0; #else return 1; #endif +#else + return 2; +#endif } diff --git a/config/auto-aux/async_io.c b/config/auto-aux/async_io.c index 3e2bb983..b8f52572 100644 --- a/config/auto-aux/async_io.c +++ b/config/auto-aux/async_io.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/config/auto-aux/bytecopy.c b/config/auto-aux/bytecopy.c deleted file mode 100644 index 34f29c48..00000000 --- a/config/auto-aux/bytecopy.c +++ /dev/null @@ -1,32 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -char buffer[27]; - -#ifdef reverse -#define cpy(s1,s2,n) copy(s2,s1,n) -#else -#define cpy copy -#endif - -int main(int argc, char ** argv) -{ - cpy("abcdefghijklmnopqrstuvwxyz", buffer, 27); - if (strcmp(buffer, "abcdefghijklmnopqrstuvwxyz") != 0) exit(1); - cpy(buffer, buffer+3, 26-3); - if (strcmp(buffer, "abcabcdefghijklmnopqrstuvw") != 0) exit(1); - cpy("abcdefghijklmnopqrstuvwxyz", buffer, 27); - cpy(buffer+3, buffer, 26-3); - if (strcmp(buffer, "defghijklmnopqrstuvwxyzxyz") != 0) exit(1); - exit(0); -} diff --git a/config/auto-aux/cckind.c b/config/auto-aux/cckind.c new file mode 100644 index 00000000..7277a7ad --- /dev/null +++ b/config/auto-aux/cckind.c @@ -0,0 +1,30 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2015 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. */ +/* */ +/**************************************************************************/ + +/* Determine vendor and version of C compiler */ + +/* This file is to be preprocessed and its output examined. */ +/* It is not C source code to be executed. */ +/* This helps with cross-compilation. */ + +#if defined(__INTEL_COMPILER) +icc __INTEL_COMPILER +#elif defined(__clang_major__) && defined(__clang_minor__) +clang __clang_major__ __clang_minor__ +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) +gcc __GNUC__ __GNUC_MINOR__ +#else +unknown +#endif diff --git a/config/auto-aux/dblalign.c b/config/auto-aux/dblalign.c index e86fb198..69097103 100644 --- a/config/auto-aux/dblalign.c +++ b/config/auto-aux/dblalign.c @@ -1,23 +1,25 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include -double foo; +volatile double foo; -void access_double(double *p) +void access_double(volatile double *p) { foo = *p; } @@ -38,8 +40,8 @@ int main(void) signal(SIGBUS, sig_handler); #endif if(setjmp(failure) == 0) { - access_double((double *) n); - access_double((double *) (n+1)); + access_double((volatile double *) n); + access_double((volatile double *) (n+1)); res = 0; } else { res = 1; @@ -48,5 +50,5 @@ int main(void) #ifdef SIGBUS signal(SIGBUS, SIG_DFL); #endif - exit(res); + return res; } diff --git a/config/auto-aux/divmod.c b/config/auto-aux/divmod.c deleted file mode 100644 index e85e4b3f..00000000 --- a/config/auto-aux/divmod.c +++ /dev/null @@ -1,45 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* Test semantics of division and modulus for negative arguments */ - -long div4[] = -{ -4,-3,-3,-3,-3,-2,-2,-2,-2,-1,-1,-1,-1,0,0,0, - 0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4 }; - -long divm4[] = -{ 4,3,3,3,3,2,2,2,2,1,1,1,1,0,0,0, - 0,0,0,0,-1,-1,-1,-1,-2,-2,-2,-2,-3,-3,-3,-3,-4 }; - -long mod4[] = -{ 0,-3,-2,-1,0,-3,-2,-1,0,-3,-2,-1,0,-3,-2,-1, - 0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0 }; - -long modm4[] = -{ 0,-3,-2,-1,0,-3,-2,-1,0,-3,-2,-1,0,-3,-2,-1, - 0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0 }; - -long q1 = 4; -long q2 = -4; - -int main() -{ - int i; - for (i = -16; i <= 16; i++) { - if (i / q1 != div4[i+16]) return 1; - if (i / q2 != divm4[i+16]) return 1; - if (i % q1 != mod4[i+16]) return 1; - if (i % q2 != modm4[i+16]) return 1; - } - return 0; -} diff --git a/config/auto-aux/elf.c b/config/auto-aux/elf.c index c7548ae4..e7f044b9 100644 --- a/config/auto-aux/elf.c +++ b/config/auto-aux/elf.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* 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 Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* 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 diff --git a/config/auto-aux/endian.c b/config/auto-aux/endian.c index 91312f71..bd2bbe04 100644 --- a/config/auto-aux/endian.c +++ b/config/auto-aux/endian.c @@ -1,16 +1,19 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "m.h" #ifndef ARCH_SIXTYFOUR @@ -23,7 +26,7 @@ char * bigendian = "ABCDEFGH"; char * littleendian = "HGFEDCBA"; #endif -main(void) +int main(void) { long n[2]; char * p; @@ -32,8 +35,8 @@ main(void) n[1] = 0; p = (char *) n; if (strcmp(p, bigendian) == 0) - exit(0); + return 0; if (strcmp(p, littleendian) == 0) - exit(1); - exit(2); + return 1; + return 2; } diff --git a/config/auto-aux/expm1.c b/config/auto-aux/expm1.c deleted file mode 100644 index 2cfbe737..00000000 --- a/config/auto-aux/expm1.c +++ /dev/null @@ -1,24 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2011 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -#include - -volatile double x; - -int main(int argc, char **argv) -{ - x = 3.1415; - x = expm1(x); - x = log1p(x); - return 0; -} diff --git a/config/auto-aux/getgroups.c b/config/auto-aux/getgroups.c index e3f73f52..a538ed03 100644 --- a/config/auto-aux/getgroups.c +++ b/config/auto-aux/getgroups.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/config/auto-aux/gethostbyaddr.c b/config/auto-aux/gethostbyaddr.c index f09d65a8..a932d11f 100644 --- a/config/auto-aux/gethostbyaddr.c +++ b/config/auto-aux/gethostbyaddr.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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. */ +/* */ +/**************************************************************************/ #ifndef _REENTRANT /* This helps detection on Digital Unix... */ @@ -19,6 +21,10 @@ #include #include +#ifdef SYS_netbsd +#error "this OS doesn't have gethostbyaddr_r" +#endif + int main(int argc, char ** argv) { #if NUM_ARGS == 7 diff --git a/config/auto-aux/gethostbyname.c b/config/auto-aux/gethostbyname.c index da52d89b..aefd85fc 100644 --- a/config/auto-aux/gethostbyname.c +++ b/config/auto-aux/gethostbyname.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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. */ +/* */ +/**************************************************************************/ #ifndef _REENTRANT /* This helps detection on Digital Unix... */ @@ -19,6 +21,10 @@ #include #include +#ifdef SYS_netbsd +#error "this OS doesn't have gethostbyname_r" +#endif + int main(int argc, char ** argv) { #if NUM_ARGS == 5 diff --git a/config/auto-aux/hasgot b/config/auto-aux/hasgot index 53d57866..1ba464ca 100755 --- a/config/auto-aux/hasgot +++ b/config/auto-aux/hasgot @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 1995 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1995 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. * +#* * +#************************************************************************** opts="" libs="$cclibs" @@ -30,9 +32,9 @@ while : ; do shift done -(echo "main() {" +(echo "int main() {" for f in $*; do echo " $f();"; done - echo "}") >> hasgot.c + echo " return 0; }") >> hasgot.c if test "$verbose" = yes; then echo "hasgot $args: $cc $opts -o tst hasgot.c $libs" >&2 diff --git a/config/auto-aux/hasgot2 b/config/auto-aux/hasgot2 index 0e9cef9b..6ec6b904 100644 --- a/config/auto-aux/hasgot2 +++ b/config/auto-aux/hasgot2 @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2011 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 2011 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. * +#* * +#************************************************************************** opts="" libs="$cclibs" @@ -30,9 +32,9 @@ while : ; do shift done -(echo "main() {" +(echo "int main() {" for f in $*; do echo " (void) & $f;"; done - echo "}") >> hasgot.c + echo " return 0; }") >> hasgot.c if test "$verbose" = yes; then echo "hasgot2 $args: $cc $opts -o tst hasgot.c $libs" >&2 diff --git a/config/auto-aux/ia32sse2.c b/config/auto-aux/ia32sse2.c index 47bafb60..d0391eaf 100644 --- a/config/auto-aux/ia32sse2.c +++ b/config/auto-aux/ia32sse2.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /* Test whether IA32 assembler supports SSE2 instructions */ diff --git a/config/auto-aux/initgroups.c b/config/auto-aux/initgroups.c index 0086e92a..af968039 100644 --- a/config/auto-aux/initgroups.c +++ b/config/auto-aux/initgroups.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Stephane Glondu */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Stephane Glondu */ +/* */ +/* Copyright 2009 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 diff --git a/config/auto-aux/int64align.c b/config/auto-aux/int64align.c index 5795e484..5914d1c2 100644 --- a/config/auto-aux/int64align.c +++ b/config/auto-aux/int64align.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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 #include @@ -17,18 +19,18 @@ #include "m.h" #if defined(ARCH_INT64_TYPE) -typedef ARCH_INT64_TYPE int64; +typedef ARCH_INT64_TYPE int64_t; #elif SIZEOF_LONG == 8 -typedef long int64; +typedef long int64_t; #elif SIZEOF_LONGLONG == 8 -typedef long long int64; +typedef long long int64_t; #else #error "No 64-bit integer type available" #endif -int64 foo; +volatile int64_t foo; -void access_int64(int64 *p) +void access_int64(volatile int64_t *p) { foo = *p; } @@ -49,8 +51,8 @@ int main(void) signal(SIGBUS, sig_handler); #endif if(setjmp(failure) == 0) { - access_int64((int64 *) n); - access_int64((int64 *) (n+1)); + access_int64((volatile int64_t *) n); + access_int64((volatile int64_t *) (n+1)); res = 0; } else { res = 1; @@ -59,5 +61,5 @@ int main(void) #ifdef SIGBUS signal(SIGBUS, SIG_DFL); #endif - exit(res); + return res; } diff --git a/config/auto-aux/longlong.c b/config/auto-aux/longlong.c deleted file mode 100644 index e18f9e28..00000000 --- a/config/auto-aux/longlong.c +++ /dev/null @@ -1,41 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -#include -#include - -/* Check for the availability of "long long" type as per ISO C9X */ - -/* Meaning of return code: - 0 long long OK, printf with %ll - 1 long long OK, printf with %q - 2 long long OK, no printf - 3 long long not suitable */ - -int main(int argc, char **argv) -{ - long long l; - unsigned long long u; - char buffer[64]; - - if (sizeof(long long) != 8) return 3; - l = 123456789123456789LL; - buffer[0] = '\0'; - sprintf(buffer, "%lld", l); - if (strcmp(buffer, "123456789123456789") == 0) return 0; - /* the MacOS X library uses qd to format long longs */ - buffer[0] = '\0'; - sprintf (buffer, "%qd", l); - if (strcmp (buffer, "123456789123456789") == 0) return 1; - return 2; -} diff --git a/config/auto-aux/mmap-huge.c b/config/auto-aux/mmap-huge.c new file mode 100644 index 00000000..9bd43ba1 --- /dev/null +++ b/config/auto-aux/mmap-huge.c @@ -0,0 +1,51 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, Jane Street Group, LLC */ +/* */ +/* Copyright 2015 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 +#include +#include + +#define huge_page_size (4 * 1024 * 1024) + +/* Test for the possible availability of huge pages. Answer yes + if the OS knows about huge pages, even if they are not available + on the build machine at configure time, because (on Linux) huge + pages can be activated and deactivated easily while the system + is running. +*/ + +int main (int argc, char *argv[]){ + void *block; + char *p; + int i, res; + block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, + -1, 0); + if (block == MAP_FAILED){ + block = mmap (NULL, huge_page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + } + if (block == MAP_FAILED){ + perror ("mmap"); + return 3; + } + /*printf ("block = %p\n", block);*/ + p = (char *) block; + for (i = 0; i < huge_page_size; i += 4096){ + p[i] = (char) i; + } + return 0; +} diff --git a/config/auto-aux/nanosecond_stat.c b/config/auto-aux/nanosecond_stat.c index fc92e67b..8a15a30d 100644 --- a/config/auto-aux/nanosecond_stat.c +++ b/config/auto-aux/nanosecond_stat.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Jeremie Dimino, Jane Street Group, LLC */ -/* */ -/* Copyright 2015 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jeremie Dimino, Jane Street Group, LLC */ +/* */ +/* Copyright 2015 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. */ +/* */ +/**************************************************************************/ #define _GNU_SOURCE #include diff --git a/config/auto-aux/runtest b/config/auto-aux/runtest index c8d7c435..2950f801 100755 --- a/config/auto-aux/runtest +++ b/config/auto-aux/runtest @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 1995 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1995 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. * +#* * +#************************************************************************** if test "$verbose" = yes; then echo "runtest: $cc -o tst $* $cclibs" >&2 diff --git a/config/auto-aux/schar.c b/config/auto-aux/schar.c deleted file mode 100644 index a9c355e5..00000000 --- a/config/auto-aux/schar.c +++ /dev/null @@ -1,21 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -char foo[]="\377"; - -int main(int argc, char ** argv) -{ - int i; - i = foo[0]; - exit(i != -1); -} diff --git a/config/auto-aux/schar2.c b/config/auto-aux/schar2.c deleted file mode 100644 index 9d18d2ac..00000000 --- a/config/auto-aux/schar2.c +++ /dev/null @@ -1,21 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -signed char foo[]="\377"; - -int main(int argc, char ** argv) -{ - int i; - i = foo[0]; - exit(i != -1); -} diff --git a/config/auto-aux/searchpath b/config/auto-aux/searchpath index e229ac92..0f5d9e8c 100755 --- a/config/auto-aux/searchpath +++ b/config/auto-aux/searchpath @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 1996 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1996 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. * +#* * +#************************************************************************** # Find a program in the path diff --git a/config/auto-aux/setgroups.c b/config/auto-aux/setgroups.c index 4be3c1d7..8a9e3658 100644 --- a/config/auto-aux/setgroups.c +++ b/config/auto-aux/setgroups.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Stephane Glondu */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Stephane Glondu */ +/* */ +/* Copyright 2009 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 diff --git a/config/auto-aux/sighandler.c b/config/auto-aux/sighandler.c deleted file mode 100644 index 3c341fea..00000000 --- a/config/auto-aux/sighandler.c +++ /dev/null @@ -1,21 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -#include - -int main(void) -{ - SIGRETURN (*old)(); - old = signal(SIGQUIT, SIG_DFL); - return 0; -} diff --git a/config/auto-aux/signals.c b/config/auto-aux/signals.c index ed84e980..90b893f7 100644 --- a/config/auto-aux/signals.c +++ b/config/auto-aux/signals.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* To determine the semantics of signal handlers (System V: signal is reset to default behavior on entrance to the handler diff --git a/config/auto-aux/sizes.c b/config/auto-aux/sizes.c index daa9615d..ffa9fb7d 100644 --- a/config/auto-aux/sizes.c +++ b/config/auto-aux/sizes.c @@ -1,22 +1,27 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 int main(int argc, char **argv) { printf("%d %d %d %d %d\n", - sizeof(int), sizeof(long), sizeof(long *), sizeof(short), - sizeof(long long)); + (int) sizeof(int), + (int) sizeof(long), + (int) sizeof(long *), + (int) sizeof(short), + (int) sizeof(long long)); return 0; } diff --git a/config/auto-aux/solaris-ld b/config/auto-aux/solaris-ld index cc846a31..bd0da5dd 100644 --- a/config/auto-aux/solaris-ld +++ b/config/auto-aux/solaris-ld @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2001 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* 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. * +#* * +#************************************************************************** # Determine if gcc calls the Solaris ld or the GNU ld # Exit code is 0 for Solaris ld, 1 for GNU ld diff --git a/config/auto-aux/stackov.c b/config/auto-aux/stackov.c deleted file mode 100644 index 3e3181bd..00000000 --- a/config/auto-aux/stackov.c +++ /dev/null @@ -1,66 +0,0 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -#include -#include -#include - -static char sig_alt_stack[SIGSTKSZ]; -static char * system_stack_top; - -#if defined(TARGET_i386) && defined(SYS_linux_elf) -static void segv_handler(int signo, struct sigcontext sc) -{ - char * fault_addr = (char *) sc.cr2; -#else -static void segv_handler(int signo, siginfo_t * info, void * context) -{ - char * fault_addr = (char *) info->si_addr; -#endif - struct rlimit limit; - - if (getrlimit(RLIMIT_STACK, &limit) == 0 && - ((long) fault_addr & (sizeof(long) - 1)) == 0 && - fault_addr < system_stack_top && - fault_addr >= system_stack_top - limit.rlim_cur - 0x2000) { - _exit(0); - } else { - _exit(4); - } -} - -int main(int argc, char ** argv) -{ - stack_t stk; - struct sigaction act; - - stk.ss_sp = sig_alt_stack; - stk.ss_size = SIGSTKSZ; - stk.ss_flags = 0; -#if defined(TARGET_i386) && defined(SYS_linux_elf) - act.sa_handler = (void (*)(int)) segv_handler; - act.sa_flags = SA_ONSTACK | SA_NODEFER; -#else - act.sa_sigaction = segv_handler; - act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER; -#endif - sigemptyset(&act.sa_mask); - system_stack_top = (char *) &act; - if (sigaltstack(&stk, NULL) != 0) { perror("sigaltstack"); return 2; } - if (sigaction(SIGSEGV, &act, NULL) != 0) { perror("sigaction"); return 2; } - /* We used to trigger a stack overflow at this point to test whether - the code above works, but this causes problems with POSIX threads - on some BSD systems. So, instead, we just test that all this - code compiles, indicating that the required syscalls are there. */ - return 0; -} diff --git a/config/auto-aux/tryassemble b/config/auto-aux/tryassemble index 06b9b27c..b6d5217c 100644 --- a/config/auto-aux/tryassemble +++ b/config/auto-aux/tryassemble @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2012 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 2012 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. * +#* * +#************************************************************************** if test "$verbose" = yes; then echo "tryassemble: $aspp -o tst $*" >&2 diff --git a/config/auto-aux/trycompile b/config/auto-aux/trycompile index 934a00a9..845061d7 100755 --- a/config/auto-aux/trycompile +++ b/config/auto-aux/trycompile @@ -1,17 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2002 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 2002 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. * +#* * +#************************************************************************** if test "$verbose" = yes; then echo "trycompile: $cc -o tst $* $cclibs" >&2 diff --git a/config/m-nt.h b/config/m-nt.h index a80b0ac5..900e3f09 100644 --- a/config/m-nt.h +++ b/config/m-nt.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Machine configuration, Intel x86 processors, Win32, Visual C++ or Mingw compiler */ @@ -40,4 +42,8 @@ #endif #define ARCH_INT64_PRINTF_FORMAT "I64" +#if defined(_MSC_VER) && !defined(__cplusplus) +#define inline __inline +#endif + #undef NONSTANDARD_DIV_MOD diff --git a/config/m-templ.h b/config/m-templ.h index a5497b56..74ce64e1 100644 --- a/config/m-templ.h +++ b/config/m-templ.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Processor dependencies */ diff --git a/config/s-nt.h b/config/s-nt.h index e8aa8785..79a716f2 100644 --- a/config/s-nt.h +++ b/config/s-nt.h @@ -1,20 +1,25 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Operating system dependencies, Intel x86 processors, Windows NT */ #define OCAML_OS_TYPE "Win32" +#ifdef __MINGW32__ +#define HAS_STDINT_H +#endif #undef BSD_SIGNALS #define HAS_STRERROR #define HAS_SOCKETS @@ -28,3 +33,4 @@ #define HAS_BROKEN_PRINTF #define HAS_IPV6 #define HAS_NICE +#define SUPPORT_DYNAMIC_LINKING diff --git a/config/s-templ.h b/config/s-templ.h index 383b4015..567f10b1 100644 --- a/config/s-templ.h +++ b/config/s-templ.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* Operating system and standard library dependencies. */ diff --git a/configure b/configure index 4ea1498c..0bb2d35f 100755 --- a/configure +++ b/configure @@ -1,17 +1,22 @@ #! /bin/sh -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +ocamlversion=`head -1 VERSION` +echo "Configuring OCaml version $ocamlversion" configure_options="$*" prefix=/usr/local @@ -37,16 +42,18 @@ dl_defs='' verbose=no with_curses=yes debugruntime=noruntimed +with_instrumented_runtime=false with_sharedlibs=yes -gcc_warnings="-Wall" partialld="ld -r" with_debugger=ocamldebugger with_ocamldoc=ocamldoc -with_ocamlbuild=ocamlbuild with_frame_pointers=false no_naked_pointers=false +native_compiler=true TOOLPREF="" with_cfi=true +flambda=false +max_testsuite_dir_retries=0 # Try to turn internationalization off, can cause config.guess to malfunction! unset LANG @@ -142,18 +149,24 @@ while : ; do verbose=yes;; -with-debug-runtime|--with-debug-runtime) debugruntime=runtimed;; + -with-instrumented-runtime|--with-instrumented-runtime) + with_instrumented_runtime=true;; -no-debugger|--no-debugger) with_debugger="";; -no-ocamldoc|--no-ocamldoc) with_ocamldoc="";; -no-ocamlbuild|--no-ocamlbuild) - with_ocamlbuild="";; + ;; # ignored for backward compatibility -with-frame-pointers|--with-frame-pointers) with_frame_pointers=true;; -no-naked-pointers|--no-naked-pointers) no_naked_pointers=true;; -no-cfi|--no-cfi) with_cfi=false;; + -no-native-compiler) + native_compiler=false;; + -flambda) + flambda=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 '=')." @@ -265,50 +278,13 @@ fi inf "Using compiler $cc." -# Check for buggy versions of GCC -# These checks are not done for cross-compilation (yet at least) because after -# 15 years, I doubt someone will try to use an experimental (2.96) or -# known-unstable (2.7.2.1) version for cross-compilation. - -buggycc="no" - -case "$target,$cc" in - i[3456]86-*-*,gcc*) - case `$cc --version` in - 2.7.2.1) cat <<'EOF' - -WARNING: you are using gcc version 2.7.2.1 on an Intel x86 processor. -This version of gcc is known to generate incorrect code for the -OCaml runtime system on some Intel x86 machines. (The symptom -is a crash of boot/ocamlc when compiling stdlib/pervasives.mli.) -In particular, the version of gcc 2.7.2.1 that comes with -Linux RedHat 4.x / Intel is affected by this problem. -Other Linux distributions might also be affected. -If you are using one of these configurations, you are strongly advised -to use another version of gcc, such as 2.95, which are -known to work well with OCaml. - -Press to proceed or to stop. -EOF - read reply;; - 2.96*) cat <<'EOF' - -WARNING: you are using gcc version 2.96 on an Intel x86 processor. -Certain patched versions of gcc 2.96 are known to generate incorrect -code for the OCaml runtime system. (The symptom is a segmentation -violation on boot/ocamlc.) Those incorrectly patched versions can be found -in RedHat 7.2 and Mandrake 8.0 and 8.1; other Linux distributions -might also be affected. (See bug #57760 on bugzilla.redhat.com) +# Determine the C compiler family (GCC, Clang, etc) -Auto-configuration will now select gcc compiler flags that work around -the problem. Still, if you observe segmentation faults while running -ocamlc or ocamlopt, you are advised to try another version of gcc, -such as 2.95.3 or 3.2. - -EOF - buggycc="gcc.2.96";; - - esac;; +ccfamily=`$cc -E cckind.c | grep '^[a-z]' | tr -s ' ' '-'` +case $? in + 0) inf "Compiler family and version: $ccfamily.";; + *) err "Unable to preprocess the test program.\n" \ + "Make sure the C compiler $cc is properly installed.";; esac # Configure the bytecode compiler @@ -325,17 +301,53 @@ iflexdir="" SO="so" TOOLCHAIN="cc" +# Choose reasonable options based on compiler kind +# We select high optimization levels, provided we can turn off: +# - strict type-based aliasing analysis (too risky for the OCaml runtime) +# - strict no-overflow conditions on signed integer arithmetic +# (the OCaml runtime assumes Java-style behavior of signed integer arith.) +# Concerning optimization level, -O3 is somewhat risky, so take -O2. +# Concerning language version, gnu99 is ISO C99 plus GNU extensions +# that are often used in standard headers. Older GCC versions +# defaults to gnu89, which is not C99. Clang defaults to gnu99 or +# gnu11, which is fine. + +case "$ocamlversion" in + *+dev*) gcc_warnings="-Wall -Werror";; + *) gcc_warnings="-Wall";; +esac + +case "$ccfamily" in + clang-*) + bytecccompopts="-O2 -fno-strict-aliasing -fwrapv $gcc_warnings";; + gcc-[012]-*) + # Some versions known to miscompile OCaml, e,g, 2.7.2.1, some 2.96. + # Plus: C99 support unknown. + err "This version of GCC is too old. Please use GCC version 4.2 or above.";; + gcc-3-*|gcc-4-[01]) + # No -fwrapv option before GCC 3.4. + # 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";; + gcc-*) + bytecccompopts="-std=gnu99 -O2 -fno-strict-aliasing -fwrapv $gcc_warnings";; + *) + bytecccompopts="-O";; +esac + +# Adjust according to target + case "$bytecc,$target" in cc,*-*-nextstep*) # GNU C extensions disabled, but __GNUC__ still defined! - bytecccompopts="-fno-defer-pop $gcc_warnings -U__GNUC__ -posix" + bytecccompopts="$bytecccompopts -U__GNUC__ -posix" bytecclinkopts="-posix";; *,*-*-rhapsody*) # Almost the same as NeXTStep - bytecccompopts="-fno-defer-pop $gcc_warnings -DSHRINKED_GNUC" + bytecccompopts="$bytecccompopts -DSHRINKED_GNUC" mathlib="";; *,*-*-darwin*) - bytecccompopts="$gcc_warnings" mathlib="" mkexe="$mkexe -Wl,-no_compact_unwind" # Tell gcc that we can use 32-bit code addresses for threaded code @@ -344,15 +356,12 @@ case "$bytecc,$target" in echo "# define ARCH_CODE32" >> m.h echo "#endif" >> m.h;; *,*-*-haiku*) - bytecccompopts="-fno-defer-pop $gcc_warnings" # No -lm library mathlib="";; *,*-*-beos*) - bytecccompopts="-fno-defer-pop $gcc_warnings" # No -lm library mathlib="";; *gcc,alpha*-*-osf*) - bytecccompopts="-fno-defer-pop $gcc_warnings" if cc="$bytecc" sh ./hasgot -mieee; then bytecccompopts="-mieee $bytecccompopts"; fi @@ -366,34 +375,26 @@ case "$bytecc,$target" in if cc="$bytecc" sh ./hasgot -mieee; then bytecccompopts="-mieee $bytecccompopts"; fi;; - cc,mips-*-irix6*) - # Add -n32 flag to ensure compatibility with native-code compiler - bytecccompopts="-n32" + *,mips-*-irix6*) # Turn off warning "unused library" bytecclinkopts="-n32 -Wl,-woff,84";; - cc*,mips-*-irix6*) - # (For those who want to force "cc -64") - # Turn off warning "unused library" - bytecclinkopts="-Wl,-woff,84";; *,alpha*-*-unicos*) # For the Cray T3E - bytecccompopts="-DUMK";; - *gcc*,powerpc-*-aix*) - # Avoid name-space pollution by requiring Unix98-conformant includes - bytecccompopts="-fno-defer-pop $gcc_warnings -D_XOPEN_SOURCE=500";; + bytecccompopts="$bytecccompopts -DUMK";; *,powerpc-*-aix*) - bytecccompopts="-D_XOPEN_SOURCE=500";; - *gcc*,*-*-cygwin*) + # Avoid name-space pollution by requiring Unix98-conformant includes + bytecccompopts="$bytecccompopts -D_XOPEN_SOURCE=500 -D_ALL_SOURCE";; + *,*-*-cygwin*) case $target in i686-*) flavor=cygwin;; x86_64-*) flavor=cygwin64;; *) err "unknown cygwin variant";; esac - bytecccompopts="-fno-defer-pop $gcc_warnings -U_WIN32" + 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 | dos2unix` + flexdir=`$flexlink -where | tr -d '\015'` if test -z "$flexdir"; then wrn "flexlink not found: native shared libraries won't be available." with_sharedlibs=no @@ -409,8 +410,7 @@ case "$bytecc,$target" in fi exe=".exe" ostype="Cygwin";; - *gcc*,*-*-mingw*) - bytecccompopts="-fno-defer-pop $gcc_warnings" + *,*-*-mingw*) dllccompopt="-DCAML_DLL" if test $with_sharedlibs = yes; then case "$target" in @@ -433,34 +433,33 @@ case "$bytecc,$target" in TOOLCHAIN="mingw" SO="dll" ;; - *gcc*,x86_64-*-linux*) - bytecccompopts="-fno-defer-pop $gcc_warnings" + *,x86_64-*-linux*) # Tell gcc that we can use 32-bit code addresses for threaded code # unless we are compiled for a shared library (-fPIC option) echo "#ifndef __PIC__" >> m.h echo "# define ARCH_CODE32" >> m.h echo "#endif" >> m.h;; - *gcc*) - bytecccompopts="-fno-defer-pop $gcc_warnings";; esac -# Configure compiler to use in further tests +# Configure compiler to use in further tests. -cc="$bytecc -O $bytecclinkopts" +cc="$bytecc $bytecclinkopts" export cc cclibs verbose -# Check C compiler +# Check C compiler. -sh ./runtest ansi.c +cc="$bytecc $bytecccompopts $bytecclinkopts" sh ./runtest ansi.c case $? in - 0) inf "The C compiler is ANSI-compliant." ;; - 1) err "The C compiler $cc is not ANSI-compliant.\n" \ - "You need an ANSI C compiler to build OCaml.";; + 0) inf "The C compiler is ISO C99 compliant." ;; + 1) wrn "The C compiler is ANSI / ISO C90 compliant, but not ISO C99" \ + "compliant.";; + 2) err "The C compiler $cc is not ISO C compliant.\n" \ + "You need an ISO C99 compiler to build OCaml.";; *) if $cross_compiler; then wrn "Unable to compile the test program.\n" \ "This failure is expected for cross-compilation:\n" \ - "we will assume the C compiler is ANSI-compliant." + "we will assume the C compiler is ISO C99-compliant." else err "Unable to compile the test program.\n" \ "Make sure the C compiler $cc is properly installed." @@ -479,8 +478,8 @@ if $cross_compiler; then ocaml_source_version=`sed -n '1 s/\([0-9\.]*\).*/\1/ p' < ../../VERSION` if test x"$ocaml_system_version" != x"$ocaml_source_version"; then err "While you have an ocaml runtime environment, its version\n" \ - "($ocaml_system_version) doesn't match the version of these sources\n" \ - "($ocaml_source_version)." + "($ocaml_system_version) doesn't match the version of these\n" \ + "sources ($ocaml_source_version)." else echo "CAMLRUN=`./searchpath -p ocamlrun`" >> Makefile fi @@ -491,7 +490,8 @@ if $cross_compiler; then else ocamlyacc 2>/dev/null if test "$?" -ne 1; then - err "While you have an ocamlyacc binary, it cannot be executed successfully." + err "While you have an ocamlyacc binary, it cannot be executed" \ + "successfully." else echo "CAMLYACC=`./searchpath -p ocamlyacc`" >> Makefile fi @@ -573,13 +573,14 @@ case $? in echo "#define ARCH_BIG_ENDIAN" >> m.h;; 1) inf "This is a little-endian architecture." echo "#undef ARCH_BIG_ENDIAN" >> m.h;; - 2) err "This architecture seems to be neither big endian nor little endian.\n" \ - "OCaml won't run on this architecture.";; + 2) err "This architecture seems to be neither big endian nor little" \ + "endian.\n OCaml won't run on this architecture.";; *) case $target in *-*-mingw*) inf "This is a little-endian architecture." echo "#undef ARCH_BIG_ENDIAN" >> m.h;; *) wrn "Something went wrong during endianness determination.\n" \ - "You will have to figure out endianness yourself (option ARCH_BIG_ENDIAN in m.h).";; + "You will have to figure out endianness yourself\n" \ + "(option ARCH_BIG_ENDIAN in m.h).";; esac;; esac @@ -612,7 +613,8 @@ case "$target" in *) case "$target" in *-*-mingw*) inf "Doubles can be word-aligned." echo "#undef ARCH_ALIGN_DOUBLE" >> m.h;; - *) wrn "Something went wrong during alignment determination for doubles.\n" \ + *) wrn "Something went wrong during alignment determination for" \ + "doubles.\n" \ "We will assume alignment constraints over doubles.\n" \ "That's a safe bet: OCaml will work even if\n" \ "this architecture actually has no alignment constraints." @@ -648,32 +650,12 @@ case "$target" in esac esac -# Check semantics of division and modulus - -sh ./runtest divmod.c -case $? in - 0) inf "Native division and modulus have round-towards-zero semantics," \ - "will use them." - echo "#undef NONSTANDARD_DIV_MOD" >> m.h;; - 1) inf "Native division and modulus do not have round-towards-zero" - "semantics, will use software emulation." - echo "#define NONSTANDARD_DIV_MOD" >> m.h;; - *) case $target in - *-*-mingw*) inf "Native division and modulus have round-towards-zero" \ - "semantics, will use them." - echo "#undef NONSTANDARD_DIV_MOD" >> m.h;; - *) wrn "Something went wrong while checking native division and modulus"\ - "please report it at http://http://caml.inria.fr/mantis/" - echo "#define NONSTANDARD_DIV_MOD" >> m.h;; - esac;; -esac - # Shared library support shared_libraries_supported=false dl_needs_underscore=false sharedcccompopts='' -mksharedlib='' +mksharedlib='shared-libs-not-available' byteccrpath='' mksharedlibrpath='' natdynlinkopts="" @@ -688,7 +670,8 @@ 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*|*-*-gnu*|*-*-haiku*) + *-*-linux-gnu|*-*-linux|*-*-freebsd[3-9]*|*-*-freebsd[1-9][0-9]*\ + |*-*-openbsd*|*-*-netbsd*|*-*-gnu*|*-*-haiku*) sharedcccompopts="-fPIC" mksharedlib="$bytecc -shared" bytecclinkopts="$bytecclinkopts -Wl,-E" @@ -716,7 +699,7 @@ if test $with_sharedlibs = "yes"; then *gcc*) sharedcccompopts="-fPIC" if sh ./solaris-ld; then - mksharedlib="$bytecc -shared" + mksharedlib="ld -G" byteccrpath="-R" mksharedlibrpath="-R" else @@ -744,12 +727,14 @@ if test $with_sharedlibs = "yes"; then mksharedlibrpath="-rpath " shared_libraries_supported=true;; i[3456]86-*-darwin[89].*) - mksharedlib="$bytecc -bundle -flat_namespace -undefined suppress -read_only_relocs suppress" + mksharedlib="$bytecc -bundle -flat_namespace -undefined suppress \ + -read_only_relocs suppress" bytecccompopts="$dl_defs $bytecccompopts" dl_needs_underscore=false shared_libraries_supported=true;; *-apple-darwin*) - mksharedlib="$bytecc -bundle -flat_namespace -undefined suppress -Wl,-no_compact_unwind" + mksharedlib="$bytecc -bundle -flat_namespace -undefined suppress \ + -Wl,-no_compact_unwind" bytecccompopts="$dl_defs $bytecccompopts" dl_needs_underscore=false shared_libraries_supported=true;; @@ -789,6 +774,7 @@ if test $with_sharedlibs = "yes"; then natdynlink=true fi;; x86_64-*-darwin*) natdynlink=true;; + s390x*-*-linux*) natdynlink=true;; powerpc*-*-linux*) natdynlink=true;; sparc*-*-linux*) natdynlink=true;; i686-*-kfreebsd*) natdynlink=true;; @@ -803,6 +789,7 @@ if test $with_sharedlibs = "yes"; then i[3456]86-*-haiku*) natdynlink=true;; arm*-*-linux*) natdynlink=true;; arm*-*-freebsd*) natdynlink=true;; + earm*-*-netbsd*) natdynlink=true;; aarch64-*-linux*) natdynlink=true;; esac fi @@ -843,18 +830,21 @@ case "$target" in fi;; i[3456]86-*-gnu*) arch=i386; system=gnu;; i[3456]86-*-mingw*) arch=i386; system=mingw;; - powerpc*-*-linux*) arch=power; model=ppc; system=elf;; + powerpc64le*-*-linux*) arch=power; model=ppc64le; system=elf;; + powerpc*-*-linux*) arch=power; + if $arch64; then model=ppc64; else model=ppc; fi + system=elf;; powerpc-*-netbsd*) arch=power; model=ppc; system=elf;; powerpc-*-openbsd*) arch=power; model=ppc; system=bsd_elf;; - powerpc-*-rhapsody*) arch=power; model=ppc; system=rhapsody;; - powerpc-*-darwin*) arch=power; system=rhapsody - if $arch64;then model=ppc64;else model=ppc;fi;; + s390x*-*-linux*) arch=s390x; model=z10; system=elf;; armv6*-*-linux-gnueabihf) arch=arm; model=armv6; system=linux_eabihf;; arm*-*-linux-gnueabihf) arch=arm; system=linux_eabihf;; armv7*-*-linux-gnueabi) arch=arm; model=armv7; system=linux_eabi;; armv6t2*-*-linux-gnueabi) arch=arm; model=armv6t2; system=linux_eabi;; armv6*-*-linux-gnueabi) arch=arm; model=armv6; system=linux_eabi;; armv6*-*-freebsd*) arch=arm; model=armv6; system=freebsd;; + earmv6*-*-netbsd*) arch=arm; model=armv6; system=netbsd;; + earmv7*-*-netbsd*) arch=arm; model=armv7; system=netbsd;; armv5te*-*-linux-gnueabi) arch=arm; model=armv5te; system=linux_eabi;; armv5*-*-linux-gnueabi) arch=arm; model=armv5; system=linux_eabi;; arm*-*-linux-gnueabi) arch=arm; system=linux_eabi;; @@ -873,14 +863,19 @@ esac # Some platforms exist both in 32-bit and 64-bit variants, not distinguished # by $target. Turn off native code compilation on platforms where 64-bit mode -# is not supported. (PR#4441) +# is not supported (PR#4441). +# Sometimes, it's 32-bit mode that is not supported (PR#6722). -if $arch64; then - case "$arch,$model" in - sparc,default|power,ppc) +case "$arch64,$arch,$model" in + true,sparc,*|true,power,ppc|false,amd64,*) arch=none; model=default; system=unknown;; - esac -fi +esac + +case "$native_compiler" in + true) ;; + false) + arch=none; model=default; system=unknown; natdynlink=false;; +esac if test -z "$ccoption"; then nativecc="$bytecc" @@ -888,23 +883,21 @@ else nativecc="$ccoption" fi -nativecccompopts='' +nativecccompopts="$bytecccompopts" +nativeccprofopts='' nativecclinkopts='' # FIXME the naming of nativecclinkopts is broken: these are options for # ld (for shared libs), not for cc nativeccrpath="$byteccrpath" -case "$arch,$nativecc,$system,$target" in - *,*,nextstep,*) nativecccompopts="$gcc_warnings -U__GNUC__ -posix" - nativecclinkopts="-posix";; - *,*,rhapsody,*darwin[1-5].*) - nativecccompopts="$gcc_warnings -DSHRINKED_GNUC";; - *,*,rhapsody,*) nativecccompopts="$gcc_warnings -DDARWIN_VERSION_6 $dl_defs" - if $arch64; then partialld="ld -r -arch ppc64"; fi;; - *,gcc*,cygwin,*) nativecccompopts="$gcc_warnings -U_WIN32";; +case "$arch,$nativecc,$system,$model" in + *,*,nextstep,*) nativecclinkopts="-posix";; + *,*,rhapsody,*) if $arch64; then partialld="ld -r -arch ppc64"; fi;; amd64,gcc*,macosx,*) partialld="ld -r -arch x86_64";; amd64,gcc*,solaris,*) partialld="ld -r -m elf_x86_64";; - *,gcc*,*,*) nativecccompopts="$gcc_warnings";; + power,gcc*,elf,ppc) partialld="ld -r -m elf32ppclinux";; + power,gcc*,elf,ppc64) partialld="ld -r -m elf64ppc";; + power,gcc*,elf,ppc64le) partialld="ld -r -m elf64lppc";; esac asppprofflags='-DPROFILING' @@ -921,10 +914,15 @@ case "$arch,$system" in aspp="${TOOLPREF}gcc -m64 -c";; i386,solaris) as="${TOOLPREF}as" aspp="/usr/ccs/bin/${TOOLPREF}as -P";; - power,elf) as="${TOOLPREF}as -u -m ppc" - aspp="${TOOLPREF}gcc -c";; - power,rhapsody) as="${TOOLPREF}as -arch $model" - aspp="$bytecc -c";; + power,elf) if $arch64; then + as="${TOOLPREF}as -a64 -mppc64" + aspp="${TOOLPREF}gcc -m64 -c" + else + as="${TOOLPREF}as -mppc" + aspp="${TOOLPREF}gcc -m32 -c" + fi;; + s390x,elf) as="${TOOLPREF}as -m 64 -march=$model" + aspp="${TOOLPREF}gcc -c -Wa,-march=$model";; sparc,solaris) as="${TOOLPREF}as" case "$cc" in *gcc*) aspp="${TOOLPREF}gcc -c";; @@ -957,6 +955,7 @@ case "$arch,$system" in 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';; @@ -1064,6 +1063,24 @@ if test "$with_curses" = "yes"; then done fi +# For instrumented runtime +# (clock_gettime needs -lrt for glibc before 2.17) +if $with_instrumented_runtime; then + with_instrumented_runtime=false #enabled it only if found + for libs in "" "-lrt"; do + if sh ./hasgot $libs clock_gettime; then + inf "clock_gettime functions found (with libraries '$libs')" + instrumented_runtime_libs="${libs}" + with_instrumented_runtime=true; + break + fi + done + if ! $with_instrumented_runtime; then + err "clock_gettime functions not found. " \ + "Instrumented runtime can't be built." + fi +fi + # Configuration for the libraries case "$system" in @@ -1123,6 +1140,11 @@ if sh ./hasgot -i sys/types.h -i sys/socket.h -i netinet/in.h \ echo "#define HAS_IPV6" >> s.h fi +if sh ./hasgot -i stdint.h; then + inf "stdint.h found." + echo "#define HAS_STDINT_H" >> s.h +fi + if sh ./hasgot -i unistd.h; then inf "unistd.h found." echo "#define HAS_UNISTD" >> s.h @@ -1332,7 +1354,9 @@ fi nanosecond_stat=none for i in 1 2 3; do - if sh ./trycompile -DHAS_NANOSECOND_STAT=$i nanosecond_stat.c; then nanosecond_stat=$i; break; fi + if sh ./trycompile -DHAS_NANOSECOND_STAT=$i nanosecond_stat.c; then + nanosecond_stat=$i; break + fi done if test $nanosecond_stat != "none"; then inf "stat() supports nanosecond precision." @@ -1341,7 +1365,10 @@ fi nargs=none for i in 5 6; do - if sh ./trycompile -DNUM_ARGS=${i} gethostbyname.c; then nargs=$i; break; fi + if sh ./trycompile -DSYS_${system} -DNUM_ARGS=${i} gethostbyname.c; then + nargs=$i; + break; + fi done if test $nargs != "none"; then inf "gethostbyname_r() found (with ${nargs} arguments)." @@ -1350,7 +1377,10 @@ fi nargs=none for i in 7 8; do - if sh ./trycompile -DNUM_ARGS=${i} gethostbyaddr.c; then nargs=$i; break; fi + if sh ./trycompile -DSYS_${system} -DNUM_ARGS=${i} gethostbyaddr.c; then + nargs=$i; + break; + fi done if test $nargs != "none"; then inf "gethostbyaddr_r() found (with ${nargs} arguments)." @@ -1648,9 +1678,21 @@ if sh ./hasgot -DPACKAGE=ocaml -i bfd.h && \ inf "BFD library found." echo "#define HAS_LIBBFD" >> s.h echo "LIBBFD_LINK=-lbfd -ldl -liberty -lz" >> Makefile + echo LIBBFD_INCLUDE= >>Makefile +elif sh ./hasgot -DPACKAGE=ocaml -I/opt/local/include -i bfd.h && \ + sh ./hasgot -DPACKAGE=ocaml -L/opt/local/lib -lbfd -ldl \ + -liberty -lz -lintl bfd_openr +then + # MacOSX with binutils from MacPorts + inf "BFD library found." + echo "#define HAS_LIBBFD" >> s.h + echo "LIBBFD_LINK=-L/opt/local/lib -lbfd -ldl -liberty -lz -lintl" >> Makefile + echo LIBBFD_INCLUDE=-I/opt/local/include >>Makefile else - wrn "BFD library not found, 'objinfo' will be unable to display info on .cmxs files." + wrn "BFD library not found, 'objinfo' will be unable to display info" \ + " on .cmxs files." echo "LIBBFD_LINK=" >> Makefile + echo "LIBBFD_INCLUDE=" >> Makefile fi # Check whether assembler supports CFI directives @@ -1679,27 +1721,21 @@ if test "$with_frame_pointers" = "true"; then ;; *) err "Unsupported architecture with frame pointers";; esac - fi if $no_naked_pointers; then echo "#define NO_NAKED_POINTERS" >> m.h fi -# Add Unix-style optimization flag -bytecccompopts="-O $bytecccompopts" -dllcccompopts="-O $dllcccompopts" -nativecccompopts="-O $nativecccompopts" -sharedcccompopts="-O $sharedcccompopts" - -# Final twiddling of compiler options to work around known bugs - -nativeccprofopts="$nativecccompopts" -case "$buggycc" in - gcc.2.96) - bytecccompopts="$bytecccompopts -fomit-frame-pointer" - nativecccompopts="$nativecccompopts -fomit-frame-pointer";; -esac +# Check for mmap support for huge pages and contiguous heap +if sh ./runtest mmap-huge.c; then + has_huge_pages=true + echo "#define HAS_HUGE_PAGES" >>s.h + echo "#define HUGE_PAGE_SIZE (4 * 1024 * 1024)" >>s.h + inf "mmap supports huge pages" +else + has_huge_pages=false +fi # Finish generated files @@ -1708,7 +1744,8 @@ cclibs="$cclibs $mathlib" echo "BYTECC=$bytecc" >> Makefile echo "BYTECCCOMPOPTS=$bytecccompopts" >> Makefile echo "BYTECCLINKOPTS=$bytecclinkopts" >> Makefile -echo "BYTECCLIBS=$cclibs $dllib $curseslibs $pthread_link" >> Makefile +echo "BYTECCLIBS=$cclibs $dllib $curseslibs $pthread_link \ + $instrumented_runtime_libs" >> Makefile echo "BYTECCRPATH=$byteccrpath" >> Makefile echo "EXE=$exe" >> Makefile echo "SUPPORTS_SHARED_LIBRARIES=$shared_libraries_supported" >> Makefile @@ -1721,7 +1758,9 @@ SYSLIB=-l\$(1) ### How to build a static library MKLIB=${TOOLPREF}ar rc \$(1) \$(2); ${TOOLPREF}ranlib \$(1) -#ml let mklib out files opts = Printf.sprintf "${TOOLPREF}ar rc %s %s %s; ${TOOLPREF}ranlib %s" out opts files out;; +#ml let mklib out files opts = (* "" *) +#ml Printf.sprintf "${TOOLPREF}ar rc %s %s %s; ${TOOLPREF}ranlib %s" +#ml out opts files out;; EOF echo "ARCH=$arch" >> Makefile echo "MODEL=$model" >> Makefile @@ -1767,9 +1806,9 @@ if $shared_libraries_supported; then 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 "WITH_OCAMLBUILD=${with_ocamlbuild}" >>Makefile echo "ASM_CFI_SUPPORTED=$asm_cfi_supported" >> Makefile echo "WITH_FRAME_POINTERS=$with_frame_pointers" >> Makefile echo "TARGET=$target" >> Makefile @@ -1777,6 +1816,8 @@ echo "HOST=$host" >> Makefile if [ "$ostype" = Cygwin ]; then echo "DIFF=diff -q --strip-trailing-cr" >>Makefile fi +echo "FLAMBDA=$flambda" >> Makefile +echo "MAX_TESTSUITE_DIR_RETRIES=$max_testsuite_dir_retries" >> Makefile rm -f tst hasgot.c @@ -1796,11 +1837,13 @@ inf " manual pages.............. $mandir (with extension .$manext)" inf "Configuration for the bytecode compiler:" inf " C compiler used........... $bytecc" inf " options for compiling..... $bytecccompopts" -inf " options for linking....... $bytecclinkopts $cclibs $dllib $curseslibs $pthread_link" +inf " options for linking....... $bytecclinkopts $cclibs $dllib" \ + "$curseslibs $pthread_link" if $shared_libraries_supported; then inf " shared libraries are supported" inf " options for compiling..... $sharedcccompopts $bytecccompopts" -inf " command for building...... $mksharedlib -o lib.so $mksharedlibrpath/a/path objs" +inf " command for building...... $mksharedlib -o lib.so" \ + "$mksharedlibrpath/a/path objs" else inf " shared libraries not supported" fi @@ -1843,6 +1886,11 @@ else else inf " profiling with gprof ..... not supported" fi + if test "$flambda" = "true"; then + inf " using flambda middle-end . yes" + else + inf " using flambda middle-end . no" + fi fi if test "$with_debugger" = "ocamldebugger"; then @@ -1855,6 +1903,10 @@ if test "$debugruntime" = "runtimed"; then inf "Debug runtime will be compiled and installed" fi +if $with_instrumented_runtime; then + inf "Instrumented runtime will be compiled and installed" +fi + inf "Additional libraries supported:" inf " $otherlibraries" diff --git a/debugger/.ignore b/debugger/.ignore deleted file mode 100644 index 45eec7cc..00000000 --- a/debugger/.ignore +++ /dev/null @@ -1,7 +0,0 @@ -lexer.ml -parser.ml -parser.mli -ocamldebug -ocamldebug.exe -dynlink.ml -dynlink.mli diff --git a/debugger/Makefile b/debugger/Makefile index 75f4aa8e..d0ac2565 100644 --- a/debugger/Makefile +++ b/debugger/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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. * +#* * +#************************************************************************** UNIXDIR=../otherlibs/$(UNIXLIB) include Makefile.shared diff --git a/debugger/Makefile.nt b/debugger/Makefile.nt index 4182c7c7..86a6d00d 100644 --- a/debugger/Makefile.nt +++ b/debugger/Makefile.nt @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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. * +#* * +#************************************************************************** UNIXDIR=../otherlibs/win32unix include Makefile.shared diff --git a/debugger/Makefile.shared b/debugger/Makefile.shared index f3859c63..520f883d 100644 --- a/debugger/Makefile.shared +++ b/debugger/Makefile.shared @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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 @@ -30,10 +33,15 @@ INCLUDES=\ OTHEROBJS=\ $(UNIXDIR)/unix.cma \ - ../utils/misc.cmo ../utils/config.cmo ../utils/tbl.cmo \ - ../utils/clflags.cmo ../utils/consistbl.cmo ../utils/warnings.cmo \ + ../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 \ @@ -86,7 +94,7 @@ ocamldebug$(EXE): $(OBJS) $(OTHEROBJS) $(CAMLC) $(LINKFLAGS) -o ocamldebug$(EXE) -linkall $(OTHEROBJS) $(OBJS) install: - cp ocamldebug$(EXE) $(INSTALL_BINDIR)/ocamldebug$(EXE) + cp ocamldebug$(EXE) "$(INSTALL_BINDIR)/ocamldebug$(EXE)" clean:: rm -f ocamldebug$(EXE) diff --git a/debugger/breakpoints.ml b/debugger/breakpoints.ml index de4c95bd..587b9164 100644 --- a/debugger/breakpoints.ml +++ b/debugger/breakpoints.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (******************************* Breakpoints ***************************) diff --git a/debugger/breakpoints.mli b/debugger/breakpoints.mli index ef518852..2d5a8d87 100644 --- a/debugger/breakpoints.mli +++ b/debugger/breakpoints.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (******************************* Breakpoints ***************************) diff --git a/debugger/checkpoints.ml b/debugger/checkpoints.ml index f0df2389..7ab8de72 100644 --- a/debugger/checkpoints.ml +++ b/debugger/checkpoints.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (*************************** Checkpoints *******************************) diff --git a/debugger/checkpoints.mli b/debugger/checkpoints.mli index 95eaf1b0..f3ca1380 100644 --- a/debugger/checkpoints.mli +++ b/debugger/checkpoints.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (***************************** Checkpoints *****************************) diff --git a/debugger/command_line.ml b/debugger/command_line.ml index b4f9f693..4cb6a4fc 100644 --- a/debugger/command_line.ml +++ b/debugger/command_line.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************ Reading and executing commands ***************) @@ -77,7 +80,7 @@ let error text = let check_not_windows feature = match Sys.os_type with | "Win32" -> - error ("'"^feature^"' feature not supported on Windows") + error ("\'"^feature^"\' feature not supported on Windows") | _ -> () @@ -124,7 +127,7 @@ let add_breakpoint_at_pc pc = new_breakpoint (any_event_at_pc pc) with | Not_found -> - eprintf "Can't add breakpoint at pc %i: no event there.@." pc; + eprintf "Can\'t add breakpoint at pc %i: no event there.@." pc; raise Toplevel let add_breakpoint_after_pc pc = @@ -137,7 +140,7 @@ let add_breakpoint_after_pc pc = try_add (n+1) end else begin error - "Can't add breakpoint at beginning of function: no event there" + "Can\'t add breakpoint at beginning of function: no event there" end in try_add 0 @@ -150,9 +153,9 @@ let convert_module mdle = match mdle with | Some m -> (* Strip .ml extension if any, and capitalize *) - String.capitalize(if Filename.check_suffix m ".ml" - then Filename.chop_suffix m ".ml" - else m) + String.capitalize_ascii(if Filename.check_suffix m ".ml" + then Filename.chop_suffix m ".ml" + else m) | None -> try (get_current_event ()).ev_module @@ -185,7 +188,7 @@ let interprete_line ppf line = with | Parsing.Parse_error -> error "Syntax error." - | Failure "int_of_string" -> + | Lexer.Int_overflow -> error "Integer overflow" let line_loop ppf line_buffer = @@ -270,7 +273,7 @@ let instr_dir ppf lexbuf = let new_directory' = List.rev new_directory in match new_directory' with | mdl :: for_keyw :: tl - when (String.lowercase for_keyw) = "for" && (List.length tl) > 0 -> + when String.lowercase_ascii for_keyw = "for" && List.length tl > 0 -> List.iter (function x -> add_path_for mdl (expand_path x)) tl | _ -> List.iter (function x -> add_path (expand_path x)) new_directory' @@ -291,6 +294,11 @@ let instr_kill ppf lexbuf = show_no_point() end +let instr_pid ppf lexbuf = + eol lexbuf; + if not !loaded then error "The program is not being run."; + fprintf ppf "@[%d@]@." !current_checkpoint.c_pid + let instr_run ppf lexbuf = eol lexbuf; ensure_loaded (); @@ -514,13 +522,37 @@ let instr_print ppf lexbuf = print_command !max_printer_depth ppf lexbuf let instr_display ppf lexbuf = print_command 1 ppf lexbuf +let instr_address ppf lexbuf = + let exprs = expression_list_eol Lexer.lexeme lexbuf in + ensure_loaded (); + let env = + try + env_of_event !selected_event + with + | Envaux.Error msg -> + Envaux.report_error ppf msg; + raise Toplevel + in + let print_addr expr = + let (v, _ty) = + try Eval.expression !selected_event env expr + with Eval.Error msg -> + Eval.report_error ppf msg; + raise Toplevel + in + match Remote_value.pointer v with + | "" -> fprintf ppf "[not a remote value]@." + | s -> fprintf ppf "0x%s@." s + in + List.iter print_addr exprs + (* Loading of command files *) let extract_filename arg = (* Allow enclosing filename in quotes *) let l = String.length arg in - let pos1 = if l > 0 && arg.[0] = '"' then 1 else 0 in - let pos2 = if l > 0 && arg.[l-1] = '"' then l-1 else l in + let pos1 = if l > 0 && arg.[0] = '\"' then 1 else 0 in + let pos2 = if l > 0 && arg.[l-1] = '\"' then l-1 else l in String.sub arg pos1 (pos2 - pos1) let instr_source ppf lexbuf = @@ -581,7 +613,7 @@ let instr_break ppf lexbuf = | Some ev -> new_breakpoint ev | None -> - error "Can't add breakpoint at this point.") + error "Can\'t add breakpoint at this point.") | BA_pc pc -> (* break PC *) add_breakpoint_at_pc pc | BA_function expr -> (* break FUNCTION *) @@ -627,7 +659,7 @@ let instr_break ppf lexbuf = event_near_pos module_name (point_of_coord buffer line col) with | Not_found -> (* event_at_pos / event_near pos *) - eprintf "Can't find any event there.@."; + eprintf "Can\'t find any event there.@."; raise Toplevel | Out_of_range -> (* pos_of_line / point_of_coord *) eprintf "Position out of range.@."; @@ -639,7 +671,7 @@ let instr_break ppf lexbuf = position) with | Not_found -> - eprintf "Can't find any event there.@." + eprintf "Can\'t find any event there.@." let instr_delete ppf lexbuf = match integer_list_eol Lexer.lexeme lexbuf with @@ -748,7 +780,11 @@ let instr_list ppf lexbuf = | Not_found -> ("", -1, -1) in - let mdle = convert_module (module_of_longident mo) in + let mdle = + match mo with + | None -> curr_mod + | _ -> convert_module (module_of_longident mo) + in let pos = Lexing.dummy_pos in let buffer = try get_buffer pos mdle with @@ -991,6 +1027,12 @@ With no argument, reset the search path." }; { instr_name = "kill"; instr_prio = false; instr_action = instr_kill; instr_repeat = true; instr_help = "kill the program being debugged." }; + { instr_name = "pid"; instr_prio = false; + instr_action = instr_pid; instr_repeat = true; instr_help = +"print the process ID of the current active process." }; + { instr_name = "address"; instr_prio = false; + instr_action = instr_address; instr_repeat = true; instr_help = +"print the raw address of a value." }; { instr_name = "help"; instr_prio = false; instr_action = instr_help; instr_repeat = true; instr_help = "print list of commands." }; @@ -1124,7 +1166,7 @@ using \"load_printer\"." }; "mode of loading.\n\ It can be either:\n\ direct: the program is directly called by the debugger.\n\ - runtime: the debugger execute `ocamlrun programname arguments'.\n\ + runtime: the debugger execute `ocamlrun programname arguments\'.\n\ manual: the program is not launched by the debugger,\n\ but manually by the user." }; { var_name = "processcount"; diff --git a/debugger/command_line.mli b/debugger/command_line.mli index f7fb1605..dc3a8d51 100644 --- a/debugger/command_line.mli +++ b/debugger/command_line.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************ Reading and executing commands ***************) diff --git a/debugger/debugcom.ml b/debugger/debugcom.ml index 8bfd3aab..a8079cbc 100644 --- a/debugger/debugcom.ml +++ b/debugger/debugcom.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Low-level communication with the debuggee *) @@ -293,4 +296,14 @@ module Remote_value = (* string equality -> equality of remote pointers *) | (_, _) -> false + let pointer rv = + match rv with + | Remote v -> + let bytes = ref [] in + String.iter (fun c -> bytes := c :: !bytes) v; + let obytes = if Sys.big_endian then List.rev !bytes else !bytes in + let to_hex c = Printf.sprintf "%02x" (Char.code c) in + String.concat "" (List.map to_hex obytes) + | Local _ -> "" + end diff --git a/debugger/debugcom.mli b/debugger/debugcom.mli index 3dce2abb..6f94df5c 100644 --- a/debugger/debugcom.mli +++ b/debugger/debugcom.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Low-level communication with the debuggee *) @@ -105,4 +108,7 @@ module Remote_value : val accu : unit -> t val closure_code : t -> int + (* Returns a hexadecimal representation of the remote address, + or [""] if the value is local. *) + val pointer : t -> string end diff --git a/debugger/debugger_config.ml b/debugger/debugger_config.ml index a16fdca2..194a13dd 100644 --- a/debugger/debugger_config.ml +++ b/debugger/debugger_config.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (**************************** Configuration file ***********************) diff --git a/debugger/debugger_config.mli b/debugger/debugger_config.mli index ab935d93..74c6d5f3 100644 --- a/debugger/debugger_config.mli +++ b/debugger/debugger_config.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (********************** Configuration file *****************************) diff --git a/debugger/eval.ml b/debugger/eval.ml index 1d1ab388..e4e9aaf1 100644 --- a/debugger/eval.ml +++ b/debugger/eval.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Misc open Path diff --git a/debugger/eval.mli b/debugger/eval.mli index c5e04f33..51d27136 100644 --- a/debugger/eval.mli +++ b/debugger/eval.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Types open Parser_aux diff --git a/debugger/events.ml b/debugger/events.ml index c622f672..a50eae0d 100644 --- a/debugger/events.ml +++ b/debugger/events.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (********************************* Events ******************************) diff --git a/debugger/events.mli b/debugger/events.mli index e593be03..f50f156e 100644 --- a/debugger/events.mli +++ b/debugger/events.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Instruct diff --git a/debugger/exec.ml b/debugger/exec.ml index 931c0a91..0fc59528 100644 --- a/debugger/exec.ml +++ b/debugger/exec.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Handling of keyboard interrupts *) diff --git a/debugger/exec.mli b/debugger/exec.mli index a820589b..05e2e5f8 100644 --- a/debugger/exec.mli +++ b/debugger/exec.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Handling of keyboard interrupts *) diff --git a/debugger/frames.ml b/debugger/frames.ml index d3456284..2db2e1b1 100644 --- a/debugger/frames.ml +++ b/debugger/frames.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (***************************** Frames **********************************) diff --git a/debugger/frames.mli b/debugger/frames.mli index fa652b0c..faaf516b 100644 --- a/debugger/frames.mli +++ b/debugger/frames.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (****************************** Frames *********************************) diff --git a/debugger/history.ml b/debugger/history.ml index 4d08f587..0ece812b 100644 --- a/debugger/history.ml +++ b/debugger/history.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Int64ops open Checkpoints diff --git a/debugger/history.mli b/debugger/history.mli index 121c732f..a184e7b9 100644 --- a/debugger/history.mli +++ b/debugger/history.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) val empty_history : unit -> unit diff --git a/debugger/input_handling.ml b/debugger/input_handling.ml index f3bd57b6..91f4cc50 100644 --- a/debugger/input_handling.ml +++ b/debugger/input_handling.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (**************************** Input control ****************************) diff --git a/debugger/input_handling.mli b/debugger/input_handling.mli index 66db47f1..e333c785 100644 --- a/debugger/input_handling.mli +++ b/debugger/input_handling.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (***************************** Input control ***************************) diff --git a/debugger/int64ops.ml b/debugger/int64ops.ml index 527bdcef..7f6df618 100644 --- a/debugger/int64ops.ml +++ b/debugger/int64ops.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocqencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocqencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (****************** arithmetic operators for Int64 *********************) diff --git a/debugger/int64ops.mli b/debugger/int64ops.mli index 5491c8f7..29d69bd1 100644 --- a/debugger/int64ops.mli +++ b/debugger/int64ops.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocqencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocqencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (****************** arithmetic operators for Int64 *********************) diff --git a/debugger/lexer.mli b/debugger/lexer.mli index 7508bedd..41424dd2 100644 --- a/debugger/lexer.mli +++ b/debugger/lexer.mli @@ -1,15 +1,20 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +exception Int_overflow val line: Lexing.lexbuf -> string val lexeme: Lexing.lexbuf -> Parser.token diff --git a/debugger/lexer.mll b/debugger/lexer.mll index 721645c8..133d2732 100644 --- a/debugger/lexer.mll +++ b/debugger/lexer.mll @@ -1,20 +1,25 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) { open Parser +exception Int_overflow + } rule line = (* Read a whole line *) @@ -63,7 +68,9 @@ and lexeme = (* Read a lexeme *) | '0' ['x' 'X'] ['0'-'9' 'A'-'F' 'a'-'f']+ | '0' ['o' 'O'] ['0'-'7']+ | '0' ['b' 'B'] ['0'-'1']+ - { INTEGER (Int64.of_string (Lexing.lexeme lexbuf)) } + { try INTEGER (Int64.of_string (Lexing.lexeme lexbuf)) + with Failure _ -> raise Int_overflow + } | '*' { STAR } | "-" diff --git a/debugger/loadprinter.ml b/debugger/loadprinter.ml index 98e79d79..113ae89f 100644 --- a/debugger/loadprinter.ml +++ b/debugger/loadprinter.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1997 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1997 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. *) +(* *) +(**************************************************************************) (* Loading and installation of user-defined printer functions *) @@ -70,12 +73,15 @@ let rec loadfiles ppf name = true with | Dynlink.Error (Dynlink.Unavailable_unit unit) -> - loadfiles ppf (String.uncapitalize unit ^ ".cmo") + loadfiles ppf (String.uncapitalize_ascii unit ^ ".cmo") && loadfiles ppf name | Not_found -> fprintf ppf "Cannot find file %s@." name; false + | Sys_error msg -> + fprintf ppf "%s: %s@." name msg; + false | Dynlink.Error e -> raise(Error(Load_failure e)) diff --git a/debugger/loadprinter.mli b/debugger/loadprinter.mli index 4851a4d5..8fc6f7a6 100644 --- a/debugger/loadprinter.mli +++ b/debugger/loadprinter.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1997 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1997 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. *) +(* *) +(**************************************************************************) (* Loading and installation of user-defined printer functions *) diff --git a/debugger/main.ml b/debugger/main.ml index 60cd96a8..50ffcf5c 100644 --- a/debugger/main.ml +++ b/debugger/main.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Input_handling open Question diff --git a/debugger/parameters.ml b/debugger/parameters.ml index d8c85efe..f9192a7a 100644 --- a/debugger/parameters.ml +++ b/debugger/parameters.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Miscellaneous parameters *) diff --git a/debugger/parameters.mli b/debugger/parameters.mli index 44c850d5..388fb94d 100644 --- a/debugger/parameters.mli +++ b/debugger/parameters.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Miscellaneous parameters *) diff --git a/debugger/parser.mly b/debugger/parser.mly index 1d394e34..060aee74 100644 --- a/debugger/parser.mly +++ b/debugger/parser.mly @@ -1,15 +1,18 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Jerome Vouillon, projet Cristal, INRIA Rocquencourt */ -/* OCaml port by John Malecki and Xavier Leroy */ -/* */ -/* Copyright 1996 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. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jerome Vouillon, projet Cristal, INRIA Rocquencourt */ +/* OCaml port by John Malecki and Xavier Leroy */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ %{ diff --git a/debugger/parser_aux.mli b/debugger/parser_aux.mli index 542affbd..a218a104 100644 --- a/debugger/parser_aux.mli +++ b/debugger/parser_aux.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (*open Globals*) diff --git a/debugger/pattern_matching.ml b/debugger/pattern_matching.ml index 7b297869..f44d16ee 100644 --- a/debugger/pattern_matching.ml +++ b/debugger/pattern_matching.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************ Simple pattern matching **********************) diff --git a/debugger/pattern_matching.mli b/debugger/pattern_matching.mli index 71e88c05..35b541e6 100644 --- a/debugger/pattern_matching.mli +++ b/debugger/pattern_matching.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************ Simple pattern matching **********************) diff --git a/debugger/pos.ml b/debugger/pos.ml index c9e93280..7546df50 100644 --- a/debugger/pos.ml +++ b/debugger/pos.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2003 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2003 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. *) +(* *) +(**************************************************************************) open Instruct;; open Lexing;; diff --git a/debugger/pos.mli b/debugger/pos.mli index 4eacab78..f5c37650 100644 --- a/debugger/pos.mli +++ b/debugger/pos.mli @@ -1,13 +1,16 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2003 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2003 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. *) +(* *) +(**************************************************************************) val get_desc : Instruct.debug_event -> string;; diff --git a/debugger/primitives.ml b/debugger/primitives.ml index 8cbc5387..498a8c54 100644 --- a/debugger/primitives.ml +++ b/debugger/primitives.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (*********************** Basic functions and types *********************) diff --git a/debugger/primitives.mli b/debugger/primitives.mli index 0e36b414..f977b498 100644 --- a/debugger/primitives.mli +++ b/debugger/primitives.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (********************* Basic functions and types ***********************) diff --git a/debugger/printval.ml b/debugger/printval.ml index 5170ef3b..30f111ea 100644 --- a/debugger/printval.ml +++ b/debugger/printval.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* To print values *) diff --git a/debugger/printval.mli b/debugger/printval.mli index ba6c25ad..53c0ee4e 100644 --- a/debugger/printval.mli +++ b/debugger/printval.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format diff --git a/debugger/program_loading.ml b/debugger/program_loading.ml index 1ebbd1e8..d804b88e 100644 --- a/debugger/program_loading.ml +++ b/debugger/program_loading.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Program loading *) diff --git a/debugger/program_loading.mli b/debugger/program_loading.mli index 23ea47a6..cb4c2161 100644 --- a/debugger/program_loading.mli +++ b/debugger/program_loading.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (*** Debugging. ***) diff --git a/debugger/program_management.ml b/debugger/program_management.ml index 48118573..c8d81e43 100644 --- a/debugger/program_management.ml +++ b/debugger/program_management.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Manage the loading of the program *) diff --git a/debugger/program_management.mli b/debugger/program_management.mli index 0b8a09b8..aca1cddc 100644 --- a/debugger/program_management.mli +++ b/debugger/program_management.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (*** Program loading and initializations. ***) diff --git a/debugger/question.ml b/debugger/question.ml index f17227b9..32daa640 100644 --- a/debugger/question.ml +++ b/debugger/question.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Nicolas Pouillard, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2006 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Nicolas Pouillard, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2006 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. *) +(* *) +(**************************************************************************) open Input_handling open Primitives diff --git a/debugger/question.mli b/debugger/question.mli index d8e50ef9..75f22555 100644 --- a/debugger/question.mli +++ b/debugger/question.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Nicolas Pouillard, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2006 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Nicolas Pouillard, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2006 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. *) +(* *) +(**************************************************************************) (* Ask user a yes or no question. *) val yes_or_no : string -> bool diff --git a/debugger/show_information.ml b/debugger/show_information.ml index 690645df..9e34b61c 100644 --- a/debugger/show_information.ml +++ b/debugger/show_information.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Instruct open Format diff --git a/debugger/show_information.mli b/debugger/show_information.mli index 45329be4..88c51379 100644 --- a/debugger/show_information.mli +++ b/debugger/show_information.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format;; diff --git a/debugger/show_source.ml b/debugger/show_source.ml index db2484f5..ac478717 100644 --- a/debugger/show_source.ml +++ b/debugger/show_source.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Debugger_config open Instruct diff --git a/debugger/show_source.mli b/debugger/show_source.mli index c1aa204e..2d77caa8 100644 --- a/debugger/show_source.mli +++ b/debugger/show_source.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Print the line containing the point *) val show_point : Instruct.debug_event -> bool -> unit;; diff --git a/debugger/source.ml b/debugger/source.ml index fa2b3c7e..4ab79363 100644 --- a/debugger/source.ml +++ b/debugger/source.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************ Source management ****************************) diff --git a/debugger/source.mli b/debugger/source.mli index 640ebc85..119d6704 100644 --- a/debugger/source.mli +++ b/debugger/source.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************ Source management ****************************) diff --git a/debugger/symbols.ml b/debugger/symbols.ml index 1be72533..9a9c8f9c 100644 --- a/debugger/symbols.ml +++ b/debugger/symbols.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Handling of symbol tables (globals and events) *) diff --git a/debugger/symbols.mli b/debugger/symbols.mli index 883b81aa..b1fc9d6f 100644 --- a/debugger/symbols.mli +++ b/debugger/symbols.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Modules used by the program. *) val modules : string list ref diff --git a/debugger/time_travel.ml b/debugger/time_travel.ml index c55c7540..c7d6e9a8 100644 --- a/debugger/time_travel.ml +++ b/debugger/time_travel.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (**************************** Time travel ******************************) @@ -384,6 +387,7 @@ let forget_process fd pid = let checkpoint = List.find (function c -> c.c_pid = pid) (!current_checkpoint::!checkpoints) in + if pid > 0 then begin Printf.eprintf "Lost connection with process %d" pid; let kont = if checkpoint == !current_checkpoint then begin @@ -409,6 +413,7 @@ let forget_process fd pid = if checkpoint.c_parent.c_pid > 0 then wait_child checkpoint.c_parent.c_fd; kont () + end (* Try to recover when the current checkpoint is lost. *) let recover () = diff --git a/debugger/time_travel.mli b/debugger/time_travel.mli index 2d352320..e25bad9f 100644 --- a/debugger/time_travel.mli +++ b/debugger/time_travel.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (**************************** Time travel ******************************) diff --git a/debugger/trap_barrier.ml b/debugger/trap_barrier.ml index ce5fe762..33dfb04f 100644 --- a/debugger/trap_barrier.ml +++ b/debugger/trap_barrier.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************** Trap barrier *******************************) diff --git a/debugger/trap_barrier.mli b/debugger/trap_barrier.mli index 239c12a6..7ff28631 100644 --- a/debugger/trap_barrier.mli +++ b/debugger/trap_barrier.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (************************* Trap barrier ********************************) diff --git a/debugger/unix_tools.ml b/debugger/unix_tools.ml index 8cefd37e..faf5fb7b 100644 --- a/debugger/unix_tools.ml +++ b/debugger/unix_tools.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (****************** Tools for Unix *************************************) diff --git a/debugger/unix_tools.mli b/debugger/unix_tools.mli index b1ac62db..db3af072 100644 --- a/debugger/unix_tools.mli +++ b/debugger/unix_tools.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (**************************** Tools for Unix ***************************) diff --git a/driver/compenv.ml b/driver/compenv.ml index e7b4987c..cbdb59c4 100644 --- a/driver/compenv.ml +++ b/driver/compenv.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) -(* *) -(* Copyright 2013 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) +(* *) +(* Copyright 2013 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. *) +(* *) +(**************************************************************************) open Clflags @@ -58,6 +61,7 @@ let last_objfiles = ref [] (* Check validity of module name *) let is_unit_name name = try + if name = "" then raise Exit; begin match name.[0] with | 'A'..'Z' -> () | _ -> @@ -87,14 +91,15 @@ let module_of_filename ppf inputfile outputprefix = String.sub basename 0 pos with Not_found -> basename in - let name = String.capitalize name in + let name = String.capitalize_ascii name in check_unit_name ppf inputfile name; name ;; +type filename = string type readenv_position = - Before_args | Before_compile | Before_link + Before_args | Before_compile of filename | Before_link (* Syntax of OCAMLPARAM: (name=VALUE,)* _ (,name=VALUE)* where VALUE should not contain ',' *) @@ -137,10 +142,270 @@ let setter ppf f name options s = (Warnings.Bad_env_variable ("OCAMLPARAM", Printf.sprintf "bad value for %s" name)) +let int_setter ppf name option s = + try + option := int_of_string s + with _ -> + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable + ("OCAMLPARAM", Printf.sprintf "non-integer parameter for \"%s\"" name)) + +let int_option_setter ppf name option s = + try + option := Some (int_of_string s) + with _ -> + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable + ("OCAMLPARAM", Printf.sprintf "non-integer parameter for \"%s\"" name)) + +let float_setter ppf name option s = + try + option := float_of_string s + with _ -> + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable + ("OCAMLPARAM", Printf.sprintf "non-float parameter for \"%s\"" name)) + +let check_bool ppf name s = + match s with + | "0" -> false + | "1" -> true + | _ -> + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable ("OCAMLPARAM", + Printf.sprintf "bad value for %s" name)); + false + (* 'can-discard=' specifies which arguments can be discarded without warning because they are not understood by some versions of OCaml. *) let can_discard = ref [] +let read_one_param ppf position name v = + let set name options s = setter ppf (fun b -> b) name options s in + let clear name options s = setter ppf (fun b -> not b) name options s in + match name with + | "g" -> set "g" [ Clflags.debug ] v + | "p" -> set "p" [ Clflags.gprofile ] v + | "bin-annot" -> set "bin-annot" [ Clflags.binary_annotations ] v + | "annot" -> set "annot" [ Clflags.annotations ] v + | "absname" -> set "absname" [ Location.absname ] v + | "compat-32" -> set "compat-32" [ bytecode_compatible_32 ] v + | "noassert" -> set "noassert" [ noassert ] v + | "noautolink" -> set "noautolink" [ no_auto_link ] v + | "nostdlib" -> set "nostdlib" [ no_std_include ] v + | "linkall" -> set "linkall" [ link_everything ] v + | "nolabels" -> set "nolabels" [ classic ] v + | "principal" -> set "principal" [ principal ] v + | "rectypes" -> set "rectypes" [ recursive_types ] v + | "safe-string" -> clear "safe-string" [ unsafe_string ] v + | "strict-sequence" -> set "strict-sequence" [ strict_sequence ] v + | "strict-formats" -> set "strict-formats" [ strict_formats ] v + | "thread" -> set "thread" [ use_threads ] v + | "unsafe" -> set "unsafe" [ fast ] v + | "verbose" -> set "verbose" [ verbose ] v + | "nopervasives" -> set "nopervasives" [ nopervasives ] v + | "slash" -> set "slash" [ force_slash ] v (* for ocamldep *) + | "keep-docs" -> set "keep-docs" [ Clflags.keep_docs ] v + | "keep-locs" -> set "keep-locs" [ Clflags.keep_locs ] v + + | "compact" -> clear "compact" [ optimize_for_speed ] v + | "no-app-funct" -> clear "no-app-funct" [ applicative_functors ] v + | "nodynlink" -> clear "nodynlink" [ dlcode ] v + | "short-paths" -> clear "short-paths" [ real_paths ] v + | "trans-mod" -> set "trans-mod" [ transparent_modules ] v + | "opaque" -> set "opaque" [ opaque ] v + + | "pp" -> preprocessor := Some v + | "runtime-variant" -> runtime_variant := v + | "cc" -> c_compiler := Some v + + | "clambda-checks" -> set "clambda-checks" [ clambda_checks ] v + + (* assembly sources *) + | "s" -> + set "s" [ Clflags.keep_asm_file ; Clflags.keep_startup_file ] v + | "S" -> set "S" [ Clflags.keep_asm_file ] v + | "dstartup" -> set "dstartup" [ Clflags.keep_startup_file ] v + + (* warn-errors *) + | "we" | "warn-error" -> Warnings.parse_options true v + (* warnings *) + | "w" -> Warnings.parse_options false v + (* warn-errors *) + | "wwe" -> Warnings.parse_options false v + + (* inlining *) + | "inline" -> + let module F = Float_arg_helper in + begin match F.parse_no_error v inline_threshold with + | F.Ok -> () + | F.Parse_failed exn -> + let error = + Printf.sprintf "bad syntax for \"inline\": %s" + (Printexc.to_string exn) + in + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable ("OCAMLPARAM", error)) + end + + | "inline-toplevel" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-toplevel'" + inline_toplevel_threshold + + | "rounds" -> int_option_setter ppf "rounds" simplify_rounds v + | "inline-max-unroll" -> + Int_arg_helper.parse v "Bad syntax in OCAMLPARAM for 'inline-max-unroll'" + inline_max_unroll + | "inline-call-cost" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-call-cost'" + inline_call_cost + | "inline-alloc-cost" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-alloc-cost'" + inline_alloc_cost + | "inline-prim-cost" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-prim-cost'" + inline_prim_cost + | "inline-branch-cost" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-branch-cost'" + inline_branch_cost + | "inline-indirect-cost" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-indirect-cost'" + inline_indirect_cost + | "inline-lifting-benefit" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-lifting-benefit'" + inline_lifting_benefit + | "inline-branch-factor" -> + Float_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-branch-factor'" + inline_branch_factor + | "inline-max-depth" -> + Int_arg_helper.parse v + "Bad syntax in OCAMLPARAM for 'inline-max-depth'" + inline_max_depth + + | "Oclassic" -> + set "Oclassic" [ classic_inlining ] v + | "O2" -> + if check_bool ppf "O2" v then begin + default_simplify_rounds := 2; + use_inlining_arguments_set o2_arguments; + use_inlining_arguments_set ~round:0 o1_arguments + end + + | "O3" -> + if check_bool ppf "O3" v then begin + default_simplify_rounds := 3; + use_inlining_arguments_set o3_arguments; + use_inlining_arguments_set ~round:1 o2_arguments; + use_inlining_arguments_set ~round:0 o1_arguments + end + | "unbox-closures" -> + set "unbox-closures" [ unbox_closures ] v + | "unbox-closures-factor" -> + int_setter ppf "unbox-closures-factor" unbox_closures_factor v + | "remove-unused-arguments" -> + set "remove-unused-arguments" [ remove_unused_arguments ] v + + | "inlining-report" -> + if !native_code then + set "inlining-report" [ inlining_report ] v + + | "flambda-verbose" -> + set "flambda-verbose" [ dump_flambda_verbose ] v + | "flambda-invariants" -> + set "flambda-invariants" [ flambda_invariant_checks ] v + + (* color output *) + | "color" -> + begin match parse_color_setting v with + | None -> + Location.print_warning Location.none ppf + (Warnings.Bad_env_variable ("OCAMLPARAM", + "bad value for \"color\", \ + (expected \"auto\", \"always\" or \"never\")")) + | Some setting -> color := setting + end + + | "intf-suffix" -> Config.interface_suffix := v + + | "I" -> begin + match position with + | Before_args -> first_include_dirs := v :: !first_include_dirs + | Before_link | Before_compile _ -> + last_include_dirs := v :: !last_include_dirs + end + + | "cclib" -> + begin + match position with + | Before_compile _ -> () + | Before_link | Before_args -> + ccobjs := Misc.rev_split_words v @ !ccobjs + end + + | "ccopts" -> + begin + match position with + | Before_link | Before_compile _ -> + last_ccopts := v :: !last_ccopts + | Before_args -> + first_ccopts := v :: !first_ccopts + end + + | "ppx" -> + begin + match position with + | Before_link | Before_compile _ -> + last_ppx := v :: !last_ppx + | Before_args -> + first_ppx := v :: !first_ppx + end + + + | "cmo" | "cma" -> + if not !native_code then + begin + match position with + | Before_link | Before_compile _ -> + last_objfiles := v ::! last_objfiles + | Before_args -> + first_objfiles := v :: !first_objfiles + end + + | "cmx" | "cmxa" -> + if !native_code then + begin + match position with + | Before_link | Before_compile _ -> + last_objfiles := v ::! last_objfiles + | Before_args -> + first_objfiles := v :: !first_objfiles + end + + | "pic" -> + if !native_code then + set "pic" [ pic_code ] v + + | "can-discard" -> + can_discard := v ::!can_discard + + | "timings" -> set "timings" [ print_timings ] v + + | _ -> + if not (List.mem name !can_discard) then begin + can_discard := name :: !can_discard; + Printf.eprintf + "Warning: discarding value of variable %S in OCAMLPARAM\n%!" + name + end + let read_OCAMLPARAM ppf position = try let s = Sys.getenv "OCAMLPARAM" in @@ -152,142 +417,105 @@ let read_OCAMLPARAM ppf position = (Warnings.Bad_env_variable ("OCAMLPARAM", s)); [],[] in - let set name options s = setter ppf (fun b -> b) name options s in - let clear name options s = setter ppf (fun b -> not b) name options s in - List.iter (fun (name, v) -> - match name with - | "g" -> set "g" [ Clflags.debug ] v - | "p" -> set "p" [ Clflags.gprofile ] v - | "bin-annot" -> set "bin-annot" [ Clflags.binary_annotations ] v - | "annot" -> set "annot" [ Clflags.annotations ] v - | "absname" -> set "absname" [ Location.absname ] v - | "compat-32" -> set "compat-32" [ bytecode_compatible_32 ] v - | "noassert" -> set "noassert" [ noassert ] v - | "noautolink" -> set "noautolink" [ no_auto_link ] v - | "nostdlib" -> set "nostdlib" [ no_std_include ] v - | "linkall" -> set "linkall" [ link_everything ] v - | "nolabels" -> set "nolabels" [ classic ] v - | "principal" -> set "principal" [ principal ] v - | "rectypes" -> set "rectypes" [ recursive_types ] v - | "safe-string" -> clear "safe-string" [ unsafe_string ] v - | "strict-sequence" -> set "strict-sequence" [ strict_sequence ] v - | "strict-formats" -> set "strict-formats" [ strict_formats ] v - | "thread" -> set "thread" [ use_threads ] v - | "unsafe" -> set "unsafe" [ fast ] v - | "verbose" -> set "verbose" [ verbose ] v - | "nopervasives" -> set "nopervasives" [ nopervasives ] v - | "slash" -> set "slash" [ force_slash ] v (* for ocamldep *) - | "keep-docs" -> set "keep-docs" [ Clflags.keep_docs ] v - | "keep-locs" -> set "keep-locs" [ Clflags.keep_locs ] v - - | "compact" -> clear "compact" [ optimize_for_speed ] v - | "no-app-funct" -> clear "no-app-funct" [ applicative_functors ] v - | "nodynlink" -> clear "nodynlink" [ dlcode ] v - | "short-paths" -> clear "short-paths" [ real_paths ] v - | "trans-mod" -> set "trans-mod" [ transparent_modules ] v - - | "pp" -> preprocessor := Some v - | "runtime-variant" -> runtime_variant := v - | "cc" -> c_compiler := Some v - - (* assembly sources *) - | "s" -> - set "s" [ Clflags.keep_asm_file ; Clflags.keep_startup_file ] v - | "S" -> set "S" [ Clflags.keep_asm_file ] v - | "dstartup" -> set "dstartup" [ Clflags.keep_startup_file ] v - - (* warn-errors *) - | "we" | "warn-error" -> Warnings.parse_options true v - (* warnings *) - | "w" -> Warnings.parse_options false v - (* warn-errors *) - | "wwe" -> Warnings.parse_options false v - - (* inlining *) - | "inline" -> begin try - inline_threshold := 8 * int_of_string v - with _ -> - Location.print_warning Location.none ppf - (Warnings.Bad_env_variable ("OCAMLPARAM", - "non-integer parameter for \"inline\"")) - end - - | "intf-suffix" -> Config.interface_suffix := v - - | "I" -> begin - match position with - | Before_args -> first_include_dirs := v :: !first_include_dirs - | Before_link | Before_compile -> - last_include_dirs := v :: !last_include_dirs - end - - | "cclib" -> - begin - match position with - | Before_compile -> () - | Before_link | Before_args -> - ccobjs := Misc.rev_split_words v @ !ccobjs - end - - | "ccopts" -> - begin - match position with - | Before_link | Before_compile -> - last_ccopts := v :: !last_ccopts - | Before_args -> - first_ccopts := v :: !first_ccopts - end - - | "ppx" -> - begin - match position with - | Before_link | Before_compile -> - last_ppx := v :: !last_ppx - | Before_args -> - first_ppx := v :: !first_ppx - end - - - | "cmo" | "cma" -> - if not !native_code then - begin - match position with - | Before_link | Before_compile -> - last_objfiles := v ::! last_objfiles - | Before_args -> - first_objfiles := v :: !first_objfiles - end - - | "cmx" | "cmxa" -> - if !native_code then - begin - match position with - | Before_link | Before_compile -> - last_objfiles := v ::! last_objfiles - | Before_args -> - first_objfiles := v :: !first_objfiles - end - - | "can-discard" -> - can_discard := v ::!can_discard - - | _ -> - if not (List.mem name !can_discard) then begin - can_discard := name :: !can_discard; - Printf.eprintf - "Warning: discarding value of variable %S in OCAMLPARAM\n%!" - name - end - ) (match position with - Before_args -> before - | Before_compile | Before_link -> after) + List.iter (fun (name, v) -> read_one_param ppf position name v) + (match position with + Before_args -> before + | Before_compile _ | Before_link -> after) with Not_found -> () +(* OCAMLPARAM passed as file *) + +type pattern = + | Filename of string + | Any + +type file_option = { + pattern : pattern; + name : string; + value : string; +} + +let scan_line ic = + Scanf.bscanf ic "%[0-9a-zA-Z_.*] : %[a-zA-Z_-] = %s " + (fun pattern name value -> + let pattern = + match pattern with + | "*" -> Any + | _ -> Filename pattern + in + { pattern; name; value }) + +let load_config ppf filename = + match open_in_bin filename with + | exception e -> + Location.print_error ppf (Location.in_file filename); + Format.fprintf ppf "Cannot open file %s@." (Printexc.to_string e); + raise Exit + | ic -> + let sic = Scanf.Scanning.from_channel ic in + let rec read line_number line_start acc = + match scan_line sic with + | exception End_of_file -> + close_in ic; + acc + | exception Scanf.Scan_failure error -> + let position = Lexing.{ + pos_fname = filename; + pos_lnum = line_number; + pos_bol = line_start; + pos_cnum = pos_in ic; + } + in + let loc = Location.{ + loc_start = position; + loc_end = position; + loc_ghost = false; + } + in + Location.print_error ppf loc; + Format.fprintf ppf "Configuration file error %s@." error; + close_in ic; + raise Exit + | line -> + read (line_number + 1) (pos_in ic) (line :: acc) + in + let lines = read 0 0 [] in + lines + +let matching_filename filename { pattern } = + match pattern with + | Any -> true + | Filename pattern -> + let filename = String.lowercase_ascii filename in + let pattern = String.lowercase_ascii pattern in + filename = pattern + +let apply_config_file ppf position = + let config_file = + Filename.concat Config.standard_library "ocaml_compiler_internal_params" + in + let config = + if Sys.file_exists config_file then + load_config ppf config_file + else + [] + in + let config = + match position with + | Before_compile filename -> + List.filter (matching_filename filename) config + | Before_args | Before_link -> + List.filter (fun { pattern } -> pattern = Any) config + in + List.iter (fun { name; value } -> read_one_param ppf position name value) + config + let readenv ppf position = last_include_dirs := []; last_ccopts := []; last_ppx := []; last_objfiles := []; + apply_config_file ppf position; read_OCAMLPARAM ppf position; all_ccopts := !last_ccopts @ !first_ccopts; all_ppx := !last_ppx @ !first_ppx diff --git a/driver/compenv.mli b/driver/compenv.mli index 59cd1012..413420d4 100644 --- a/driver/compenv.mli +++ b/driver/compenv.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) -(* *) -(* Copyright 2013 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) +(* *) +(* Copyright 2013 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. *) +(* *) +(**************************************************************************) val module_of_filename : Format.formatter -> string -> string -> string @@ -30,8 +33,10 @@ val implicit_modules : string list ref (* return the list of objfiles, after OCAMLPARAM and List.rev *) val get_objfiles : unit -> string list +type filename = string + type readenv_position = - Before_args | Before_compile | Before_link + Before_args | Before_compile of filename | Before_link val readenv : Format.formatter -> readenv_position -> unit diff --git a/driver/compile.ml b/driver/compile.ml index 9edfb804..053327f2 100644 --- a/driver/compile.ml +++ b/driver/compile.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* The batch compiler *) @@ -42,7 +45,10 @@ let interface ppf sourcefile outputprefix = Typecore.force_delayed_checks (); Warnings.check_fatal (); if not !Clflags.print_types then begin - let sg = Env.save_signature sg modulename (outputprefix ^ ".cmi") in + 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 @@ -65,7 +71,8 @@ let implementation ppf sourcefile outputprefix = Pparse.parse_implementation ~tool_name ppf sourcefile ++ print_if ppf Clflags.dump_parsetree Printast.implementation ++ print_if ppf Clflags.dump_source Pprintast.structure - ++ Typemod.type_implementation sourcefile outputprefix modulename env + ++ Timings.(time (Typing sourcefile)) + (Typemod.type_implementation sourcefile outputprefix modulename env) ++ print_if ppf Clflags.dump_typedtree Printtyped.implementation_with_coercion in @@ -75,18 +82,22 @@ let implementation ppf sourcefile outputprefix = end else begin let bytecode = (typedtree, coercion) - ++ Translmod.transl_implementation modulename + ++ Timings.(time (Transl sourcefile)) + (Translmod.transl_implementation modulename) ++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda - ++ Simplif.simplify_lambda - ++ print_if ppf Clflags.dump_lambda Printlambda.lambda - ++ Bytegen.compile_implementation modulename - ++ print_if ppf Clflags.dump_instr Printinstr.instrlist + ++ Timings.(accumulate_time (Generate sourcefile)) + (fun lambda -> + Simplif.simplify_lambda lambda + ++ print_if ppf Clflags.dump_lambda Printlambda.lambda + ++ Bytegen.compile_implementation modulename + ++ print_if ppf Clflags.dump_instr Printinstr.instrlist) in let objfile = outputprefix ^ ".cmo" in let oc = open_out_bin objfile in try bytecode - ++ Emitcode.to_file oc modulename objfile; + ++ Timings.(accumulate_time (Generate sourcefile)) + (Emitcode.to_file oc modulename objfile); Warnings.check_fatal (); close_out oc; Stypes.dump (Some (outputprefix ^ ".annot")) diff --git a/driver/compile.mli b/driver/compile.mli index 00f9029a..2ae4f7a4 100644 --- a/driver/compile.mli +++ b/driver/compile.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compile a .ml or .mli file *) diff --git a/driver/compmisc.ml b/driver/compmisc.ml index a2bc4b83..27efafd1 100644 --- a/driver/compmisc.ml +++ b/driver/compmisc.ml @@ -1,24 +1,27 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) -(* *) -(* Copyright 2013 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) +(* *) +(* Copyright 2013 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. *) +(* *) +(**************************************************************************) open Compenv (* Initialize the search path. - The current directory is always searched first, + [dir] is always searched first (default: the current directory), then the directories specified with the -I option (in command-line order), then the standard library directory (unless the -nostdlib option is given). *) -let init_path native = +let init_path ?(dir="") native = let dirs = if !Clflags.use_threads then "+threads" :: !Clflags.include_dirs else if !Clflags.use_vmthreads && not native then @@ -30,7 +33,7 @@ let init_path native = in let exp_dirs = List.map (Misc.expand_directory Config.standard_library) dirs in - Config.load_path := "" :: + Config.load_path := dir :: List.rev_append exp_dirs (Clflags.std_include_dir ()); Env.reset_cache () diff --git a/driver/compmisc.mli b/driver/compmisc.mli index 032e9fe4..ade4761a 100644 --- a/driver/compmisc.mli +++ b/driver/compmisc.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) -(* *) -(* Copyright 2013 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, EPI Gallium, INRIA Paris-Rocquencourt *) +(* *) +(* Copyright 2013 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. *) +(* *) +(**************************************************************************) -val init_path : bool -> unit +val init_path : ?dir:string -> bool -> unit val initial_env : unit -> Env.t diff --git a/driver/errors.ml b/driver/errors.ml index bda1a30a..96fa0240 100644 --- a/driver/errors.ml +++ b/driver/errors.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* This module should be removed. We keep it for now, to avoid breaking external tools depending on it. *) diff --git a/driver/errors.mli b/driver/errors.mli index c9f1ee95..f5608931 100644 --- a/driver/errors.mli +++ b/driver/errors.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Error report *) open Format diff --git a/driver/main.ml b/driver/main.ml index e3c59c9e..3bfd8f3d 100644 --- a/driver/main.ml +++ b/driver/main.ml @@ -1,21 +1,26 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Config open Clflags open Compenv let process_interface_file ppf name = - Compile.interface ppf name (output_prefix name) + let opref = output_prefix name in + Compile.interface ppf name opref; + if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles let process_implementation_file ppf name = let opref = output_prefix name in @@ -24,16 +29,10 @@ let process_implementation_file ppf name = let process_file ppf name = if Filename.check_suffix name ".ml" - || Filename.check_suffix name ".mlt" then begin - let opref = output_prefix name in - Compile.implementation ppf name opref; - objfiles := (opref ^ ".cmo") :: !objfiles - end - else if Filename.check_suffix name !Config.interface_suffix then begin - let opref = output_prefix name in - Compile.interface ppf name opref; - if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles - end + || Filename.check_suffix name ".mlt" then + process_implementation_file ppf name + else if Filename.check_suffix name !Config.interface_suffix then + process_interface_file ppf name else if Filename.check_suffix name ".cmo" || Filename.check_suffix name ".cma" then objfiles := name :: !objfiles @@ -58,11 +57,16 @@ let ppf = Format.err_formatter (* Error messages to standard error formatter *) let anonymous filename = - readenv ppf Before_compile; process_file ppf filename;; + readenv ppf (Before_compile filename); + process_file ppf filename;; + let impl filename = - readenv ppf Before_compile; process_implementation_file ppf filename;; + readenv ppf (Before_compile filename); + process_implementation_file ppf filename;; + let intf filename = - readenv ppf Before_compile; process_interface_file ppf filename;; + readenv ppf (Before_compile filename); + process_interface_file ppf filename;; let show_config () = Config.print_config stdout; @@ -94,32 +98,43 @@ module Options = Main_args.Make_bytecomp_options (struct let _intf = intf let _intf_suffix s = Config.interface_suffix := s let _keep_docs = set keep_docs + let _no_keep_docs = unset keep_docs let _keep_locs = set keep_locs + let _no_keep_locs = unset keep_locs let _labels = unset classic let _linkall = set link_everything let _make_runtime () = custom_runtime := true; make_runtime := true; link_everything := true + let _alias_deps = unset transparent_modules let _no_alias_deps = set transparent_modules + let _app_funct = set applicative_functors let _no_app_funct = unset applicative_functors let _noassert = set noassert let _nolabels = set classic let _noautolink = set no_auto_link let _nostdlib = set no_std_include let _o s = output_name := Some s + let _opaque = set opaque let _open s = open_modules := s :: !open_modules let _output_obj () = output_c_object := true; custom_runtime := true let _output_complete_obj () = - output_c_object := true; output_complete_object := true; custom_runtime := true + output_c_object := true; + output_complete_object := true; + custom_runtime := true let _pack = set make_package let _pp s = preprocessor := Some s let _ppx s = first_ppx := s :: !first_ppx let _principal = set principal + let _no_principal = unset principal let _rectypes = set recursive_types + let _no_rectypes = unset recursive_types let _runtime_variant s = runtime_variant := s let _safe_string = unset unsafe_string let _short_paths = unset real_paths let _strict_sequence = set strict_sequence + let _no_strict_sequence = unset strict_sequence let _strict_formats = set strict_formats + let _no_strict_formats = unset strict_formats let _thread = set use_threads let _vmthread = set use_vmthreads let _unsafe = set fast @@ -132,6 +147,11 @@ module Options = Main_args.Make_bytecomp_options (struct let _w = (Warnings.parse_options false) let _warn_error = (Warnings.parse_options true) let _warn_help = Warnings.help_warnings + let _color option = + begin match Clflags.parse_color_setting option with + | None -> () + | Some setting -> Clflags.color := setting + end let _where = print_standard_library let _verbose = set verbose let _nopervasives = set nopervasives @@ -141,6 +161,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _drawlambda = set dump_rawlambda let _dlambda = set dump_lambda let _dinstr = set dump_instr + let _dtimings = set print_timings let anonymous = anonymous end) @@ -194,13 +215,11 @@ let main () = Bytelink.link ppf (get_objfiles ()) target; Warnings.check_fatal (); end; - exit 0 with x -> Location.report_exception ppf x; exit 2 -let _ = main () - - - - +let _ = + Timings.(time All) main (); + if !Clflags.print_timings then Timings.print Format.std_formatter; + exit 0 diff --git a/driver/main.mli b/driver/main.mli index b2176ff9..ec43cbd7 100644 --- a/driver/main.mli +++ b/driver/main.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* this "empty" file is here to speed up garbage collection in ocamlc.opt diff --git a/driver/main_args.ml b/driver/main_args.ml index f5d7e316..ea89daf3 100644 --- a/driver/main_args.ml +++ b/driver/main_args.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Para, INRIA Rocquencourt *) -(* *) -(* Copyright 1998 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Para, INRIA Rocquencourt *) +(* *) +(* Copyright 1998 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. *) +(* *) +(**************************************************************************) let mk_a f = "-a", Arg.Unit f, " Build a library" @@ -43,6 +46,11 @@ let mk_ccopt f = " Pass option to the C compiler and linker" ;; +let mk_clambda_checks f = + "-clambda-checks", Arg.Unit f, " Instrument clambda code with closure and \ + field access checks (for debugging the compiler)" +;; + let mk_compact f = "-compact", Arg.Unit f, " Optimize code size rather than speed" ;; @@ -110,7 +118,96 @@ let mk_init f = ;; let mk_inline f = - "-inline", Arg.Int f, " Set aggressiveness of inlining to " + "-inline", Arg.String f, + Printf.sprintf "|=[,...] Aggressiveness of inlining \ + (default %.02f, higher numbers mean more aggressive)" + Clflags.default_inline_threshold +;; + +let mk_inline_toplevel f = + "-inline-toplevel", Arg.String f, + Printf.sprintf "|=[,...] Aggressiveness of inlining at \ + toplevel (higher numbers mean more aggressive)" +;; + +let mk_inlining_report f = + "-inlining-report", Arg.Unit f, " Emit `..inlining' file(s) (one per \ + round) showing the inliner's decisions" +;; + +let mk_dump_pass f = + "-dump-pass", Arg.String f, + Format.asprintf + " @[<4>Record transformations performed by these passes:@ @[%a@]@]" + (Format.pp_print_list + ~pp_sep:Format.pp_print_space + Format.pp_print_string) + !Clflags.all_passes +;; + +let mk_o2 f = + "-O2", Arg.Unit f, " Apply increased optimization for speed" +;; + +let mk_o3 f = + "-O3", Arg.Unit f, " Apply aggressive optimization for speed (may \ + significantly increase code size and compilation time)" +;; + +let mk_rounds f = + "-rounds", Arg.Int f, + Printf.sprintf " Repeat tree optimization and inlining phases this \ + many times (default %d). Rounds are numbered starting from zero." + !Clflags.default_simplify_rounds +;; + +let mk_inline_max_unroll f = + "-inline-max-unroll", Arg.String f, + Printf.sprintf "|=[,...] Unroll recursive functions at most \ + this many times (default %d)" + Clflags.default_inline_max_unroll +;; + +let mk_classic_inlining f = + "-Oclassic", Arg.Unit f, " Make inlining decisions at function definition \ + time rather than at the call site (replicates previous behaviour of the \ + compiler)" +;; + +let mk_inline_cost arg descr default f = + Printf.sprintf "-inline-%s-cost" arg, + Arg.String f, + Printf.sprintf "|=[,...] The cost of not removing %s during \ + inlining (default %d, higher numbers more costly)" + descr + default +;; + +let mk_inline_call_cost = + mk_inline_cost "call" "a call" Clflags.default_inline_call_cost +let mk_inline_alloc_cost = + mk_inline_cost "alloc" "an allocation" Clflags.default_inline_alloc_cost +let mk_inline_prim_cost = + mk_inline_cost "prim" "a primitive" Clflags.default_inline_prim_cost +let mk_inline_branch_cost = + mk_inline_cost "branch" "a conditional" Clflags.default_inline_branch_cost +let mk_inline_indirect_cost = + mk_inline_cost "indirect" "an indirect call" + Clflags.default_inline_indirect_cost + +let mk_inline_lifting_benefit f = + "-inline-lifting-benefit", + Arg.String f, + Printf.sprintf "|=[,...] The benefit of lifting definitions \ + to toplevel during inlining (default %d, higher numbers more beneficial)" + Clflags.default_inline_lifting_benefit +;; + +let mk_inline_branch_factor f = + "-inline-branch-factor", Arg.String f, + Printf.sprintf "|=[,...] Estimate the probability of a \ + branch being cold as 1/(1+n) (used for inlining) (default %.2f)" + Clflags.default_inline_branch_factor ;; let mk_intf f = @@ -130,10 +227,19 @@ let mk_keep_docs f = "-keep-docs", Arg.Unit f, " Keep documentation strings in .cmi files" ;; +let mk_no_keep_docs f = + "-keep-docs", Arg.Unit f, + " Do not keep documentation strings in .cmi files (default)" +;; + let mk_keep_locs f = "-keep-locs", Arg.Unit f, " Keep locations in .cmi files" ;; +let mk_no_keep_locs f = + "-no-keep-locs", Arg.Unit f, " Do not keep locations in .cmi files (default)" +;; + let mk_labels f = "-labels", Arg.Unit f, " Use commuting label mode" ;; @@ -151,15 +257,31 @@ let mk_make_runtime_2 f = "-make_runtime", Arg.Unit f, " (deprecated) same as -make-runtime" ;; +let mk_inline_max_depth f = + "-inline-max-depth", Arg.String f, + Printf.sprintf "|=[,...] Maximum depth of search for \ + inlining opportunities inside inlined functions (default %d)" + Clflags.default_inline_max_depth +;; + let mk_modern f = "-modern", Arg.Unit f, " (deprecated) same as -labels" ;; +let mk_alias_deps f = + "-alias-deps", Arg.Unit f, + " Do record dependencies for module aliases" +;; + let mk_no_alias_deps f = "-no-alias-deps", Arg.Unit f, " Do not record dependencies for module aliases" ;; +let mk_app_funct f = + "-app-funct", Arg.Unit f, " Activate applicative functors" +;; + let mk_no_app_funct f = "-no-app-funct", Arg.Unit f, " Deactivate applicative functors" ;; @@ -214,6 +336,16 @@ let mk_nostdlib f = " Do not add default directory to the list of include directories" ;; +let mk_no_unbox_free_vars_of_closures f = + "-no-unbox-free-vars-of-closures", Arg.Unit f, + " Do not unbox variables that will appear inside function closures" +;; + +let mk_no_unbox_specialised_args f = + "-no-unbox-specialised-args", Arg.Unit f, + " Do not unbox arguments to which functions have been specialised" +;; + let mk_o f = "-o", Arg.String f, " Set output file name to " ;; @@ -257,10 +389,25 @@ let mk_principal f = "-principal", Arg.Unit f, " Check principality of type inference" ;; +let mk_no_principal f = + "-no-principal", Arg.Unit f, + " Do not check principality of type inference (default)" +;; + let mk_rectypes f = "-rectypes", Arg.Unit f, " Allow arbitrary recursive types" ;; +let mk_no_rectypes f = + "-no-rectypes", Arg.Unit f, + " Do not allow arbitrary recursive types (default)" +;; + +let mk_remove_unused_arguments f = + "-remove-unused-arguments", Arg.Unit f, + " Remove unused function arguments" +;; + let mk_runtime_variant f = "-runtime-variant", Arg.String f, " Use the variant of the run-time system" @@ -286,6 +433,11 @@ let mk_stdin f = "-stdin", Arg.Unit f, " Read script from standard input" ;; +let mk_no_strict_sequence f = + "-no-strict-sequence", Arg.Unit f, + " Left-hand part of a sequence need not have type unit (default)" +;; + let mk_strict_sequence f = "-strict-sequence", Arg.Unit f, " Left-hand part of a sequence must have type unit" @@ -296,6 +448,23 @@ let mk_thread f = " Generate code that supports the system threads library" ;; +let mk_dtimings f = + "-dtimings", Arg.Unit f, " Print timings" +;; + +let mk_unbox_closures f = + "-unbox-closures", Arg.Unit f, + " Pass free variables via specialised arguments rather than closures" +;; + +let mk_unbox_closures_factor f = + "-unbox-closures-factor", Arg.Int f, + Printf.sprintf " 0> Scale the size threshold above which \ + unbox-closures will slow down indirect calls rather than duplicating a \ + function (default %d)" + Clflags.default_unbox_closures_factor +;; + let mk_unsafe f = "-unsafe", Arg.Unit f, " Do not compile bounds checking on array and string access" @@ -328,6 +497,10 @@ let mk_version f = "-version", Arg.Unit f, " Print version and exit" ;; +let mk__version f = + "--version", Arg.Unit f, " Print version and exit" +;; + let mk_vmthread f = "-vmthread", Arg.Unit f, " Generate code that supports the threads library with VM-level\n\ @@ -364,6 +537,19 @@ let mk_warn_help f = "-warn-help", Arg.Unit f, " Show description of warning numbers" ;; +let mk_color f = + "-color", Arg.Symbol (["auto"; "always"; "never"], f), + Printf.sprintf + " Enable or disable colors in compiler messages\n\ + \ The following settings are supported:\n\ + \ auto use heuristics to enable colors only if supported\n\ + \ always enable colors\n\ + \ never disable colors\n\ + \ The default setting is 'auto', and the current heuristic\n\ + \ checks that the TERM environment variable exists and is\n\ + \ not empty or \"dumb\", and that isatty(stderr) holds." +;; + let mk_where f = "-where", Arg.Unit f, " Print location of standard library and exit" ;; @@ -396,10 +582,37 @@ let mk_dlambda f = "-dlambda", Arg.Unit f, " (undocumented)" ;; +let mk_drawclambda f = + "-drawclambda", Arg.Unit f, " (undocumented)" +;; + let mk_dclambda f = "-dclambda", Arg.Unit f, " (undocumented)" ;; +let mk_dflambda f = + "-dflambda", Arg.Unit f, " Print Flambda terms" +;; + +let mk_drawflambda f = + "-drawflambda", Arg.Unit f, " Print Flambda terms after closure conversion" +;; + +let mk_dflambda_no_invariants f = + "-dflambda-no-invariants", Arg.Unit f, " Do not Check Flambda invariants \ + around each pass" +;; + +let mk_dflambda_let f = + "-dflambda-let", Arg.Int f, " Print when the given Flambda [Let] \ + is created" +;; + +let mk_dflambda_verbose f = + "-dflambda-verbose", Arg.Unit f, " Print Flambda terms including around \ + each pass" +;; + let mk_dinstr f = "-dinstr", Arg.Unit f, " (undocumented)" ;; @@ -471,8 +684,16 @@ let mk_strict_formats f = " Reject invalid formats accepted by legacy implementations\n\ \ (Warning: Invalid formats may behave differently from\n\ \ previous OCaml versions, and will become always-rejected\n\ - \ in future OCaml versions. You should use this flag\n\ - \ to detect and fix invalid formats.)" + \ in future OCaml versions. You should always use this flag\n\ + \ to detect invalid formats so you can fix them.)" + +let mk_no_strict_formats f = + "-no-strict-formats", Arg.Unit f, + " Accept invalid formats accepted by legacy implementations (default)\n\ + \ (Warning: Invalid formats may behave differently from\n\ + \ previous OCaml versions, and will become always-rejected\n\ + \ in future OCaml versions. You should never use this flag\n\ + \ and instead fix invalid formats.)" ;; let mk__ f = @@ -484,7 +705,9 @@ module type Common_options = sig val _absname : unit -> unit val _I : string -> unit val _labels : unit -> unit + val _alias_deps : unit -> unit val _no_alias_deps : unit -> unit + val _app_funct : unit -> unit val _no_app_funct : unit -> unit val _noassert : unit -> unit val _nolabels : unit -> unit @@ -492,11 +715,15 @@ module type Common_options = sig val _open : string -> unit val _ppx : string -> unit val _principal : unit -> unit + val _no_principal : unit -> unit val _rectypes : unit -> unit + val _no_rectypes : unit -> unit val _safe_string : unit -> unit val _short_paths : unit -> unit val _strict_sequence : unit -> unit + val _no_strict_sequence : unit -> unit val _strict_formats : unit -> unit + val _no_strict_formats : unit -> unit val _unsafe : unit -> unit val _unsafe_string : unit -> unit val _version : unit -> unit @@ -512,7 +739,7 @@ module type Common_options = sig val _dlambda : unit -> unit val anonymous : string -> unit -end;; +end module type Compiler_options = sig val _a : unit -> unit @@ -530,15 +757,19 @@ module type Compiler_options = sig val _intf : string -> unit val _intf_suffix : string -> unit val _keep_docs : unit -> unit + val _no_keep_docs : unit -> unit val _keep_locs : unit -> unit + val _no_keep_locs : unit -> unit val _linkall : unit -> unit val _noautolink : unit -> unit val _o : string -> unit + val _opaque : unit -> unit val _output_obj : unit -> unit val _output_complete_obj : unit -> unit val _pack : unit -> unit val _pp : string -> unit val _principal : unit -> unit + val _no_principal : unit -> unit val _rectypes : unit -> unit val _runtime_variant : string -> unit val _safe_string : unit -> unit @@ -547,7 +778,10 @@ module type Compiler_options = sig val _v : unit -> unit val _verbose : unit -> unit val _where : unit -> unit + val _color : string -> unit + val _nopervasives : unit -> unit + val _dtimings : unit -> unit end ;; @@ -581,8 +815,36 @@ end;; module type Optcommon_options = sig val _compact : unit -> unit - val _inline : int -> unit - + val _inline : string -> unit + val _inline_toplevel : string -> unit + val _inlining_report : unit -> unit + val _dump_pass : string -> unit + val _inline_max_depth : string -> unit + val _rounds : int -> unit + val _inline_max_unroll : string -> unit + val _classic_inlining : unit -> unit + val _inline_call_cost : string -> unit + val _inline_alloc_cost : string -> unit + val _inline_prim_cost : string -> unit + val _inline_branch_cost : string -> unit + val _inline_indirect_cost : string -> unit + val _inline_lifting_benefit : string -> unit + val _unbox_closures : unit -> unit + val _unbox_closures_factor : int -> unit + val _inline_branch_factor : string -> unit + val _remove_unused_arguments : unit -> unit + val _no_unbox_free_vars_of_closures : unit -> unit + val _no_unbox_specialised_args : unit -> unit + val _o2 : unit -> unit + val _o3 : unit -> unit + + val _clambda_checks : unit -> unit + val _dflambda : unit -> unit + val _drawflambda : unit -> unit + val _dflambda_no_invariants : unit -> unit + val _dflambda_let : int -> unit + val _dflambda_verbose : unit -> unit + val _drawclambda : unit -> unit val _dclambda : unit -> unit val _dcmm : unit -> unit val _dsel : unit -> unit @@ -610,7 +872,6 @@ module type Optcomp_options = sig val _pp : string -> unit val _S : unit -> unit val _shared : unit -> unit - val _opaque : unit -> unit end;; module type Opttop_options = sig @@ -638,7 +899,7 @@ module type Ocamldoc_options = sig val _v : unit -> unit val _verbose : unit -> unit val _vmthread : unit -> unit -end;; +end module type Arg_list = sig val list : (string * Arg.spec * string) list @@ -655,10 +916,10 @@ struct mk_cc F._cc; mk_cclib F._cclib; mk_ccopt F._ccopt; + mk_color F._color; mk_compat_32 F._compat_32; mk_config F._config; mk_custom F._custom; - mk_custom F._no_check_prims; mk_dllib F._dllib; mk_dllpath F._dllpath; mk_dtypes F._annot; @@ -671,13 +932,17 @@ struct mk_intf_suffix F._intf_suffix; mk_intf_suffix_2 F._intf_suffix; mk_keep_docs F._keep_docs; + mk_no_keep_docs F._no_keep_docs; mk_keep_locs F._keep_locs; + mk_no_keep_locs F._no_keep_locs; mk_labels F._labels; mk_linkall F._linkall; mk_make_runtime F._make_runtime; mk_make_runtime_2 F._make_runtime; mk_modern F._labels; + mk_alias_deps F._alias_deps; mk_no_alias_deps F._no_alias_deps; + mk_app_funct F._app_funct; mk_no_app_funct F._no_app_funct; mk_no_check_prims F._no_check_prims; mk_noassert F._noassert; @@ -685,6 +950,7 @@ struct mk_nolabels F._nolabels; mk_nostdlib F._nostdlib; mk_o F._o; + mk_opaque F._opaque; mk_open F._open; mk_output_obj F._output_obj; mk_output_complete_obj F._output_complete_obj; @@ -692,12 +958,16 @@ struct mk_pp F._pp; mk_ppx F._ppx; mk_principal F._principal; + mk_no_principal F._no_principal; mk_rectypes F._rectypes; + mk_no_rectypes F._no_rectypes; mk_runtime_variant F._runtime_variant; mk_safe_string F._safe_string; mk_short_paths F._short_paths; mk_strict_sequence F._strict_sequence; + mk_no_strict_sequence F._no_strict_sequence; mk_strict_formats F._strict_formats; + mk_no_strict_formats F._no_strict_formats; mk_thread F._thread; mk_unsafe F._unsafe; mk_unsafe_string F._unsafe_string; @@ -706,6 +976,7 @@ struct mk_v F._v; mk_verbose F._verbose; mk_version F._version; + mk__version F._version; mk_vmthread F._vmthread; mk_vnum F._vnum; mk_w F._w; @@ -722,6 +993,7 @@ struct mk_drawlambda F._drawlambda; mk_dlambda F._dlambda; mk_dinstr F._dinstr; + mk_dtimings F._dtimings; ] end;; @@ -732,7 +1004,9 @@ struct mk_I F._I; mk_init F._init; mk_labels F._labels; + mk_alias_deps F._alias_deps; mk_no_alias_deps F._no_alias_deps; + mk_app_funct F._app_funct; mk_no_app_funct F._no_app_funct; mk_noassert F._noassert; mk_noinit F._noinit; @@ -743,15 +1017,20 @@ struct mk_open F._open; mk_ppx F._ppx; mk_principal F._principal; + mk_no_principal F._no_principal; mk_rectypes F._rectypes; + mk_no_rectypes F._no_rectypes; mk_safe_string F._safe_string; mk_short_paths F._short_paths; mk_stdin F._stdin; mk_strict_sequence F._strict_sequence; + mk_no_strict_sequence F._no_strict_sequence; mk_strict_formats F._strict_formats; + mk_no_strict_formats F._no_strict_formats; mk_unsafe F._unsafe; mk_unsafe_string F._unsafe_string; mk_version F._version; + mk__version F._version; mk_vnum F._vnum; mk_w F._w; mk_warn_error F._warn_error; @@ -774,10 +1053,14 @@ struct mk_absname F._absname; mk_annot F._annot; mk_binannot F._binannot; + mk_inline_branch_factor F._inline_branch_factor; mk_c F._c; mk_cc F._cc; mk_cclib F._cclib; mk_ccopt F._ccopt; + mk_clambda_checks F._clambda_checks; + mk_classic_inlining F._classic_inlining; + mk_color F._color; mk_compact F._compact; mk_config F._config; mk_dtypes F._annot; @@ -787,13 +1070,26 @@ struct mk_I F._I; mk_impl F._impl; mk_inline F._inline; + mk_inline_toplevel F._inline_toplevel; + mk_inline_alloc_cost F._inline_alloc_cost; + mk_inline_branch_cost F._inline_branch_cost; + mk_inline_call_cost F._inline_call_cost; + mk_inline_prim_cost F._inline_prim_cost; + mk_inline_indirect_cost F._inline_indirect_cost; + mk_inline_lifting_benefit F._inline_lifting_benefit; + mk_inlining_report F._inlining_report; mk_intf F._intf; mk_intf_suffix F._intf_suffix; mk_keep_docs F._keep_docs; + mk_no_keep_docs F._no_keep_docs; mk_keep_locs F._keep_locs; + mk_no_keep_locs F._no_keep_locs; mk_labels F._labels; mk_linkall F._linkall; + mk_inline_max_depth F._inline_max_depth; + mk_alias_deps F._alias_deps; mk_no_alias_deps F._no_alias_deps; + mk_app_funct F._app_funct; mk_no_app_funct F._no_app_funct; mk_no_float_const_prop F._no_float_const_prop; mk_noassert F._noassert; @@ -801,7 +1097,12 @@ struct mk_nodynlink F._nodynlink; mk_nolabels F._nolabels; mk_nostdlib F._nostdlib; + mk_no_unbox_free_vars_of_closures F._no_unbox_free_vars_of_closures; + mk_no_unbox_specialised_args F._no_unbox_specialised_args; mk_o F._o; + mk_o2 F._o2; + mk_o3 F._o3; + mk_opaque F._opaque; mk_open F._open; mk_output_obj F._output_obj; mk_output_complete_obj F._output_complete_obj; @@ -810,20 +1111,30 @@ struct mk_pp F._pp; mk_ppx F._ppx; mk_principal F._principal; + mk_no_principal F._no_principal; mk_rectypes F._rectypes; + mk_no_rectypes F._no_rectypes; + mk_remove_unused_arguments F._remove_unused_arguments; + mk_rounds F._rounds; mk_runtime_variant F._runtime_variant; mk_S F._S; mk_safe_string F._safe_string; mk_shared F._shared; mk_short_paths F._short_paths; mk_strict_sequence F._strict_sequence; + mk_no_strict_sequence F._no_strict_sequence; mk_strict_formats F._strict_formats; + mk_no_strict_formats F._no_strict_formats; mk_thread F._thread; + mk_unbox_closures F._unbox_closures; + mk_unbox_closures_factor F._unbox_closures_factor; + mk_inline_max_unroll F._inline_max_unroll; mk_unsafe F._unsafe; mk_unsafe_string F._unsafe_string; mk_v F._v; mk_verbose F._verbose; mk_version F._version; + mk__version F._version; mk_vnum F._vnum; mk_w F._w; mk_warn_error F._warn_error; @@ -837,7 +1148,13 @@ struct mk_dtypedtree F._dtypedtree; mk_drawlambda F._drawlambda; mk_dlambda F._dlambda; + mk_drawclambda F._drawclambda; mk_dclambda F._dclambda; + mk_dflambda F._dflambda; + mk_drawflambda F._drawflambda; + mk_dflambda_no_invariants F._dflambda_no_invariants; + mk_dflambda_let F._dflambda_let; + mk_dflambda_verbose F._dflambda_verbose; mk_dcmm F._dcmm; mk_dsel F._dsel; mk_dcombine F._dcombine; @@ -852,7 +1169,8 @@ struct mk_dscheduling F._dscheduling; mk_dlinear F._dlinear; mk_dstartup F._dstartup; - mk_opaque F._opaque; + mk_dtimings F._dtimings; + mk_dump_pass F._dump_pass; ] end;; @@ -863,8 +1181,22 @@ module Make_opttop_options (F : Opttop_options) = struct mk_I F._I; mk_init F._init; mk_inline F._inline; + mk_inline_toplevel F._inline_toplevel; + mk_inlining_report F._inlining_report; + mk_rounds F._rounds; + mk_inline_max_unroll F._inline_max_unroll; + mk_classic_inlining F._classic_inlining; + mk_inline_call_cost F._inline_call_cost; + mk_inline_alloc_cost F._inline_alloc_cost; + mk_inline_prim_cost F._inline_prim_cost; + mk_inline_branch_cost F._inline_branch_cost; + mk_inline_indirect_cost F._inline_indirect_cost; + mk_inline_lifting_benefit F._inline_lifting_benefit; + mk_inline_branch_factor F._inline_branch_factor; mk_labels F._labels; + mk_alias_deps F._alias_deps; mk_no_alias_deps F._no_alias_deps; + mk_app_funct F._app_funct; mk_no_app_funct F._no_app_funct; mk_noassert F._noassert; mk_noinit F._noinit; @@ -872,19 +1204,31 @@ module Make_opttop_options (F : Opttop_options) = struct mk_noprompt F._noprompt; mk_nopromptcont F._nopromptcont; mk_nostdlib F._nostdlib; + mk_no_unbox_free_vars_of_closures F._no_unbox_free_vars_of_closures; + mk_no_unbox_specialised_args F._no_unbox_specialised_args; + mk_o2 F._o2; + mk_o3 F._o3; mk_open F._open; mk_ppx F._ppx; mk_principal F._principal; + mk_no_principal F._no_principal; mk_rectypes F._rectypes; + mk_no_rectypes F._no_rectypes; + mk_remove_unused_arguments F._remove_unused_arguments; mk_S F._S; mk_safe_string F._safe_string; mk_short_paths F._short_paths; mk_stdin F._stdin; mk_strict_sequence F._strict_sequence; + mk_no_strict_sequence F._no_strict_sequence; mk_strict_formats F._strict_formats; + mk_no_strict_formats F._no_strict_formats; + mk_unbox_closures F._unbox_closures; + mk_unbox_closures_factor F._unbox_closures_factor; mk_unsafe F._unsafe; mk_unsafe_string F._unsafe_string; mk_version F._version; + mk__version F._version; mk_vnum F._vnum; mk_w F._w; mk_warn_error F._warn_error; @@ -895,7 +1239,10 @@ module Make_opttop_options (F : Opttop_options) = struct mk_dparsetree F._dparsetree; mk_dtypedtree F._dtypedtree; mk_drawlambda F._drawlambda; + mk_drawclambda F._drawclambda; mk_dclambda F._dclambda; + mk_drawflambda F._drawflambda; + mk_dflambda F._dflambda; mk_dcmm F._dcmm; mk_dsel F._dsel; mk_dcombine F._dcombine; @@ -910,6 +1257,7 @@ module Make_opttop_options (F : Opttop_options) = struct mk_dscheduling F._dscheduling; mk_dlinear F._dlinear; mk_dstartup F._dstartup; + mk_dump_pass F._dump_pass; ] end;; @@ -924,7 +1272,9 @@ struct mk_intf_suffix_2 F._intf_suffix; mk_labels F._labels; mk_modern F._labels; + mk_alias_deps F._alias_deps; mk_no_alias_deps F._no_alias_deps; + mk_app_funct F._app_funct; mk_no_app_funct F._no_app_funct; mk_noassert F._noassert; mk_nolabels F._nolabels; @@ -933,16 +1283,21 @@ struct mk_pp F._pp; mk_ppx F._ppx; mk_principal F._principal; + mk_no_principal F._no_principal; mk_rectypes F._rectypes; + mk_no_rectypes F._no_rectypes; mk_safe_string F._safe_string; mk_short_paths F._short_paths; mk_strict_sequence F._strict_sequence; + mk_no_strict_sequence F._no_strict_sequence; mk_strict_formats F._strict_formats; + mk_no_strict_formats F._no_strict_formats; mk_thread F._thread; mk_unsafe_string F._unsafe_string; mk_v F._v; mk_verbose F._verbose; mk_version F._version; + mk__version F._version; mk_vmthread F._vmthread; mk_vnum F._vnum; mk_w F._w; diff --git a/driver/main_args.mli b/driver/main_args.mli index ddee921d..49de50d5 100644 --- a/driver/main_args.mli +++ b/driver/main_args.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Para, INRIA Rocquencourt *) -(* *) -(* Copyright 1998 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Para, INRIA Rocquencourt *) +(* *) +(* Copyright 1998 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. *) +(* *) +(**************************************************************************) (* ATTENTION ! When you add or modify a parsing or typing option, do not forget to update ocamldoc options too, in odoc_args.ml. *) @@ -17,7 +20,9 @@ module type Common_options = sig val _absname : unit -> unit val _I : string -> unit val _labels : unit -> unit + val _alias_deps : unit -> unit val _no_alias_deps : unit -> unit + val _app_funct : unit -> unit val _no_app_funct : unit -> unit val _noassert : unit -> unit val _nolabels : unit -> unit @@ -25,11 +30,15 @@ module type Common_options = sig val _open : string -> unit val _ppx : string -> unit val _principal : unit -> unit + val _no_principal : unit -> unit val _rectypes : unit -> unit + val _no_rectypes : unit -> unit val _safe_string : unit -> unit val _short_paths : unit -> unit val _strict_sequence : unit -> unit + val _no_strict_sequence : unit -> unit val _strict_formats : unit -> unit + val _no_strict_formats : unit -> unit val _unsafe : unit -> unit val _unsafe_string : unit -> unit val _version : unit -> unit @@ -45,9 +54,9 @@ module type Common_options = sig val _dlambda : unit -> unit val anonymous : string -> unit -end +end;; -module type Compiler_options = sig +module type Compiler_options = sig val _a : unit -> unit val _annot : unit -> unit val _binannot : unit -> unit @@ -63,15 +72,19 @@ module type Compiler_options = sig val _intf : string -> unit val _intf_suffix : string -> unit val _keep_docs : unit -> unit + val _no_keep_docs : unit -> unit val _keep_locs : unit -> unit + val _no_keep_locs : unit -> unit val _linkall : unit -> unit val _noautolink : unit -> unit val _o : string -> unit + val _opaque : unit -> unit val _output_obj : unit -> unit val _output_complete_obj : unit -> unit val _pack : unit -> unit val _pp : string -> unit val _principal : unit -> unit + val _no_principal : unit -> unit val _rectypes : unit -> unit val _runtime_variant : string -> unit val _safe_string : unit -> unit @@ -80,8 +93,10 @@ module type Compiler_options = sig val _v : unit -> unit val _verbose : unit -> unit val _where : unit -> unit + val _color : string -> unit val _nopervasives : unit -> unit + val _dtimings : unit -> unit end ;; @@ -115,8 +130,36 @@ end;; module type Optcommon_options = sig val _compact : unit -> unit - val _inline : int -> unit - + val _inline : string -> unit + val _inline_toplevel : string -> unit + val _inlining_report : unit -> unit + val _dump_pass : string -> unit + val _inline_max_depth : string -> unit + val _rounds : int -> unit + val _inline_max_unroll : string -> unit + val _classic_inlining : unit -> unit + val _inline_call_cost : string -> unit + val _inline_alloc_cost : string -> unit + val _inline_prim_cost : string -> unit + val _inline_branch_cost : string -> unit + val _inline_indirect_cost : string -> unit + val _inline_lifting_benefit : string -> unit + val _unbox_closures : unit -> unit + val _unbox_closures_factor : int -> unit + val _inline_branch_factor : string -> unit + val _remove_unused_arguments : unit -> unit + val _no_unbox_free_vars_of_closures : unit -> unit + val _no_unbox_specialised_args : unit -> unit + val _o2 : unit -> unit + val _o3 : unit -> unit + + val _clambda_checks : unit -> unit + val _dflambda : unit -> unit + val _drawflambda : unit -> unit + val _dflambda_no_invariants : unit -> unit + val _dflambda_let : int -> unit + val _dflambda_verbose : unit -> unit + val _drawclambda : unit -> unit val _dclambda : unit -> unit val _dcmm : unit -> unit val _dsel : unit -> unit @@ -144,7 +187,6 @@ module type Optcomp_options = sig val _pp : string -> unit val _S : unit -> unit val _shared : unit -> unit - val _opaque : unit -> unit end;; module type Opttop_options = sig @@ -158,7 +200,7 @@ module type Opttop_options = sig val _stdin : unit -> unit end;; -module type Ocamldoc_options = sig +module type Ocamldoc_options = sig include Common_options val _impl : string -> unit val _intf : string -> unit @@ -172,7 +214,7 @@ module type Ocamldoc_options = sig val _v : unit -> unit val _verbose : unit -> unit val _vmthread : unit -> unit -end +end;; module type Arg_list = sig val list : (string * Arg.spec * string) list diff --git a/driver/ocamlcomp.sh.in b/driver/ocamlcomp.sh.in index fc0a8e11..fb011c8b 100644 --- a/driver/ocamlcomp.sh.in +++ b/driver/ocamlcomp.sh.in @@ -1,16 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Jacques Garrigue, Kyoto University RIMS # -# # -# Copyright 2002 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Jacques Garrigue, Kyoto University RIMS * +#* * +#* Copyright 2002 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. * +#* * +#************************************************************************** topdir=`dirname $0` diff --git a/driver/optcompile.ml b/driver/optcompile.ml index 9a5f3b93..00e424bc 100644 --- a/driver/optcompile.ml +++ b/driver/optcompile.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* The batch compiler *) @@ -43,7 +46,10 @@ let interface ppf sourcefile outputprefix = Typecore.force_delayed_checks (); Warnings.check_fatal (); if not !Clflags.print_types then begin - let sg = Env.save_signature sg modulename (outputprefix ^ ".cmi") in + 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 @@ -57,12 +63,13 @@ let print_if ppf flag printer arg = let (++) x f = f x let (+++) (x, y) f = (x, f y) -let implementation ppf sourcefile outputprefix = +let implementation ppf sourcefile outputprefix ~backend = + let source_provenance = Timings.File sourcefile in Compmisc.init_path true; let modulename = module_of_filename ppf sourcefile outputprefix in Env.set_unit_name modulename; let env = Compmisc.initial_env() in - Compilenv.reset ?packname:!Clflags.for_package modulename; + Compilenv.reset ~source_provenance ?packname:!Clflags.for_package modulename; let cmxfile = outputprefix ^ ".cmx" in let objfile = outputprefix ^ ext_obj in let comp ast = @@ -70,18 +77,54 @@ let implementation ppf sourcefile outputprefix = ast ++ print_if ppf Clflags.dump_parsetree Printast.implementation ++ print_if ppf Clflags.dump_source Pprintast.structure - ++ Typemod.type_implementation sourcefile outputprefix modulename env + ++ Timings.(time (Typing sourcefile)) + (Typemod.type_implementation sourcefile outputprefix modulename env) ++ print_if ppf Clflags.dump_typedtree - Printtyped.implementation_with_coercion + Printtyped.implementation_with_coercion in if not !Clflags.print_types then begin - (typedtree, coercion) - ++ Translmod.transl_store_implementation modulename - +++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda - +++ Simplif.simplify_lambda - +++ print_if ppf Clflags.dump_lambda Printlambda.lambda - ++ Asmgen.compile_implementation outputprefix ppf; - Compilenv.save_unit_info cmxfile; + if Config.flambda then begin + if !Clflags.classic_inlining then begin + Clflags.default_simplify_rounds := 1; + Clflags.use_inlining_arguments_set Clflags.classic_arguments; + Clflags.unbox_free_vars_of_closures := false; + Clflags.unbox_specialised_args := false + end; + (typedtree, coercion) + ++ Timings.(time (Timings.Transl sourcefile) + (Translmod.transl_implementation_flambda modulename)) + +++ print_if ppf Clflags.dump_rawlambda Printlambda.lambda + ++ Timings.time (Timings.Generate sourcefile) (fun lambda -> + lambda + +++ Simplif.simplify_lambda + +++ print_if ppf Clflags.dump_lambda Printlambda.lambda + ++ (fun ((module_ident, size), lam) -> + Middle_end.middle_end ppf ~source_provenance + ~prefixname:outputprefix + ~size + ~filename:sourcefile + ~module_ident + ~backend + ~module_initializer:lam) + ++ Asmgen.compile_implementation_flambda ~source_provenance + outputprefix ~backend ppf; + Compilenv.save_unit_info cmxfile) + end + else begin + Clflags.use_inlining_arguments_set Clflags.classic_arguments; + (typedtree, coercion) + ++ Timings.(time (Transl sourcefile)) + (Translmod.transl_store_implementation modulename) + ++ print_if ppf Clflags.dump_rawlambda Printlambda.program + ++ Timings.(time (Generate sourcefile)) + (fun { Lambda.code; main_module_block_size } -> + { Lambda.code = Simplif.simplify_lambda code; + main_module_block_size } + ++ print_if ppf Clflags.dump_lambda Printlambda.program + ++ Asmgen.compile_implementation_clambda ~source_provenance + outputprefix ppf; + Compilenv.save_unit_info cmxfile) + end end; Warnings.check_fatal (); Stypes.dump (Some (outputprefix ^ ".annot")) diff --git a/driver/optcompile.mli b/driver/optcompile.mli index 00f9029a..8c6865da 100644 --- a/driver/optcompile.mli +++ b/driver/optcompile.mli @@ -1,19 +1,29 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compile a .ml or .mli file *) open Format val interface: formatter -> string -> string -> unit -val implementation: formatter -> string -> string -> unit + +val implementation + : formatter + -> string + -> string + -> backend:(module Backend_intf.S) + -> unit + val c_file: string -> unit diff --git a/driver/opterrors.ml b/driver/opterrors.ml index bda1a30a..96fa0240 100644 --- a/driver/opterrors.ml +++ b/driver/opterrors.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* This module should be removed. We keep it for now, to avoid breaking external tools depending on it. *) diff --git a/driver/opterrors.mli b/driver/opterrors.mli index 6267091b..75827239 100644 --- a/driver/opterrors.mli +++ b/driver/opterrors.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Error report *) diff --git a/driver/optmain.ml b/driver/optmain.ml index 0a680ce4..8d1d3dd3 100644 --- a/driver/optmain.ml +++ b/driver/optmain.ml @@ -1,25 +1,48 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Config open Clflags open Compenv +module Backend = struct + (* See backend_intf.mli. *) + + let symbol_for_global' = Compilenv.symbol_for_global' + let closure_symbol = Compilenv.closure_symbol + + let really_import_approx = Import_approx.really_import_approx + let import_symbol = Import_approx.import_symbol + + let size_int = Arch.size_int + let big_endian = Arch.big_endian + + let max_sensible_number_of_arguments = + (* The "-1" is to allow for a potential closure environment parameter. *) + Proc.max_arguments_for_tailcalls - 1 +end +let backend = (module Backend : Backend_intf.S) + let process_interface_file ppf name = - Optcompile.interface ppf name (output_prefix name) + let opref = output_prefix name in + Optcompile.interface ppf name opref; + if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles let process_implementation_file ppf name = let opref = output_prefix name in - Optcompile.implementation ppf name opref; + Optcompile.implementation ppf name opref ~backend; objfiles := (opref ^ ".cmx") :: !objfiles let cmxa_present = ref false;; @@ -28,11 +51,8 @@ let process_file ppf name = if Filename.check_suffix name ".ml" || Filename.check_suffix name ".mlt" then process_implementation_file ppf name - else if Filename.check_suffix name !Config.interface_suffix then begin - let opref = output_prefix name in - Optcompile.interface ppf name opref; - if !make_package then objfiles := (opref ^ ".cmi") :: !objfiles - end + else if Filename.check_suffix name !Config.interface_suffix then + process_interface_file ppf name else if Filename.check_suffix name ".cmx" then objfiles := name :: !objfiles else if Filename.check_suffix name ".cmxa" then begin @@ -57,11 +77,16 @@ let ppf = Format.err_formatter (* Error messages to standard error formatter *) let anonymous filename = - readenv ppf Before_compile; process_file ppf filename;; + readenv ppf (Before_compile filename); + process_file ppf filename;; + let impl filename = - readenv ppf Before_compile; process_implementation_file ppf filename;; + readenv ppf (Before_compile filename); + process_implementation_file ppf filename;; + let intf filename = - readenv ppf Before_compile; process_interface_file ppf filename;; + readenv ppf (Before_compile filename); + process_interface_file ppf filename;; let show_config () = Config.print_config stdout; @@ -80,6 +105,7 @@ module Options = Main_args.Make_optcomp_options (struct let _cc s = c_compiler := Some s let _cclib s = ccobjs := Misc.rev_split_words s @ !ccobjs let _ccopt s = first_ccopts := s :: !first_ccopts + let _clambda_checks () = clambda_checks := true let _compact = clear optimize_for_speed let _config () = show_config () let _for_pack s = for_package := Some s @@ -87,14 +113,54 @@ module Options = Main_args.Make_optcomp_options (struct let _i () = print_types := true; compile_only := true let _I dir = include_dirs := dir :: !include_dirs let _impl = impl - let _inline n = inline_threshold := n * 8 + let _inline spec = + Float_arg_helper.parse spec ~update:inline_threshold + ~help_text:"Syntax: -inline | =[,...]" + let _inline_toplevel spec = + Int_arg_helper.parse spec ~update:inline_toplevel_threshold + ~help_text:"Syntax: -inline-toplevel | =[,...]" + let _inlining_report () = inlining_report := true + let _dump_pass pass = set_dumped_pass pass true + let _rounds n = simplify_rounds := Some n + let _inline_max_unroll spec = + Int_arg_helper.parse spec ~update:inline_max_unroll + ~help_text:"Syntax: -inline-max-unroll | =[,...]" + let _classic_inlining () = classic_inlining := true + let _inline_call_cost spec = + Int_arg_helper.parse spec ~update:inline_call_cost + ~help_text:"Syntax: -inline-call-cost | =[,...]" + let _inline_alloc_cost spec = + Int_arg_helper.parse spec ~update:inline_alloc_cost + ~help_text:"Syntax: -inline-alloc-cost | =[,...]" + let _inline_prim_cost spec = + Int_arg_helper.parse spec ~update:inline_prim_cost + ~help_text:"Syntax: -inline-prim-cost | =[,...]" + let _inline_branch_cost spec = + Int_arg_helper.parse spec ~update:inline_branch_cost + ~help_text:"Syntax: -inline-branch-cost | =[,...]" + let _inline_indirect_cost spec = + Int_arg_helper.parse spec ~update:inline_indirect_cost + ~help_text:"Syntax: -inline-indirect-cost | =[,...]" + let _inline_lifting_benefit spec = + Int_arg_helper.parse spec ~update:inline_lifting_benefit + ~help_text:"Syntax: -inline-lifting-benefit | =[,...]" + let _inline_branch_factor spec = + Float_arg_helper.parse spec ~update:inline_branch_factor + ~help_text:"Syntax: -inline-branch-factor | =[,...]" let _intf = intf let _intf_suffix s = Config.interface_suffix := s let _keep_docs = set keep_docs + let _no_keep_docs = clear keep_docs let _keep_locs = set keep_locs + let _no_keep_locs = clear keep_locs let _labels = clear classic let _linkall = set link_everything + let _inline_max_depth spec = + Int_arg_helper.parse spec ~update:inline_max_depth + ~help_text:"Syntax: -inline-max-depth | =[,...]" + let _alias_deps = clear transparent_modules let _no_alias_deps = set transparent_modules + let _app_funct = set applicative_functors let _no_app_funct = clear applicative_functors let _no_float_const_prop = clear float_const_prop let _noassert = set noassert @@ -102,25 +168,52 @@ module Options = Main_args.Make_optcomp_options (struct let _nodynlink = clear dlcode let _nolabels = set classic let _nostdlib = set no_std_include + let _no_unbox_free_vars_of_closures = clear unbox_free_vars_of_closures + let _no_unbox_specialised_args = clear unbox_specialised_args let _o s = output_name := Some s + (* CR-someday mshinwell: should stop e.g. -O2 -classic-inlining + lgesbert: could be done in main() below, like for -pack and -c, but that + would prevent overriding using OCAMLPARAM. + mshinwell: We're going to defer this for the moment and add a note in + the manual that the behaviour is unspecified in cases such as this. + We should refactor the code so that the user's requirements are + collected, then checked all at once for illegal combinations, and then + transformed into the settings of the individual parameters. + *) + let _o2 () = + default_simplify_rounds := 2; + use_inlining_arguments_set o2_arguments; + use_inlining_arguments_set ~round:0 o1_arguments + let _o3 () = + default_simplify_rounds := 3; + use_inlining_arguments_set o3_arguments; + use_inlining_arguments_set ~round:1 o2_arguments; + use_inlining_arguments_set ~round:0 o1_arguments let _open s = open_modules := s :: !open_modules let _output_obj = set output_c_object - let _output_complete_obj s = - set output_c_object s; set output_complete_object s + let _output_complete_obj () = + set output_c_object (); set output_complete_object () let _p = set gprofile let _pack = set make_package let _pp s = preprocessor := Some s let _ppx s = first_ppx := s :: !first_ppx let _principal = set principal + let _no_principal = clear principal let _rectypes = set recursive_types + let _no_rectypes = clear recursive_types + let _remove_unused_arguments = set remove_unused_arguments let _runtime_variant s = runtime_variant := s let _safe_string = clear unsafe_string let _short_paths = clear real_paths let _strict_sequence = set strict_sequence + let _no_strict_sequence = clear strict_sequence let _strict_formats = set strict_formats + let _no_strict_formats = clear strict_formats let _shared () = shared := true; dlcode := true let _S = set keep_asm_file let _thread = set use_threads + let _unbox_closures = set unbox_closures + let _unbox_closures_factor f = unbox_closures_factor := f let _unsafe = set fast let _unsafe_string = set unsafe_string let _v () = print_version_and_library "native-code compiler" @@ -130,6 +223,11 @@ module Options = Main_args.Make_optcomp_options (struct let _w s = Warnings.parse_options false s 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 + | None -> () + | Some setting -> Clflags.color := setting + end let _where () = print_standard_library () let _nopervasives = set nopervasives @@ -138,7 +236,15 @@ module Options = Main_args.Make_optcomp_options (struct let _dtypedtree = set dump_typedtree let _drawlambda = set dump_rawlambda let _dlambda = set dump_lambda + let _drawclambda = set dump_rawclambda let _dclambda = set dump_clambda + let _drawflambda = set dump_rawflambda + let _dflambda = set dump_flambda + let _dflambda_let stamp = dump_flambda_let := Some stamp + let _dflambda_verbose () = + set dump_flambda (); + set dump_flambda_verbose () + let _dflambda_no_invariants = clear flambda_invariant_checks let _dcmm = set dump_cmm let _dsel = set dump_selection let _dcombine = set dump_combine @@ -153,6 +259,7 @@ module Options = Main_args.Make_optcomp_options (struct let _dscheduling = set dump_scheduling let _dlinear = set dump_linear let _dstartup = set keep_startup_file + let _dtimings = set print_timings let _opaque = set opaque let anonymous = anonymous @@ -183,7 +290,7 @@ let main () = Compmisc.init_path true; let target = extract_output !output_name in Asmpackager.package_files ppf (Compmisc.initial_env ()) - (get_objfiles ()) target; + (get_objfiles ()) target ~backend; Warnings.check_fatal (); end else if !shared then begin @@ -212,9 +319,11 @@ let main () = Asmlink.link ppf (get_objfiles ()) target; Warnings.check_fatal (); end; - exit 0 with x -> Location.report_exception ppf x; exit 2 -let _ = main () +let _ = + Timings.(time All) main (); + if !Clflags.print_timings then Timings.print Format.std_formatter; + exit 0 diff --git a/driver/optmain.mli b/driver/optmain.mli index d43cb760..f0911cea 100644 --- a/driver/optmain.mli +++ b/driver/optmain.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* this "empty" file is here to speed up garbage collection in ocamlopt.opt diff --git a/driver/pparse.ml b/driver/pparse.ml index b67c1805..527291ed 100644 --- a/driver/pparse.ml +++ b/driver/pparse.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) open Format @@ -34,7 +37,9 @@ let call_external_preprocessor sourcefile pp = let preprocess sourcefile = match !Clflags.preprocessor with None -> sourcefile - | Some pp -> call_external_preprocessor sourcefile pp + | Some pp -> + Timings.(time (Preprocessing sourcefile)) + (call_external_preprocessor sourcefile) pp let remove_preprocessed inputfile = @@ -143,7 +148,7 @@ let open_and_check_magic inputfile ast_magic = in (ic, is_ast_file) -let file ppf ~tool_name inputfile parse_fun ast_magic = +let file_aux ppf ~tool_name inputfile parse_fun invariant_fun ast_magic = let (ic, is_ast_file) = open_and_check_magic inputfile ast_magic in let ast = try @@ -164,8 +169,12 @@ let file ppf ~tool_name inputfile parse_fun ast_magic = with x -> close_in ic; raise x in close_in ic; - apply_rewriters ~restore:false ~tool_name ast_magic ast + let ast = apply_rewriters ~restore:false ~tool_name ast_magic ast in + if is_ast_file || !Clflags.all_ppx <> [] then invariant_fun ast; + ast +let file ppf ~tool_name inputfile parse_fun ast_magic = + file_aux ppf ~tool_name inputfile parse_fun ignore ast_magic let report_error ppf = function | CannotRun cmd -> @@ -182,11 +191,11 @@ let () = | _ -> None ) -let parse_all ~tool_name parse_fun magic ppf sourcefile = +let parse_all ~tool_name parse_fun invariant_fun magic ppf sourcefile = Location.input_name := sourcefile; let inputfile = preprocess sourcefile in let ast = - try file ppf ~tool_name inputfile parse_fun magic + try file_aux ppf ~tool_name inputfile parse_fun invariant_fun magic with exn -> remove_preprocessed inputfile; raise exn @@ -195,8 +204,12 @@ let parse_all ~tool_name parse_fun magic ppf sourcefile = ast let parse_implementation ppf ~tool_name sourcefile = - parse_all ~tool_name Parse.implementation + parse_all ~tool_name + (Timings.(time (Parsing sourcefile)) Parse.implementation) + Ast_invariants.structure Config.ast_impl_magic_number ppf sourcefile let parse_interface ppf ~tool_name sourcefile = - parse_all ~tool_name Parse.interface + parse_all ~tool_name + (Timings.(time (Parsing sourcefile)) Parse.interface) + Ast_invariants.signature Config.ast_intf_magic_number ppf sourcefile diff --git a/driver/pparse.mli b/driver/pparse.mli index 64976989..4ccb0925 100644 --- a/driver/pparse.mli +++ b/driver/pparse.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) open Format @@ -20,20 +23,28 @@ exception Error of error val preprocess : string -> string val remove_preprocessed : string -> unit -val file : formatter -> tool_name:string -> string -> (Lexing.lexbuf -> 'a) -> string -> 'a +val file : + formatter -> tool_name:string -> string -> (Lexing.lexbuf -> 'a) -> string -> + 'a val apply_rewriters: ?restore:bool -> tool_name:string -> string -> 'a -> 'a - (** If [restore = true] (the default), cookies set by external rewriters will be - kept for later calls. *) + (** If [restore = true] (the default), cookies set by external + rewriters will be kept for later calls. *) -val apply_rewriters_str: ?restore:bool -> tool_name:string -> Parsetree.structure -> Parsetree.structure -val apply_rewriters_sig: ?restore:bool -> tool_name:string -> Parsetree.signature -> Parsetree.signature +val apply_rewriters_str: + ?restore:bool -> tool_name:string -> Parsetree.structure -> + Parsetree.structure +val apply_rewriters_sig: + ?restore:bool -> tool_name:string -> Parsetree.signature -> + Parsetree.signature val report_error : formatter -> error -> unit -val parse_implementation: formatter -> tool_name:string -> string -> Parsetree.structure -val parse_interface: formatter -> tool_name:string -> string -> Parsetree.signature +val parse_implementation: + formatter -> tool_name:string -> string -> Parsetree.structure +val parse_interface: + formatter -> tool_name:string -> string -> Parsetree.signature (* [call_external_preprocessor sourcefile pp] *) val call_external_preprocessor : string -> string -> string diff --git a/emacs/.ignore b/emacs/.ignore deleted file mode 100644 index ba5f96cd..00000000 --- a/emacs/.ignore +++ /dev/null @@ -1,2 +0,0 @@ -ocamltags -*.elc diff --git a/emacs/Makefile b/emacs/Makefile index 22b2a19b..93b2d7d7 100644 --- a/emacs/Makefile +++ b/emacs/Makefile @@ -1,14 +1,16 @@ -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 1997 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU General Public License. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1997 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU General Public License. * +#* * +#************************************************************************** include ../config/Makefile diff --git a/emacs/caml-compat.el b/emacs/caml-compat.el index a5cff879..782d2d47 100644 --- a/emacs/caml-compat.el +++ b/emacs/caml-compat.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -;(* *) -;(* Copyright 1998 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +;* * +;* Copyright 1998 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;; function definitions for old versions of emacs diff --git a/emacs/caml-emacs.el b/emacs/caml-emacs.el index 7166d1a8..13f72c46 100644 --- a/emacs/caml-emacs.el +++ b/emacs/caml-emacs.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Didier Remy, projet Cristal, INRIA Rocquencourt *) -;(* *) -;(* Copyright 2003 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Didier Remy, projet Cristal, INRIA Rocquencourt * +;* * +;* Copyright 2003 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;; for caml-help.el (defalias 'caml-info-other-window 'info-other-window) diff --git a/emacs/caml-font-old.el b/emacs/caml-font-old.el index 7456e8c5..674beb68 100644 --- a/emacs/caml-font-old.el +++ b/emacs/caml-font-old.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Jacques Garrigue and Ian T Zimmerman *) -;(* *) -;(* Copyright 1997 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Jacques Garrigue and Ian T Zimmerman * +;* * +;* Copyright 1997 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;; useful colors diff --git a/emacs/caml-font.el b/emacs/caml-font.el index 40bee0a3..ac339744 100644 --- a/emacs/caml-font.el +++ b/emacs/caml-font.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Jacques Garrigue, Ian T Zimmerman, Damien Doligez *) -;(* *) -;(* Copyright 1997 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Jacques Garrigue, Ian T Zimmerman, Damien Doligez * +;* * +;* Copyright 1997 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;; caml-font: font-lock support for OCaml files ;; now with perfect parsing of comments and strings @@ -172,23 +174,28 @@ "'\\(\015\012\\|[\012\015]\\)" ) +; match an opening delimiter for a quoted string +(defconst caml-font-quoted-string-start-re + "{\\([a-z]*\\)|" +) + ; match any token or sequence of tokens that cannot contain a -; quote, double quote, a start of comment, or a newline +; quote, double quote, a start of comment or quoted string, or a newline ; note: this is only to go faster than one character at a time (defconst caml-font-other-re - "[^A-Za-z_0-9\012\015\300-\326\330-\366\370-\377'\"(]+" + "[^A-Za-z_0-9\012\015\300-\326\330-\366\370-\377'\"({]+" ) ; match any sequence of non-special characters in a comment ; note: this is only to go faster than one character at a time (defconst caml-font-other-comment-re - "[^(*\"'\012\015]+" + "[^{(*\"'\012\015]+" ) ; match any sequence of non-special characters in a string ; note: this is only to go faster than one character at a time (defconst caml-font-other-string-re - "[^\\\"\012\015]" + "[^|\\\"\012\015]" ) ; match a newline @@ -230,8 +237,9 @@ ; depth is the depth of nested comments at this point ; it must be a non-negative integer ; st can be: -; nil -- we are in the base state -; t -- we are within a string +; nil -- we are in the base state +; t -- we are within a string +; a string -- we are within a quoted string and st is the closing delimiter (defun caml-font-annotate (st depth) (let ((continue t)) @@ -254,6 +262,11 @@ 'syntax-table (string-to-syntax "|")) (goto-char (match-end 0)) (setq st t)) + ((caml-font-looking-at caml-font-quoted-string-start-re) + (put-text-property (point) (1+ (point)) + 'syntax-table (string-to-syntax "|")) + (goto-char (match-end 0)) + (setq st (concat "|" (match-string 1) "}"))) ((caml-font-looking-at "(\\*") (put-text-property (point) (1+ (point)) 'syntax-table (string-to-syntax "!")) @@ -297,7 +310,7 @@ (remove-text-properties (point) (1+ (point)) '(syntax-table nil caml-font-state nil)) (goto-char (1+ (point)))))) - (t ; string state inside or outside a comment + ((equal st t) ; string state inside or outside a comment (cond ((caml-font-looking-at "\"") (when (= depth 0) @@ -315,7 +328,24 @@ (t (remove-text-properties (point) (1+ (point)) '(syntax-table nil caml-font-state nil)) - (goto-char (1+ (point))))))))) + (goto-char (1+ (point)))))) + ((stringp st) ; quoted-string state inside or outside comment + (cond + ((caml-font-looking-at st) + (when (= depth 0) + (put-text-property (1- (match-end 0)) (match-end 0) + 'syntax-table (string-to-syntax "|"))) + (goto-char (match-end 0)) + (setq st nil)) + ((caml-font-looking-at caml-font-other-string-re) + (goto-char (match-end 0))) + (t + (remove-text-properties (point) (1+ (point)) + '(syntax-table nil caml-font-state nil)) + (goto-char (1+ (point)))))) + (t ; should not happen + (remove-text-properties (point) (1+ (point)) + '(syntax-table nil caml-font-state nil)))))) ) ; This is the hook function for font-lock-extend-after-change-function diff --git a/emacs/caml-help.el b/emacs/caml-help.el index 82defadc..6b1abc65 100644 --- a/emacs/caml-help.el +++ b/emacs/caml-help.el @@ -1,15 +1,17 @@ ;;; caml-help.el --- Contextual completion and help to caml-mode -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Didier Remy, projet Cristal, INRIA Rocquencourt *) -;(* *) -;(* Copyright 2001 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Didier Remy, projet Cristal, INRIA Rocquencourt * +;* * +;* Copyright 2001 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;; Author: Didier Remy, November 2001. @@ -197,7 +199,8 @@ (insert-file-contents file)) (message "Module %s not found" module)) (while (re-search-forward - "\\([ \t]*val\\|let\\|exception\\|external\\| [|]\\) \\([a-zA-Z_0-9'][a-zA-Z_0-9']*\\)\\|^ *[{]* \\([a-z_][A-Za-z_0-9]*\\) : [^;\n][^;\n]*;" + (concat "\\([ \t]*val\\|let\\|exception\\|external\\| [|]\\) \\([a-zA-Z_0-9'][a-zA-Z_0-9']*\\)" + "\\|^ *[{]* \\([a-z_][A-Za-z_0-9]*\\) : [^;\n][^;\n]*;") (point-max) 'move) (pop-to-buffer (current-buffer)) (setq alist (cons (or (match-string 2) (match-string 3)) alist))) diff --git a/emacs/caml-hilit.el b/emacs/caml-hilit.el index 13735594..03d6465c 100644 --- a/emacs/caml-hilit.el +++ b/emacs/caml-hilit.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Jacques Garrigue and Ian T Zimmerman *) -;(* *) -;(* Copyright 1997 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Jacques Garrigue and Ian T Zimmerman * +;* * +;* Copyright 1997 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ; Highlighting patterns for hilit19 under caml-mode diff --git a/emacs/caml-types.el b/emacs/caml-types.el index 0af667bd..7ecc5d4b 100644 --- a/emacs/caml-types.el +++ b/emacs/caml-types.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -;(* *) -;(* Copyright 2003 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Damien Doligez, projet Moscova, INRIA Rocquencourt * +;* * +;* Copyright 2003 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ; An emacs-lisp complement to the "-annot" option of ocamlc and ocamlopt. diff --git a/emacs/caml-xemacs.el b/emacs/caml-xemacs.el index f74c883c..110817ff 100644 --- a/emacs/caml-xemacs.el +++ b/emacs/caml-xemacs.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Didier Remy, projet Cristal, INRIA Rocquencourt *) -;(* *) -;(* Copyright 2003 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Didier Remy, projet Cristal, INRIA Rocquencourt * +;* * +;* Copyright 2003 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** (require 'overlay) diff --git a/emacs/caml.el b/emacs/caml.el index 6ad464ae..2bf4246d 100644 --- a/emacs/caml.el +++ b/emacs/caml.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Jacques Garrigue and Ian T Zimmerman *) -;(* *) -;(* Copyright 1997 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Jacques Garrigue and Ian T Zimmerman * +;* * +;* Copyright 1997 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;;; caml.el --- OCaml code editing commands for Emacs diff --git a/emacs/camldebug.el b/emacs/camldebug.el index 6e83bacc..674cd320 100644 --- a/emacs/camldebug.el +++ b/emacs/camldebug.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Jacques Garrigue and Ian T Zimmerman *) -;(* *) -;(* Copyright 1997 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Jacques Garrigue and Ian T Zimmerman * +;* * +;* Copyright 1997 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;;; Run camldebug under Emacs ;;; Derived from gdb.el. diff --git a/emacs/inf-caml.el b/emacs/inf-caml.el index 8a775772..05bf318f 100644 --- a/emacs/inf-caml.el +++ b/emacs/inf-caml.el @@ -1,14 +1,16 @@ -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Xavier Leroy and Jacques Garrigue *) -;(* *) -;(* Copyright 1997 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Xavier Leroy and Jacques Garrigue * +;* * +;* Copyright 1997 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;;; inf-caml.el --- run the OCaml toplevel in an Emacs buffer diff --git a/emacs/ocamltags.in b/emacs/ocamltags.in index 7b1f41cf..4be9e79d 100644 --- a/emacs/ocamltags.in +++ b/emacs/ocamltags.in @@ -1,16 +1,18 @@ ":" ; @EMACS@ -batch -l $0 "$@" ; status=$? ; : '--*-Emacs-Lisp-*--' <<';' -;(***********************************************************************) -;(* *) -;(* OCaml *) -;(* *) -;(* Jacques Garrigue and Ian T Zimmerman *) -;(* *) -;(* Copyright 1998 Institut National de Recherche en Informatique et *) -;(* en Automatique. All rights reserved. This file is distributed *) -;(* under the terms of the GNU General Public License. *) -;(* *) -;(***********************************************************************) +;************************************************************************** +;* * +;* OCaml * +;* * +;* Jacques Garrigue and Ian T Zimmerman * +;* * +;* Copyright 1998 Institut National de Recherche en Informatique et * +;* en Automatique. * +;* * +;* All rights reserved. This file is distributed under the terms of * +;* the GNU General Public License. * +;* * +;************************************************************************** ;; Copyright (C) 1998 Ian Zimmerman ;; This program is free software; you can redistribute it and/or diff --git a/lex/.ignore b/lex/.ignore deleted file mode 100644 index 9f4f308d..00000000 --- a/lex/.ignore +++ /dev/null @@ -1,6 +0,0 @@ -parser.ml -parser.mli -lexer.ml -ocamllex -ocamllex.opt -parser.output diff --git a/lex/Makefile b/lex/Makefile index 3691cb2b..fefaaa2c 100644 --- a/lex/Makefile +++ b/lex/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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. * +#* * +#************************************************************************** # The lexer generator include ../config/Makefile diff --git a/lex/Makefile.nt b/lex/Makefile.nt index 6bd85604..44384c77 100644 --- a/lex/Makefile.nt +++ b/lex/Makefile.nt @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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. * +#* * +#************************************************************************** # The lexer generator @@ -17,7 +20,12 @@ CAMLRUN ?= ../boot/ocamlrun CAMLYACC ?= ../boot/ocamlyacc CAMLC=$(CAMLRUN) ../boot/ocamlc -I ../boot -CAMLOPT=$(CAMLRUN) ../ocamlopt -I ../stdlib +ifeq "$(wildcard ../flexdll/Makefile)" "" + FLEXLINK_ENV= +else + FLEXLINK_ENV=OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe" +endif +CAMLOPT=$(FLEXLINK_ENV) $(CAMLRUN) ../ocamlopt -I ../stdlib COMPFLAGS=-warn-error A LINKFLAGS= YACCFLAGS=-v @@ -45,7 +53,7 @@ parser.ml parser.mli: parser.mly $(CAMLYACC) $(YACCFLAGS) parser.mly clean:: - rm -f parser.ml parser.mli + rm -f parser.ml parser.mli parser.output beforedepend:: parser.ml parser.mli diff --git a/lex/common.ml b/lex/common.ml index 9b86ba11..38f82915 100644 --- a/lex/common.ml +++ b/lex/common.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, projet Moscova, *) -(* INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, projet Moscova, *) +(* INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) open Printf open Syntax diff --git a/lex/common.mli b/lex/common.mli index de23959c..f00b50d7 100644 --- a/lex/common.mli +++ b/lex/common.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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 line_tracker;; val open_tracker : string -> out_channel -> line_tracker diff --git a/lex/compact.ml b/lex/compact.ml index f468a557..5bf7e68d 100644 --- a/lex/compact.ml +++ b/lex/compact.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compaction of an automata *) diff --git a/lex/compact.mli b/lex/compact.mli index 90f2ed99..936835eb 100644 --- a/lex/compact.mli +++ b/lex/compact.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compaction of an automata *) type lex_tables = diff --git a/lex/cset.ml b/lex/cset.ml index f4581ba3..81515eae 100644 --- a/lex/cset.ml +++ b/lex/cset.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, Jerome Vouillon projet Cristal, *) -(* INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, Jerome Vouillon projet Cristal, *) +(* INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) exception Bad diff --git a/lex/cset.mli b/lex/cset.mli index daad6e59..527d53d1 100644 --- a/lex/cset.mli +++ b/lex/cset.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, Jerome Vouillon projet Cristal, *) -(* INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, Jerome Vouillon projet Cristal, *) +(* INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* Set of characters encoded as list of intervals *) diff --git a/lex/lexer.mli b/lex/lexer.mli index ca8e4c49..28d00eaa 100644 --- a/lex/lexer.mli +++ b/lex/lexer.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) val main: Lexing.lexbuf -> Parser.token diff --git a/lex/lexer.mll b/lex/lexer.mll index eebd7115..99dd66f5 100644 --- a/lex/lexer.mll +++ b/lex/lexer.mll @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexical analyzer for lexer definitions. Bootstrapped! *) @@ -226,7 +229,8 @@ and string = parse | eof { raise(Lexical_error("unterminated string", "", 0, 0)) } | '\013'* '\010' as s - { warning lexbuf (Printf.sprintf "unescaped newline in string") ; + { if !comment_depth = 0 then + warning lexbuf (Printf.sprintf "unescaped newline in string") ; store_string_chars s; incr_loc lexbuf 0; string lexbuf } @@ -299,5 +303,5 @@ and skip_char = parse | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] "'" | '\\' 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "'" {()} -(* A dieu va ! *) +(* Perilous *) | "" {()} diff --git a/lex/lexgen.ml b/lex/lexgen.ml index 503b08fa..74d99c74 100644 --- a/lex/lexgen.ml +++ b/lex/lexgen.ml @@ -1,16 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, *) -(* Luc Maranget, projet Moscova, *) -(* INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compiling a lexer definition *) diff --git a/lex/lexgen.mli b/lex/lexgen.mli index 3fc8c905..306f475a 100644 --- a/lex/lexgen.mli +++ b/lex/lexgen.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* raised when there are too many bindings (>= 254 memory cells) *) exception Memory_overflow diff --git a/lex/main.ml b/lex/main.ml index 076873f1..d49d832e 100644 --- a/lex/main.ml +++ b/lex/main.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexer generator. Command-line parsing. *) diff --git a/lex/output.ml b/lex/output.ml index 638260c2..28832039 100644 --- a/lex/output.ml +++ b/lex/output.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Output the DFA tables and its entry points *) diff --git a/lex/output.mli b/lex/output.mli index 9d0bd9fc..c591824b 100644 --- a/lex/output.mli +++ b/lex/output.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Output the DFA tables and its entry points *) diff --git a/lex/outputbis.ml b/lex/outputbis.ml index 709ec0ee..05b83118 100644 --- a/lex/outputbis.ml +++ b/lex/outputbis.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Output the DFA tables and its entry points *) diff --git a/lex/outputbis.mli b/lex/outputbis.mli index fb51cdec..93a84b0d 100644 --- a/lex/outputbis.mli +++ b/lex/outputbis.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget projet Moscova INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget projet Moscova INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) val output_lexdef : string -> diff --git a/lex/parser.mly b/lex/parser.mly index 459b7870..99586528 100644 --- a/lex/parser.mly +++ b/lex/parser.mly @@ -1,14 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 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. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The grammar for lexer definitions */ diff --git a/lex/syntax.ml b/lex/syntax.ml index b2993eaa..61a9d793 100644 --- a/lex/syntax.ml +++ b/lex/syntax.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* This apparently useless implementation file is in fact required by the pa_ocamllex syntax extension *) diff --git a/lex/syntax.mli b/lex/syntax.mli index 6871dd11..eb0acefa 100644 --- a/lex/syntax.mli +++ b/lex/syntax.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The shallow abstract syntax *) diff --git a/lex/table.ml b/lex/table.ml index 715d9075..7e0b9d0c 100644 --- a/lex/table.ml +++ b/lex/table.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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 'a t = {mutable next : int ; mutable data : 'a array} diff --git a/lex/table.mli b/lex/table.mli index 8d9938cb..492626b9 100644 --- a/lex/table.mli +++ b/lex/table.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Luc Maranget, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* Table used for code emission, ie extensible arrays *) type 'a t diff --git a/man/Makefile b/man/Makefile index c1c2df37..7008b951 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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 diff --git a/man/ocaml.m b/man/ocaml.m index 5c839ea6..54d20a99 100644 --- a/man/ocaml.m +++ b/man/ocaml.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAML 1 @@ -93,11 +96,7 @@ directive. .TP .BI \-init \ file Load the given file instead of the default initialization file. -The default file is -.B .ocamlinit -in the current directory if it exists, otherwise -.B .ocamlinit -in the user's home directory. +See the "Initialization file" section below. .TP .B \-labels Labels are not ignored in types, labels may be used in applications, @@ -114,6 +113,10 @@ Do not compile assertion checks. Note that the special form .B assert\ false is always compiled because it is typed specially. .TP +.B \-noinit +Do not load any initialization file. +See the "Initialization file" section below. +.TP .B \-nolabels Ignore non-optional labels in types. Labels cannot be used in applications, and parameter order becomes strict. @@ -235,6 +238,26 @@ as a script file name, even when it starts with a hyphen (-). .BR \-help \ or \ \-\-help Display a short usage summary and exit. +.SH INITIALIZATION FILE + +When +.BR ocaml (1) +is invoked, it will read phrases from an initialization file before +giving control to the user. The default file is +.B .ocamlinit +in the current directory if it exists, otherwise +.B .ocamlinit +in the user's home directory. You can specify a different initialization file +by using the +.BI \-init \ file +option, and disable initialization files by using the +.B \-noinit +option. + +Note that you can also use the +.B #use +directive to read phrases from a file. + .SH ENVIRONMENT VARIABLES .TP .B LC_CTYPE diff --git a/man/ocamlc.m b/man/ocamlc.m index adb28092..b5360dcf 100644 --- a/man/ocamlc.m +++ b/man/ocamlc.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLC 1 @@ -190,7 +193,7 @@ linking with this library automatically adds back the .BR \-custom , \ \-cclib \ and \ \-ccopt options as if they had been provided on the command line, unless the -.B -noautolink +.B \-noautolink option is given. Additionally, a substring .B $CAMLORIGIN inside a @@ -258,6 +261,27 @@ option). 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. + .TP .B \-compat\-32 Check that the generated bytecode executable can run on 32-bit @@ -313,10 +337,18 @@ executable file, where .BR ocamlrun (1) can find it and use it. .TP -.BI \-for\-pack \ ident -This option is accepted for compatibility with -.BR ocamlopt (1) -; it does nothing. +.BI \-for\-pack \ module\-path +Generate an object file (.cmo file) that can later be included +as a sub-module (with the given access path) of a compilation unit +constructed with +.BR \-pack . +For instance, +.B ocamlc\ \-for\-pack\ P\ \-c\ A.ml +will generate a.cmo that can later be used with +.BR "ocamlc -pack -o P.cmo a.cmo" . +Note: you can still pack a module that was compiled without +.B \-for\-pack +but in this case exceptions will be printed with the wrong names. .TP .B \-g Add debugging information while compiling and linking. This option is @@ -847,6 +879,9 @@ mutually recursive types. 50 \ \ Unexpected documentation comment. +59 +\ \ Assignment on non-mutable value. + The letters stand for the following sets of warnings. Any letter not mentioned here corresponds to the empty set. @@ -929,8 +964,8 @@ compiling your program with later versions of OCaml when they add new warnings or modify existing warnings. The default setting is -.B \-warn\-error \-a -(all warnings are non-fatal). +.B \-warn\-error \-a+31 +(all warnings are non-fatal except 31). .TP .B \-warn\-help Show the description of all available warning numbers. diff --git a/man/ocamlcp.m b/man/ocamlcp.m index 7967f25d..d6c983d1 100644 --- a/man/ocamlcp.m +++ b/man/ocamlcp.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH "OCAMLCP" 1 diff --git a/man/ocamldebug.m b/man/ocamldebug.m index 50354d93..f03ad60f 100644 --- a/man/ocamldebug.m +++ b/man/ocamldebug.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 2001 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLDEBUG 1 @@ -95,6 +98,22 @@ Print short version number and exit. .TP .BR \-help \ or \ \-\-help Display a short usage summary and exit. + +.SH INITIALIZATION FILE + +When +.BR ocamldebug (1) +is invoked, it will read commands from an initialization file before +giving control to the user. The default file is +.B .ocamldebug +in the current directory if it exists, otherwise +.B .ocamldebug +in the user's home directory. + +Note that you can also use the +.B source file +command to read commands from a file. + .SH SEE ALSO .BR ocamlc (1) .br diff --git a/man/ocamldep.m b/man/ocamldep.m index ba7ddb8c..ee6a641a 100644 --- a/man/ocamldep.m +++ b/man/ocamldep.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLDEP 1 @@ -57,6 +60,26 @@ The following command-line options are recognized by .B \-absname Show absolute filenames in error messages. .TP +.B \-all +Generate dependencies on all required files, rather than assuming +implicit dependencies. +.TP +.B \-allow\-approx +Allow falling back on a lexer-based approximation when parsing fails. +.TP +.B \-as\-map +For the following files, do not include delayed dependencies for +module aliases. +This option assumes that they are compiled using options +"\-no\-alias\-deps \-w \-49", and that those files or their interface are +passed with the "\-map" option when computing dependencies for other +files. Note also that for dependencies to be correct in the +implementation of a map file, its interface should not coerce any of +the aliases it contains. +.TP +.B \-debug\-map +Dump the delayed dependency map for each map file. +.TP .BI \-I \ directory Add the given directory to the list of directories searched for source files. If a source file foo.ml mentions an external @@ -72,6 +95,22 @@ the same .B \-I options that are passed to the compiler. .TP +.BI \-impl \ file +Process +.IR file +as a .ml file. +.TP +.BI \-intf \ file +Process +.IR file +as a .mli file. +.TP +.BI \-map \ file +Read an propagate the delayed dependencies for module aliases in +.IR file , +so that the following files will depend on the +exported aliased modules if they use them. +.TP .BI \-ml\-synonym \ .ext Consider the given extension (with leading dot) to be a synonym for .ml. .TP @@ -107,6 +146,15 @@ causes dependencies on native compiled files (.cmx) to be generated instead of on .cmo files. (This flag makes no difference if all source files have explicit .mli interface files.) .TP +.B \-one-line +Output one line per file, regardless of the length. +.TP +.BI \-open \ module +Assume that module +.IR module +is opened before parsing each of the +following files. +.TP .BI \-pp \ command Cause .BR ocamldep (1) @@ -121,6 +169,9 @@ Pipe abstract syntax tree through preprocessor .B \-slash Under Unix, this option does nothing. .TP +.B \-sort +Sort files according to their dependencies. +.TP .B \-version Print version string and exit. .TP diff --git a/man/ocamldoc.m b/man/ocamldoc.m index ca0a2334..2b2ba3c6 100644 --- a/man/ocamldoc.m +++ b/man/ocamldoc.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Maxence Guesdon, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 2004 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Maxence Guesdon, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 2004 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLDOC 1 diff --git a/man/ocamllex.m b/man/ocamllex.m index d59755ba..58e03627 100644 --- a/man/ocamllex.m +++ b/man/ocamllex.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLLEX 1 diff --git a/man/ocamlmktop.m b/man/ocamlmktop.m index fd6aaa82..09a4126c 100644 --- a/man/ocamlmktop.m +++ b/man/ocamlmktop.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* 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 Q Public License version 1.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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLMKTOP 1 diff --git a/man/ocamlopt.m b/man/ocamlopt.m index a541e598..1d50c143 100644 --- a/man/ocamlopt.m +++ b/man/ocamlopt.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLOPT 1 diff --git a/man/ocamlprof.m b/man/ocamlprof.m index a3bac2c6..97d56714 100644 --- a/man/ocamlprof.m +++ b/man/ocamlprof.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLPROF 1 diff --git a/man/ocamlrun.m b/man/ocamlrun.m index 810f5258..737ac696 100644 --- a/man/ocamlrun.m +++ b/man/ocamlrun.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLRUN 1 @@ -108,11 +111,15 @@ default to the library directory specified when compiling OCaml. .B OCAMLRUNPARAM Set the runtime system options and garbage collection parameters. (If OCAMLRUNPARAM is not set, CAMLRUNPARAM will be used instead.) -This variable must be a sequence of parameter specifications. -A parameter specification is an option letter followed by an = +This variable must be a sequence of parameter specifications separated +by commas. +A parameter specification is a letter, optionally followed by an = sign, a decimal number (or a hexadecimal number prefixed by .BR 0x ), -and an optional multiplier. The options are documented below; the +and an optional multiplier. If the letter is followed by anything +else, the corresponding option is set to 1. Unknown letters +are ignored. +The options are documented below; the last six correspond to the fields of the .B control record documented in @@ -196,11 +203,19 @@ shared libraries). .BR 0x200 Computation of compaction-triggering condition. +.BR 0x400 +Output GC statistics at program exit, in the same format as Gc.print_stat. + The multiplier is .BR k , .BR M ,\ or .BR G , for multiplication by 2^10, 2^20, and 2^30 respectively. + +If the option letter is not recognized, the whole parameter is ignored; +if the equal sign or the number is missing, the value is taken as 1; +if the multiplier is not recognized, it is ignored. + For example, on a 32-bit machine under bash, the command .B export OCAMLRUNPARAM='s=256k,v=1' tells a subsequent @@ -210,7 +225,7 @@ a message at the start of each major GC cycle. .TP .B CAMLRUNPARAM If OCAMLRUNPARAM is not found in the environment, then CAMLRUNPARAM -will be used instead. If CAMLRUNPARAM is not found, then the default +will be used instead. If CAMLRUNPARAM is also not found, then the default values will be used. .TP .B PATH diff --git a/man/ocamlyacc.m b/man/ocamlyacc.m index 133994e2..57df9e74 100644 --- a/man/ocamlyacc.m +++ b/man/ocamlyacc.m @@ -1,14 +1,17 @@ -.\"*********************************************************************** -.\"* * -.\"* OCaml * -.\"* * -.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * -.\"* * -.\"* Copyright 1996 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. * -.\"* * -.\"*********************************************************************** +.\"************************************************************************** +.\"* * +.\"* OCaml * +.\"* * +.\"* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +.\"* * +.\"* Copyright 1996 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. * +.\"* * +.\"************************************************************************** .\" .TH OCAMLYACC 1 diff --git a/middle_end/alias_analysis.ml b/middle_end/alias_analysis.ml new file mode 100644 index 00000000..2486312f --- /dev/null +++ b/middle_end/alias_analysis.ml @@ -0,0 +1,167 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type allocation_point = + | Symbol of Symbol.t + | Variable of Variable.t + +type allocated_const = + | Normal of Allocated_const.t + | Array of Lambda.array_kind * Asttypes.mutable_flag * Variable.t list + | Duplicate_array of Lambda.array_kind * Asttypes.mutable_flag * Variable.t + +type constant_defining_value = + | Allocated_const of allocated_const + | Block of Tag.t * Variable.t list + | Set_of_closures of Flambda.set_of_closures + | Project_closure of Flambda.project_closure + | Move_within_set_of_closures of Flambda.move_within_set_of_closures + | Project_var of Flambda.project_var + | Field of Variable.t * int + | Symbol_field of Symbol.t * int + | Const of Flambda.const + | Symbol of Symbol.t + | Variable of Variable.t + +type initialize_symbol_field = Variable.t option + +type definitions = { + variable : constant_defining_value Variable.Tbl.t; + initialize_symbol : initialize_symbol_field list Symbol.Tbl.t; + symbol : Flambda.constant_defining_value Symbol.Tbl.t; +} + +let print_constant_defining_value ppf = function + | Allocated_const (Normal const) -> Allocated_const.print ppf const + | Allocated_const (Array (_, _, vars)) -> + Format.fprintf ppf "[| %a |]" + (Format.pp_print_list Variable.print) vars + | Allocated_const (Duplicate_array (_, _, var)) -> + Format.fprintf ppf "dup_array(%a)" Variable.print var + | Block (tag, vars) -> + Format.fprintf ppf "[|%a: %a|]" + Tag.print tag + (Format.pp_print_list Variable.print) vars + | Set_of_closures set -> Flambda.print_set_of_closures ppf set + | Project_closure project -> Flambda.print_project_closure ppf project + | Move_within_set_of_closures move -> + Flambda.print_move_within_set_of_closures ppf move + | Project_var project -> Flambda.print_project_var ppf project + | Field (var, field) -> Format.fprintf ppf "%a.(%d)" Variable.print var field + | Symbol_field (sym, field) -> + Format.fprintf ppf "%a.(%d)" Symbol.print sym field + | Const const -> Flambda.print_const ppf const + | Symbol symbol -> Symbol.print ppf symbol + | Variable var -> Variable.print ppf var + +let rec resolve_definition + (definitions: definitions) + (var: Variable.t) + (def: constant_defining_value) + ~the_dead_constant : allocation_point = + match def with + | Allocated_const _ + | Block _ + | Set_of_closures _ + | Project_closure _ + | Const _ + | Move_within_set_of_closures _ -> + Variable var + | Project_var {var} -> + fetch_variable definitions (Var_within_closure.unwrap var) + ~the_dead_constant + | Variable v -> + fetch_variable definitions v + ~the_dead_constant + | Symbol sym -> Symbol sym + | Field (v, n) -> + begin match fetch_variable definitions v ~the_dead_constant with + | Symbol s -> + fetch_symbol_field definitions s n ~the_dead_constant + | Variable v -> + fetch_variable_field definitions v n ~the_dead_constant + end + | Symbol_field (symbol, field) -> + fetch_symbol_field definitions symbol field ~the_dead_constant + +and fetch_variable + (definitions: definitions) + (var: Variable.t) + ~the_dead_constant : allocation_point = + match Variable.Tbl.find definitions.variable var with + | exception Not_found -> Variable var + | def -> resolve_definition definitions var def ~the_dead_constant + +and fetch_variable_field + (definitions: definitions) + (var: Variable.t) + (field: int) + ~the_dead_constant : allocation_point = + match Variable.Tbl.find definitions.variable var with + | Block (_, fields) -> + begin match List.nth fields field with + | exception Not_found -> Symbol the_dead_constant + | v -> fetch_variable definitions v ~the_dead_constant + end + | exception Not_found -> + Misc.fatal_errorf "No definition for field access to %a" Variable.print var + | Symbol _ | Variable _ | Project_var _ | Field _ | Symbol_field _ -> + (* Must have been resolved *) + assert false + | Const _ | Allocated_const _ + | Set_of_closures _ | Project_closure _ | Move_within_set_of_closures _ -> + Symbol the_dead_constant + +and fetch_symbol_field + (definitions: definitions) + (sym: Symbol.t) + (field: int) + ~the_dead_constant : allocation_point = + match Symbol.Tbl.find definitions.symbol sym with + | Block (_, fields) -> + begin match List.nth fields field with + | exception Not_found -> Symbol the_dead_constant + | Symbol s -> Symbol s + | Const _ -> Symbol sym + end + | exception Not_found -> + begin match Symbol.Tbl.find definitions.initialize_symbol sym with + | fields -> + begin match List.nth fields field with + | None -> + Misc.fatal_errorf "constant field access to an inconstant %a" + Symbol.print sym + | Some v -> + fetch_variable definitions v ~the_dead_constant + end + | exception Not_found -> + Misc.fatal_errorf "No definition for field access to %a" + Symbol.print sym + end + | Allocated_const _ | Set_of_closures _ | Project_closure _ -> + Symbol the_dead_constant + +let run variable initialize_symbol symbol ~the_dead_constant = + let definitions = { variable; initialize_symbol; symbol; } in + Variable.Tbl.fold (fun var definition result -> + let definition = + resolve_definition definitions var definition ~the_dead_constant + in + Variable.Map.add var definition result) + definitions.variable + Variable.Map.empty diff --git a/middle_end/alias_analysis.mli b/middle_end/alias_analysis.mli new file mode 100644 index 00000000..515daeff --- /dev/null +++ b/middle_end/alias_analysis.mli @@ -0,0 +1,63 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type allocation_point = + | Symbol of Symbol.t + | Variable of Variable.t + +type allocated_const = + | Normal of Allocated_const.t + | Array of Lambda.array_kind * Asttypes.mutable_flag * Variable.t list + | Duplicate_array of Lambda.array_kind * Asttypes.mutable_flag * Variable.t + +type constant_defining_value = + | Allocated_const of allocated_const + | Block of Tag.t * Variable.t list + | Set_of_closures of Flambda.set_of_closures + | Project_closure of Flambda.project_closure + | Move_within_set_of_closures of Flambda.move_within_set_of_closures + | Project_var of Flambda.project_var + | Field of Variable.t * int + | Symbol_field of Symbol.t * int + | Const of Flambda.const + | Symbol of Symbol.t + | Variable of Variable.t + +type initialize_symbol_field = Variable.t option + +(** Simple alias analysis working over information about which + symbols have been assigned to variables; and which constants have + been assigned to symbols. The return value gives the assignment + of the defining values of constants to variables. + Also see comments for [Lift_constants], whose input feeds this + pass. + + Variables found to be ill-typed accesses to other constants, for + example arising from dead code, will be pointed at [the_dead_constant]. +*) +val run + : constant_defining_value Variable.Tbl.t + -> initialize_symbol_field list Symbol.Tbl.t + -> Flambda.constant_defining_value Symbol.Tbl.t + -> the_dead_constant:Symbol.t + -> allocation_point Variable.Map.t + +val print_constant_defining_value + : Format.formatter + -> constant_defining_value + -> unit diff --git a/middle_end/allocated_const.ml b/middle_end/allocated_const.ml new file mode 100644 index 00000000..10632a5f --- /dev/null +++ b/middle_end/allocated_const.ml @@ -0,0 +1,85 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = + | Float of float + | Int32 of int32 + | Int64 of int64 + | Nativeint of nativeint + | Float_array of float list + | Immutable_float_array of float list + | String of string + | Immutable_string of string + +let compare (x : t) (y : t) = + let compare_floats x1 x2 = + (* It is important to compare the bit patterns here, so as not to + be subject to bugs such as GPR#295. *) + Int64.compare (Int64.bits_of_float x1) (Int64.bits_of_float x2) + in + let rec compare_float_lists l1 l2 = + match l1, l2 with + | [], [] -> 0 + | [], _::_ -> -1 + | _::_, [] -> 1 + | h1::t1, h2::t2 -> + let c = compare_floats h1 h2 in + if c <> 0 then c else compare_float_lists t1 t2 + in + match x, y with + | Float x, Float y -> compare_floats x y + | Int32 x, Int32 y -> compare x y + | Int64 x, Int64 y -> compare x y + | Nativeint x, Nativeint y -> compare x y + | Float_array x, Float_array y -> compare_float_lists x y + | Immutable_float_array x, Immutable_float_array y -> compare_float_lists x y + | String x, String y -> compare x y + | Immutable_string x, Immutable_string y -> compare x y + | Float _, _ -> -1 + | _, Float _ -> 1 + | Int32 _, _ -> -1 + | _, Int32 _ -> 1 + | Int64 _, _ -> -1 + | _, Int64 _ -> 1 + | Nativeint _, _ -> -1 + | _, Nativeint _ -> 1 + | Float_array _, _ -> -1 + | _, Float_array _ -> 1 + | Immutable_float_array _, _ -> -1 + | _, Immutable_float_array _ -> 1 + | String _, _ -> -1 + | _, String _ -> 1 + +let print ppf (t : t) = + let fprintf = Format.fprintf in + let floats ppf fl = + List.iter (fun f -> fprintf ppf "@ %f" f) fl + in + match t with + | String s -> fprintf ppf "%S" s + | Immutable_string s -> fprintf ppf "#%S" s + | Int32 n -> fprintf ppf "%lil" n + | Int64 n -> fprintf ppf "%LiL" n + | Nativeint n -> fprintf ppf "%nin" n + | Float f -> fprintf ppf "%f" f + | Float_array [] -> fprintf ppf "[| |]" + | Float_array (f1 :: fl) -> + fprintf ppf "@[<1>[|@[%f%a@]|]@]" f1 floats fl + | Immutable_float_array [] -> fprintf ppf "[|# |]" + | Immutable_float_array (f1 :: fl) -> + fprintf ppf "@[<1>[|# @[%f%a@]|]@]" f1 floats fl diff --git a/middle_end/allocated_const.mli b/middle_end/allocated_const.mli new file mode 100644 index 00000000..3182ab09 --- /dev/null +++ b/middle_end/allocated_const.mli @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Constants that are always allocated (possibly statically). Blocks + are not included here since they are always encoded using + [Prim (Pmakeblock, ...)]. *) + +type t = + | Float of float + | Int32 of int32 + | Int64 of int64 + | Nativeint of nativeint + (* CR-someday mshinwell: consider using "float array" *) + | Float_array of float list + | Immutable_float_array of float list + | String of string + | Immutable_string of string + +val compare : t -> t -> int + +val print : Format.formatter -> t -> unit diff --git a/middle_end/augment_specialised_args.ml b/middle_end/augment_specialised_args.ml new file mode 100644 index 00000000..50f6420f --- /dev/null +++ b/middle_end/augment_specialised_args.ml @@ -0,0 +1,755 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module E = Inline_and_simplify_aux.Env +module B = Inlining_cost.Benefit + +module Definition = struct + type t = + | Existing_inner_free_var of Variable.t + | Projection_from_existing_specialised_arg of Projection.t + + include Identifiable.Make (struct + type nonrec t = t + + let compare t1 t2 = + match t1, t2 with + | Existing_inner_free_var var1, Existing_inner_free_var var2 -> + Variable.compare var1 var2 + | Projection_from_existing_specialised_arg proj1, + Projection_from_existing_specialised_arg proj2 -> + Projection.compare proj1 proj2 + | Existing_inner_free_var _, _ -> -1 + | _, Existing_inner_free_var _ -> 1 + + let equal t1 t2 = + (compare t1 t2) = 0 + + let hash = Hashtbl.hash + + let print ppf t = + match t with + | Existing_inner_free_var var -> + Format.fprintf ppf "Existing_inner_free_var %a" + Variable.print var + | Projection_from_existing_specialised_arg projection -> + Format.fprintf ppf "Projection_from_existing_specialised_arg %a" + Projection.print projection + + let output _ _ = failwith "Definition.output not yet implemented" + end) +end + +module What_to_specialise = struct + type t = { + (* [definitions] is indexed by (fun_var, group) *) + definitions : Definition.t list Variable.Pair.Map.t; + set_of_closures : Flambda.set_of_closures; + make_direct_call_surrogates_for : Variable.Set.t; + } + + let create ~set_of_closures = + { definitions = Variable.Pair.Map.empty; + set_of_closures; + make_direct_call_surrogates_for = Variable.Set.empty; + } + + let new_specialised_arg t ~fun_var ~group ~definition = + let key = fun_var, group in + let definitions = + match Variable.Pair.Map.find key t.definitions with + | exception Not_found -> [] + | definitions -> definitions + in + let definitions = + Variable.Pair.Map.add (fun_var, group) (definition :: definitions) + t.definitions + in + { t with definitions; } + + let make_direct_call_surrogate_for t ~fun_var = + match Variable.Map.find fun_var t.set_of_closures.function_decls.funs with + | exception Not_found -> + Misc.fatal_errorf "use_direct_call_surrogate_for: %a is not a fun_var \ + from the given set of closures" + Variable.print fun_var + | _ -> + { t with + make_direct_call_surrogates_for = + Variable.Set.add fun_var t.make_direct_call_surrogates_for; + } +end + +module W = What_to_specialise + +module type S = sig + val pass_name : string + val variable_suffix : string + + val what_to_specialise + : env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> What_to_specialise.t +end + +module Processed_what_to_specialise = struct + type for_one_function = { + fun_var : Variable.t; + function_decl : Flambda.function_declaration; + make_direct_call_surrogates : bool; + new_definitions_indexed_by_new_inner_vars : Definition.t Variable.Map.t; + all_new_definitions : Definition.Set.t; + new_inner_to_new_outer_vars : Variable.t Variable.Map.t; + total_number_of_args : int; + existing_specialised_args : Flambda.specialised_to Variable.Map.t; + } + + type t = { + variable_suffix : string; + set_of_closures : Flambda.set_of_closures; + existing_definitions_via_spec_args_indexed_by_fun_var + : Definition.Set.t Variable.Map.t; + (* The following two maps' definitions have already been rewritten + into their lifted form (i.e. they reference outer rather than inner + variables). *) + new_lifted_defns_indexed_by_new_outer_vars : Projection.t Variable.Map.t; + new_outer_vars_indexed_by_new_lifted_defns : Variable.t Projection.Map.t; + functions : for_one_function Variable.Map.t; + make_direct_call_surrogates_for : Variable.Set.t; + } + + let lift_projection t ~(projection : Projection.t) = + (* The lifted definition must be in terms of outer variables, + not inner variables. *) + let find_outer_var inner_var = + match Variable.Map.find inner_var t.set_of_closures.specialised_args with + | (outer_var : Flambda.specialised_to) -> outer_var.var + | exception Not_found -> + Misc.fatal_errorf "find_outer_var: expected %a \ + to be in [specialised_args], but it is \ + not. The projection was: %a. Set of closures: %a" + Variable.print inner_var + Projection.print projection + Flambda.print_set_of_closures t.set_of_closures + in + Projection.map_projecting_from projection ~f:find_outer_var + + let really_add_new_specialised_arg t ~group ~(definition : Definition.t) + ~(for_one_function : for_one_function) = + let fun_var = for_one_function.fun_var in + (* We know here that a new specialised argument must be added. This + needs a "new inner var" and a "new outer var". However if there + is already a lifted projection being introduced around the set + of closures (corresponding to another new specialised argument), + we should re-use its "new outer var" to avoid duplication of + projection definitions. Likewise if the definition is just + [Existing_inner_free_var], in in which case we can use the + corresponding existing outer free variable. *) + let new_outer_var, t = + let existing_outer_var = + match definition with + | Existing_inner_free_var _ -> None + | Projection_from_existing_specialised_arg projection -> + let projection = lift_projection t ~projection in + match + Projection.Map.find projection + t.new_outer_vars_indexed_by_new_lifted_defns + with + | new_outer_var -> Some new_outer_var + | exception Not_found -> None + in + match existing_outer_var with + | Some existing_outer_var -> existing_outer_var, t + | None -> + match definition with + | Existing_inner_free_var existing_inner_var -> + begin match + Variable.Map.find existing_inner_var + t.set_of_closures.free_vars + with + | exception Not_found -> + Misc.fatal_errorf "really_add_new_specialised_arg: \ + Existing_inner_free_var %a is not an inner free variable \ + of %a in %a" + Variable.print existing_inner_var + Variable.print fun_var + Flambda.print_set_of_closures t.set_of_closures + | existing_outer_var -> existing_outer_var.var, t + end + | Projection_from_existing_specialised_arg projection -> + let new_outer_var = + Variable.rename group ~append:t.variable_suffix + in + let projection = lift_projection t ~projection in + let new_outer_vars_indexed_by_new_lifted_defns = + Projection.Map.add + projection new_outer_var + t.new_outer_vars_indexed_by_new_lifted_defns + in + let new_lifted_defns_indexed_by_new_outer_vars = + Variable.Map.add + new_outer_var projection + t.new_lifted_defns_indexed_by_new_outer_vars + in + let t = + { t with + new_outer_vars_indexed_by_new_lifted_defns; + new_lifted_defns_indexed_by_new_outer_vars; + } + in + new_outer_var, t + in + let new_inner_var = + Variable.rename group ~append:t.variable_suffix + in + let new_inner_to_new_outer_vars = + Variable.Map.add new_inner_var new_outer_var + for_one_function.new_inner_to_new_outer_vars + in + let for_one_function : for_one_function = + { for_one_function with + new_definitions_indexed_by_new_inner_vars = + Variable.Map.add new_inner_var definition + for_one_function.new_definitions_indexed_by_new_inner_vars; + all_new_definitions = + Definition.Set.add definition + for_one_function.all_new_definitions; + new_inner_to_new_outer_vars; + total_number_of_args = for_one_function.total_number_of_args + 1; + } + in + { t with + functions = Variable.Map.add fun_var for_one_function t.functions; + } + + let new_specialised_arg t ~fun_var ~group ~definition = + let for_one_function : for_one_function = + match Variable.Map.find fun_var t.functions with + | exception Not_found -> + begin + match Variable.Map.find fun_var t.set_of_closures.function_decls.funs + with + | exception Not_found -> assert false + | (function_decl : Flambda.function_declaration) -> + let params = Variable.Set.of_list function_decl.params in + let existing_specialised_args = + Variable.Map.filter (fun inner_var _spec_to -> + Variable.Set.mem inner_var params) + t.set_of_closures.specialised_args + in + let make_direct_call_surrogates = + Variable.Set.mem fun_var t.make_direct_call_surrogates_for + in + { fun_var; + function_decl; + make_direct_call_surrogates; + new_definitions_indexed_by_new_inner_vars = Variable.Map.empty; + all_new_definitions = Definition.Set.empty; + new_inner_to_new_outer_vars = Variable.Map.empty; + (* The "+ 1" is just in case there is a closure environment + parameter added later. *) + total_number_of_args = List.length function_decl.params + 1; + existing_specialised_args; + } + end + | for_one_function -> for_one_function + in + (* Determine whether there already exists an existing specialised argument + that is known to be equal to the one proposed to this function. If so, + use that instead. (Note that we also desire to dedup against any + new specialised arguments added to the current function; but that + happens automatically since [Extract_projections] returns a set.) *) + let exists_already = + match + Variable.Map.find fun_var + t.existing_definitions_via_spec_args_indexed_by_fun_var + with + | exception Not_found -> false + | definitions -> Definition.Set.mem definition definitions + in + if exists_already then t + else really_add_new_specialised_arg t ~group ~definition ~for_one_function + + let create ~env ~(what_to_specialise : W.t) ~variable_suffix = + let existing_definitions_via_spec_args_indexed_by_fun_var = + Variable.Map.map (fun (function_decl : Flambda.function_declaration) -> + if function_decl.stub then + Definition.Set.empty + else + let params = Variable.Set.of_list function_decl.params in + Variable.Map.fold (fun inner_var + (spec_to : Flambda.specialised_to) definitions -> + if not (Variable.Set.mem inner_var params) then + definitions + else + let definition : Definition.t = + match spec_to.projection with + | None -> Existing_inner_free_var inner_var + | Some projection -> + Projection_from_existing_specialised_arg projection + in + Definition.Set.add definition definitions) + what_to_specialise.set_of_closures.specialised_args + Definition.Set.empty) + what_to_specialise.set_of_closures.function_decls.funs + in + let t : t = + { variable_suffix; + set_of_closures = what_to_specialise.set_of_closures; + existing_definitions_via_spec_args_indexed_by_fun_var; + new_lifted_defns_indexed_by_new_outer_vars = Variable.Map.empty; + new_outer_vars_indexed_by_new_lifted_defns = Projection.Map.empty; + functions = Variable.Map.empty; + make_direct_call_surrogates_for = + what_to_specialise.make_direct_call_surrogates_for; + } + in + (* It is important to limit the number of arguments added: if arguments + end up being passed on the stack, tail call optimization will be + disabled (see asmcomp/selectgen.ml). + For each group of new specialised args provided by [T], either all or + none of them will be added. (This is to avoid the situation where we + add extra arguments but yet fail to eliminate an original one by + stopping part-way through the specialised args addition.) *) + let by_group = + Variable.Pair.Map.fold (fun (fun_var, group) definitions by_group -> + let fun_vars_and_definitions = + match Variable.Map.find group by_group with + | exception Not_found -> [] + | fun_vars_and_definitions -> fun_vars_and_definitions + in + Variable.Map.add group + ((fun_var, definitions)::fun_vars_and_definitions) + by_group) + what_to_specialise.definitions + Variable.Map.empty + in + let module Backend = (val (E.backend env) : Backend_intf.S) in + Variable.Map.fold (fun group fun_vars_and_definitions t -> + let original_t = t in + let t = + (* Try adding all specialised args in the current group. *) + List.fold_left (fun t (fun_var, definitions) -> + List.fold_left (fun t definition -> + new_specialised_arg t ~fun_var ~group ~definition) + t + definitions) + t + fun_vars_and_definitions + in + let some_function_has_too_many_args = + Variable.Map.exists (fun _ (for_one_function : for_one_function) -> + for_one_function.total_number_of_args + > Backend.max_sensible_number_of_arguments) + t.functions + in + if some_function_has_too_many_args then + original_t (* drop this group *) + else + t) + by_group + t +end + +module P = Processed_what_to_specialise + +let check_invariants ~pass_name ~(set_of_closures : Flambda.set_of_closures) + ~original_set_of_closures = + if !Clflags.flambda_invariant_checks then begin + Variable.Map.iter (fun fun_var + (function_decl : Flambda.function_declaration) -> + let params = Variable.Set.of_list function_decl.params in + Variable.Map.iter (fun inner_var + (outer_var : Flambda.specialised_to) -> + if Variable.Set.mem inner_var params then begin + assert (not (Variable.Set.mem outer_var.var + function_decl.free_variables)); + match outer_var.projection with + | None -> () + | Some projection -> + let from = Projection.projecting_from projection in + if not (Variable.Set.mem from params) then begin + Misc.fatal_errorf "Augment_specialised_args (%s): \ + specialised argument (%a -> %a) references a \ + projection variable that is not a specialised \ + argument of the function %a. @ The set of closures \ + before the transformation was:@ %a. @ The set of \ + closures after the transformation was:@ %a." + pass_name + Variable.print inner_var + Flambda.print_specialised_to outer_var + Variable.print fun_var + Flambda.print_set_of_closures original_set_of_closures + Flambda.print_set_of_closures set_of_closures + end + end) + set_of_closures.specialised_args) + set_of_closures.function_decls.funs + end + +module Make (T : S) = struct + let () = Pass_wrapper.register ~pass_name:T.pass_name + + let rename_function_and_parameters ~fun_var + ~(function_decl : Flambda.function_declaration) = + let new_fun_var = Variable.rename fun_var ~append:T.variable_suffix in + let params_renaming = + Variable.Map.of_list + (List.map (fun param -> + let new_param = Variable.rename param ~append:T.variable_suffix in + param, new_param) + function_decl.params) + in + let renamed_params = + List.map (fun param -> Variable.Map.find param params_renaming) + function_decl.params + in + new_fun_var, params_renaming, renamed_params + + let create_wrapper ~(for_one_function : P.for_one_function) ~benefit = + let fun_var = for_one_function.fun_var in + let function_decl = for_one_function.function_decl in + (* To avoid increasing the free variables of the wrapper, for + general cleanliness, we restate the definitions of the + newly-specialised arguments in the wrapper itself in terms of the + original specialised arguments. The variables bound to these + definitions are called the "specialised args bound in the wrapper". + Note that the domain of [params_renaming] is a (non-strict) superset + of the "inner vars" of the original specialised args. *) + let params = Variable.Set.of_list function_decl.params in + let new_fun_var, params_renaming, wrapper_params = + rename_function_and_parameters ~fun_var ~function_decl + in + let find_wrapper_param param = + assert (Variable.Set.mem param params); + match Variable.Map.find param params_renaming with + | wrapper_param -> wrapper_param + | exception Not_found -> + Misc.fatal_errorf "find_wrapper_param: expected %a \ + to be in [params_renaming], but it is not." + Variable.print param + in + let new_inner_vars_to_spec_args_bound_in_the_wrapper_renaming = + Variable.Map.mapi (fun new_inner_var _ -> + Variable.rename new_inner_var) + for_one_function.new_definitions_indexed_by_new_inner_vars + in + let spec_args_bound_in_the_wrapper = + (* N.B.: in the order matching the new specialised argument parameters + to the main function. *) + Variable.Map.data + new_inner_vars_to_spec_args_bound_in_the_wrapper_renaming + in + (* New definitions that project from existing specialised args need + to be rewritten to use the corresponding specialised args of + the wrapper. Definitions that are just equality to existing + inner free variables do not need to be changed. Once this has + been done the wrapper body can be constructed. + We also need to rewrite definitions for any existing specialised + args; these now have corresponding wrapper parameters that must + also be specialised. *) + let wrapper_body, benefit = + let apply : Flambda.expr = + Apply { + func = new_fun_var; + args = wrapper_params @ spec_args_bound_in_the_wrapper; + kind = Direct (Closure_id.wrap new_fun_var); + dbg = Debuginfo.none; + inline = Default_inline; + specialise = Default_specialise; + } + in + Variable.Map.fold (fun new_inner_var definition (wrapper_body, benefit) -> + let definition : Definition.t = + match (definition : Definition.t) with + | Existing_inner_free_var _ -> definition + | Projection_from_existing_specialised_arg projection -> + Projection_from_existing_specialised_arg + (Projection.map_projecting_from projection + ~f:find_wrapper_param) + in + let benefit = + match (definition : Definition.t) with + | Existing_inner_free_var _ -> benefit + | Projection_from_existing_specialised_arg projection -> + B.add_projection projection benefit + in + match + Variable.Map.find new_inner_var + new_inner_vars_to_spec_args_bound_in_the_wrapper_renaming + with + | exception Not_found -> assert false + | new_inner_var_of_wrapper -> + let named : Flambda.named = + match definition with + | Existing_inner_free_var existing_inner_var -> + Expr (Var existing_inner_var) + | Projection_from_existing_specialised_arg projection -> + Flambda_utils.projection_to_named projection + in + let wrapper_body = + Flambda.create_let new_inner_var_of_wrapper named wrapper_body + in + (wrapper_body, benefit)) + for_one_function.new_definitions_indexed_by_new_inner_vars + (apply, benefit) + in + let rewritten_existing_specialised_args = + Variable.Map.fold (fun inner_var (spec_to : Flambda.specialised_to) + result -> + let inner_var = find_wrapper_param inner_var in + let projection = + match spec_to.projection with + | None -> None + | Some projection -> + Some (Projection.map_projecting_from projection + ~f:find_wrapper_param) + in + let spec_to : Flambda.specialised_to = + { var = spec_to.var; + projection; + } + in + Variable.Map.add inner_var spec_to result) + for_one_function.existing_specialised_args + Variable.Map.empty + in + let new_function_decl = + Flambda.create_function_declaration + ~params:wrapper_params + ~body:wrapper_body + ~stub:true + ~dbg:Debuginfo.none + ~inline:Default_inline + ~specialise:Default_specialise + ~is_a_functor:false + in + new_fun_var, new_function_decl, rewritten_existing_specialised_args, + benefit + + let rewrite_function_decl (t : P.t) ~env ~duplicate_function + ~(for_one_function : P.for_one_function) ~benefit = + let set_of_closures = t.set_of_closures in + let fun_var = for_one_function.fun_var in + let function_decl = for_one_function.function_decl in + let num_definitions = + Variable.Map.cardinal for_one_function. + new_definitions_indexed_by_new_inner_vars + in + if function_decl.stub + || num_definitions < 1 + || Variable.Map.mem fun_var set_of_closures.direct_call_surrogates + then + None + else + let new_fun_var, wrapper, rewritten_existing_specialised_args, benefit = + create_wrapper ~for_one_function ~benefit + in + let new_specialised_args = + Variable.Map.mapi (fun new_inner_var (definition : Definition.t) + : Flambda.specialised_to -> + assert (not (Variable.Map.mem new_inner_var + set_of_closures.specialised_args)); + match + Variable.Map.find new_inner_var + for_one_function.new_inner_to_new_outer_vars + with + | exception Not_found -> assert false + | new_outer_var -> + match definition with + | Existing_inner_free_var _ -> + { var = new_outer_var; + projection = None; + } + | Projection_from_existing_specialised_arg projection -> + let projecting_from = Projection.projecting_from projection in + assert (Variable.Map.mem projecting_from + set_of_closures.specialised_args); + assert (Variable.Set.mem projecting_from + (Variable.Set.of_list function_decl.params)); + { var = new_outer_var; + projection = Some projection; + }) + for_one_function.new_definitions_indexed_by_new_inner_vars + in + let specialised_args = + Variable.Map.disjoint_union rewritten_existing_specialised_args + new_specialised_args + in + let specialised_args, existing_function_decl = + if not for_one_function.make_direct_call_surrogates then + specialised_args, None + else + let function_decl, new_specialised_args = + duplicate_function ~env ~set_of_closures ~fun_var + in + let specialised_args = + Variable.Map.disjoint_union specialised_args new_specialised_args + in + specialised_args, Some function_decl + in + let all_params = + let new_params = + Variable.Set.elements (Variable.Map.keys + for_one_function.new_inner_to_new_outer_vars) + in + function_decl.params @ new_params + in + let rewritten_function_decl = + Flambda.create_function_declaration + ~params:all_params + ~body:function_decl.body + ~stub:function_decl.stub + ~dbg:function_decl.dbg + ~inline:function_decl.inline + ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + in + let funs, direct_call_surrogates = + if for_one_function.make_direct_call_surrogates then + let surrogate = Variable.rename fun_var ~append:"_surrogate" in + let funs = + (* In this case, the original function declaration remains + untouched up to alpha-equivalence. Direct calls to it + (including inside the rewritten original function) will be + replaced by calls to the surrogate (i.e. the wrapper) which + will then be inlined. *) + let existing_function_decl = + match existing_function_decl with + | Some decl -> decl + | None -> assert false + in + Variable.Map.add new_fun_var rewritten_function_decl + (Variable.Map.add surrogate wrapper + (Variable.Map.add fun_var existing_function_decl + Variable.Map.empty)) + in + let direct_call_surrogates = + Variable.Map.add fun_var surrogate Variable.Map.empty + in + funs, direct_call_surrogates + else + let funs = + Variable.Map.add new_fun_var rewritten_function_decl + (Variable.Map.add fun_var wrapper Variable.Map.empty) + in + funs, Variable.Map.empty + in + let free_vars = Variable.Map.empty in + Some (funs, free_vars, specialised_args, direct_call_surrogates, benefit) + + let add_lifted_projections_around_set_of_closures + ~(set_of_closures : Flambda.set_of_closures) ~benefit + ~new_lifted_defns_indexed_by_new_outer_vars = + let body = + Flambda_utils.name_expr (Set_of_closures set_of_closures) + ~name:("set_of_closures" ^ T.variable_suffix) + in + Variable.Map.fold (fun new_outer_var (projection : Projection.t) + (expr, benefit) -> + let named = Flambda_utils.projection_to_named projection in + let benefit = B.add_projection projection benefit in + let expr = Flambda.create_let new_outer_var named expr in + expr, benefit) + new_lifted_defns_indexed_by_new_outer_vars + (body, benefit) + + let rewrite_set_of_closures_core ~env ~duplicate_function ~benefit + ~(set_of_closures : Flambda.set_of_closures) = + let what_to_specialise = + P.create ~env ~variable_suffix:T.variable_suffix + ~what_to_specialise:(T.what_to_specialise ~env ~set_of_closures) + in + let original_set_of_closures = set_of_closures in + let funs, free_vars, specialised_args, direct_call_surrogates, + done_something, benefit = + Variable.Map.fold (fun fun_var function_decl + (funs, free_vars, specialised_args, direct_call_surrogates, + done_something, benefit) -> + match Variable.Map.find fun_var what_to_specialise.functions with + | exception Not_found -> + let funs = Variable.Map.add fun_var function_decl funs in + funs, free_vars, specialised_args, direct_call_surrogates, + done_something, benefit + | (for_one_function : P.for_one_function) -> + assert (Variable.equal fun_var for_one_function.fun_var); + match + rewrite_function_decl what_to_specialise ~env + ~duplicate_function ~for_one_function ~benefit + with + | None -> + let function_decl = for_one_function.function_decl in + let funs = Variable.Map.add fun_var function_decl funs in + funs, free_vars, specialised_args, direct_call_surrogates, + done_something, benefit + | Some (funs', free_vars', specialised_args', + direct_call_surrogates', benefit) -> + let funs = Variable.Map.disjoint_union funs funs' in + let direct_call_surrogates = + Variable.Map.disjoint_union direct_call_surrogates + direct_call_surrogates' + in + let free_vars = + Variable.Map.disjoint_union free_vars free_vars' + in + let specialised_args = + Variable.Map.disjoint_union specialised_args specialised_args' + in + funs, free_vars, specialised_args, direct_call_surrogates, true, + benefit) + set_of_closures.function_decls.funs + (Variable.Map.empty, set_of_closures.free_vars, + set_of_closures.specialised_args, + set_of_closures.direct_call_surrogates, false, benefit) + in + if not done_something then + None + else + let function_decls = + Flambda.update_function_declarations set_of_closures.function_decls + ~funs + in + assert (Variable.Map.cardinal specialised_args + >= Variable.Map.cardinal original_set_of_closures.specialised_args); + let set_of_closures = + Flambda.create_set_of_closures + ~function_decls + ~free_vars + ~specialised_args + ~direct_call_surrogates + in + if !Clflags.flambda_invariant_checks then begin + check_invariants ~set_of_closures ~original_set_of_closures + ~pass_name:T.pass_name + end; + let expr, benefit = + add_lifted_projections_around_set_of_closures ~set_of_closures ~benefit + ~new_lifted_defns_indexed_by_new_outer_vars: + what_to_specialise.new_lifted_defns_indexed_by_new_outer_vars + in + Some (expr, benefit) + + let rewrite_set_of_closures ~env ~duplicate_function ~set_of_closures = + Pass_wrapper.with_dump ~pass_name:T.pass_name ~input:set_of_closures + ~print_input:Flambda.print_set_of_closures + ~print_output:(fun ppf (expr, _) -> Flambda.print ppf expr) + ~f:(fun () -> + rewrite_set_of_closures_core ~env ~duplicate_function + ~benefit:B.zero ~set_of_closures) +end diff --git a/middle_end/augment_specialised_args.mli b/middle_end/augment_specialised_args.mli new file mode 100644 index 00000000..94ccfc09 --- /dev/null +++ b/middle_end/augment_specialised_args.mli @@ -0,0 +1,65 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +(** Helper module for adding specialised arguments to sets of closures. *) + +module Definition : sig + type t = + | Existing_inner_free_var of Variable.t + | Projection_from_existing_specialised_arg of Projection.t +end + +module What_to_specialise : sig + type t + + val create + : set_of_closures:Flambda.set_of_closures + -> t + + val new_specialised_arg + : t + -> fun_var:Variable.t + -> group:Variable.t + -> definition:Definition.t (* [projecting_from] "existing inner vars" *) + -> t + + val make_direct_call_surrogate_for : t -> fun_var:Variable.t -> t +end + +module type S = sig + val pass_name : string + val variable_suffix : string + + val what_to_specialise + : env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> What_to_specialise.t +end + +module Make (T : S) : sig + (** [duplicate_function] should be + [Inline_and_simplify.duplicate_function]. *) + val rewrite_set_of_closures + : env:Inline_and_simplify_aux.Env.t + -> duplicate_function:( + env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> fun_var:Variable.t + -> Flambda.function_declaration + * Flambda.specialised_to Variable.Map.t) + -> set_of_closures:Flambda.set_of_closures + -> (Flambda.expr * Inlining_cost.Benefit.t) option +end diff --git a/middle_end/backend_intf.mli b/middle_end/backend_intf.mli new file mode 100644 index 00000000..efdbbc3c --- /dev/null +++ b/middle_end/backend_intf.mli @@ -0,0 +1,47 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Knowledge that the middle end needs about the backend. *) + +module type S = sig + (** Compute the symbol for the given identifier. *) + val symbol_for_global' : (Ident.t -> Symbol.t) + + (** If the given approximation is that of a symbol (Value_symbol) or an + external (Value_extern), attempt to find a more informative + approximation from a previously-written compilation artifact. In the + native code backend, for example, this might consult a .cmx file. *) + val really_import_approx : Simple_value_approx.t -> Simple_value_approx.t + + val import_symbol : Symbol.t -> Simple_value_approx.t + + val closure_symbol : Closure_id.t -> Symbol.t + + (** The natural size of an integer on the target architecture + (cf. [Arch.size_int] in the native code backend). *) + val size_int : int + + (** [true] iff the target architecture is big endian. *) + val big_endian : bool + + (** The maximum number of arguments that is is reasonable for a function + to have. This should be fewer than the threshold that causes non-self + tail call optimization to be inhibited (in particular, if it would + entail passing arguments on the stack; see [Selectgen]). *) + val max_sensible_number_of_arguments : int +end diff --git a/middle_end/base_types/closure_element.ml b/middle_end/base_types/closure_element.ml new file mode 100644 index 00000000..a1c866e2 --- /dev/null +++ b/middle_end/base_types/closure_element.ml @@ -0,0 +1,25 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Variable + +let wrap t = t +let unwrap t = t + +let wrap_map t = t +let unwrap_set t = t diff --git a/middle_end/base_types/closure_element.mli b/middle_end/base_types/closure_element.mli new file mode 100644 index 00000000..d78dd9b3 --- /dev/null +++ b/middle_end/base_types/closure_element.mli @@ -0,0 +1,32 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Identifiable.S + +val wrap : Variable.t -> t +val unwrap : t -> Variable.t + +val wrap_map : 'a Variable.Map.t -> 'a Map.t +val unwrap_set : Set.t -> Variable.Set.t + +val in_compilation_unit : t -> Compilation_unit.t -> bool +val get_compilation_unit : t -> Compilation_unit.t + +val unique_name : t -> string + +val output_full : out_channel -> t -> unit diff --git a/middle_end/base_types/closure_id.ml b/middle_end/base_types/closure_id.ml new file mode 100644 index 00000000..4003a609 --- /dev/null +++ b/middle_end/base_types/closure_id.ml @@ -0,0 +1,19 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Closure_element diff --git a/middle_end/base_types/closure_id.mli b/middle_end/base_types/closure_id.mli new file mode 100644 index 00000000..853a07f7 --- /dev/null +++ b/middle_end/base_types/closure_id.mli @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** CR-someday lwhite: "Closure_id" is quite a generic name. I wonder + whether something like "Closure_label" would better capture that it is + the label of a projection. *) + +(** An identifier, unique across the whole program (not just one compilation + unit), that identifies a closure within a particular set of closures + (viz. [Project_closure]). *) + +include module type of Closure_element diff --git a/middle_end/base_types/compilation_unit.ml b/middle_end/base_types/compilation_unit.ml new file mode 100644 index 00000000..a21d9f1e --- /dev/null +++ b/middle_end/base_types/compilation_unit.ml @@ -0,0 +1,73 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = { + id : Ident.t; + linkage_name : Linkage_name.t; + hash : int; +} + +let string_for_printing t = Ident.name t.id + +include Identifiable.Make (struct + type nonrec t = t + + (* Multiple units can have the same [id] if they come from different packs. + To distinguish these we also keep the linkage name, which contains the + name of the pack. *) + let compare v1 v2 = + if v1 == v2 then 0 + else + let c = compare v1.hash v2.hash in + if c = 0 then + let v1_id = Ident.name v1.id in + let v2_id = Ident.name v2.id in + let c = String.compare v1_id v2_id in + if c = 0 then + Linkage_name.compare v1.linkage_name v2.linkage_name + else + c + else c + + let equal x y = + if x == y then true + else compare x y = 0 + + let print ppf t = Format.pp_print_string ppf (string_for_printing t) + + let output oc x = output_string oc (Ident.name x.id) + let hash x = x.hash +end) + +let create (id : Ident.t) linkage_name = + if not (Ident.persistent id) then begin + Misc.fatal_error "Compilation_unit.create with non-persistent Ident.t" + end; + { id; linkage_name; hash = Hashtbl.hash id.name } + +let get_persistent_ident cu = cu.id +let get_linkage_name cu = cu.linkage_name + +let current = ref None +let set_current t = current := Some t +let get_current () = !current +let get_current_exn () = + match !current with + | Some current -> current + | None -> Misc.fatal_error "Compilation_unit.get_current_exn" +let get_current_id_exn () = get_persistent_ident (get_current_exn ()) diff --git a/middle_end/base_types/compilation_unit.mli b/middle_end/base_types/compilation_unit.mli new file mode 100644 index 00000000..e9375685 --- /dev/null +++ b/middle_end/base_types/compilation_unit.mli @@ -0,0 +1,33 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Identifiable.S + +(* The [Ident.t] must be persistent. This function raises an exception + if that is not the case. *) +val create : Ident.t -> Linkage_name.t -> t + +val get_persistent_ident : t -> Ident.t +val get_linkage_name : t -> Linkage_name.t + +val set_current : t -> unit +val get_current : unit -> t option +val get_current_exn : unit -> t +val get_current_id_exn : unit -> Ident.t + +val string_for_printing : t -> string diff --git a/middle_end/base_types/export_id.ml b/middle_end/base_types/export_id.ml new file mode 100644 index 00000000..52db870a --- /dev/null +++ b/middle_end/base_types/export_id.ml @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Id : Id_types.Id = Id_types.Id (struct end) +module Unit_id = Id_types.UnitId (Id) (Compilation_unit) + +type t = Unit_id.t + +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/export_id.mli b/middle_end/base_types/export_id.mli new file mode 100644 index 00000000..54c14418 --- /dev/null +++ b/middle_end/base_types/export_id.mli @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* Keys representing value descriptions that may be written into + intermediate files and loaded by a dependent compilation unit. + These keys are used to ensure maximal sharing of value descriptions, + which may be substantial. *) + +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/id_types.ml b/middle_end/base_types/id_types.ml new file mode 100644 index 00000000..172e8af5 --- /dev/null +++ b/middle_end/base_types/id_types.ml @@ -0,0 +1,92 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module type BaseId = sig + type t + val equal : t -> t -> bool + val compare : t -> t -> int + val hash : t -> int + val name : t -> string option + val to_string : t -> string + val output : out_channel -> t -> unit + val print : Format.formatter -> t -> unit +end + +module type Id = sig + include BaseId + val create : ?name:string -> unit -> t +end + +module type UnitId = sig + module Compilation_unit : Identifiable.Thing + include BaseId + val create : ?name:string -> Compilation_unit.t -> t + val unit : t -> Compilation_unit.t +end + +module Id(E:sig end) : Id = struct + type t = int * string + let empty_string = "" + let create = let r = ref 0 in + fun ?(name=empty_string) () -> incr r; !r, name + let equal (t1,_) (t2,_) = (t1:int) = t2 + let compare (t1,_) (t2,_) = t1 - t2 + let hash (t,_) = t + let name (_,name) = + if name == empty_string + then None + else Some name + let to_string (t,name) = + if name == empty_string + then string_of_int t + else Printf.sprintf "%s_%i" name t + let output fd t = output_string fd (to_string t) + let print ppf v = Format.pp_print_string ppf (to_string v) +end + +module UnitId(Innerid:Id)(Compilation_unit:Identifiable.Thing) : + UnitId with module Compilation_unit := Compilation_unit = struct + type t = { + id : Innerid.t; + unit : Compilation_unit.t; + } + let compare x y = + let c = Innerid.compare x.id y.id in + if c <> 0 + then c + else Compilation_unit.compare x.unit y.unit + let output oc x = + Printf.fprintf oc "%a.%a" + Compilation_unit.output x.unit + Innerid.output x.id + let print ppf x = + Format.fprintf ppf "%a.%a" + Compilation_unit.print x.unit + Innerid.print x.id + let hash off = Hashtbl.hash off + let equal o1 o2 = compare o1 o2 = 0 + let name o = Innerid.name o.id + let to_string x = + Format.asprintf "%a.%a" + Compilation_unit.print x.unit + Innerid.print x.id + let create ?name unit = + let id = Innerid.create ?name () in + { id; unit } + let unit x = x.unit +end diff --git a/middle_end/base_types/id_types.mli b/middle_end/base_types/id_types.mli new file mode 100644 index 00000000..48ca037c --- /dev/null +++ b/middle_end/base_types/id_types.mli @@ -0,0 +1,56 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-soon mshinwell: This module should be removed. *) + +(** Generic identifier type *) +module type BaseId = +sig + type t + val equal : t -> t -> bool + val compare : t -> t -> int + val hash : t -> int + val name : t -> string option + val to_string : t -> string + val output : out_channel -> t -> unit + val print : Format.formatter -> t -> unit +end + +module type Id = +sig + include BaseId + val create : ?name:string -> unit -> t +end + +(** Fully qualified identifiers *) +module type UnitId = +sig + module Compilation_unit : Identifiable.Thing + include BaseId + val create : ?name:string -> Compilation_unit.t -> t + val unit : t -> Compilation_unit.t +end + +(** If applied generatively, i.e. [Id(struct end)], creates a new type + of identifiers. *) +module Id : functor (E : sig end) -> Id + +module UnitId : + functor (Id : Id) -> + functor (Compilation_unit : Identifiable.Thing) -> + UnitId with module Compilation_unit := Compilation_unit diff --git a/middle_end/base_types/linkage_name.ml b/middle_end/base_types/linkage_name.ml new file mode 100644 index 00000000..83b790b2 --- /dev/null +++ b/middle_end/base_types/linkage_name.ml @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = string + +include Identifiable.Make (struct + include String + let hash = Hashtbl.hash + let print ppf t = Format.pp_print_string ppf t + let output chan t = output_string chan t +end) + +let create t = t +let to_string t = t diff --git a/middle_end/base_types/linkage_name.mli b/middle_end/base_types/linkage_name.mli new file mode 100644 index 00000000..58731917 --- /dev/null +++ b/middle_end/base_types/linkage_name.mli @@ -0,0 +1,22 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Identifiable.S + +val create : string -> t +val to_string : t -> string diff --git a/middle_end/base_types/mutable_variable.ml b/middle_end/base_types/mutable_variable.ml new file mode 100644 index 00000000..a320806e --- /dev/null +++ b/middle_end/base_types/mutable_variable.ml @@ -0,0 +1,91 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = { + compilation_unit : Compilation_unit.t; + ident : Ident.t; +} + +include Identifiable.Make (struct + type nonrec t = t + + let compare v1 v2 = + let c = Ident.compare v1.ident v2.ident in + if c = 0 + then Compilation_unit.compare v1.compilation_unit v2.compilation_unit + else c + + let output c v = Ident.output c v.ident + + let hash v = Ident.hash v.ident + + let equal v1 v2 = + Ident.same v1.ident v2.ident && + Compilation_unit.equal v1.compilation_unit v2.compilation_unit + + let print ppf v = + Format.fprintf ppf "%a.%a" + Compilation_unit.print v.compilation_unit + Ident.print v.ident +end) + +let create ?current_compilation_unit name = + let compilation_unit = + match current_compilation_unit with + | Some compilation_unit -> compilation_unit + | None -> Compilation_unit.get_current_exn () + in + { compilation_unit; + ident = Ident.create name; + } + +let of_ident ident = create (Ident.name ident) + +let unique_ident t = + { t.ident with + name = + Format.asprintf "%a_%s" + Compilation_unit.print t.compilation_unit + t.ident.name; + } + +let rename ?current_compilation_unit ?append t = + let compilation_unit = + match current_compilation_unit with + | Some compilation_unit -> compilation_unit + | None -> Compilation_unit.get_current_exn () + in + let ident = + match append with + | None -> Ident.rename t.ident + | Some s -> Ident.create (t.ident.Ident.name ^ s) + in + { compilation_unit = compilation_unit; + ident; + } + +let freshen t = + rename t ~current_compilation_unit:(Compilation_unit.get_current_exn ()) + +let in_compilation_unit t cu = + Compilation_unit.equal t.compilation_unit cu + +let output_full c t = + Compilation_unit.output c t.compilation_unit; + Printf.fprintf c "."; + Ident.output c t.ident diff --git a/middle_end/base_types/mutable_variable.mli b/middle_end/base_types/mutable_variable.mli new file mode 100644 index 00000000..b33beee2 --- /dev/null +++ b/middle_end/base_types/mutable_variable.mli @@ -0,0 +1,37 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Identifiable.S + +val create : ?current_compilation_unit:Compilation_unit.t -> string -> t +val of_ident : Ident.t -> t + +(** For [Flambda_to_clambda] only. *) +val unique_ident : t -> Ident.t + +val freshen : t -> t + +val rename + : ?current_compilation_unit:Compilation_unit.t + -> ?append:string + -> t + -> t + +val in_compilation_unit : t -> Compilation_unit.t -> bool + +val output_full : out_channel -> t -> unit diff --git a/middle_end/base_types/set_of_closures_id.ml b/middle_end/base_types/set_of_closures_id.ml new file mode 100644 index 00000000..d6ac221c --- /dev/null +++ b/middle_end/base_types/set_of_closures_id.ml @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Id : Id_types.Id = Id_types.Id (struct end) +module Unit_id = Id_types.UnitId (Id) (Compilation_unit) + +type t = Unit_id.t + +include Identifiable.Make (Unit_id) + +let create = Unit_id.create +let get_compilation_unit = Unit_id.unit diff --git a/middle_end/base_types/set_of_closures_id.mli b/middle_end/base_types/set_of_closures_id.mli new file mode 100644 index 00000000..1bcfc694 --- /dev/null +++ b/middle_end/base_types/set_of_closures_id.mli @@ -0,0 +1,25 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** An identifier, unique across the whole program, that identifies a set + of a closures (viz. [Set_of_closures]). *) + +include Identifiable.S + +val create : ?name:string -> Compilation_unit.t -> t +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 new file mode 100644 index 00000000..ce10a740 --- /dev/null +++ b/middle_end/base_types/set_of_closures_origin.ml @@ -0,0 +1,21 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Set_of_closures_id + +let create t = t diff --git a/middle_end/base_types/set_of_closures_origin.mli b/middle_end/base_types/set_of_closures_origin.mli new file mode 100644 index 00000000..2f2c6341 --- /dev/null +++ b/middle_end/base_types/set_of_closures_origin.mli @@ -0,0 +1,21 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +include Identifiable.S + +val create : Set_of_closures_id.t -> t + +val get_compilation_unit : t -> Compilation_unit.t diff --git a/middle_end/base_types/static_exception.ml b/middle_end/base_types/static_exception.ml new file mode 100644 index 00000000..3701befa --- /dev/null +++ b/middle_end/base_types/static_exception.ml @@ -0,0 +1,22 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Numbers.Int + +let create () = Lambda.next_raise_count () +let to_int t = t diff --git a/middle_end/base_types/static_exception.mli b/middle_end/base_types/static_exception.mli new file mode 100644 index 00000000..88f690aa --- /dev/null +++ b/middle_end/base_types/static_exception.mli @@ -0,0 +1,26 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** An identifier that is used to label static exceptions. Its + uniqueness properties are unspecified. *) + +include Identifiable.S + +val create : unit -> t + +val to_int : t -> int diff --git a/middle_end/base_types/symbol.ml b/middle_end/base_types/symbol.ml new file mode 100644 index 00000000..3dee3cb1 --- /dev/null +++ b/middle_end/base_types/symbol.ml @@ -0,0 +1,79 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = { + compilation_unit : Compilation_unit.t; + label : Linkage_name.t; + hash : int; +} + +include Identifiable.Make (struct + type nonrec t = t + + let compare t1 t2 = + (* Linkage names are unique across a whole project, so just comparing + those is sufficient. *) + if t1 == t2 then 0 + else + let c = compare t1.hash t2.hash in + if c <> 0 then c + else Linkage_name.compare t1.label t2.label + + let equal x y = + if x == y then true + else compare x y = 0 + + let output chan t = Linkage_name.output chan t.label + + let hash t = t.hash + + let print ppf t = + Compilation_unit.print ppf t.compilation_unit; + Format.pp_print_string ppf "."; + Linkage_name.print ppf t.label +end) + +let create compilation_unit label = + let unit_linkage_name = + Linkage_name.to_string + (Compilation_unit.get_linkage_name compilation_unit) + in + let label = + Linkage_name.create + (unit_linkage_name ^ "__" ^ (Linkage_name.to_string label)) + in + let hash = Linkage_name.hash label in + { compilation_unit; label; hash; } + +let unsafe_create compilation_unit label = + let hash = Linkage_name.hash label in + { compilation_unit; label; hash; } + +let import_for_pack ~pack:compilation_unit symbol = + let hash = Linkage_name.hash symbol.label in + { compilation_unit; label = symbol.label; hash; } + +let compilation_unit t = t.compilation_unit +let label t = t.label + +let print_opt ppf = function + | None -> Format.fprintf ppf "" + | Some t -> print ppf t + +let compare_lists l1 l2 = + Misc.Stdlib.List.compare compare l1 l2 diff --git a/middle_end/base_types/symbol.mli b/middle_end/base_types/symbol.mli new file mode 100644 index 00000000..fdf6aae2 --- /dev/null +++ b/middle_end/base_types/symbol.mli @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** A symbol identifies a constant provided by either: + - another compilation unit; or + - a top-level module. + + * [sym_unit] is the compilation unit containing the value. + * [sym_label] is the linkage name of the variable. + + The label must be globally unique: two compilation units linked in the + same program must not share labels. *) + +include Identifiable.S + +val create : Compilation_unit.t -> Linkage_name.t -> t +(* Create the symbol without prefixing with the compilation unit. + Used for predefined exceptions *) +val unsafe_create : Compilation_unit.t -> Linkage_name.t -> t + +val import_for_pack : pack:Compilation_unit.t -> t -> t + +val compilation_unit : t -> Compilation_unit.t +val label : t -> Linkage_name.t + +val print_opt : Format.formatter -> t option -> unit + +val compare_lists : t list -> t list -> int diff --git a/middle_end/base_types/tag.ml b/middle_end/base_types/tag.ml new file mode 100644 index 00000000..a781cee1 --- /dev/null +++ b/middle_end/base_types/tag.ml @@ -0,0 +1,32 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = int + +include Identifiable.Make (Numbers.Int) + +let create_exn tag = + if tag < 0 || tag > 255 then + Misc.fatal_error (Printf.sprintf "Tag.create_exn %d" tag) + else + tag + +let to_int t = t + +let zero = 0 +let object_tag = Obj.object_tag diff --git a/middle_end/base_types/tag.mli b/middle_end/base_types/tag.mli new file mode 100644 index 00000000..20f8bcad --- /dev/null +++ b/middle_end/base_types/tag.mli @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Tags on runtime boxed values. *) + +include Identifiable.S + +val create_exn : int -> t +val to_int : t -> int + +val zero : t +val object_tag : t diff --git a/middle_end/base_types/var_within_closure.ml b/middle_end/base_types/var_within_closure.ml new file mode 100644 index 00000000..4003a609 --- /dev/null +++ b/middle_end/base_types/var_within_closure.ml @@ -0,0 +1,19 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +include Closure_element diff --git a/middle_end/base_types/var_within_closure.mli b/middle_end/base_types/var_within_closure.mli new file mode 100644 index 00000000..56f0af0a --- /dev/null +++ b/middle_end/base_types/var_within_closure.mli @@ -0,0 +1,24 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** An identifier, unique across the whole program, that identifies a + particular variable within a particular closure. Only + [Project_var], and not [Var], nodes are tagged with these + identifiers. *) + +include module type of Closure_element diff --git a/middle_end/base_types/variable.ml b/middle_end/base_types/variable.ml new file mode 100644 index 00000000..b2ad07a0 --- /dev/null +++ b/middle_end/base_types/variable.ml @@ -0,0 +1,124 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type t = { + compilation_unit : Compilation_unit.t; + name : string; + name_stamp : int; + (** [name_stamp]s are unique within any given compilation unit. *) +} + +include Identifiable.Make (struct + type nonrec t = t + + let compare t1 t2 = + if t1 == t2 then 0 + else + let c = t1.name_stamp - t2.name_stamp in + if c <> 0 then c + else Compilation_unit.compare t1.compilation_unit t2.compilation_unit + + let equal t1 t2 = + if t1 == t2 then true + else + t1.name_stamp = t2.name_stamp + && Compilation_unit.equal t1.compilation_unit t2.compilation_unit + + let output chan t = + output_string chan t.name; + output_string chan "_"; + output_string chan (string_of_int t.name_stamp) + + let hash t = t.name_stamp lxor (Compilation_unit.hash t.compilation_unit) + + let print ppf t = + if Compilation_unit.equal t.compilation_unit + (Compilation_unit.get_current_exn ()) + then begin + Format.fprintf ppf "%s/%d" + t.name t.name_stamp + end else begin + Format.fprintf ppf "%a.%s/%d" + Compilation_unit.print t.compilation_unit + t.name t.name_stamp + end +end) + +let previous_name_stamp = ref (-1) + +let create ?current_compilation_unit name = + let compilation_unit = + match current_compilation_unit with + | Some compilation_unit -> compilation_unit + | None -> Compilation_unit.get_current_exn () + in + let name_stamp = + incr previous_name_stamp; + !previous_name_stamp + in + { compilation_unit; + name; + name_stamp; + } + +let create_with_same_name_as_ident ident = create (Ident.name ident) + +let clambda_name t = + (Compilation_unit.string_for_printing t.compilation_unit) ^ "_" ^ t.name + +let rename ?current_compilation_unit ?append t = + let current_compilation_unit = + match current_compilation_unit with + | Some compilation_unit -> compilation_unit + | None -> Compilation_unit.get_current_exn () + in + let name = + match append with + | None -> t.name + | Some s -> t.name ^ s + in + create ~current_compilation_unit name + +let in_compilation_unit t cu = + Compilation_unit.equal cu t.compilation_unit + +let get_compilation_unit t = t.compilation_unit + +let unique_name t = + t.name ^ "_" ^ (string_of_int t.name_stamp) + +let print_list ppf ts = + List.iter (fun t -> Format.fprintf ppf "@ %a" print t) ts + +let debug_when_stamp_matches t ~stamp ~f = + if t.name_stamp = stamp then f () + +let print_opt ppf = function + | None -> Format.fprintf ppf "" + | Some t -> print ppf t + +type pair = t * t +module Pair = Identifiable.Make (Identifiable.Pair (T) (T)) + +let compare_lists l1 l2 = + Misc.Stdlib.List.compare compare l1 l2 + +let output_full chan t = + Compilation_unit.output chan t.compilation_unit; + output_string chan "."; + output chan t diff --git a/middle_end/base_types/variable.mli b/middle_end/base_types/variable.mli new file mode 100644 index 00000000..9cd469b0 --- /dev/null +++ b/middle_end/base_types/variable.mli @@ -0,0 +1,62 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** [Variable.t] is the equivalent of a non-persistent [Ident.t] in + the [Flambda] tree. It wraps an [Ident.t] together with its source + [compilation_unit]. As such, it is unique within a whole program, + not just one compilation unit. + + Introducing a new type helps in tracing the source of identifiers + when debugging the inliner. It also avoids Ident renaming when + importing cmx files. +*) + +include Identifiable.S + +val create : ?current_compilation_unit:Compilation_unit.t -> string -> t +val create_with_same_name_as_ident : Ident.t -> t + +val clambda_name : t -> string +(* CR-someday pchambart: Should we propagate Variable.t into clambda ??? *) + +val rename + : ?current_compilation_unit:Compilation_unit.t + -> ?append:string + -> t + -> t + +val in_compilation_unit : t -> Compilation_unit.t -> bool + +val unique_name : t -> string + +val get_compilation_unit : t -> Compilation_unit.t + +val print_list : Format.formatter -> t list -> unit +val print_opt : Format.formatter -> t option -> unit + +(** If the given variable has the given stamp, call the user-supplied + function. For debugging purposes only. *) +val debug_when_stamp_matches : t -> stamp:int -> f:(unit -> unit) -> unit + +type pair = t * t +module Pair : Identifiable.S with type t := pair + +val compare_lists : t list -> t list -> int + +val output_full : out_channel -> t -> unit +(** Unlike [output], [output_full] includes the compilation unit. *) diff --git a/middle_end/closure_conversion.ml b/middle_end/closure_conversion.ml new file mode 100644 index 00000000..7f01971b --- /dev/null +++ b/middle_end/closure_conversion.ml @@ -0,0 +1,672 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Env = Closure_conversion_aux.Env +module Function_decls = Closure_conversion_aux.Function_decls +module Function_decl = Function_decls.Function_decl +module IdentSet = Lambda.IdentSet + +let name_expr = Flambda_utils.name_expr + +type t = { + current_unit_id : Ident.t; + symbol_for_global' : (Ident.t -> Symbol.t); + filename : string; + mutable imported_symbols : Symbol.Set.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]) + in + let defs_are_all_functions (defs : (_ * Lambda.lambda) list) = + List.for_all (function (_, Lambda.Lfunction _) -> true | _ -> false) defs + in + let f (lam : Lambda.lambda) : Lambda.lambda = + match lam with + | Llet (( Strict | Alias | StrictOpt), id, + Lfunction {kind; params; body = fbody; attr}, body) -> + begin match + Simplif.split_default_wrapper id kind params fbody attr + ~create_wrapper_body:stubify + with + | [fun_id, def] -> Llet (Alias, fun_id, def, body) + | [fun_id, def; inner_fun_id, def_inner] -> + Llet (Alias, inner_fun_id, def_inner, Llet (Alias, fun_id, def, body)) + | _ -> assert false + end + | Lletrec (defs, body) as lam -> + if defs_are_all_functions defs then + let defs = + List.flatten + (List.map + (function + | (id, Lambda.Lfunction {kind; params; body; attr}) -> + Simplif.split_default_wrapper id kind params body attr + ~create_wrapper_body:stubify + | _ -> assert false) + defs) + in + Lletrec (defs, body) + else lam + | lam -> lam + in + Lambda.map f lam + +(** Generate a wrapper ("stub") function that accepts a tuple argument and + calls another function with arguments extracted in the obvious + manner from the tuple. *) +let tupled_function_call_stub original_params unboxed_version + : Flambda.function_declaration = + let tuple_param = + Variable.rename ~append:"tupled_stub_param" unboxed_version + in + let params = List.map (fun p -> Variable.rename p) original_params in + let call : Flambda.t = + Apply ({ + func = unboxed_version; + args = params; + (* CR-someday mshinwell for mshinwell: investigate if there is some + redundancy here (func is also unboxed_version) *) + kind = Direct (Closure_id.wrap unboxed_version); + dbg = Debuginfo.none; + inline = Default_inline; + specialise = Default_specialise; + }) + in + let _, body = + List.fold_left (fun (pos, body) param -> + let lam : Flambda.named = + Prim (Pfield pos, [tuple_param], Debuginfo.none) + in + pos + 1, Flambda.create_let param lam body) + (0, call) params + in + Flambda.create_function_declaration ~params:[tuple_param] + ~body ~stub:true ~dbg:Debuginfo.none ~inline:Default_inline + ~specialise:Default_specialise ~is_a_functor:false + +let rec eliminate_const_block (const : Lambda.structured_constant) + : Lambda.lambda = + match const with + | Const_block (tag, consts) -> + Lprim (Pmakeblock (tag, Asttypes.Immutable), + List.map eliminate_const_block consts) + | Const_base _ + | Const_pointer _ + | Const_immstring _ + | Const_float_array _ -> Lconst const + +let default_debuginfo ?(inner_debuginfo = Debuginfo.none) env_debuginfo = + match env_debuginfo with + | None -> inner_debuginfo + | Some debuginfo -> debuginfo + +let rec close_const t env (const : Lambda.structured_constant) + : Flambda.named * string = + match const with + | Const_base (Const_int c) -> Const (Int c), "int" + | Const_base (Const_char c) -> Const (Char c), "char" + | Const_base (Const_string (s, _)) -> Allocated_const (String s), "string" + | Const_base (Const_float c) -> + Allocated_const (Float (float_of_string c)), "float" + | Const_base (Const_int32 c) -> Allocated_const (Int32 c), "int32" + | Const_base (Const_int64 c) -> Allocated_const (Int64 c), "int64" + | Const_base (Const_nativeint c) -> + Allocated_const (Nativeint c), "nativeint" + | Const_pointer c -> Const (Const_pointer c), "pointer" + | Const_immstring c -> Allocated_const (Immutable_string c), "immstring" + | Const_float_array c -> + Allocated_const (Immutable_float_array (List.map float_of_string c)), + "float_array" + | Const_block _ -> + Expr (close t env (eliminate_const_block const)), "const_block" + +and close t ?debuginfo env (lam : Lambda.lambda) : Flambda.t = + match lam with + | Lvar id -> + begin match Env.find_var_exn env id with + | var -> Var var + | exception Not_found -> + match Env.find_mutable_var_exn env id with + | mut_var -> name_expr (Read_mutable mut_var) ~name:"read_mutable" + | exception Not_found -> + Misc.fatal_errorf "Closure_conversion.close: unbound identifier %a" + Ident.print id + end + | Lconst cst -> + let cst, name = close_const t env cst in + name_expr cst ~name:("const_" ^ name) + | Llet ((Strict | Alias | StrictOpt), id, defining_expr, body) -> + let var = Variable.create_with_same_name_as_ident id in + let defining_expr = + close_let_bound_expression t var env defining_expr + in + let body = close t (Env.add_var env id var) body in + Flambda.create_let var defining_expr body + | Llet (Variable, id, defining_expr, body) -> + let mut_var = Mutable_variable.of_ident id in + let var = Variable.create_with_same_name_as_ident id in + let defining_expr = + close_let_bound_expression t var env defining_expr + in + let body = close t (Env.add_mutable_var env id mut_var) body in + Flambda.create_let var defining_expr (Let_mutable (mut_var, var, body)) + | Lfunction { kind; params; body; attr; } -> + let name = + (* Name anonymous functions by their source location, if known. *) + match body with + | Levent (_, { lev_loc }) -> + Format.asprintf "anon-fn[%a]" Location.print_compact lev_loc + | _ -> "anon-fn" + in + let closure_bound_var = Variable.create name in + (* CR-soon mshinwell: some of this is now very similar to the let rec case + below *) + let set_of_closures_var = Variable.create ("set_of_closures_" ^ name) in + 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 + in + close_functions t env (Function_decls.create [decl]) + in + let project_closure : Flambda.project_closure = + { set_of_closures = set_of_closures_var; + closure_id = Closure_id.wrap closure_bound_var; + } + in + Flambda.create_let set_of_closures_var set_of_closures + (name_expr (Project_closure (project_closure)) + ~name:("project_closure_" ^ name)) + | Lapply { ap_func; ap_args; ap_loc; ap_should_be_tailcall = _; + ap_inlined; ap_specialised; } -> + Lift_code.lifting_helper (close_list t env ap_args) + ~evaluation_order:`Right_to_left + ~name:"apply_arg" + ~create_body:(fun args -> + let func = close t env ap_func in + let func_var = Variable.create "apply_funct" in + Flambda.create_let func_var (Expr func) + (Apply ({ + func = func_var; + args; + kind = Indirect; + dbg = + default_debuginfo + ~inner_debuginfo:(Debuginfo.from_location Dinfo_call ap_loc) + debuginfo; + inline = ap_inlined; + specialise = ap_specialised; + }))) + | Lletrec (defs, body) -> + let env = + List.fold_right (fun (id, _) env -> + Env.add_var env id (Variable.create_with_same_name_as_ident id)) + defs env + in + let function_declarations = + (* Identify any bindings in the [let rec] that are functions. These + will be named after the corresponding identifier in the [let rec]. *) + List.map (function + | (let_rec_ident, Lambda.Lfunction { kind; params; body; attr; }) -> + let closure_bound_var = + Variable.create_with_same_name_as_ident let_rec_ident + in + 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 + in + Some function_declaration + | _ -> None) + defs + in + begin match + Misc.Stdlib.List.some_if_all_elements_are_some function_declarations + with + | Some function_declarations -> + (* When all the bindings are (syntactically) functions, we can + eliminate the [let rec] construction, instead producing a normal + [Let] that binds a set of closures containing all of the functions. + *) + (* CR-someday lwhite: This is a very syntactic criteria. Adding an + unused value to a set of recursive bindings changes how + functions are represented at runtime. *) + let name = + (* The Microsoft assembler has a 247-character limit on symbol + names, so we keep them shorter to try not to hit this. *) + if Sys.win32 then begin + match defs with + | (id, _)::_ -> (Ident.unique_name id) ^ "_let_rec" + | _ -> "let_rec" + end else begin + String.concat "_and_" + (List.map (fun (id, _) -> Ident.unique_name id) defs) + end + in + let set_of_closures_var = Variable.create name in + let set_of_closures = + close_functions t env (Function_decls.create function_declarations) + in + let body = + List.fold_left (fun body decl -> + let let_rec_ident = Function_decl.let_rec_ident decl in + let closure_bound_var = Function_decl.closure_bound_var decl in + let let_bound_var = Env.find_var env let_rec_ident in + (* Inside the body of the [let], each function is referred to by + a [Project_closure] expression, which projects from the set of + closures. *) + (Flambda.create_let let_bound_var + (Project_closure { + set_of_closures = set_of_closures_var; + closure_id = Closure_id.wrap closure_bound_var; + }) + body)) + (close t env body) function_declarations + in + Flambda.create_let set_of_closures_var set_of_closures body + | None -> + (* If the condition above is not satisfied, we build a [Let_rec] + expression; any functions bound by it will have their own + individual closures. *) + let defs = + List.map (fun (id, def) -> + let var = Env.find_var env id in + var, close_let_bound_expression t ~let_rec_ident:id var env def) + defs + in + Let_rec (defs, close t env body) + end + | Lsend (kind, meth, obj, args, loc) -> + let meth_var = Variable.create "meth" in + let obj_var = Variable.create "obj" in + let dbg = Debuginfo.from_location Dinfo_call loc in + Flambda.create_let meth_var (Expr (close t env meth)) + (Flambda.create_let obj_var (Expr (close t env obj)) + (Lift_code.lifting_helper (close_list t env args) + ~evaluation_order:`Right_to_left + ~name:"send_arg" + ~create_body:(fun args -> + Send { kind; meth = meth_var; obj = obj_var; args; dbg; }))) + | Lprim ((Pdivint | Pmodint) as prim, [arg1; arg2]) + when not !Clflags.fast -> (* not -unsafe *) + let arg2 = close t env arg2 in + let arg1 = close t env arg1 in + let numerator = Variable.create "numerator" in + let denominator = Variable.create "denominator" in + let zero = Variable.create "zero" in + let is_zero = Variable.create "is_zero" in + let exn = Variable.create "division_by_zero" in + let exn_symbol = + t.symbol_for_global' Predef.ident_division_by_zero + in + t.imported_symbols <- Symbol.Set.add exn_symbol t.imported_symbols; + Flambda.create_let zero (Const (Int 0)) + (Flambda.create_let exn (Symbol exn_symbol) + (Flambda.create_let denominator (Expr arg2) + (Flambda.create_let numerator (Expr arg1) + (Flambda.create_let is_zero + (Prim (Pintcomp Ceq, [zero; denominator], Debuginfo.none)) + (If_then_else (is_zero, + name_expr (Prim (Praise Raise_regular, [exn], + default_debuginfo debuginfo)) + ~name:"dummy", + (* CR-someday pchambart: find the right event. + mshinwell: I briefly looked at this, and couldn't + figure it out. + lwhite: I don't think any of the existing events + are suitable. I had to add a new one for a similar + case in the array data types work. + mshinwell: deferred CR *) + (* Debuginfo.from_raise event *) + name_expr ~name:"result" + (Prim (prim, [numerator; denominator], + Debuginfo.none)))))))) + | Lprim ((Pdivint | Pmodint), _) when not !Clflags.fast -> + Misc.fatal_error "Pdivint / Pmodint must have exactly two arguments" + | Lprim (Psequor, [arg1; arg2]) -> + let arg1 = close t env arg1 in + let arg2 = close t env arg2 in + let const_true = Variable.create "const_true" in + let cond = Variable.create "cond_sequor" in + Flambda.create_let const_true (Const (Int 1)) + (Flambda.create_let cond (Expr arg1) + (If_then_else (cond, Var const_true, arg2))) + | Lprim (Psequand, [arg1; arg2]) -> + let arg1 = close t env arg1 in + let arg2 = close t env arg2 in + let const_false = Variable.create "const_false" in + let cond = Variable.create "cond_sequand" in + Flambda.create_let const_false (Const (Int 0)) + (Flambda.create_let cond (Expr arg1) + (If_then_else (cond, arg2, Var const_false))) + | Lprim ((Psequand | Psequor), _) -> + Misc.fatal_error "Psequand / Psequor must have exactly two arguments" + | Lprim (Pidentity, [arg]) -> close t env arg + | Lprim (Pdirapply loc, [funct; arg]) + | Lprim (Prevapply loc, [arg; funct]) -> + let apply : Lambda.lambda_apply = + { ap_func = funct; + ap_args = [arg]; + ap_loc = loc; + ap_should_be_tailcall = false; + (* CR-someday lwhite: it would be nice to be able to give + inlined attributes to functions applied with the application + operators. *) + ap_inlined = Default_inline; + ap_specialised = Default_specialise; + } + in + close t env ?debuginfo (Lambda.Lapply apply) + | Lprim (Praise kind, [Levent (arg, event)]) -> + let arg_var = Variable.create "raise_arg" in + Flambda.create_let arg_var (Expr (close t env arg)) + (name_expr + (Prim (Praise kind, [arg_var], + default_debuginfo ~inner_debuginfo:(Debuginfo.from_raise event) + debuginfo)) + ~name:"raise") + | Lprim (Pfield _, [Lprim (Pgetglobal id, [])]) + when Ident.same id t.current_unit_id -> + Misc.fatal_errorf "[Pfield (Pgetglobal ...)] for the current compilation \ + unit is forbidden upon entry to the middle end" + | Lprim (Psetfield (_, _, _), [Lprim (Pgetglobal _, []); _]) -> + Misc.fatal_errorf "[Psetfield (Pgetglobal ...)] is \ + forbidden upon entry to the middle end" + | Lprim (Pgetglobal id, []) when Ident.is_predef_exn id -> + let symbol = t.symbol_for_global' id in + t.imported_symbols <- Symbol.Set.add symbol t.imported_symbols; + name_expr (Symbol symbol) ~name:"predef_exn" + | Lprim (Pgetglobal id, []) -> + assert (not (Ident.same id t.current_unit_id)); + let symbol = t.symbol_for_global' id in + t.imported_symbols <- Symbol.Set.add symbol t.imported_symbols; + name_expr (Symbol symbol) ~name:"Pgetglobal" + | Lprim (p, args) -> + (* One of the important consequences of the ANF-like representation + here is that we obtain names corresponding to the components of + blocks being made (with [Pmakeblock]). This information can be used + by the simplification pass to increase the likelihood of eliminating + the allocation, since some field accesses can be tracked back to known + field values. ,*) + let name = Printlambda.name_of_primitive p in + Lift_code.lifting_helper (close_list t env args) + ~evaluation_order:`Right_to_left + ~name:(name ^ "_arg") + ~create_body:(fun args -> + let inner_debuginfo = + Debuginfo.from_filename Debuginfo.Dinfo_call t.filename + in + name_expr (Prim (p, args, default_debuginfo debuginfo ~inner_debuginfo)) + ~name) + | Lswitch (arg, sw) -> + let scrutinee = Variable.create "switch" in + let aux (i, lam) = i, close t env lam in + let zero_to_n = Numbers.Int.zero_to_n in + Flambda.create_let scrutinee (Expr (close t env arg)) + (Switch (scrutinee, + { numconsts = zero_to_n (sw.sw_numconsts - 1); + consts = List.map aux sw.sw_consts; + numblocks = zero_to_n (sw.sw_numblocks - 1); + blocks = List.map aux sw.sw_blocks; + failaction = Misc.may_map (close t env) sw.sw_failaction; + })) + | Lstringswitch (arg, sw, def) -> + let scrutinee = Variable.create "string_switch" in + Flambda.create_let scrutinee (Expr (close t env arg)) + (String_switch (scrutinee, + List.map (fun (s, e) -> s, close t env e) sw, + Misc.may_map (close t env) def)) + | Lstaticraise (i, args) -> + Lift_code.lifting_helper (close_list t env args) + ~evaluation_order:`Right_to_left + ~name:"staticraise_arg" + ~create_body:(fun args -> + let static_exn = Env.find_static_exception env i in + Static_raise (static_exn, args)) + | Lstaticcatch (body, (i, ids), handler) -> + let st_exn = Static_exception.create () in + let env = Env.add_static_exception env i st_exn in + let vars = List.map (Variable.create_with_same_name_as_ident) ids in + Static_catch (st_exn, vars, close t env body, + close t (Env.add_vars env ids vars) handler) + | Ltrywith (body, id, handler) -> + let var = Variable.create_with_same_name_as_ident id in + Try_with (close t env body, var, close t (Env.add_var env id var) handler) + | Lifthenelse (cond, ifso, ifnot) -> + let cond = close t env cond in + let cond_var = Variable.create "cond" in + Flambda.create_let cond_var (Expr cond) + (If_then_else (cond_var, close t env ifso, close t env ifnot)) + | Lsequence (lam1, lam2) -> + let var = Variable.create "sequence" in + let lam1 = Flambda.Expr (close t env lam1) in + let lam2 = close t env lam2 in + Flambda.create_let var lam1 lam2 + | Lwhile (cond, body) -> While (close t env cond, close t env body) + | Lfor (id, lo, hi, direction, body) -> + let bound_var = Variable.create_with_same_name_as_ident id in + let from_value = Variable.create "for_from" in + let to_value = Variable.create "for_to" in + let body = close t (Env.add_var env id bound_var) body in + Flambda.create_let from_value (Expr (close t env lo)) + (Flambda.create_let to_value (Expr (close t env hi)) + (For { bound_var; from_value; to_value; direction; body; })) + | Lassign (id, new_value) -> + let being_assigned = + match Env.find_mutable_var_exn env id with + | being_assigned -> being_assigned + | exception Not_found -> + Misc.fatal_errorf "Closure_conversion.close: unbound mutable \ + variable %s in assignment" + (Ident.unique_name id) + in + let new_value_var = Variable.create "new_value" in + Flambda.create_let new_value_var (Expr (close t env new_value)) + (Assign { being_assigned; new_value = new_value_var; }) + | Levent (lam, ev) -> begin + match ev.lev_kind with + | Lev_after _ -> + close t env ~debuginfo:(Debuginfo.from_call ev) lam + | _ -> + close t env lam + end + | Lifused _ -> + (* [Lifused] is used to mark that this expression should be alive only if + an identifier is. Every use should have been removed by + [Simplif.simplify_lets], either by replacing by the inner expression, + or by completely removing it (replacing by unit). *) + Misc.fatal_error "[Lifused] should have been removed by \ + [Simplif.simplify_lets]" + +(** Perform closure conversion on a set of function declarations, returning a + set of closures. (The set will often only contain a single function; + the only case where it cannot is for "let rec".) *) +and close_functions t external_env function_declarations : Flambda.named = + let closure_env_without_parameters = + Function_decls.closure_env_without_parameters + external_env function_declarations + in + let all_free_idents = Function_decls.all_free_idents function_declarations in + let close_one_function map decl = + let body = Function_decl.body decl in + let dbg = + (* Move any debugging event that may exist at the start of the function + body onto the function declaration itself. *) + match body with + | Levent (_, ({ lev_kind = Lev_function } as ev)) -> + Debuginfo.from_call ev + | _ -> Debuginfo.none + in + let params = Function_decl.params decl in + (* Create fresh variables for the elements of the closure (cf. + the comment on [Function_decl.closure_env_without_parameters], above). + This induces a renaming on [Function_decl.free_idents]; the results of + that renaming are stored in [free_variables]. *) + let closure_env = + List.fold_right (fun id env -> + Env.add_var env id (Variable.create_with_same_name_as_ident id)) + params closure_env_without_parameters + in + (* If the function is the wrapper for a function with an optional + 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 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 + let fun_decl = + Flambda.create_function_declaration ~params ~body ~stub ~dbg + ~inline:(Function_decl.inline decl) + ~specialise:(Function_decl.specialise decl) + ~is_a_functor:(Function_decl.is_a_functor decl) + in + match Function_decl.kind decl with + | Curried -> Variable.Map.add closure_bound_var fun_decl map + | Tupled -> + let unboxed_version = Variable.rename closure_bound_var in + let generic_function_stub = + tupled_function_call_stub params unboxed_version + in + Variable.Map.add unboxed_version fun_decl + (Variable.Map.add closure_bound_var generic_function_stub map) + in + let function_decls = + Flambda.create_function_declarations + ~funs: + (List.fold_left close_one_function Variable.Map.empty + (Function_decls.to_list function_declarations)) + in + (* The closed representation of a set of functions is a "set of closures". + (For avoidance of doubt, the runtime representation of the *whole set* is + a single block with tag [Closure_tag].) *) + let set_of_closures = + let free_vars = + IdentSet.fold (fun var map -> + let internal_var = + Env.find_var closure_env_without_parameters var + in + let external_var : Flambda.specialised_to = + { var = Env.find_var external_env var; + projection = None; + } + in + Variable.Map.add internal_var external_var map) + all_free_idents Variable.Map.empty + in + Flambda.create_set_of_closures ~function_decls ~free_vars + ~specialised_args:Variable.Map.empty + ~direct_call_surrogates:Variable.Map.empty + in + Set_of_closures set_of_closures + +and close_list t sb l = List.map (close t sb) l + +and close_let_bound_expression t ?let_rec_ident let_bound_var env + (lam : Lambda.lambda) : Flambda.named = + match lam with + | Lfunction { kind; params; body; attr; } -> + (* Ensure that [let] and [let rec]-bound functions have appropriate + names. *) + 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 + in + let set_of_closures_var = + Variable.rename let_bound_var ~append:"_set_of_closures" + in + let set_of_closures = + close_functions t env (Function_decls.create [decl]) + in + let project_closure : Flambda.project_closure = + { set_of_closures = set_of_closures_var; + closure_id = Closure_id.wrap closure_bound_var; + } + in + Expr (Flambda.create_let set_of_closures_var set_of_closures + (name_expr (Project_closure (project_closure)) + ~name:(Variable.unique_name let_bound_var))) + | lam -> Expr (close t env lam) + +let lambda_to_flambda ~backend ~module_ident ~size ~filename lam + : Flambda.program = + let lam = add_default_argument_wrappers lam in + let module Backend = (val backend : Backend_intf.S) in + let compilation_unit = Compilation_unit.get_current_exn () in + let t = + { current_unit_id = Compilation_unit.get_persistent_ident compilation_unit; + symbol_for_global' = Backend.symbol_for_global'; + filename; + imported_symbols = Symbol.Set.empty; + } + in + let module_symbol = Backend.symbol_for_global' module_ident in + let block_symbol = + let linkage_name = Linkage_name.create "module_as_block" in + Symbol.create compilation_unit linkage_name + in + (* The global module block is built by accessing the fields of all the + introduced symbols. *) + (* CR-soon mshinwell for mshinwell: Add a comment describing how modules are + compiled. *) + let fields = + Array.init size (fun pos -> + let pos_str = string_of_int pos in + let sym_v = Variable.create ("block_symbol_" ^ pos_str) in + let result_v = Variable.create ("block_symbol_get_" ^ pos_str) in + let value_v = Variable.create ("block_symbol_get_field_" ^ pos_str) in + Flambda.create_let + sym_v (Symbol block_symbol) + (Flambda.create_let result_v + (Prim (Pfield 0, [sym_v], Debuginfo.none)) + (Flambda.create_let value_v + (Prim (Pfield pos, [result_v], Debuginfo.none)) + (Var value_v)))) + in + let module_initializer : Flambda.program_body = + Initialize_symbol ( + block_symbol, + Tag.create_exn 0, + [close t Env.empty lam], + Initialize_symbol ( + module_symbol, + Tag.create_exn 0, + Array.to_list fields, + End module_symbol)) + in + { imported_symbols = t.imported_symbols; + program_body = module_initializer; + } diff --git a/middle_end/closure_conversion.mli b/middle_end/closure_conversion.mli new file mode 100644 index 00000000..f5fab0a7 --- /dev/null +++ b/middle_end/closure_conversion.mli @@ -0,0 +1,53 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Generation of [Flambda] intermediate language code from [Lambda] code + by performing a form of closure conversion. + + Function declarations (which may bind one or more variables identifying + functions, possibly with mutual recursion) are transformed to + [Set_of_closures] expressions. [Project_closure] expressions are then + used to select a closure for a particular function from a [Set_of_closures] + expression. The [Set_of_closures] expressions say nothing about the + actual runtime layout of the closures; this is handled when [Flambda] code + is translated to [Clambda] code. + + The following transformations are also performed during closure + conversion: + - Constant blocks (by which is meant things wrapped in [Lambda.Const_block]) + are converted to applications of the [Pmakeblock] primitive. + - [Levent] debugging event nodes are removed and the information within + them attached to function, method and [raise] calls. + - Tuplified functions are converted to curried functions and a stub + function emitted to call the curried version. For example: + let rec f (x, y) = f (x + 1, y + 1) + is transformed to: + let rec internal_f x y = f (x + 1,y + 1) + and f (x, y) = internal_f x y (* [f] is marked as a stub function *) + - The [Pdirapply] and [Prevapply] application primitives are removed and + converted to normal [Flambda] application nodes. + + The [lambda_to_flambda] function is not re-entrant. +*) +val lambda_to_flambda + : backend:(module Backend_intf.S) + -> module_ident:Ident.t + -> size:int + -> filename:string + -> Lambda.lambda + -> Flambda.program diff --git a/middle_end/closure_conversion_aux.ml b/middle_end/closure_conversion_aux.ml new file mode 100644 index 00000000..d6270580 --- /dev/null +++ b/middle_end/closure_conversion_aux.ml @@ -0,0 +1,192 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module IdentSet = Lambda.IdentSet + +module Env = struct + type t = { + variables : Variable.t Ident.tbl; + mutable_variables : Mutable_variable.t Ident.tbl; + static_exceptions : Static_exception.t Numbers.Int.Map.t; + globals : Symbol.t Numbers.Int.Map.t; + at_toplevel : bool; + } + + let empty = { + variables = Ident.empty; + mutable_variables = Ident.empty; + static_exceptions = Numbers.Int.Map.empty; + globals = Numbers.Int.Map.empty; + at_toplevel = true; + } + + let clear_local_bindings env = + { empty with globals = env.globals } + + let add_var t id var = { t with variables = Ident.add id var t.variables } + let add_vars t ids vars = List.fold_left2 add_var t ids vars + + let find_var t id = + try Ident.find_same id t.variables + with Not_found -> + Misc.fatal_errorf "Closure_conversion.Env.find_var: %s@ %s" + (Ident.unique_name id) + (Printexc.raw_backtrace_to_string (Printexc.get_callstack 42)) + + let find_var_exn t id = + Ident.find_same id t.variables + + let add_mutable_var t id mutable_var = + { t with mutable_variables = Ident.add id mutable_var t.mutable_variables } + + let find_mutable_var_exn t id = + Ident.find_same id t.mutable_variables + + let add_static_exception t st_exn fresh_st_exn = + { t with + static_exceptions = + Numbers.Int.Map.add st_exn fresh_st_exn t.static_exceptions } + + let find_static_exception t st_exn = + try Numbers.Int.Map.find st_exn t.static_exceptions + with Not_found -> + Misc.fatal_error ("Closure_conversion.Env.find_static_exception: exn " + ^ string_of_int st_exn) + + let add_global t pos symbol = + { t with globals = Numbers.Int.Map.add pos symbol t.globals } + + let find_global t pos = + try Numbers.Int.Map.find pos t.globals + with Not_found -> + Misc.fatal_error ("Closure_conversion.Env.find_global: global " + ^ string_of_int pos) + + let at_toplevel t = t.at_toplevel + + 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 = { + let_rec_ident : Ident.t; + closure_bound_var : Variable.t; + kind : Lambda.function_kind; + 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; + } + + let create ~let_rec_ident ~closure_bound_var ~kind ~params ~body ~inline + ~specialise ~is_a_functor = + let let_rec_ident = + match let_rec_ident with + | None -> Ident.create "unnamed_function" + | Some let_rec_ident -> let_rec_ident + in + { let_rec_ident; + closure_bound_var; + kind; + params; + body; + free_idents_of_body = Lambda.free_variables body; + inline; + specialise; + is_a_functor; + } + + let let_rec_ident t = t.let_rec_ident + let closure_bound_var t = t.closure_bound_var + let kind t = t.kind + 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 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 = { + function_decls : Function_decl.t list; + all_free_idents : IdentSet.t; + } + + (* All identifiers free in the bodies of the given function declarations, + indexed by the identifiers corresponding to the functions themselves. *) + let free_idents_by_function function_decls = + List.fold_right (fun decl map -> + Variable.Map.add (Function_decl.closure_bound_var decl) + (Function_decl.free_idents decl) map) + function_decls Variable.Map.empty + + let all_free_idents function_decls = + Variable.Map.fold (fun _ -> IdentSet.union) + (free_idents_by_function function_decls) IdentSet.empty + + (* All identifiers of simultaneously-defined functions in [ts]. *) + let let_rec_idents function_decls = + List.map Function_decl.let_rec_ident function_decls + + (* All parameters of functions in [ts]. *) + let all_params function_decls = + List.concat (List.map Function_decl.params function_decls) + + let set_diff (from : IdentSet.t) (idents : Ident.t list) = + List.fold_right IdentSet.remove idents from + + (* CR-someday lwhite: use a different name from above or explain the + difference *) + let all_free_idents function_decls = + set_diff (set_diff (all_free_idents function_decls) + (all_params function_decls)) + (let_rec_idents function_decls) + + let create function_decls = + { function_decls; + all_free_idents = all_free_idents function_decls; + } + + let to_list t = t.function_decls + + let all_free_idents t = t.all_free_idents + + let closure_env_without_parameters external_env t = + let closure_env = + (* For "let rec"-bound functions. *) + List.fold_right (fun function_decl env -> + Env.add_var env (Function_decl.let_rec_ident function_decl) + (Function_decl.closure_bound_var function_decl)) + t.function_decls (Env.clear_local_bindings external_env) + in + (* For free variables. *) + IdentSet.fold (fun id env -> + Env.add_var env id (Variable.create (Ident.name id))) + t.all_free_idents closure_env +end diff --git a/middle_end/closure_conversion_aux.mli b/middle_end/closure_conversion_aux.mli new file mode 100644 index 00000000..b5c84dc6 --- /dev/null +++ b/middle_end/closure_conversion_aux.mli @@ -0,0 +1,100 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Environments and auxiliary structures used during closure conversion. *) + +(** Used to remember which [Variable.t] values correspond to which + [Ident.t] values during closure conversion, and similarly for + static exception identifiers. *) +module Env : sig + type t + + val empty : t + + val add_var : t -> Ident.t -> Variable.t -> t + val add_vars : t -> Ident.t list -> Variable.t list -> t + + val find_var : t -> Ident.t -> Variable.t + val find_var_exn : t -> Ident.t -> Variable.t + + val add_mutable_var : t -> Ident.t -> Mutable_variable.t -> t + val find_mutable_var_exn : t -> Ident.t -> Mutable_variable.t + + val add_static_exception : t -> int -> Static_exception.t -> t + val find_static_exception : t -> int -> Static_exception.t + + val add_global : t -> int -> Symbol.t -> t + val find_global : t -> int -> Symbol.t + + val at_toplevel : t -> bool + val not_at_toplevel : t -> t +end + +(** Used to represent information about a set of function declarations + during closure conversion. (The only case in which such a set may + contain more than one declaration is when processing "let rec".) *) +module Function_decls : sig + module Function_decl : sig + type t + + val create + : let_rec_ident:Ident.t option + -> closure_bound_var:Variable.t + -> kind:Lambda.function_kind + -> params:Ident.t list + -> body:Lambda.lambda + -> inline:Lambda.inline_attribute + -> specialise:Lambda.specialise_attribute + -> is_a_functor:bool + -> t + + val let_rec_ident : t -> Ident.t + val closure_bound_var : t -> Variable.t + val kind : t -> Lambda.function_kind + val params : t -> Ident.t list + val body : t -> Lambda.lambda + val inline : t -> Lambda.inline_attribute + val specialise : t -> Lambda.specialise_attribute + val is_a_functor : t -> bool + + (* [primitive_wrapper t] is [None] iff [t] is not a wrapper for a function + with default optionnal 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 + + type t + + val create : Function_decl.t list -> t + val to_list : t -> Function_decl.t list + + (* All identifiers free in the given function declarations after the binding + of parameters and function identifiers has been performed. *) + val all_free_idents : t -> Lambda.IdentSet.t + + (* A map from identifiers to their corresponding [Variable.t]s whose domain + is the set of all identifiers free in the bodies of the declarations that + are not bound as parameters. + 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/effect_analysis.ml b/middle_end/effect_analysis.ml new file mode 100644 index 00000000..a8c7ccb9 --- /dev/null +++ b/middle_end/effect_analysis.ml @@ -0,0 +1,59 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let no_effects_prim (prim : Lambda.primitive) = + match Semantics_of_primitives.for_primitive prim with + | (No_effects | Only_generative_effects), (No_coeffects | Has_coeffects) -> + true + | _ -> false + +let rec no_effects (flam : Flambda.t) = + match flam with + | Var _ -> true + | Let { defining_expr; body; _ } -> + no_effects_named defining_expr && no_effects body + | Let_mutable (_, _, body) -> no_effects body + | Let_rec (defs, body) -> + no_effects body + && List.for_all (fun (_, def) -> no_effects_named def) defs + | If_then_else (_, ifso, ifnot) -> no_effects ifso && no_effects ifnot + | Switch (_, sw) -> + let aux (_, flam) = no_effects flam in + List.for_all aux sw.blocks + && List.for_all aux sw.consts + && Misc.Stdlib.Option.value_default no_effects sw.failaction + ~default:true + | String_switch (_, sw, def) -> + List.for_all (fun (_, lam) -> no_effects lam) sw + && Misc.Stdlib.Option.value_default no_effects def + ~default:true + | Static_catch (_, _, body, _) | Try_with (body, _, _) -> + (* If there is a [raise] in [body], the whole [Try_with] may have an + effect, so there is no need to test the handler. *) + no_effects body + | While _ | For _ | Apply _ | Send _ | Assign _ | Static_raise _ -> false + | Proved_unreachable -> true + +and no_effects_named (named : Flambda.named) = + match named with + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ + | Set_of_closures _ | Project_closure _ | Project_var _ + | Move_within_set_of_closures _ -> true + | Prim (prim, _, _) -> no_effects_prim prim + | Expr flam -> no_effects flam diff --git a/middle_end/effect_analysis.mli b/middle_end/effect_analysis.mli new file mode 100644 index 00000000..b025bf0f --- /dev/null +++ b/middle_end/effect_analysis.mli @@ -0,0 +1,27 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Simple side effect analysis. *) + +(* CR-someday pchambart: Replace by call to [Purity] module. + mshinwell: Where is the [Purity] module? *) +(** Conservative approximation as to whether a given Flambda expression may + have any side effects. *) +val no_effects : Flambda.t -> bool + +val no_effects_named : Flambda.named -> bool diff --git a/middle_end/extract_projections.ml b/middle_end/extract_projections.ml new file mode 100644 index 00000000..e8171f8a --- /dev/null +++ b/middle_end/extract_projections.ml @@ -0,0 +1,189 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module E = Inline_and_simplify_aux.Env + +(* CR-soon pchambart: should we restrict only to cases + when the field is aliased to a variable outside + of the closure (i.e. when we can certainly remove + the allocation of the block) ? + Note that this may prevent cases with imbricated + closures from benefiting from this transformations. + mshinwell: What word was "imbricated" supposed to be? + (The code this referred to has been deleted, but the same thing is + probably still happening). +*) + +let known_valid_projections ~env ~projections ~which_variables = + Projection.Set.filter (fun projection -> + let from = Projection.projecting_from projection in + let outer_var = + match Variable.Map.find from which_variables with + | exception Not_found -> assert false + | (outer_var : Flambda.specialised_to) -> + Freshening.apply_variable (E.freshening env) outer_var.var + in + let approx = E.find_exn env outer_var in + match projection with + | Project_var project_var -> + begin match A.check_approx_for_closure approx with + | Ok (_value_closure, _approx_var, _approx_sym, + value_set_of_closures) -> + Var_within_closure.Map.mem project_var.var + value_set_of_closures.bound_vars + | Wrong -> false + end + | Project_closure project_closure -> + begin match A.strict_check_approx_for_set_of_closures approx with + | Ok (_var, value_set_of_closures) -> + Variable.Set.mem (Closure_id.unwrap project_closure.closure_id) + (Variable.Map.keys value_set_of_closures.function_decls.funs) + | Wrong -> false + end + | Move_within_set_of_closures move -> + begin match A.check_approx_for_closure approx with + | Ok (value_closure, _approx_var, _approx_sym, + _value_set_of_closures) -> + (* We could check that [move.move_to] is in [value_set_of_closures], + but this is unnecessary, since [Closure_id]s are unique. *) + Closure_id.equal value_closure.closure_id move.start_from + | Wrong -> false + end + | Field (field_index, _) -> + match A.check_approx_for_block approx with + | Wrong -> false + | Ok (_tag, fields) -> + field_index >= 0 && field_index < Array.length fields) + projections + +let rec analyse_expr ~which_variables expr = + let projections = ref Projection.Set.empty in + let used_which_variables = ref Variable.Set.empty in + let check_free_variable var = + if Variable.Map.mem var which_variables then begin + used_which_variables := Variable.Set.add var !used_which_variables + end + in + let for_expr (expr : Flambda.expr) = + match expr with + | Var var + | Let_mutable (_, var, _) -> + check_free_variable var + (* CR-soon mshinwell: We don't handle [Apply] for the moment to + avoid disabling unboxing optimizations whenever we see a recursive + call. We should improve this analysis. Leo says this can be + done by a similar thing to the unused argument analysis. *) + | Apply _ -> () + | Send { meth; obj; args; _ } -> + check_free_variable meth; + check_free_variable obj; + List.iter check_free_variable args + | Assign { new_value; _ } -> + check_free_variable new_value + | If_then_else (var, _, _) + | Switch (var, _) + | String_switch (var, _, _) -> + check_free_variable var + | Static_raise (_, args) -> + List.iter check_free_variable args + | For { from_value; to_value; _ } -> + check_free_variable from_value; + check_free_variable to_value + | Let _ | Let_rec _ | Static_catch _ | While _ | Try_with _ + | Proved_unreachable -> () + in + let for_named (named : Flambda.named) = + match named with + | Project_var project_var + when Variable.Map.mem project_var.closure which_variables -> + projections := + Projection.Set.add (Project_var project_var) !projections + | Project_closure project_closure + when Variable.Map.mem project_closure.set_of_closures + which_variables -> + projections := + Projection.Set.add (Project_closure project_closure) !projections + | Move_within_set_of_closures move + when Variable.Map.mem move.closure which_variables -> + projections := + Projection.Set.add (Move_within_set_of_closures move) !projections + | Prim (Pfield field_index, [var], _dbg) + when Variable.Map.mem var which_variables -> + projections := + Projection.Set.add (Field (field_index, var)) !projections + | Set_of_closures set_of_closures -> + let aliasing_free_vars = + Variable.Map.filter (fun _ (spec_to : Flambda.specialised_to) -> + Variable.Map.mem spec_to.var which_variables) + set_of_closures.free_vars + in + let aliasing_specialised_args = + Variable.Map.filter (fun _ (spec_to : Flambda.specialised_to) -> + Variable.Map.mem spec_to.var which_variables) + set_of_closures.specialised_args + in + let aliasing_vars = + Variable.Map.disjoint_union + aliasing_free_vars aliasing_specialised_args + in + if not (Variable.Map.is_empty aliasing_vars) then begin + Variable.Map.iter (fun _ (fun_decl : Flambda.function_declaration) -> + (* We ignore projections from within nested sets of closures. *) + let _, used = + analyse_expr fun_decl.body ~which_variables:aliasing_vars + in + Variable.Set.iter (fun var -> + match Variable.Map.find var aliasing_vars with + | exception Not_found -> assert false + | spec_to -> check_free_variable spec_to.var) + used) + set_of_closures.function_decls.funs + end + | Prim (_, vars, _) -> + List.iter check_free_variable vars + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ | Project_var _ | Project_closure _ + | Move_within_set_of_closures _ + | Expr _ -> () + in + Flambda_iterators.iter_toplevel for_expr for_named expr; + let projections = !projections in + let used_which_variables = !used_which_variables in + projections, used_which_variables + +let from_function_decl ~env ~which_variables + ~(function_decl : Flambda.function_declaration) = + let projections, used_which_variables = + analyse_expr ~which_variables function_decl.body + in + (* We must use approximation information to determine which projections + are actually valid in the current environment, other we might lift + expressions too far. *) + let projections = + known_valid_projections ~env ~projections ~which_variables + in + (* Don't extract projections whose [projecting_from] variable is also + used boxed. We could in the future consider being more sophisticated + about this based on the uses in the body, but given we are not doing + that yet, it seems safest in performance terms not to (e.g.) unbox a + specialised argument whose boxed version is used. *) + Projection.Set.filter (fun projection -> + let projecting_from = Projection.projecting_from projection in + not (Variable.Set.mem projecting_from used_which_variables)) + projections diff --git a/middle_end/extract_projections.mli b/middle_end/extract_projections.mli new file mode 100644 index 00000000..47456bda --- /dev/null +++ b/middle_end/extract_projections.mli @@ -0,0 +1,33 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +(** Identify projections from variables used in function bodies (free + variables or specialised args, for example, according to [which_variables] + below). Projections from variables that are also used boxed are not + returned. *) + +(** [which_variables] maps (existing) inner variables to (existing) outer + variables in the manner of [free_vars] and [specialised_args] in + [Flambda.set_of_closures]. + + The returned projections are [projecting_from] (cf. projection.mli) + the "existing inner vars". +*) +val from_function_decl + : env:Inline_and_simplify_aux.Env.t + -> which_variables:Flambda.specialised_to Variable.Map.t + -> function_decl:Flambda.function_declaration + -> Projection.Set.t diff --git a/middle_end/find_recursive_functions.ml b/middle_end/find_recursive_functions.ml new file mode 100644 index 00000000..e701e096 --- /dev/null +++ b/middle_end/find_recursive_functions.ml @@ -0,0 +1,31 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let in_function_declarations (function_decls : Flambda.function_declarations) + ~backend = + let module VCC = Strongly_connected_components.Make (Variable) in + let directed_graph = + Flambda_utils.fun_vars_referenced_in_decls function_decls ~backend + in + let connected_components = + VCC.connected_components_sorted_from_roots_to_leaf directed_graph + in + Array.fold_left (fun rec_fun -> function + | VCC.No_loop _ -> rec_fun + | VCC.Has_loop elts -> List.fold_right Variable.Set.add elts rec_fun) + Variable.Set.empty connected_components diff --git a/middle_end/find_recursive_functions.mli b/middle_end/find_recursive_functions.mli new file mode 100644 index 00000000..3c2dd5b1 --- /dev/null +++ b/middle_end/find_recursive_functions.mli @@ -0,0 +1,37 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** "Recursive functions" are those functions [f] that might call either: + - themselves, or + - another function that in turn might call [f]. + + For example in the following simultaneous definition of [f] [g] and [h], + [f] and [g] are recursive functions, but not [h]: + [let rec f x = g x + and g x = f x + and h x = g x] +*) + +(** Determine the recursive functions, if any, bound by the given set of + function declarations. + This is only intended to be used by [Flambda.create_function_declarations]. +*) +val in_function_declarations + : Flambda.function_declarations + -> backend:(module Backend_intf.S) + -> Variable.Set.t diff --git a/middle_end/flambda.ml b/middle_end/flambda.ml new file mode 100644 index 00000000..bbc66382 --- /dev/null +++ b/middle_end/flambda.ml @@ -0,0 +1,1173 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type call_kind = + | Indirect + | Direct of Closure_id.t + +type const = + | Int of int + | Char of char + | Const_pointer of int + +type apply = { + func : Variable.t; + args : Variable.t list; + kind : call_kind; + dbg : Debuginfo.t; + inline : Lambda.inline_attribute; + specialise : Lambda.specialise_attribute; +} + +type assign = { + being_assigned : Mutable_variable.t; + new_value : Variable.t; +} + +type send = { + kind : Lambda.meth_kind; + meth : Variable.t; + obj : Variable.t; + args : Variable.t list; + dbg : Debuginfo.t; +} + +type project_closure = Projection.project_closure +type move_within_set_of_closures = Projection.move_within_set_of_closures +type project_var = Projection.project_var + +type specialised_to = { + var : Variable.t; + projection : Projection.t option; +} + +type t = + | Var of Variable.t + | Let of let_expr + | Let_mutable of Mutable_variable.t * Variable.t * t + | Let_rec of (Variable.t * named) list * t + | Apply of apply + | Send of send + | Assign of assign + | If_then_else of Variable.t * t * t + | Switch of Variable.t * switch + | String_switch of Variable.t * (string * t) list * t option + | Static_raise of Static_exception.t * Variable.t list + | Static_catch of Static_exception.t * Variable.t list * t * t + | Try_with of t * Variable.t * t + | While of t * t + | For of for_loop + | Proved_unreachable + +and named = + | Symbol of Symbol.t + | Const of const + | Allocated_const of Allocated_const.t + | Read_mutable of Mutable_variable.t + | Read_symbol_field of Symbol.t * int + | Set_of_closures of set_of_closures + | Project_closure of project_closure + | Move_within_set_of_closures of move_within_set_of_closures + | Project_var of project_var + | Prim of Lambda.primitive * Variable.t list * Debuginfo.t + | Expr of t + +and let_expr = { + var : Variable.t; + defining_expr : named; + body : t; + free_vars_of_defining_expr : Variable.Set.t; + free_vars_of_body : Variable.Set.t; +} + +and set_of_closures = { + function_decls : function_declarations; + free_vars : specialised_to Variable.Map.t; + specialised_args : specialised_to Variable.Map.t; + direct_call_surrogates : Variable.t Variable.Map.t; +} + +and function_declarations = { + set_of_closures_id : Set_of_closures_id.t; + set_of_closures_origin : Set_of_closures_origin.t; + funs : function_declaration Variable.Map.t; +} + +and function_declaration = { + params : Variable.t list; + body : t; + free_variables : Variable.Set.t; + free_symbols : Symbol.Set.t; + stub : bool; + dbg : Debuginfo.t; + inline : Lambda.inline_attribute; + specialise : Lambda.specialise_attribute; + is_a_functor : bool; +} + +and switch = { + numconsts : Numbers.Int.Set.t; + consts : (int * t) list; + numblocks : Numbers.Int.Set.t; + blocks : (int * t) list; + failaction : t option; +} + +and for_loop = { + bound_var : Variable.t; + from_value : Variable.t; + to_value : Variable.t; + direction : Asttypes.direction_flag; + body : t +} + +and constant_defining_value = + | Allocated_const of Allocated_const.t + | Block of Tag.t * constant_defining_value_block_field list + | Set_of_closures of set_of_closures (* [free_vars] must be empty *) + | Project_closure of Symbol.t * Closure_id.t + +and constant_defining_value_block_field = + | Symbol of Symbol.t + | Const of const + +type expr = t + +type program_body = + | Let_symbol of Symbol.t * constant_defining_value * program_body + | Let_rec_symbol of (Symbol.t * constant_defining_value) list * program_body + | Initialize_symbol of Symbol.t * Tag.t * t list * program_body + | Effect of t * program_body + | End of Symbol.t + +type program = { + imported_symbols : Symbol.Set.t; + program_body : program_body; +} + +let fprintf = Format.fprintf +module Int = Numbers.Int + +let print_specialised_to ppf (spec_to : specialised_to) = + match spec_to.projection with + | None -> fprintf ppf "%a" Variable.print spec_to.var + | Some projection -> + fprintf ppf "%a(= %a)" + Variable.print spec_to.var + Projection.print projection + +(* CR-soon mshinwell: delete uses of old names *) +let print_project_var = Projection.print_project_var +let print_move_within_set_of_closures = + Projection.print_move_within_set_of_closures +let print_project_closure = Projection.print_project_closure + +(** CR-someday lwhite: use better name than this *) +let rec lam ppf (flam : t) = + match flam with + | Var (id) -> + Variable.print ppf id + | Apply({func; args; kind; inline}) -> + let direct ppf () = + match kind with + | Indirect -> () + | Direct closure_id -> fprintf ppf "*[%a]" Closure_id.print closure_id + in + let inline ppf () = + match inline with + | Always_inline -> fprintf ppf "" + | Never_inline -> fprintf ppf "" + | Unroll i -> fprintf ppf "" i + | Default_inline -> () + in + fprintf ppf "@[<2>(apply%a%a@ %a%a)@]" direct () inline () + Variable.print func Variable.print_list args + | Assign { being_assigned; new_value; } -> + fprintf ppf "@[<2>(assign@ %a@ %a)@]" + Mutable_variable.print being_assigned + Variable.print new_value + | Send { kind; meth; obj; args; dbg = _; } -> + let print_args ppf args = + List.iter (fun l -> fprintf ppf "@ %a" Variable.print l) args + in + let kind = + match kind with + | Self -> "self" + | Public -> "public" + | Cached -> "cached" + in + fprintf ppf "@[<2>(send%s@ %a@ %a%a)@]" kind + Variable.print obj Variable.print meth + print_args args + | Proved_unreachable -> + fprintf ppf "unreachable" + | Let { var = id; defining_expr = arg; body; _ } -> + let rec letbody (ul : t) = + match ul with + | Let { var = id; defining_expr = arg; body; _ } -> + fprintf ppf "@ @[<2>%a@ %a@]" Variable.print id print_named arg; + letbody body + | _ -> ul + in + fprintf ppf "@[<2>(let@ @[(@[<2>%a@ %a@]" + Variable.print id print_named arg; + let expr = letbody body in + fprintf ppf ")@]@ %a)@]" lam expr + | Let_mutable (mut_var, var, body) -> + fprintf ppf "@[<2>(let_mutable@ @[<2>%a@ %a@]@ %a)@]" + Mutable_variable.print mut_var + Variable.print var + lam body + | Let_rec(id_arg_list, body) -> + let bindings ppf id_arg_list = + let spc = ref false in + List.iter + (fun (id, l) -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[<2>%a@ %a@]" Variable.print id print_named l) + id_arg_list in + fprintf ppf + "@[<2>(letrec@ (@[%a@])@ %a)@]" bindings id_arg_list lam body + | Switch(larg, sw) -> + let switch ppf (sw : switch) = + let spc = ref false in + List.iter + (fun (n, l) -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[case int %i:@ %a@]" n lam l) + sw.consts; + List.iter + (fun (n, l) -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[case tag %i:@ %a@]" n lam l) + sw.blocks ; + begin match sw.failaction with + | None -> () + | Some l -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[default:@ %a@]" lam l + end in + fprintf ppf + "@[<1>(%s(%i,%i) %a@ @[%a@])@]" + (match sw.failaction with None -> "switch*" | _ -> "switch") + (Int.Set.cardinal sw.numconsts) + (Int.Set.cardinal sw.numblocks) + Variable.print larg switch sw + | String_switch(arg, cases, default) -> + let switch ppf cases = + let spc = ref false in + List.iter + (fun (s, l) -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[case \"%s\":@ %a@]" (String.escaped s) lam l) + cases; + begin match default with + | Some default -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[default:@ %a@]" lam default + | None -> () + end in + fprintf ppf + "@[<1>(stringswitch %a@ @[%a@])@]" Variable.print arg switch cases + | Static_raise (i, ls) -> + let lams ppf largs = + List.iter (fun l -> fprintf ppf "@ %a" Variable.print l) largs in + fprintf ppf "@[<2>(exit@ %a%a)@]" Static_exception.print i lams ls; + | Static_catch(i, vars, lbody, lhandler) -> + fprintf ppf "@[<2>(catch@ %a@;<1 -1>with (%a%a)@ %a)@]" + lam lbody Static_exception.print i + (fun ppf vars -> match vars with + | [] -> () + | _ -> + List.iter + (fun x -> fprintf ppf " %a" Variable.print x) + vars) + vars + lam lhandler + | Try_with(lbody, param, lhandler) -> + fprintf ppf "@[<2>(try@ %a@;<1 -1>with %a@ %a)@]" + lam lbody Variable.print param lam lhandler + | If_then_else(lcond, lif, lelse) -> + fprintf ppf "@[<2>(if@ %a@ then begin@ %a@ end else begin@ %a@ end)@]" + Variable.print lcond + lam lif lam lelse + | While(lcond, lbody) -> + fprintf ppf "@[<2>(while@ %a@ %a)@]" lam lcond lam lbody + | For { bound_var; from_value; to_value; direction; body; } -> + fprintf ppf "@[<2>(for %a@ %a@ %s@ %a@ %a)@]" + Variable.print bound_var Variable.print from_value + (match direction with + Asttypes.Upto -> "to" | Asttypes.Downto -> "downto") + Variable.print to_value lam body +and print_named ppf (named : named) = + match named with + | Symbol (symbol) -> Symbol.print ppf symbol + | Const (cst) -> fprintf ppf "Const(%a)" print_const cst + | Allocated_const (cst) -> fprintf ppf "Aconst(%a)" Allocated_const.print cst + | Read_mutable mut_var -> + fprintf ppf "Read_mut(%a)" Mutable_variable.print mut_var + | Read_symbol_field (symbol, field) -> + fprintf ppf "%a.(%d)" Symbol.print symbol field + | Project_closure (project_closure) -> + print_project_closure ppf project_closure + | Project_var (project_var) -> print_project_var ppf project_var + | Move_within_set_of_closures (move_within_set_of_closures) -> + print_move_within_set_of_closures ppf move_within_set_of_closures + | Set_of_closures (set_of_closures) -> + print_set_of_closures ppf set_of_closures + | Prim(prim, args, _) -> + fprintf ppf "@[<2>(%a%a)@]" Printlambda.primitive prim + Variable.print_list args + | Expr expr -> + fprintf ppf "*%a" lam expr + (* lam ppf expr *) + +and print_function_declaration ppf var (f : function_declaration) = + let idents ppf = + List.iter (fprintf ppf "@ %a" Variable.print) in + let stub = + if f.stub then + " *stub*" + else + "" + in + let is_a_functor = + if f.is_a_functor then + " *functor*" + else + "" + in + let inline = + match f.inline with + | Always_inline -> " *inline*" + | Never_inline -> " *never_inline*" + | Unroll _ -> " *unroll*" + | Default_inline -> "" + in + let specialise = + match f.specialise with + | Always_specialise -> " *specialise*" + | Never_specialise -> " *never_specialise*" + | Default_specialise -> "" + in + fprintf ppf "@[<2>(%a%s%s%s%s@ =@ fun@[<2>%a@] ->@ @[<2>%a@])@]@ " + Variable.print var stub is_a_functor inline specialise + idents f.params lam f.body + +and print_set_of_closures ppf (set_of_closures : set_of_closures) = + match set_of_closures with + | { function_decls; free_vars; specialised_args} -> + let funs ppf = + Variable.Map.iter (print_function_declaration ppf) + in + let vars ppf = + Variable.Map.iter (fun id v -> + fprintf ppf "@ %a -rename-> %a" + Variable.print id print_specialised_to v) + in + let spec ppf spec_args = + if not (Variable.Map.is_empty spec_args) + then begin + fprintf ppf "@ "; + Variable.Map.iter (fun id (spec_to : specialised_to) -> + fprintf ppf "@ %a := %a" + Variable.print id print_specialised_to spec_to) + spec_args + end + in + fprintf ppf "@[<2>(set_of_closures id=%a@ %a@ @[<2>free_vars={%a@ }@]@ \ + @[<2>specialised_args={%a})@]@ \ + @[<2>direct_call_surrogates=%a@]@]" + Set_of_closures_id.print function_decls.set_of_closures_id + funs function_decls.funs + vars free_vars + spec specialised_args + (Variable.Map.print Variable.print) + set_of_closures.direct_call_surrogates + +and print_const ppf (c : const) = + match c with + | Int n -> fprintf ppf "%i" n + | Char c -> fprintf ppf "%C" c + | Const_pointer n -> fprintf ppf "%ia" n + +let print_function_declarations ppf (fd : function_declarations) = + let funs ppf = + Variable.Map.iter (print_function_declaration ppf) + in + fprintf ppf "@[<2>(%a)@]" funs fd.funs + +let print ppf flam = + fprintf ppf "%a@." lam flam + +let print_function_declaration ppf (var, decl) = + print_function_declaration ppf var decl + +let print_constant_defining_value ppf (const : constant_defining_value) = + match const with + | Allocated_const const -> + fprintf ppf "(Allocated_const %a)" Allocated_const.print const + | Block (tag, []) -> fprintf ppf "(Atom (tag %d))" (Tag.to_int tag) + | Block (tag, fields) -> + let print_field ppf (field : constant_defining_value_block_field) = + match field with + | Symbol symbol -> Symbol.print ppf symbol + | Const const -> print_const ppf const + in + let print_fields ppf = + List.iter (fprintf ppf "@ %a" print_field) + in + fprintf ppf "(Block (tag %d, %a))" (Tag.to_int tag) + print_fields fields + | Set_of_closures set_of_closures -> + fprintf ppf "@[<2>(Set_of_closures (@ %a))@]" print_set_of_closures + set_of_closures + | Project_closure (set_of_closures, closure_id) -> + fprintf ppf "(Project_closure (%a, %a))" Symbol.print set_of_closures + Closure_id.print closure_id + +let rec print_program_body ppf (program : program_body) = + match program with + | Let_symbol (symbol, constant_defining_value, body) -> + let rec letbody (ul : program_body) = + match ul with + | Let_symbol (symbol, constant_defining_value, body) -> + fprintf ppf "@ @[<2>(%a@ %a)@]" Symbol.print symbol + print_constant_defining_value constant_defining_value; + letbody body + | _ -> ul + in + fprintf ppf "@[<2>let_symbol@ @[(@[<2>%a@ %a@])@]@ " + Symbol.print symbol + print_constant_defining_value constant_defining_value; + let program = letbody body in + fprintf ppf "@]@."; + print_program_body ppf program + | Let_rec_symbol (defs, program) -> + let bindings ppf id_arg_list = + let spc = ref false in + List.iter + (fun (symbol, constant_defining_value) -> + if !spc then fprintf ppf "@ " else spc := true; + fprintf ppf "@[<2>%a@ %a@]" + Symbol.print symbol + print_constant_defining_value constant_defining_value) + id_arg_list in + fprintf ppf + "@[<2>let_rec_symbol@ (@[%a@])@]@." + bindings defs; + print_program_body ppf program + | Initialize_symbol (symbol, tag, fields, program) -> + fprintf ppf "@[<2>initialize_symbol@ @[(@[<2>%a@ %a@ %a@])@]@]@." + Symbol.print symbol + Tag.print tag + (Format.pp_print_list lam) fields; + print_program_body ppf program + | Effect (expr, program) -> + fprintf ppf "@[effect @[%a@]@@]@." + lam expr; + print_program_body ppf program; + | End root -> fprintf ppf "End %a" Symbol.print root + +let print_program ppf program = + Symbol.Set.iter (fun symbol -> + fprintf ppf "@[import_symbol@ %a@]@." Symbol.print symbol) + program.imported_symbols; + print_program_body ppf program.program_body + +let rec variables_usage ?ignore_uses_as_callee ?ignore_uses_as_argument + ?ignore_uses_in_project_var ~all_used_variables tree = + match tree with + | Var var -> Variable.Set.singleton var + | _ -> + let free = ref Variable.Set.empty in + let bound = ref Variable.Set.empty in + let free_variables ids = free := Variable.Set.union ids !free in + let free_variable fv = free := Variable.Set.add fv !free in + let bound_variable id = bound := Variable.Set.add id !bound in + (* N.B. This function assumes that all bound identifiers are distinct. *) + let rec aux (flam : t) : unit = + match flam with + | Var var -> free_variable var + | Apply { func; args; kind = _; dbg = _} -> + begin match ignore_uses_as_callee with + | None -> free_variable func + | Some () -> () + end; + begin match ignore_uses_as_argument with + | None -> List.iter free_variable args + | Some () -> () + end + | Let { var; free_vars_of_defining_expr; free_vars_of_body; + defining_expr; body; _ } -> + bound_variable var; + if all_used_variables + || ignore_uses_as_callee <> None + || ignore_uses_as_argument <> None + || ignore_uses_in_project_var <> None + then begin + (* In these cases we can't benefit from the pre-computed free + variable sets. *) + free_variables + (variables_usage_named ?ignore_uses_in_project_var + ?ignore_uses_as_callee ?ignore_uses_as_argument + ~all_used_variables defining_expr); + aux body + end else begin + free_variables free_vars_of_defining_expr; + free_variables free_vars_of_body + end + | Let_mutable (_mut_var, var, body) -> + free_variable var; + aux body + | Let_rec (bindings, body) -> + List.iter (fun (var, defining_expr) -> + bound_variable var; + free_variables + (variables_usage_named ?ignore_uses_in_project_var + ~all_used_variables defining_expr)) + bindings; + aux body + | Switch (scrutinee, switch) -> + free_variable scrutinee; + List.iter (fun (_, e) -> aux e) switch.consts; + List.iter (fun (_, e) -> aux e) switch.blocks; + Misc.may aux switch.failaction + | String_switch (scrutinee, cases, failaction) -> + free_variable scrutinee; + List.iter (fun (_, e) -> aux e) cases; + Misc.may aux failaction + | Static_raise (_, es) -> + List.iter free_variable es + | Static_catch (_, vars, e1, e2) -> + List.iter bound_variable vars; + aux e1; + aux e2 + | Try_with (e1, var, e2) -> + aux e1; + bound_variable var; + aux e2 + | If_then_else (var, e1, e2) -> + free_variable var; + aux e1; + aux e2 + | While (e1, e2) -> + aux e1; + aux e2 + | For { bound_var; from_value; to_value; direction = _; body; } -> + bound_variable bound_var; + free_variable from_value; + free_variable to_value; + aux body + | Assign { being_assigned = _; new_value; } -> + free_variable new_value + | Send { kind = _; meth; obj; args; dbg = _ } -> + free_variable meth; + free_variable obj; + List.iter free_variable args; + | Proved_unreachable -> () + in + aux tree; + if all_used_variables then + !free + else + Variable.Set.diff !free !bound + +and variables_usage_named ?ignore_uses_in_project_var + ?ignore_uses_as_callee ?ignore_uses_as_argument + ~all_used_variables named = + let free = ref Variable.Set.empty in + let free_variable fv = free := Variable.Set.add fv !free in + begin match named with + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ -> () + | Set_of_closures { free_vars; specialised_args; _ } -> + (* Sets of closures are, well, closed---except for the free variable and + specialised argument lists, which may identify variables currently in + scope outside of the closure. *) + Variable.Map.iter (fun _ (renamed_to : specialised_to) -> + (* We don't need to do anything with [renamed_to.projectee.var], if + it is present, since it would only be another free variable + in the same set of closures. *) + free_variable renamed_to.var) + free_vars; + Variable.Map.iter (fun _ (spec_to : specialised_to) -> + (* We don't need to do anything with [spec_to.projectee.var], if + it is present, since it would only be another specialised arg + in the same set of closures. *) + free_variable spec_to.var) + specialised_args + | Project_closure { set_of_closures; closure_id = _ } -> + free_variable set_of_closures + | Project_var { closure; closure_id = _; var = _ } -> + begin match ignore_uses_in_project_var with + | None -> free_variable closure + | Some () -> () + end + | Move_within_set_of_closures { closure; start_from = _; move_to = _ } -> + free_variable closure + | Prim (_, args, _) -> List.iter free_variable args + | Expr flam -> + free := Variable.Set.union + (variables_usage ?ignore_uses_as_callee ?ignore_uses_as_argument + ~all_used_variables flam) !free + end; + !free + +let free_variables ?ignore_uses_as_callee ?ignore_uses_as_argument + ?ignore_uses_in_project_var tree = + variables_usage ?ignore_uses_as_callee ?ignore_uses_as_argument + ?ignore_uses_in_project_var ~all_used_variables:false tree + +let free_variables_named ?ignore_uses_in_project_var named = + variables_usage_named ?ignore_uses_in_project_var + ~all_used_variables:false named + +let used_variables ?ignore_uses_as_callee ?ignore_uses_as_argument + ?ignore_uses_in_project_var tree = + variables_usage ?ignore_uses_as_callee ?ignore_uses_as_argument + ?ignore_uses_in_project_var ~all_used_variables:true tree + +let used_variables_named ?ignore_uses_in_project_var named = + variables_usage_named ?ignore_uses_in_project_var + ~all_used_variables:true named + +let create_let var defining_expr body : t = + begin match !Clflags.dump_flambda_let with + | None -> () + | Some stamp -> + Variable.debug_when_stamp_matches var ~stamp ~f:(fun () -> + Printf.eprintf "Creation of [Let] with stamp %d:\n%s\n%!" + stamp + (Printexc.raw_backtrace_to_string (Printexc.get_callstack max_int))) + end; + let defining_expr, free_vars_of_defining_expr = + match defining_expr with + | Expr (Let { var = var1; defining_expr; body = Var var2; + free_vars_of_defining_expr; _ }) when Variable.equal var1 var2 -> + defining_expr, free_vars_of_defining_expr + | _ -> defining_expr, free_variables_named defining_expr + in + Let { + var; + defining_expr; + body; + free_vars_of_defining_expr; + free_vars_of_body = free_variables body; + } + +let map_defining_expr_of_let let_expr ~f = + let defining_expr = f let_expr.defining_expr in + if defining_expr == let_expr.defining_expr then + Let let_expr + else + let free_vars_of_defining_expr = + free_variables_named defining_expr + in + Let { + var = let_expr.var; + defining_expr; + body = let_expr.body; + free_vars_of_defining_expr; + free_vars_of_body = let_expr.free_vars_of_body; + } + +let iter_lets t ~for_defining_expr ~for_last_body ~for_each_let = + let rec loop (t : t) = + match t with + | Let { var; defining_expr; body; _ } -> + for_each_let t; + for_defining_expr var defining_expr; + loop body + | t -> + for_last_body t + in + loop t + +let map_lets t ~for_defining_expr ~for_last_body ~after_rebuild = + let rec loop (t : t) ~rev_lets = + match t with + | Let { var; defining_expr; body; _ } -> + let new_defining_expr = + for_defining_expr var defining_expr + in + let original = + if new_defining_expr == defining_expr then + Some t + else + None + in + let rev_lets = (var, new_defining_expr, original) :: rev_lets in + loop body ~rev_lets + | t -> + let last_body = for_last_body t in + (* As soon as we see a change, we have to rebuild that [Let] and every + outer one. *) + let seen_change = ref (not (last_body == t)) in + List.fold_left (fun t (var, defining_expr, original) -> + let let_expr = + match original with + | Some original when not !seen_change -> original + | Some _ | None -> + seen_change := true; + create_let var defining_expr t + in + let new_let = after_rebuild let_expr in + if not (new_let == let_expr) then begin + seen_change := true + end; + new_let) + last_body + rev_lets + in + loop t ~rev_lets:[] + +(** CR-someday lwhite: Why not use two functions? *) +type maybe_named = + | Is_expr of t + | Is_named of named + +let iter_general ~toplevel f f_named maybe_named = + let rec aux (t : t) = + match t with + | Let _ -> + iter_lets t + ~for_defining_expr:(fun _var named -> aux_named named) + ~for_last_body:aux + ~for_each_let:f + | _ -> + f t; + match t with + | Var _ | Apply _ | Assign _ | Send _ | Proved_unreachable + | Static_raise _ -> () + | Let _ -> assert false + | Let_mutable (_mut_var, _var, body) -> + aux body + | Let_rec (defs, body) -> + List.iter (fun (_,l) -> aux_named l) defs; + aux body + | Try_with (f1,_,f2) + | While (f1,f2) + | Static_catch (_,_,f1,f2) -> + aux f1; aux f2 + | For { body; _ } -> aux body + | If_then_else (_, f1, f2) -> + aux f1; aux f2 + | Switch (_, sw) -> + List.iter (fun (_,l) -> aux l) sw.consts; + List.iter (fun (_,l) -> aux l) sw.blocks; + Misc.may aux sw.failaction + | String_switch (_, sw, def) -> + List.iter (fun (_,l) -> aux l) sw; + Misc.may aux def + and aux_named (named : named) = + f_named named; + match named with + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ + | Project_closure _ | Project_var _ | Move_within_set_of_closures _ + | Prim _ -> () + | Set_of_closures ({ function_decls = funcs; free_vars = _; + specialised_args = _}) -> + if not toplevel then begin + Variable.Map.iter (fun _ (decl : function_declaration) -> + aux decl.body) + funcs.funs + end + | Expr flam -> aux flam + in + match maybe_named with + | Is_expr expr -> aux expr + | Is_named named -> aux_named named + +module With_free_variables = struct + type 'a t = + | Expr : expr * Variable.Set.t -> expr t + | Named : named * Variable.Set.t -> named t + + let of_defining_expr_of_let let_expr = + Named (let_expr.defining_expr, let_expr.free_vars_of_defining_expr) + + let of_body_of_let let_expr = + Expr (let_expr.body, let_expr.free_vars_of_body) + + let of_expr expr = + Expr (expr, free_variables expr) + + let of_named named = + Named (named, free_variables_named named) + + let create_let_reusing_defining_expr var (t : named t) body = + match t with + | Named (defining_expr, free_vars_of_defining_expr) -> + Let { + var; + defining_expr; + body; + free_vars_of_defining_expr; + free_vars_of_body = free_variables body; + } + + let create_let_reusing_body var defining_expr (t : expr t) = + match t with + | Expr (body, free_vars_of_body) -> + Let { + var; + defining_expr; + body; + free_vars_of_defining_expr = free_variables_named defining_expr; + free_vars_of_body; + } + + let create_let_reusing_both var (t1 : named t) (t2 : expr t) = + match t1, t2 with + | Named (defining_expr, free_vars_of_defining_expr), + Expr (body, free_vars_of_body) -> + Let { + var; + defining_expr; + body; + free_vars_of_defining_expr; + free_vars_of_body; + } + + let expr (t : expr t) = + match t with + | Expr (expr, free_vars) -> Named (Expr expr, free_vars) + + let contents (type a) (t : a t) : a = + match t with + | Expr (expr, _) -> expr + | Named (named, _) -> named + + let free_variables (type a) (t : a t) = + match t with + | Expr (_, free_vars) -> free_vars + | Named (_, free_vars) -> free_vars +end + +let fold_lets_option + t ~init + ~(for_defining_expr:('a -> Variable.t -> named -> 'a * Variable.t * named)) + ~for_last_body + ~(filter_defining_expr:('b -> Variable.t -> named -> Variable.Set.t -> + 'b * Variable.t * named option)) = + let finish ~last_body ~acc ~rev_lets = + let module W = With_free_variables in + let acc, t = + List.fold_left (fun (acc, t) (var, defining_expr) -> + let free_vars_of_body = W.free_variables t in + let acc, var, defining_expr = + filter_defining_expr acc var defining_expr free_vars_of_body + in + match defining_expr with + | None -> acc, t + | Some defining_expr -> + let let_expr = + W.create_let_reusing_body var defining_expr t + in + acc, W.of_expr let_expr) + (acc, W.of_expr last_body) + rev_lets + in + W.contents t, acc + in + let rec loop (t : t) ~acc ~rev_lets = + match t with + | Let { var; defining_expr; body; _ } -> + let acc, var, defining_expr = + for_defining_expr acc var defining_expr + in + let rev_lets = (var, defining_expr) :: rev_lets in + loop body ~acc ~rev_lets + | t -> + let last_body, acc = for_last_body acc t in + finish ~last_body ~acc ~rev_lets + in + loop t ~acc:init ~rev_lets:[] + +let free_symbols_helper symbols (named : named) = + match named with + | Symbol symbol + | Read_symbol_field (symbol, _) -> symbols := Symbol.Set.add symbol !symbols + | Set_of_closures set_of_closures -> + Variable.Map.iter (fun _ (function_decl : function_declaration) -> + symbols := Symbol.Set.union function_decl.free_symbols !symbols) + set_of_closures.function_decls.funs + | _ -> () + +let free_symbols expr = + let symbols = ref Symbol.Set.empty in + iter_general ~toplevel:true + (fun (_ : t) -> ()) + (fun (named : named) -> free_symbols_helper symbols named) + (Is_expr expr); + !symbols + +let free_symbols_named named = + let symbols = ref Symbol.Set.empty in + iter_general ~toplevel:true + (fun (_ : t) -> ()) + (fun (named : named) -> free_symbols_helper symbols named) + (Is_named named); + !symbols + +let free_symbols_allocated_constant_helper symbols + (const : constant_defining_value) = + match const with + | Allocated_const _ -> () + | Block (_, fields) -> + List.iter + (function + | (Symbol s : constant_defining_value_block_field) -> + symbols := Symbol.Set.add s !symbols + | (Const _ : constant_defining_value_block_field) -> ()) + fields + | Set_of_closures set_of_closures -> + symbols := Symbol.Set.union !symbols + (free_symbols_named (Set_of_closures set_of_closures)) + | Project_closure (s, _) -> + symbols := Symbol.Set.add s !symbols + +let free_symbols_program (program : program) = + let symbols = ref Symbol.Set.empty in + let rec loop (program : program_body) = + match program with + | Let_symbol (_, const, program) -> + free_symbols_allocated_constant_helper symbols const; + loop program + | Let_rec_symbol (defs, program) -> + List.iter (fun (_, const) -> + free_symbols_allocated_constant_helper symbols const) + defs; + loop program + | Initialize_symbol (_, _, fields, program) -> + List.iter (fun field -> + symbols := Symbol.Set.union !symbols (free_symbols field)) + fields; + loop program + | Effect (expr, program) -> + symbols := Symbol.Set.union !symbols (free_symbols expr); + loop program + | End symbol -> symbols := Symbol.Set.add symbol !symbols + in + (* Note that there is no need to count the [imported_symbols]. *) + loop program.program_body; + !symbols + +let create_function_declaration ~params ~body ~stub ~dbg + ~(inline : Lambda.inline_attribute) + ~(specialise : Lambda.specialise_attribute) ~is_a_functor + : function_declaration = + begin match stub, inline with + | true, (Never_inline | Default_inline) + | false, (Never_inline | Default_inline | Always_inline | Unroll _) -> () + | true, (Always_inline | Unroll _) -> + Misc.fatal_errorf + "Stubs may not be annotated as [Always_inline] or [Unroll]: %a" + print body + end; + begin match stub, specialise with + | true, (Never_specialise | Default_specialise) + | false, (Never_specialise | Default_specialise | Always_specialise) -> () + | true, Always_specialise -> + Misc.fatal_errorf + "Stubs may not be annotated as [Always_specialise]: %a" + print body + end; + { params; + body; + free_variables = free_variables body; + free_symbols = free_symbols body; + stub; + dbg; + inline; + specialise; + is_a_functor; + } + +let create_function_declarations ~funs = + let compilation_unit = Compilation_unit.get_current_exn () in + let set_of_closures_id = Set_of_closures_id.create compilation_unit in + let set_of_closures_origin = + Set_of_closures_origin.create set_of_closures_id + in + { set_of_closures_id; + set_of_closures_origin; + funs; + } + +let update_function_declarations function_decls ~funs = + let compilation_unit = Compilation_unit.get_current_exn () in + let set_of_closures_id = Set_of_closures_id.create compilation_unit in + let set_of_closures_origin = function_decls.set_of_closures_origin in + { set_of_closures_id; + set_of_closures_origin; + funs; + } + +let create_set_of_closures ~function_decls ~free_vars ~specialised_args + ~direct_call_surrogates = + if !Clflags.flambda_invariant_checks then begin + let all_fun_vars = Variable.Map.keys function_decls.funs in + let expected_free_vars = + Variable.Map.fold (fun _fun_var function_decl expected_free_vars -> + let free_vars = + Variable.Set.diff function_decl.free_variables + (Variable.Set.union (Variable.Set.of_list function_decl.params) + all_fun_vars) + in + Variable.Set.union free_vars expected_free_vars) + function_decls.funs + Variable.Set.empty + in + (* CR-soon pchambart: We do not seem to be able to maintain the + invariant that if a variable is not used inside the closure, it + is not used outside either. This would be a nice property for + better dead code elimination during inline_and_simplify, but it + is not obvious how to ensure that. + + This would be true when the function is known never to have + been inlined. + + Note that something like that may maybe enforcable in + inline_and_simplify, but there is no way to do that on other + passes. + + mshinwell: see CR in Flambda_invariants about this too + *) + let free_vars_domain = Variable.Map.keys free_vars in + if not (Variable.Set.subset expected_free_vars free_vars_domain) then begin + Misc.fatal_errorf "create_set_of_closures: [free_vars] mapping of \ + variables bound by the closure(s) is wrong. (Must map at least \ + %a but only maps %a.)@ \nfunction_decls:@ %a" + Variable.Set.print expected_free_vars + Variable.Set.print free_vars_domain + print_function_declarations function_decls + end; + let all_params = + Variable.Map.fold (fun _fun_var function_decl all_params -> + Variable.Set.union (Variable.Set.of_list function_decl.params) + all_params) + function_decls.funs + Variable.Set.empty + in + let spec_args_domain = Variable.Map.keys specialised_args in + if not (Variable.Set.subset spec_args_domain all_params) then begin + Misc.fatal_errorf "create_set_of_closures: [specialised_args] \ + maps variable(s) that are not parameters of the given function \ + declarations. specialised_args domain=%a all_params=%a \n\ + function_decls:@ %a" + Variable.Set.print spec_args_domain + Variable.Set.print all_params + print_function_declarations function_decls + end + end; + { function_decls; + free_vars; + specialised_args; + direct_call_surrogates; + } + +let used_params function_decl = + Variable.Set.filter + (fun param -> Variable.Set.mem param function_decl.free_variables) + (Variable.Set.of_list function_decl.params) + +let compare_const (c1:const) (c2:const) = + match c1, c2 with + | Int i1, Int i2 -> compare i1 i2 + | Char i1, Char i2 -> compare i1 i2 + | Const_pointer i1, Const_pointer i2 -> compare i1 i2 + | Int _, (Char _ | Const_pointer _) -> -1 + | (Char _ | Const_pointer _), Int _ -> 1 + | Char _, Const_pointer _ -> -1 + | Const_pointer _, Char _ -> 1 + +let compare_constant_defining_value_block_field + (c1:constant_defining_value_block_field) + (c2:constant_defining_value_block_field) = + match c1, c2 with + | Symbol s1, Symbol s2 -> Symbol.compare s1 s2 + | Const c1, Const c2 -> compare_const c1 c2 + | Symbol _, Const _ -> -1 + | Const _, Symbol _ -> 1 + +module Constant_defining_value = struct + type t = constant_defining_value + + include Identifiable.Make (struct + type nonrec t = t + + let compare (t1 : t) (t2 : t) = + match t1, t2 with + | Allocated_const c1, Allocated_const c2 -> + Allocated_const.compare c1 c2 + | Block (tag1, fields1), Block (tag2, fields2) -> + let c = Tag.compare tag1 tag2 in + if c <> 0 then c + else + Misc.Stdlib.List.compare compare_constant_defining_value_block_field + fields1 fields2 + | Set_of_closures set1, Set_of_closures set2 -> + Set_of_closures_id.compare set1.function_decls.set_of_closures_id + set2.function_decls.set_of_closures_id + | Project_closure (set1, closure_id1), + Project_closure (set2, closure_id2) -> + let c = Symbol.compare set1 set2 in + if c <> 0 then c + else Closure_id.compare closure_id1 closure_id2 + | Allocated_const _, Block _ -> -1 + | Allocated_const _, Set_of_closures _ -> -1 + | Allocated_const _, Project_closure _ -> -1 + | Block _, Allocated_const _ -> 1 + | Block _, Set_of_closures _ -> -1 + | Block _, Project_closure _ -> -1 + | Set_of_closures _, Allocated_const _ -> 1 + | Set_of_closures _, Block _ -> 1 + | Set_of_closures _, Project_closure _ -> -1 + | Project_closure _, Allocated_const _ -> 1 + | Project_closure _, Block _ -> 1 + | Project_closure _, Set_of_closures _ -> 1 + + let equal t1 t2 = + t1 == t2 || compare t1 t2 = 0 + + let hash = Hashtbl.hash + + let print = print_constant_defining_value + + let output o v = + output_string o (Format.asprintf "%a" print v) + end) +end + +let equal_specialised_to (spec_to1 : specialised_to) + (spec_to2 : specialised_to) = + Variable.equal spec_to1.var spec_to2.var + && begin + match spec_to1.projection, spec_to2.projection with + | None, None -> true + | Some _, None | None, Some _ -> false + | Some proj1, Some proj2 -> Projection.equal proj1 proj2 + end + +let compare_project_var = Projection.compare_project_var +let compare_project_closure = Projection.compare_project_closure +let compare_move_within_set_of_closures = + Projection.compare_move_within_set_of_closures diff --git a/middle_end/flambda.mli b/middle_end/flambda.mli new file mode 100644 index 00000000..6e8ede86 --- /dev/null +++ b/middle_end/flambda.mli @@ -0,0 +1,649 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Intermediate language used for tree-based analysis and optimization. *) + +(** Whether the callee in a function application is known at compile time. *) +type call_kind = + | Indirect + | Direct of Closure_id.t + +(** Simple constants. ("Structured constants" are rewritten to invocations + of [Pmakeblock] so that they easily take part in optimizations.) *) +type const = + | Int of int + | Char of char + (** [Char] is kept separate from [Int] to improve printing *) + | Const_pointer of int + (** [Const_pointer] is an immediate value of a type whose values may be + boxed (typically a variant type with both constant and non-constant + constructors). *) + +(** The application of a function to a list of arguments. *) +type apply = { + (* CR-soon mshinwell: rename func -> callee, and + lhs_of_application -> callee *) + func : Variable.t; + args : Variable.t list; + kind : call_kind; + dbg : Debuginfo.t; + inline : Lambda.inline_attribute; + (** Instructions from the source code as to whether the callee should + be inlined. *) + specialise : Lambda.specialise_attribute; + (** Instructions from the source code as to whether the callee should + be specialised. *) +} + +(** The update of a mutable variable. Mutable variables are distinct from + immutable variables in Flambda. *) +type assign = { + being_assigned : Mutable_variable.t; + new_value : Variable.t; +} + +(** The invocation of a method. *) +type send = { + kind : Lambda.meth_kind; + meth : Variable.t; + obj : Variable.t; + args : Variable.t list; + dbg : Debuginfo.t; +} + +(** For details on these types, see projection.mli. *) +type project_closure = Projection.project_closure +type move_within_set_of_closures = Projection.move_within_set_of_closures +type project_var = Projection.project_var + +(** See [free_vars] and [specialised_args], below. *) +(* CR-someday mshinwell: move to separate module and make [Identifiable]. + (Or maybe nearly Identifiable; having a special map that enforces invariants + might be good.) *) +type specialised_to = { + var : Variable.t; + (** The "outer variable". *) + projection : Projection.t option; + (** The [projecting_from] value (see projection.mli) of any [projection] + must be another free variable or specialised argument (depending on + whether this record type is involved in [free_vars] or + [specialised_args] respectively) in the same set of closures. + As such, this field describes a relation of projections between + either the [free_vars] or the [specialised_args]. *) +} + +(** Flambda terms are partitioned in a pseudo-ANF manner; many terms are + required to be [let]-bound. This in particular ensures there is always + a variable name for an expression that may be lifted out (for example + if it is found to be constant). + Note: All bound variables in Flambda terms must be distinct. + [Flambda_invariants] verifies this. *) +type t = + | Var of Variable.t + | Let of let_expr + | Let_mutable of Mutable_variable.t * Variable.t * t + | Let_rec of (Variable.t * named) list * t + (** CR-someday lwhite: give Let_rec the same fields as Let. *) + | Apply of apply + | Send of send + | Assign of assign + | If_then_else of Variable.t * t * t + | Switch of Variable.t * switch + | String_switch of Variable.t * (string * t) list * t option + (** Restrictions on [Lambda.Lstringswitch] also apply to [String_switch]. *) + | Static_raise of Static_exception.t * Variable.t list + | Static_catch of Static_exception.t * Variable.t list * t * t + | Try_with of t * Variable.t * t + | While of t * t + | For of for_loop + | Proved_unreachable + +(** Values of type [named] will always be [let]-bound to a [Variable.t]. *) +and named = + | Symbol of Symbol.t + | Const of const + | Allocated_const of Allocated_const.t + | Read_mutable of Mutable_variable.t + | Read_symbol_field of Symbol.t * int + (** During the lifting of [let] bindings to [program] constructions after + closure conversion, we generate symbols and their corresponding + definitions (which may or may not be constant), together with field + accesses to such symbols. We would like it to be the case that such + field accesses are simplified to the relevant component of the + symbol concerned. (The rationale is to generate efficient code and + share constants as expected: see e.g. tests/asmcomp/staticalloc.ml.) + The components of the symbol would be identified by other symbols. + This sort of access pattern is feasible because the top-level structure + of symbols is statically allocated and fixed at compile time. + It may seem that [Prim (Pfield, ...)] expressions could be used to + perform the field accesses. However for simplicity, to avoid having to + keep track of properties of individual fields of blocks, + [Inconstant_idents] never deems a [Prim (Pfield, ...)] expression to be + constant. This would in general prevent field accesses to symbols from + being simplified in the way we would like, since [Lift_constants] would + not assign new symbols (i.e. the things we would like to simplify to) + to the various projections from the symbols in question. + To circumvent this problem we use [Read_symbol_field] when generating + projections from the top level of symbols. Owing to the properties of + symbols described above, such expressions may be eligible for declaration + as constant by [Inconstant_idents] (and thus themselves lifted to another + symbol), without any further complication. + [Read_symbol_field] may only be used when the definition of the symbol + is in scope in the [program]. For external unresolved symbols, [Pfield] + may still be used; it will be changed to [Read_symbol_field] by + [Inline_and_simplify] when (and if) the symbol is imported. *) + | Set_of_closures of set_of_closures + | Project_closure of project_closure + | Move_within_set_of_closures of move_within_set_of_closures + | Project_var of project_var + | Prim of Lambda.primitive * Variable.t list * Debuginfo.t + | Expr of t (** ANF escape hatch. *) + +(* CR-someday mshinwell: use [letcont]-style construct to remove e.g. + [While] and [For]. *) +(* CR-someday mshinwell: try to produce a tighter definition of a "switch" + (and translate to that earlier) so that middle- and back-end code for + these can be reduced. *) +(* CR-someday mshinwell: remove [Expr], but to do this easily would probably + require a continuation-binding construct. *) +(* CR-someday mshinwell: Since we lack expression identifiers on every term, + we should probably introduce [Mutable_var] into [named] if we introduce + more complicated analyses on these in the future. Alternatively, maybe + consider removing mutable variables altogether. *) + +and let_expr = private { + var : Variable.t; + defining_expr : named; + body : t; + (* CR-someday mshinwell: we could consider having these be keys into some + kind of global cache, to reduce memory usage. *) + free_vars_of_defining_expr : Variable.Set.t; + (** A cache of the free variables in the defining expression of the [let]. *) + free_vars_of_body : Variable.Set.t; + (** A cache of the free variables of the body of the [let]. This is an + important optimization. *) +} + +(** The representation of a set of function declarations (possibly mutually + recursive). Such a set encapsulates the declarations themselves, + information about their defining environment, and information used + specifically for optimization. + Before a function can be applied it must be "projected" from a set of + closures to yield a "closure". This is done using [Project_closure] + (see above). Given a closure, not only can it be applied, but information + about its defining environment can be retrieved (using [Project_var], + see above). + At runtime, a [set_of_closures] corresponds to an OCaml value with tag + [Closure_tag] (possibly with inline [Infix_tag](s)). As an optimization, + an operation ([Move_within_set_of_closures]) is provided (see above) + which enables one closure within a set to be located given another + closure in the same set. This avoids keeping a pointer to the whole set + of closures alive when compiling, for example, mutually-recursive + functions. +*) +and set_of_closures = private { + function_decls : function_declarations; + (* CR-soon mshinwell: consider renaming [free_vars]. Also, it's still really + confusing which side of this map to use when. "Vars bound by the + closure" is the domain. + Another example of when this is confusing: + let bound_vars_approx = + Variable.Map.map (Env.find_approx env) set.free_vars + in + in [Build_export_info]. *) + (* CR-soon mshinwell: I'd like to arrange these maps so that it's impossible + to put invalid projection information into them (in particular, so that + we enforce that the relation stays within the domain of the map). *) + free_vars : specialised_to Variable.Map.t; + (** Mapping from all variables free in the body of the [function_decls] to + variables in scope at the definition point of the [set_of_closures]. + The domain of this map is sometimes known as the "variables bound by + the closure". *) + specialised_args : specialised_to Variable.Map.t; + (** Parameters whose corresponding arguments are known to always alias a + particular value. These are the only parameters that may, during + [Inline_and_simplify], have non-unknown approximations. + + An argument may only be specialised to a variable in the scope of the + corresponding set of closures declaration. Usually, that variable + itself also appears in the position of the specialised argument at + all call sites of the function. However it may also be the case (for + example in code generated as a result of [Augment_specialised_args]) + that the various call sites of such a function have differing + variables in the position of the specialised argument. This is + permissible *so long as it is certain they all alias the same value*. + Great care must be taken in transformations that result in this + situation since there are no invariant checks for correctness. + + As an example, supposing all call sites of f are represented here: + [let x = ... in + let f a b c = ... in + let y = ... in + f x y 1; + f x y 1] + the specialised arguments of f can (but does not necessarily) contain + the association [a] -> [x], but cannot contain [b] -> [y] because [f] + is not in the scope of [y]. If f were the recursive function + [let rec f a b c = f a 1 2 in], [a] -> [x] would still be a valid + specialised argument because all recursive calls maintain the invariant. + + This information is used for optimisation purposes, if such a binding is + known, it is possible to specialise the body of the function according + to its parameter. This is usually introduced when specialising a + recursive function, for instance. + [let rec map f = function + | [] -> [] + | h :: t -> f h :: map f t + let map_succ l = + let succ x = x + 1 in + map succ l] + [map] can be duplicated in [map_succ] to be specialised for the argument + [f]. This will result in + [let map_succ l = + let succ x = x + 1 in + let rec map f = function + | [] -> [] + | h :: t -> f h :: map f t in + map succ l] + with map having [f] -> [succ] in its [specialised_args] field. + + Specialised argument information for arguments that are used must + never be erased. This ensures that specialised arguments whose + approximations describe closures maintain those approximations, which + is essential to transport the closure freshening information to the + point of use (e.g. a [Project_var] from such an argument). + *) + direct_call_surrogates : Variable.t Variable.Map.t; + (** If [direct_call_surrogates] maps [fun_var1] to [fun_var2] then direct + calls to [fun_var1] should be redirected to [fun_var2]. This is used + to reduce the overhead of transformations that introduce wrapper + functions (which will be inlined at direct call sites, but will + penalise indirect call sites). + [direct_call_surrogates] may not be transitively closed. *) +} + +and function_declarations = private { + set_of_closures_id : Set_of_closures_id.t; + (** An identifier (unique across all Flambda trees currently in memory) + of the set of closures associated with this set of function + declarations. *) + set_of_closures_origin : Set_of_closures_origin.t; + (** An identifier of the original set of closures on which this set of + function declarations is based. Used to prevent different + specialisations of the same functions from being inlined/specialised + within each other. *) + funs : function_declaration Variable.Map.t; + (** The function(s) defined by the set of function declarations. The + keys of this map are often referred to in the code as "fun_var"s. *) +} + +and function_declaration = private { + params : Variable.t list; + body : t; + (* CR-soon mshinwell: inconsistent naming free_variables/free_vars here and + above *) + free_variables : Variable.Set.t; + (** All variables free in the *body* of the function. For example, a + variable that is bound as one of the function's parameters will still + be included in this set. This field is present as an optimization. *) + free_symbols : Symbol.Set.t; + (** All symbols that occur in the function's body. (Symbols can never be + bound in a function's body; the only thing that binds symbols is the + [program] constructions below.) *) + stub : bool; + (** A stub function is a generated function used to prepare arguments or + return values to allow indirect calls to functions with a special calling + convention. For instance indirect calls to tuplified functions must go + through a stub. Stubs will be unconditionally inlined. *) + dbg : Debuginfo.t; + (** Debug info for the function declaration. *) + inline : Lambda.inline_attribute; + (** Inlining requirements from the source code. *) + specialise : Lambda.specialise_attribute; + (** Specialising requirements from the source code. *) + is_a_functor : bool; + (** Whether the function is known definitively to be a functor. *) +} + +(** Equivalent to the similar type in [Lambda]. *) +and switch = { + numconsts : Numbers.Int.Set.t; (** Integer cases *) + consts : (int * t) list; (** Integer cases *) + numblocks : Numbers.Int.Set.t; (** Number of tag block cases *) + blocks : (int * t) list; (** Tag block cases *) + failaction : t option; (** Action to take if none matched *) +} + +(** Equivalent to the similar type in [Lambda]. *) +and for_loop = { + bound_var : Variable.t; + from_value : Variable.t; + to_value : Variable.t; + direction : Asttypes.direction_flag; + body : t +} + +(** Like a subset of [Flambda.named], except that instead of [Variable.t]s we + have [Symbol.t]s, and everything is a constant (i.e. with a fixed value + known at compile time). Values of this type describe constants that will + be directly assigned to symbols in the object file (see below). *) +and constant_defining_value = + | Allocated_const of Allocated_const.t + (** A single constant. These are never "simple constants" (type [const]) + but instead more complicated constructions. *) + | Block of Tag.t * constant_defining_value_block_field list + (** A pre-allocated block full of constants (either simple constants + or references to other constants, see below). *) + | Set_of_closures of set_of_closures + (** A closed (and thus constant) set of closures. (That is to say, + [free_vars] must be empty.) *) + | Project_closure of Symbol.t * Closure_id.t + (** Selection of one closure from a constant set of closures. + Analogous to the equivalent operation on expressions. *) + +and constant_defining_value_block_field = + | Symbol of Symbol.t + | Const of const + +module Constant_defining_value : + Identifiable.S with type t = constant_defining_value + +type expr = t + +(** A "program" is the contents of one compilation unit. It describes the + various values that are assigned to symbols (and in some cases fields of + such symbols) in the object file. As such, it is closely related to + the compilation of toplevel modules. *) +type program_body = + | Let_symbol of Symbol.t * constant_defining_value * program_body + (** Define the given symbol to have the given constant value. *) + | Let_rec_symbol of (Symbol.t * constant_defining_value) list * program_body + (** As for [Let_symbol], but recursive. This is needed to treat examples + like this, where a constant set of closures is lifted to toplevel: + + let rec f x = f x + + After lifting this produces (in pseudo-Flambda): + + Let_rec_symbol set_of_closures_symbol = + (Set_of_closures { f x -> + let applied_function = Symbol f_closure in + Apply (applied_function, x) }) + and f_closure = Project_closure (set_of_closures_symbol, f) + + Use of [Let_rec_symbol], by virtue of the special handling in + [Inline_and_simplify.define_let_rec_symbol_approx], enables the + approximation of the set of closures to be present in order to + correctly simplify the [Project_closure] construction. (See + [Inline_and_simplify.simplify_project_closure] for that part.) *) + | Initialize_symbol of Symbol.t * Tag.t * t list * program_body + (** Define the given symbol as a constant block of the given size and + tag; but with a possibly non-constant initializer. The initializer + will be executed at most once (from the entry point of the compilation + unit). *) + | Effect of t * program_body + (** Cause the given expression, which may have a side effect, to be + executed. The resulting value is discarded. [Effect] constructions + are never re-ordered. *) + | End of Symbol.t + (** [End] accepts the root symbol: the only symbol that can never be + eliminated. *) + +type program = { + imported_symbols : Symbol.Set.t; + program_body : program_body; +} + +(** Compute the free variables of a term. (This is O(1) for [Let]s). + If [ignore_uses_as_callee], all free variables inside [Apply] expressions + are ignored. Likewise [ignore_uses_in_project_var] for [Project_var] + expressions. +*) +val free_variables + : ?ignore_uses_as_callee:unit + -> ?ignore_uses_as_argument:unit + -> ?ignore_uses_in_project_var:unit + -> t + -> Variable.Set.t + +(** Compute the free variables of a named expression. *) +val free_variables_named + : ?ignore_uses_in_project_var:unit + -> named + -> Variable.Set.t + +(** Compute _all_ variables occuring inside an expression. *) +val used_variables + : ?ignore_uses_as_callee:unit + -> ?ignore_uses_as_argument:unit + -> ?ignore_uses_in_project_var:unit + -> t + -> Variable.Set.t + +(** Compute _all_ variables occurring inside a named expression. *) +val used_variables_named + : ?ignore_uses_in_project_var:unit + -> named + -> Variable.Set.t + +val free_symbols : expr -> Symbol.Set.t + +val free_symbols_named : named -> Symbol.Set.t + +val free_symbols_program : program -> Symbol.Set.t + +(** Used to avoid exceeding the stack limit when handling expressions with + multiple consecutive nested [Let]-expressions. This saves rewriting large + simplification functions in CPS. This function provides for the + rewriting or elimination of expressions during the fold. *) +val fold_lets_option + : t + -> init:'a + -> for_defining_expr:('a -> Variable.t -> named -> 'a * Variable.t * named) + -> for_last_body:('a -> t -> t * 'b) + (* CR-someday mshinwell: consider making [filter_defining_expr] + optional *) + -> filter_defining_expr:('b -> Variable.t -> named -> Variable.Set.t -> + 'b * Variable.t * named option) + -> t * 'b + +(** Like [fold_lets_option], but just a map. *) +val map_lets + : t + -> for_defining_expr:(Variable.t -> named -> named) + -> for_last_body:(t -> t) + -> after_rebuild:(t -> t) + -> t + +(** Like [map_lets], but just an iterator. *) +val iter_lets + : t + -> for_defining_expr:(Variable.t -> named -> unit) + -> for_last_body:(t -> unit) + -> for_each_let:(t -> unit) + -> unit + +(** Creates a [Let] expression. (This computes the free variables of the + defining expression and the body.) *) +val create_let : Variable.t -> named -> t -> t + +(** Apply the specified function [f] to the defining expression of the given + [Let]-expression, returning a new [Let]. *) +val map_defining_expr_of_let : let_expr -> f:(named -> named) -> t + +(** A module for the manipulation of terms where the recomputation of free + variable sets is to be kept to a minimum. *) +module With_free_variables : sig + type 'a t + + (** O(1) time. *) + val of_defining_expr_of_let : let_expr -> named t + + (** O(1) time. *) + val of_body_of_let : let_expr -> expr t + + (** Takes the time required to calculate the free variables of the given + term (proportional to the size of the term, except that the calculation + for [Let] is O(1)). *) + val of_expr : expr -> expr t + + val of_named : named -> named t + + (** Takes the time required to calculate the free variables of the given + [expr]. *) + val create_let_reusing_defining_expr + : Variable.t + -> named t + -> expr + -> expr + + (** Takes the time required to calculate the free variables of the given + [named]. *) + val create_let_reusing_body + : Variable.t + -> named + -> expr t + -> expr + + (** O(1) time. *) + val create_let_reusing_both + : Variable.t + -> named t + -> expr t + -> expr + + (** The equivalent of the [Expr] constructor. *) + val expr : expr t -> named t + + val contents : 'a t -> 'a + + (** O(1) time. *) + val free_variables : _ t -> Variable.Set.t +end + +(** Create a function declaration. This calculates the free variables and + symbols occurring in the specified [body]. *) +val create_function_declaration + : params:Variable.t list + -> body:t + -> stub:bool + -> dbg:Debuginfo.t + -> inline:Lambda.inline_attribute + -> specialise:Lambda.specialise_attribute + -> is_a_functor:bool + -> function_declaration + +(** Create a set of function declarations given the individual declarations. *) +val create_function_declarations + : funs:function_declaration Variable.Map.t + -> function_declarations + +(** Create a set of function declarations based on another set of function + declarations. *) +val update_function_declarations + : function_declarations + -> funs:function_declaration Variable.Map.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 + : function_decls:function_declarations + -> free_vars:specialised_to Variable.Map.t + -> specialised_args:specialised_to Variable.Map.t + -> direct_call_surrogates:Variable.t Variable.Map.t + -> set_of_closures + +(** Given a function declaration, find which of its parameters (if any) + are used in the body. *) +val used_params : function_declaration -> Variable.Set.t + +type maybe_named = + | Is_expr of t + | Is_named of named + +(** This function is designed for the internal use of [Flambda_iterators]. + See that module for iterators to be used over Flambda terms. *) +val iter_general + : toplevel:bool + -> (t -> unit) + -> (named -> unit) + -> maybe_named + -> unit + +val print : Format.formatter -> t -> unit + +val print_named : Format.formatter -> named -> unit + +val print_program : Format.formatter -> program -> unit + +val print_const : Format.formatter -> const -> unit + +val print_constant_defining_value + : Format.formatter + -> constant_defining_value + -> unit + +val print_function_declaration + : Format.formatter + -> Variable.t * function_declaration + -> unit + +val print_function_declarations + : Format.formatter + -> function_declarations + -> unit + +val print_project_closure + : Format.formatter + -> project_closure + -> unit + +val print_move_within_set_of_closures + : Format.formatter + -> move_within_set_of_closures + -> unit + +val print_project_var + : Format.formatter + -> project_var + -> unit + +val print_set_of_closures + : Format.formatter + -> set_of_closures + -> unit + +val print_specialised_to + : Format.formatter + -> specialised_to + -> unit + +val equal_specialised_to + : specialised_to + -> specialised_to + -> bool + +val compare_project_var : project_var -> project_var -> int + +val compare_move_within_set_of_closures + : move_within_set_of_closures + -> move_within_set_of_closures + -> int + +val compare_project_closure : project_closure -> project_closure -> int diff --git a/middle_end/flambda_invariants.ml b/middle_end/flambda_invariants.ml new file mode 100644 index 00000000..b007a425 --- /dev/null +++ b/middle_end/flambda_invariants.ml @@ -0,0 +1,822 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-30-40-41-42"] + +type flambda_kind = + | Normal + | Lifted + +(* Explicit "ignore" functions. We name every pattern variable, avoiding + underscores, to try to avoid accidentally failing to handle (for example) + a particular variable. + We also avoid explicit record field access during the checking functions, + preferring instead to use exhaustive record matches. +*) +(* CR-someday pchambart: for sum types, we should probably add an exhaustive + pattern in ignores functions to be reminded if a type change *) +let already_added_bound_variable_to_env (_ : Variable.t) = () +let will_traverse_named_expression_later (_ : Flambda.named) = () +let ignore_variable (_ : Variable.t) = () +let ignore_call_kind (_ : Flambda.call_kind) = () +let ignore_debuginfo (_ : Debuginfo.t) = () +let ignore_meth_kind (_ : Lambda.meth_kind) = () +let ignore_int (_ : int) = () +let ignore_int_set (_ : Numbers.Int.Set.t) = () +let ignore_bool (_ : bool) = () +let ignore_string (_ : string) = () +let ignore_static_exception (_ : Static_exception.t) = () +let ignore_direction_flag (_ : Asttypes.direction_flag) = () +let ignore_primitive ( _ : Lambda.primitive) = () +let ignore_const (_ : Flambda.const) = () +let ignore_allocated_const (_ : Allocated_const.t) = () +let ignore_set_of_closures_id (_ : Set_of_closures_id.t) = () +let ignore_set_of_closures_origin (_ : Set_of_closures_origin.t) = () +let ignore_closure_id (_ : Closure_id.t) = () +let ignore_var_within_closure (_ : Var_within_closure.t) = () +let ignore_tag (_ : Tag.t) = () +let ignore_inline_attribute (_ : Lambda.inline_attribute) = () +let ignore_specialise_attribute (_ : Lambda.specialise_attribute) = () + +exception Binding_occurrence_not_from_current_compilation_unit of Variable.t +exception Mutable_binding_occurrence_not_from_current_compilation_unit of + Mutable_variable.t +exception Binding_occurrence_of_variable_already_bound of Variable.t +exception Binding_occurrence_of_mutable_variable_already_bound of + Mutable_variable.t +exception Binding_occurrence_of_symbol_already_bound of Symbol.t +exception Unbound_variable of Variable.t +exception Unbound_mutable_variable of Mutable_variable.t +exception Unbound_symbol of Symbol.t +exception Vars_in_function_body_not_bound_by_closure_or_params of + Variable.Set.t * Flambda.set_of_closures * Variable.t +exception Function_decls_have_overlapping_parameters of Variable.Set.t +exception Specialised_arg_that_is_not_a_parameter of Variable.t +exception Projection_must_be_a_free_var of Projection.t +exception Projection_must_be_a_specialised_arg of Projection.t +exception Free_variables_set_is_lying of + Variable.t * Variable.Set.t * Variable.Set.t * Flambda.function_declaration +exception Set_of_closures_free_vars_map_has_wrong_range of Variable.Set.t +exception Static_exception_not_caught of Static_exception.t +exception Static_exception_caught_in_multiple_places of Static_exception.t +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 Sequential_logical_operator_primitives_must_be_expanded of + Lambda.primitive +exception Var_within_closure_bound_multiple_times of Var_within_closure.t +exception Declared_closure_from_another_unit of Compilation_unit.t +exception Closure_id_is_bound_multiple_times of Closure_id.t +exception Set_of_closures_id_is_bound_multiple_times of Set_of_closures_id.t +exception Unbound_closure_ids of Closure_id.Set.t +exception Unbound_vars_within_closures of Var_within_closure.Set.t +exception Move_to_a_closure_not_in_the_free_variables + of Variable.t * Variable.Set.t + +exception Flambda_invariants_failed + +(* CR-someday mshinwell: We should make "direct applications should not have + overapplication" be an invariant throughout. At the moment I think this is + only true after [Inline_and_simplify] has split overapplications. *) + +(* CR-someday mshinwell: What about checks for shadowed variables and + symbols? *) + +let variable_and_symbol_invariants (program : Flambda.program) = + let all_declared_variables = ref Variable.Set.empty in + let declare_variable var = + if Variable.Set.mem var !all_declared_variables then + raise (Binding_occurrence_of_variable_already_bound var); + all_declared_variables := Variable.Set.add var !all_declared_variables + in + let declare_variables vars = + Variable.Set.iter declare_variable vars + in + let all_declared_mutable_variables = ref Mutable_variable.Set.empty in + let declare_mutable_variable mut_var = + if Mutable_variable.Set.mem mut_var !all_declared_mutable_variables then + raise (Binding_occurrence_of_mutable_variable_already_bound mut_var); + all_declared_mutable_variables := + Mutable_variable.Set.add mut_var !all_declared_mutable_variables + in + let add_binding_occurrence (var_env, mut_var_env, sym_env) var = + let compilation_unit = Compilation_unit.get_current_exn () in + if not (Variable.in_compilation_unit var compilation_unit) then + raise (Binding_occurrence_not_from_current_compilation_unit var); + declare_variable var; + Variable.Set.add var var_env, mut_var_env, sym_env + in + let add_mutable_binding_occurrence (var_env, mut_var_env, sym_env) mut_var = + let compilation_unit = Compilation_unit.get_current_exn () in + if not (Mutable_variable.in_compilation_unit mut_var compilation_unit) then + raise (Mutable_binding_occurrence_not_from_current_compilation_unit + mut_var); + declare_mutable_variable mut_var; + var_env, Mutable_variable.Set.add mut_var mut_var_env, sym_env + in + let add_binding_occurrence_of_symbol (var_env, mut_var_env, sym_env) sym = + if Symbol.Set.mem sym sym_env then + raise (Binding_occurrence_of_symbol_already_bound sym) + else + var_env, mut_var_env, Symbol.Set.add sym sym_env + in + let add_binding_occurrences env vars = + List.fold_left (fun env var -> add_binding_occurrence env var) env vars + in + let check_variable_is_bound (var_env, _, _) var = + if not (Variable.Set.mem var var_env) then raise (Unbound_variable var) + in + let check_symbol_is_bound (_, _, sym_env) sym = + if not (Symbol.Set.mem sym sym_env) then raise (Unbound_symbol sym) + in + let check_variables_are_bound env vars = + List.iter (check_variable_is_bound env) vars + in + let check_mutable_variable_is_bound (_, mut_var_env, _) mut_var = + if not (Mutable_variable.Set.mem mut_var mut_var_env) then begin + raise (Unbound_mutable_variable mut_var) + end + in + let rec loop env (flam : Flambda.t) = + match flam with + (* Expressions that can bind [Variable.t]s: *) + | Let { var; defining_expr; body; _ } -> + loop_named env defining_expr; + loop (add_binding_occurrence env var) body + | Let_mutable (mut_var, var, body) -> + check_variable_is_bound env var; + loop (add_mutable_binding_occurrence env mut_var) body + | Let_rec (defs, body) -> + let env = + List.fold_left (fun env (var, def) -> + will_traverse_named_expression_later def; + add_binding_occurrence env var) + env defs + in + List.iter (fun (var, def) -> + already_added_bound_variable_to_env var; + loop_named env def) defs; + loop env body + | For { bound_var; from_value; to_value; direction; body; } -> + ignore_direction_flag direction; + check_variable_is_bound env from_value; + check_variable_is_bound env to_value; + loop (add_binding_occurrence env bound_var) body + | Static_catch (static_exn, vars, body, handler) -> + ignore_static_exception static_exn; + loop env body; + loop (add_binding_occurrences env vars) handler + | Try_with (body, var, handler) -> + loop env body; + loop (add_binding_occurrence env var) handler + (* Everything else: *) + | Var var -> check_variable_is_bound env var + | Apply { func; args; kind; dbg; inline; specialise; } -> + check_variable_is_bound env func; + check_variables_are_bound env args; + ignore_call_kind kind; + ignore_debuginfo dbg; + ignore_inline_attribute inline; + ignore_specialise_attribute specialise + | Assign { being_assigned; new_value; } -> + check_mutable_variable_is_bound env being_assigned; + check_variable_is_bound env new_value + | Send { kind; meth; obj; args; dbg; } -> + ignore_meth_kind kind; + check_variable_is_bound env meth; + check_variable_is_bound env obj; + check_variables_are_bound env args; + ignore_debuginfo dbg + | If_then_else (cond, ifso, ifnot) -> + check_variable_is_bound env cond; + loop env ifso; + loop env ifnot + | Switch (arg, { numconsts; consts; numblocks; blocks; failaction; }) -> + check_variable_is_bound env arg; + ignore_int_set numconsts; + ignore_int_set numblocks; + List.iter (fun (n, e) -> + ignore_int n; + loop env e) + (consts @ blocks); + Misc.may (loop env) failaction + | String_switch (arg, cases, e_opt) -> + check_variable_is_bound env arg; + List.iter (fun (label, case) -> + ignore_string label; + loop env case) + cases; + Misc.may (loop env) e_opt + | Static_raise (static_exn, es) -> + ignore_static_exception static_exn; + List.iter (check_variable_is_bound env) es + | While (e1, e2) -> + loop env e1; + loop env e2 + | Proved_unreachable -> () + and loop_named env (named : Flambda.named) = + match named with + | Symbol symbol -> check_symbol_is_bound env symbol + | Const const -> ignore_const const + | Allocated_const const -> ignore_allocated_const const + | Read_mutable mut_var -> + check_mutable_variable_is_bound env mut_var + | Read_symbol_field (symbol, index) -> + check_symbol_is_bound env symbol; + assert (index >= 0) (* CR-someday mshinwell: add proper error *) + | Set_of_closures set_of_closures -> + loop_set_of_closures env set_of_closures + | Project_closure { set_of_closures; closure_id; } -> + check_variable_is_bound env set_of_closures; + ignore_closure_id closure_id + | Move_within_set_of_closures { closure; start_from; move_to; } -> + check_variable_is_bound env closure; + ignore_closure_id start_from; + ignore_closure_id move_to; + | Project_var { closure; closure_id; var; } -> + check_variable_is_bound env closure; + ignore_closure_id closure_id; + ignore_var_within_closure var + | Prim (prim, args, dbg) -> + ignore_primitive prim; + check_variables_are_bound env args; + ignore_debuginfo dbg + | Expr expr -> + loop env expr + and loop_set_of_closures env + ({ Flambda.function_decls; free_vars; specialised_args; + direct_call_surrogates = _; } as set_of_closures) = + (* CR-soon mshinwell: check [direct_call_surrogates] *) + let { Flambda.set_of_closures_id; set_of_closures_origin; funs; } = + function_decls + in + ignore_set_of_closures_id set_of_closures_id; + ignore_set_of_closures_origin set_of_closures_origin; + let functions_in_closure = Variable.Map.keys funs in + let variables_in_closure = + Variable.Map.fold (fun var (var_in_closure : Flambda.specialised_to) + variables_in_closure -> + (* [var] may occur in the body, but will effectively be renamed + to [var_in_closure], so the latter is what we check to make + sure it's bound. *) + ignore_variable var; + check_variable_is_bound env var_in_closure.var; + Variable.Set.add var variables_in_closure) + free_vars Variable.Set.empty + in + let all_params, all_free_vars = + Variable.Map.fold (fun fun_var function_decl acc -> + let all_params, all_free_vars = acc in + (* CR-soon mshinwell: check function_decl.all_symbols *) + let { Flambda.params; body; free_variables; stub; dbg; _ } = + function_decl + in + assert (Variable.Set.mem fun_var functions_in_closure); + ignore_bool stub; + ignore_debuginfo dbg; + (* Check that [free_variables], which is only present as an + optimization, is not lying. *) + let free_variables' = Flambda.free_variables body in + if not (Variable.Set.subset free_variables' free_variables) then + raise (Free_variables_set_is_lying (fun_var, + free_variables, free_variables', function_decl)); + (* Check that every variable free in the body of the function is + bound by either the set of closures or the parameter list. *) + let acceptable_free_variables = + Variable.Set.union + (Variable.Set.union variables_in_closure functions_in_closure) + (Variable.Set.of_list params) + in + let bad = + Variable.Set.diff free_variables acceptable_free_variables + in + if not (Variable.Set.is_empty bad) then begin + raise (Vars_in_function_body_not_bound_by_closure_or_params + (bad, set_of_closures, fun_var)) + end; + (* Check that parameters are unique across all functions in the + declaration. *) + let old_all_params_size = Variable.Set.cardinal all_params in + let params = Variable.Set.of_list params in + let params_size = Variable.Set.cardinal params in + let all_params = Variable.Set.union all_params params in + let all_params_size = Variable.Set.cardinal all_params in + if all_params_size <> old_all_params_size + params_size then begin + raise (Function_decls_have_overlapping_parameters all_params) + end; + (* Check that parameters and function variables are not + bound somewhere else in the program *) + declare_variables params; + declare_variable fun_var; + (* Check that the body of the functions is correctly structured *) + let body_env = + let (var_env, _, sym_env) = env in + let var_env = + Variable.Set.fold (fun var -> Variable.Set.add var) + free_variables var_env + in + (* Mutable variables cannot be captured by closures *) + let mut_env = Mutable_variable.Set.empty in + (var_env, mut_env, sym_env) + in + loop body_env body; + all_params, Variable.Set.union free_variables all_free_vars) + funs (Variable.Set.empty, Variable.Set.empty) + in + (* CR-soon pchambart: This is not a property that we can certainly + ensure. + If the function get inlined, it is possible for the inlined version + to still use that variable. To be able to ensure that, we need to + also ensure that the inlined version will certainly be transformed + in a same way that can drop the dependency. + mshinwell: This should get some thought after the first release to + decide for sure what to do. *) + (* Check that the free variables rewriting map in the set of closures + does not contain variables in its domain that are not actually free + variables of any of the function bodies. *) + let bad_free_vars = + Variable.Set.diff (Variable.Map.keys free_vars) all_free_vars + in +(* + if not (Variable.Set.is_empty bad_free_vars) then begin + raise (Set_of_closures_free_vars_map_has_wrong_range bad_free_vars) + end; +*) + (* CR-someday pchambart: Ignore it to avoid the warning: get rid of that + when the case is settled *) + ignore (Set_of_closures_free_vars_map_has_wrong_range bad_free_vars); + (* Check that free variables variables are not bound somewhere + else in the program *) + declare_variables (Variable.Map.keys free_vars); + (* Check that every "specialised arg" is a parameter of one of the + functions being declared, and that the variable to which the + parameter is being specialised is bound. *) + Variable.Map.iter (fun _inner_var + (specialised_to : Flambda.specialised_to) -> + check_variable_is_bound env specialised_to.var; + match specialised_to.projection with + | None -> () + | Some projection -> + let projecting_from = Projection.projecting_from projection in + if not (Variable.Map.mem projecting_from free_vars) + then begin + raise (Projection_must_be_a_free_var projection) + end) + free_vars; + Variable.Map.iter (fun being_specialised + (specialised_to : Flambda.specialised_to) -> + if not (Variable.Set.mem being_specialised all_params) then begin + raise (Specialised_arg_that_is_not_a_parameter being_specialised) + end; + check_variable_is_bound env specialised_to.var; + match specialised_to.projection with + | None -> () + | Some projection -> + let projecting_from = Projection.projecting_from projection in + if not (Variable.Map.mem projecting_from specialised_args) + then begin + raise (Projection_must_be_a_specialised_arg projection) + end) + specialised_args + in + let loop_constant_defining_value env + (const : Flambda.constant_defining_value) = + match const with + | Flambda.Allocated_const c -> + ignore_allocated_const c + | Flambda.Block (tag,fields) -> + ignore_tag tag; + List.iter (fun (fields : Flambda.constant_defining_value_block_field) -> + match fields with + | Const c -> ignore_const c + | Symbol s -> check_symbol_is_bound env s) + fields + | Flambda.Set_of_closures set_of_closures -> + loop_set_of_closures env set_of_closures; + (* Constant set of closures must not have free variables *) + if not (Variable.Map.is_empty set_of_closures.free_vars) then + assert false; (* TODO: correct error *) + if not (Variable.Map.is_empty set_of_closures.specialised_args) then + assert false; (* TODO: correct error *) + | Flambda.Project_closure (symbol,closure_id) -> + ignore_closure_id closure_id; + check_symbol_is_bound env symbol + in + let rec loop_program_body env (program : Flambda.program_body) = + match program with + | Let_rec_symbol (defs, program) -> + let env = + List.fold_left (fun env (symbol, _) -> + add_binding_occurrence_of_symbol env symbol) + env defs + in + List.iter (fun (_, def) -> + loop_constant_defining_value env def) + defs; + loop_program_body env program + | Let_symbol (symbol, def, program) -> + loop_constant_defining_value env def; + let env = add_binding_occurrence_of_symbol env symbol in + loop_program_body env program + | Initialize_symbol (symbol, _tag, fields, program) -> + List.iter (loop env) fields; + let env = add_binding_occurrence_of_symbol env symbol in + loop_program_body env program + | Effect (expr, program) -> + loop env expr; + loop_program_body env program + | End root -> + check_symbol_is_bound env root + in + let env = + Symbol.Set.fold (fun symbol env -> + add_binding_occurrence_of_symbol env symbol) + program.imported_symbols + (Variable.Set.empty, Mutable_variable.Set.empty, Symbol.Set.empty) + in + loop_program_body env program.program_body + +let primitive_invariants flam ~no_access_to_global_module_identifiers = + Flambda_iterators.iter_named (function + | Prim (prim, _, _) -> + begin match prim with + | Psequand | Psequor -> + raise (Sequential_logical_operator_primitives_must_be_expanded prim) + | Pgetglobal id -> + if no_access_to_global_module_identifiers + && not (Ident.is_predef_exn id) then + begin + raise (Access_to_global_module_identifier prim) + end + | Pidentity -> raise Pidentity_should_not_occur + | Pdirapply _ -> raise Pdirapply_should_be_expanded + | Prevapply _ -> raise Prevapply_should_be_expanded + | _ -> () + end + | _ -> ()) + flam + +let declared_var_within_closure (flam:Flambda.program) = + let bound = ref Var_within_closure.Set.empty in + let bound_multiple_times = ref None in + let add_and_check var = + if Var_within_closure.Set.mem var !bound then begin + bound_multiple_times := Some var + end; + bound := Var_within_closure.Set.add var !bound + in + Flambda_iterators.iter_on_set_of_closures_of_program + ~f:(fun ~constant:_ { Flambda. free_vars; _ } -> + Variable.Map.iter (fun id _ -> + let var = Var_within_closure.wrap id in + add_and_check var) + free_vars) + flam; + !bound, !bound_multiple_times + +let no_var_within_closure_is_bound_multiple_times (flam:Flambda.program) = + match declared_var_within_closure flam with + | _, Some var -> raise (Var_within_closure_bound_multiple_times var) + | _, None -> () + +let every_declared_closure_is_from_current_compilation_unit flam = + let current_compilation_unit = Compilation_unit.get_current_exn () in + Flambda_iterators.iter_on_sets_of_closures (fun + { Flambda. function_decls; _ } -> + let compilation_unit = + Set_of_closures_id.get_compilation_unit + function_decls.set_of_closures_id + in + if not (Compilation_unit.equal compilation_unit current_compilation_unit) + then raise (Declared_closure_from_another_unit compilation_unit)) + flam + +let declared_closure_ids program = + let bound = ref Closure_id.Set.empty in + let bound_multiple_times = ref None in + let add_and_check var = + if Closure_id.Set.mem var !bound + then bound_multiple_times := Some var; + bound := Closure_id.Set.add var !bound + in + Flambda_iterators.iter_on_set_of_closures_of_program program + ~f:(fun ~constant:_ { Flambda. function_decls; _; } -> + Variable.Map.iter (fun id _ -> + let var = Closure_id.wrap id in + add_and_check var) + function_decls.funs); + !bound, !bound_multiple_times + +let no_closure_id_is_bound_multiple_times program = + match declared_closure_ids program with + | _, Some closure_id -> + raise (Closure_id_is_bound_multiple_times closure_id) + | _, None -> () + +let declared_set_of_closures_ids program = + let bound = ref Set_of_closures_id.Set.empty in + let bound_multiple_times = ref None in + let add_and_check var = + if Set_of_closures_id.Set.mem var !bound + then bound_multiple_times := Some var; + bound := Set_of_closures_id.Set.add var !bound + in + Flambda_iterators.iter_on_set_of_closures_of_program program + ~f:(fun ~constant:_ { Flambda. function_decls; _; } -> + add_and_check function_decls.set_of_closures_id); + !bound, !bound_multiple_times + +let no_set_of_closures_id_is_bound_multiple_times program = + match declared_set_of_closures_ids program with + | _, Some set_of_closures_id -> + raise (Set_of_closures_id_is_bound_multiple_times set_of_closures_id) + | _, None -> () + +let used_closure_ids (program:Flambda.program) = + let used = ref Closure_id.Set.empty in + let f (flam : Flambda.named) = + match flam with + | Project_closure { closure_id; _} -> + used := Closure_id.Set.add closure_id !used; + | Move_within_set_of_closures { closure = _; start_from; move_to; } -> + used := Closure_id.Set.add start_from !used; + used := Closure_id.Set.add move_to !used + | Project_var { closure = _; closure_id; var = _ } -> + used := Closure_id.Set.add closure_id !used + | Set_of_closures _ | Symbol _ | Const _ | Allocated_const _ + | Prim _ | Expr _ | Read_mutable _ | Read_symbol_field _ -> () + in + (* CR-someday pchambart: check closure_ids of constant_defining_values' + project_closures *) + Flambda_iterators.iter_named_of_program ~f program; + !used + +let used_vars_within_closures (flam:Flambda.program) = + let used = ref Var_within_closure.Set.empty in + let f (flam : Flambda.named) = + match flam with + | Project_var { closure = _; closure_id = _; var; } -> + used := Var_within_closure.Set.add var !used + | _ -> () + in + Flambda_iterators.iter_named_of_program ~f flam; + !used + +let every_used_function_from_current_compilation_unit_is_declared + (program:Flambda.program) = + let current_compilation_unit = Compilation_unit.get_current_exn () in + let declared, _ = declared_closure_ids program in + let used = used_closure_ids program in + let used_from_current_unit = + Closure_id.Set.filter (fun cu -> + Closure_id.in_compilation_unit cu current_compilation_unit) + used + in + let counter_examples = + Closure_id.Set.diff used_from_current_unit declared + in + if Closure_id.Set.is_empty counter_examples + then () + else raise (Unbound_closure_ids counter_examples) + +let every_used_var_within_closure_from_current_compilation_unit_is_declared + (flam:Flambda.program) = + let current_compilation_unit = Compilation_unit.get_current_exn () in + let declared, _ = declared_var_within_closure flam in + let used = used_vars_within_closures flam in + let used_from_current_unit = + Var_within_closure.Set.filter (fun cu -> + Var_within_closure.in_compilation_unit cu current_compilation_unit) + used + in + let counter_examples = + Var_within_closure.Set.diff used_from_current_unit declared in + if Var_within_closure.Set.is_empty counter_examples + then () + else raise (Unbound_vars_within_closures counter_examples) + +let every_static_exception_is_caught flam = + let check env (flam : Flambda.t) = + match flam with + | Static_raise (exn, _) -> + if not (Static_exception.Set.mem exn env) + then raise (Static_exception_not_caught exn) + | _ -> () + in + let rec loop env (flam : Flambda.t) = + match flam with + | Static_catch (i, _, body, handler) -> + let env = Static_exception.Set.add i env in + loop env handler; + loop env body + | exp -> + check env exp; + Flambda_iterators.apply_on_subexpressions (loop env) + (fun (_ : Flambda.named) -> ()) exp + in + loop Static_exception.Set.empty flam + +let every_static_exception_is_caught_at_a_single_position flam = + let caught = ref Static_exception.Set.empty in + let f (flam : Flambda.t) = + match flam with + | Static_catch (i, _, _body, _handler) -> + if Static_exception.Set.mem i !caught then + raise (Static_exception_caught_in_multiple_places i); + caught := Static_exception.Set.add i !caught + | _ -> () + in + Flambda_iterators.iter f (fun (_ : Flambda.named) -> ()) flam + +let _every_move_within_set_of_closures_is_to_a_function_in_the_free_vars + program = + let moves = ref Closure_id.Map.empty in + Flambda_iterators.iter_named_of_program program + ~f:(function + | Move_within_set_of_closures { start_from; move_to; _ } -> + let moved_to = + try Closure_id.Map.find start_from !moves with + | Not_found -> Closure_id.Set.empty + in + moves := + Closure_id.Map.add start_from + (Closure_id.Set.add move_to moved_to) + !moves + | _ -> ()); + Flambda_iterators.iter_on_set_of_closures_of_program program + ~f:(fun ~constant:_ { Flambda.function_decls = { funs; _ }; _ } -> + Variable.Map.iter (fun fun_var { Flambda.free_variables; _ } -> + match Closure_id.Map.find (Closure_id.wrap fun_var) !moves with + | exception Not_found -> () + | moved_to -> + let missing_dependencies = + Variable.Set.diff (Closure_id.unwrap_set moved_to) + free_variables + in + if not (Variable.Set.is_empty missing_dependencies) then + raise (Move_to_a_closure_not_in_the_free_variables + (fun_var, missing_dependencies))) + funs) + +let check_exn ?(kind=Normal) ?(cmxfile=false) (flam:Flambda.program) = + ignore kind; + try + variable_and_symbol_invariants flam; + no_closure_id_is_bound_multiple_times flam; + no_set_of_closures_id_is_bound_multiple_times flam; + every_used_function_from_current_compilation_unit_is_declared flam; + no_var_within_closure_is_bound_multiple_times flam; + every_used_var_within_closure_from_current_compilation_unit_is_declared + flam; + (* CR-soon pchambart: This invariant is not maintained. It should be + either relaxed or reformulated. Currently, it is safe to disable it as + the potential related errors would result in fatal errors, not in + miscompilations *) + (* every_move_within_set_of_closures_is_to_a_function_in_the_free_vars + flam; *) + Flambda_iterators.iter_exprs_at_toplevel_of_program flam ~f:(fun flam -> + primitive_invariants flam ~no_access_to_global_module_identifiers:cmxfile; + every_static_exception_is_caught flam; + every_static_exception_is_caught_at_a_single_position flam; + every_declared_closure_is_from_current_compilation_unit flam) + with exn -> begin + (* CR-someday split printing code into its own function *) + begin match exn with + | Binding_occurrence_not_from_current_compilation_unit var -> + Format.eprintf ">> Binding occurrence of variable marked as not being \ + from the current compilation unit: %a" + Variable.print var + | Mutable_binding_occurrence_not_from_current_compilation_unit mut_var -> + Format.eprintf ">> Binding occurrence of mutable variable marked as not \ + being from the current compilation unit: %a" + Mutable_variable.print mut_var + | Binding_occurrence_of_variable_already_bound var -> + Format.eprintf ">> Binding occurrence of variable that was already \ + bound: %a" + Variable.print var + | Binding_occurrence_of_mutable_variable_already_bound mut_var -> + Format.eprintf ">> Binding occurrence of mutable variable that was \ + already bound: %a" + Mutable_variable.print mut_var + | Binding_occurrence_of_symbol_already_bound sym -> + Format.eprintf ">> Binding occurrence of symbol that was already \ + bound: %a" + Symbol.print sym + | Unbound_variable var -> + Format.eprintf ">> Unbound variable: %a" Variable.print var + | Unbound_mutable_variable mut_var -> + Format.eprintf ">> Unbound mutable variable: %a" + Mutable_variable.print mut_var + | Unbound_symbol sym -> + Format.eprintf ">> Unbound symbol: %a %s" + Symbol.print sym + (Printexc.raw_backtrace_to_string (Printexc.get_callstack 100)) + | Vars_in_function_body_not_bound_by_closure_or_params + (vars, set_of_closures, fun_var) -> + Format.eprintf ">> Variable(s) (%a) in the body of a function \ + declaration (fun_var = %a) that is not bound by either the closure \ + or the function's parameter list. Set of closures: %a" + Variable.Set.print vars + Variable.print fun_var + Flambda.print_set_of_closures set_of_closures + | Function_decls_have_overlapping_parameters vars -> + Format.eprintf ">> Function declarations whose parameters overlap: \ + %a" + Variable.Set.print vars + | Specialised_arg_that_is_not_a_parameter var -> + Format.eprintf ">> Variable in [specialised_args] that is not a \ + parameter of any of the function(s) in the corresponding \ + declaration(s): %a" + Variable.print var + | Projection_must_be_a_free_var var -> + Format.eprintf ">> Projection %a in [free_vars] from a variable that is \ + not a (inner) free variable of the set of closures" + Projection.print var + | Projection_must_be_a_specialised_arg var -> + Format.eprintf ">> Projection %a in [specialised_args] from a variable \ + that is not a (inner) specialised argument variable of the set of \ + closures" + Projection.print var + | Free_variables_set_is_lying (var, claimed, calculated, function_decl) -> + Format.eprintf ">> Function declaration whose [free_variables] set (%a) \ + is not a superset of the result of [Flambda.free_variables] \ + applied to the body of the function (%a). Declaration: %a" + Variable.Set.print claimed + Variable.Set.print calculated + Flambda.print_function_declaration (var, function_decl) + | Set_of_closures_free_vars_map_has_wrong_range vars -> + Format.eprintf ">> [free_vars] map in set of closures has in its range \ + variables that are not free variables of the corresponding \ + functions: %a" + Variable.Set.print vars + | Sequential_logical_operator_primitives_must_be_expanded prim -> + Format.eprintf ">> Sequential logical operator primitives must be \ + expanded (see closure_conversion.ml): %a" + Printlambda.primitive prim + | Var_within_closure_bound_multiple_times var -> + Format.eprintf ">> Variable within a closure is bound multiple times: \ + %a" + Var_within_closure.print var + | Closure_id_is_bound_multiple_times closure_id -> + Format.eprintf ">> Closure ID is bound multiple times: %a" + Closure_id.print closure_id + | Set_of_closures_id_is_bound_multiple_times set_of_closures_id -> + Format.eprintf ">> Set of closures ID is bound multiple times: %a" + Set_of_closures_id.print set_of_closures_id + | Declared_closure_from_another_unit compilation_unit -> + Format.eprintf ">> Closure declared as being from another compilation \ + unit: %a" + Compilation_unit.print compilation_unit + | Unbound_closure_ids closure_ids -> + Format.eprintf ">> Unbound closure ID(s) from the current compilation \ + unit: %a" + Closure_id.Set.print closure_ids + | Unbound_vars_within_closures vars_within_closures -> + Format.eprintf ">> Unbound variable(s) within closure(s) from the \ + current compilation_unit: %a" + Var_within_closure.Set.print vars_within_closures + | Static_exception_not_caught static_exn -> + Format.eprintf ">> Uncaught static exception: %a" + Static_exception.print static_exn + | Static_exception_caught_in_multiple_places static_exn -> + Format.eprintf ">> Static exception caught in multiple places: %a" + Static_exception.print static_exn + | Access_to_global_module_identifier prim -> + (* CR-someday mshinwell: backend-specific checks should move to another + module, in the asmcomp/ directory. *) + Format.eprintf ">> Forbidden access to a global module identifier (not \ + allowed in Flambda that will be exported to a .cmx file): %a" + Printlambda.primitive prim + | Pidentity_should_not_occur -> + Format.eprintf ">> The Pidentity primitive should never occur in an \ + 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" + | Prevapply_should_be_expanded -> + Format.eprintf ">> The Prevapply primitive should never occur in an \ + Flambda expression (see closure_conversion.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" + Variable.print start_from + Variable.Set.print move_to + | exn -> raise exn + end; + Format.eprintf "\n@?"; + raise Flambda_invariants_failed + end diff --git a/middle_end/flambda_invariants.mli b/middle_end/flambda_invariants.mli new file mode 100644 index 00000000..6a24ef30 --- /dev/null +++ b/middle_end/flambda_invariants.mli @@ -0,0 +1,29 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type flambda_kind = + | Normal + | Lifted + +(** Checking of invariants on Flambda expressions. Raises an exception if + a check fails. *) +val check_exn + : ?kind:flambda_kind + -> ?cmxfile:bool + -> Flambda.program + -> unit diff --git a/middle_end/flambda_iterators.ml b/middle_end/flambda_iterators.ml new file mode 100644 index 00000000..170e87ed --- /dev/null +++ b/middle_end/flambda_iterators.ml @@ -0,0 +1,834 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let apply_on_subexpressions f f_named (flam : Flambda.t) = + match flam with + | Var _ | Apply _ | Assign _ | Send _ | Proved_unreachable + | Static_raise _ -> () + | Let { defining_expr; body; _ } -> + f_named defining_expr; + f body + | Let_mutable (_mut_var, _var, body) -> + f body + | Let_rec (defs, body) -> + List.iter (fun (_,l) -> f_named l) defs; + f body + | Switch (_, sw) -> + List.iter (fun (_,l) -> f l) sw.consts; + List.iter (fun (_,l) -> f l) sw.blocks; + Misc.may f sw.failaction + | String_switch (_, sw, def) -> + List.iter (fun (_,l) -> f l) sw; + Misc.may f def + | Static_catch (_,_,f1,f2) -> + f f1; f f2; + | Try_with (f1,_,f2) -> + f f1; f f2 + | If_then_else (_,f1, f2) -> + f f1;f f2 + | While (f1,f2) -> + f f1; f f2 + | For { body; _ } -> f body + +let rec list_map_sharing f l = + match l with + | [] -> l + | h :: t -> + let new_t = list_map_sharing f t in + let new_h = f h in + if h == new_h && t == new_t then + l + else + new_h :: new_t + +let may_map_sharing f v = + match v with + | None -> v + | Some s -> + let new_s = f s in + if s == new_s then + v + else + Some new_s + +let map_snd_sharing f ((a, b) as cpl) = + let new_b = f a b in + if b == new_b then + cpl + else + (a, new_b) + +let map_subexpressions f f_named (tree:Flambda.t) : Flambda.t = + match tree with + | Var _ | Apply _ | Assign _ | Send _ | Proved_unreachable + | Static_raise _ -> tree + | Let { var; defining_expr; body; _ } -> + let new_named = f_named var defining_expr in + let new_body = f body in + if new_named == defining_expr && new_body == body then + tree + else + Flambda.create_let var new_named new_body + | Let_rec (defs, body) -> + let new_defs = + list_map_sharing (map_snd_sharing f_named) defs + in + let new_body = f body in + if new_defs == defs && new_body == body then + tree + else + Let_rec (new_defs, new_body) + | Let_mutable (mut_var, var, body) -> + let new_body = f body in + if new_body == body then + tree + else + Let_mutable (mut_var, var, new_body) + | Switch (arg, sw) -> + let aux = map_snd_sharing (fun _ v -> f v) in + let new_consts = list_map_sharing aux sw.consts in + let new_blocks = list_map_sharing aux sw.blocks in + let new_failaction = may_map_sharing f sw.failaction in + if sw.failaction == new_failaction && + new_consts == sw.consts && + new_blocks == sw.blocks then + tree + else + let sw = + { sw with + failaction = new_failaction; + consts = new_consts; + blocks = new_blocks; + } + in + Switch (arg, sw) + | String_switch (arg, sw, def) -> + let new_sw = list_map_sharing (map_snd_sharing (fun _ v -> f v)) sw in + let new_def = may_map_sharing f def in + if sw == new_sw && def == new_def then + tree + else + String_switch(arg, new_sw, new_def) + | Static_catch (i, vars, body, handler) -> + let new_body = f body in + let new_handler = f handler in + if new_body == body && new_handler == handler then + tree + else + Static_catch (i, vars, new_body, new_handler) + | Try_with(body, id, handler) -> + let new_body = f body in + let new_handler = f handler in + if body == new_body && handler == new_handler then + tree + else + Try_with(new_body, id, new_handler) + | If_then_else(arg, ifso, ifnot) -> + let new_ifso = f ifso in + let new_ifnot = f ifnot in + if new_ifso == ifso && new_ifnot == ifnot then + tree + else + If_then_else(arg, new_ifso, new_ifnot) + | While(cond, body) -> + let new_cond = f cond in + let new_body = f body in + if new_cond == cond && new_body == body then + tree + else + While(new_cond, new_body) + | For { bound_var; from_value; to_value; direction; body; } -> + let new_body = f body in + if new_body == body then + tree + else + For { bound_var; from_value; to_value; direction; body = new_body; } + +let iter_general = Flambda.iter_general + +let iter f f_named t = iter_general ~toplevel:false f f_named (Is_expr t) +let iter_expr f t = iter f (fun _ -> ()) t +let iter_on_named f f_named t = + iter_general ~toplevel:false f f_named (Is_named t) +let iter_named f_named t = iter (fun (_ : Flambda.t) -> ()) f_named t +let iter_named_on_named f_named named = + iter_general ~toplevel:false (fun (_ : Flambda.t) -> ()) f_named + (Is_named named) + +let iter_toplevel f f_named t = + iter_general ~toplevel:true f f_named (Is_expr t) +let iter_named_toplevel f f_named named = + iter_general ~toplevel:true f f_named (Is_named named) + +let iter_all_immutable_let_and_let_rec_bindings t ~f = + iter_expr (function + | Let { var; defining_expr; _ } -> f var defining_expr + | Let_rec (defs, _) -> List.iter (fun (var, named) -> f var named) defs + | _ -> ()) + t + +let iter_all_toplevel_immutable_let_and_let_rec_bindings t ~f = + iter_general ~toplevel:true + (function + | Let { var; defining_expr; _ } -> f var defining_expr + | Let_rec (defs, _) -> List.iter (fun (var, named) -> f var named) defs + | _ -> ()) + (fun _ -> ()) + (Is_expr t) + +let iter_on_sets_of_closures f t = + iter_named (function + | Set_of_closures clos -> f clos + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ + | Project_closure _ | Move_within_set_of_closures _ | Project_var _ + | Prim _ | Expr _ -> ()) + t + +let iter_exprs_at_toplevel_of_program (program : Flambda.program) ~f = + let rec loop (program : Flambda.program_body) = + match program with + | Let_symbol (_, Set_of_closures set_of_closures, program) -> + Variable.Map.iter (fun _ (function_decl : Flambda.function_declaration) -> + f function_decl.body) + set_of_closures.function_decls.funs; + loop program + | Let_rec_symbol (defs, program) -> + List.iter (function + | (_, Flambda.Set_of_closures set_of_closures) -> + Variable.Map.iter + (fun _ (function_decl : Flambda.function_declaration) -> + f function_decl.body) + set_of_closures.function_decls.funs + | _ -> ()) defs; + loop program + | Let_symbol (_, _, program) -> + loop program + | Initialize_symbol (_, _, fields, program) -> + List.iter f fields; + loop program + | Effect (expr, program) -> + f expr; + loop program + | End _ -> () + in + loop program.program_body + +let iter_named_of_program program ~f = + iter_exprs_at_toplevel_of_program program ~f:(iter_named f) + +let iter_on_set_of_closures_of_program (program : Flambda.program) ~f = + let rec loop (program : Flambda.program_body) = + match program with + | Let_symbol (_, Set_of_closures set_of_closures, program) -> + f ~constant:true set_of_closures; + Variable.Map.iter (fun _ (function_decl : Flambda.function_declaration) -> + iter_on_sets_of_closures (f ~constant:false) function_decl.body) + set_of_closures.function_decls.funs; + loop program + | Let_rec_symbol (defs, program) -> + List.iter (function + | (_, Flambda.Set_of_closures set_of_closures) -> + f ~constant:true set_of_closures; + Variable.Map.iter + (fun _ (function_decl : Flambda.function_declaration) -> + iter_on_sets_of_closures (f ~constant:false) function_decl.body) + set_of_closures.function_decls.funs + | _ -> ()) defs; + loop program + | Let_symbol (_, _, program) -> + loop program + | Initialize_symbol (_, _, fields, program) -> + List.iter (iter_on_sets_of_closures (f ~constant:false)) fields; + loop program + | Effect (expr, program) -> + iter_on_sets_of_closures (f ~constant:false) expr; + loop program + | End _ -> () + in + loop program.program_body + +let iter_constant_defining_values_on_program (program : Flambda.program) ~f = + let rec loop (program : Flambda.program_body) = + match program with + | Let_symbol (_, const, program) -> + f const; + loop program + | Let_rec_symbol (defs, program) -> + List.iter (fun (_, const) -> f const) defs; + loop program + | Initialize_symbol (_, _, _, program) -> + loop program + | Effect (_, program) -> + loop program + | End _ -> () + in + loop program.program_body + +let map_general ~toplevel f f_named tree = + let rec aux (tree : Flambda.t) = + match tree with + | Let _ -> + Flambda.map_lets tree ~for_defining_expr:aux_named ~for_last_body:aux + ~after_rebuild:f + | _ -> + let exp : Flambda.t = + match tree with + | Var _ | Apply _ | Assign _ | Send _ | Proved_unreachable + | Static_raise _ -> tree + | Let _ -> assert false + | Let_mutable (mut_var, var, body) -> + let new_body = aux body in + if new_body == body then + tree + else + Let_mutable (mut_var, var, new_body) + | Let_rec (defs, body) -> + let done_something = ref false in + let defs = + List.map (fun (id, lam) -> + id, aux_named_done_something id lam done_something) + defs + in + let body = aux_done_something body done_something in + if not !done_something then + tree + else + Let_rec (defs, body) + | Switch (arg, sw) -> + let done_something = ref false in + let sw = + { sw with + failaction = + begin match sw.failaction with + | None -> None + | Some failaction -> + Some (aux_done_something failaction done_something) + end; + consts = + List.map (fun (i, v) -> + i, aux_done_something v done_something) + sw.consts; + blocks = + List.map (fun (i, v) -> + i, aux_done_something v done_something) + sw.blocks; + } + in + if not !done_something then + tree + else + Switch (arg, sw) + | String_switch (arg, sw, def) -> + let done_something = ref false in + let sw = + List.map (fun (i, v) -> i, aux_done_something v done_something) sw + in + let def = + match def with + | None -> None + | Some def -> Some (aux_done_something def done_something) + in + if not !done_something then + tree + else + String_switch(arg, sw, def) + | Static_catch (i, vars, body, handler) -> + let new_body = aux body in + let new_handler = aux handler in + if new_body == body && new_handler == handler then + tree + else + Static_catch (i, vars, new_body, new_handler) + | Try_with(body, id, handler) -> + let new_body = aux body in + let new_handler = aux handler in + if new_body == body && new_handler == handler then + tree + else + Try_with (new_body, id, new_handler) + | If_then_else (arg, ifso, ifnot) -> + let new_ifso = aux ifso in + let new_ifnot = aux ifnot in + if new_ifso == ifso && new_ifnot == ifnot then + tree + else + If_then_else (arg, new_ifso, new_ifnot) + | While (cond, body) -> + let new_cond = aux cond in + let new_body = aux body in + if new_cond == cond && new_body == body then + tree + else + While (new_cond, new_body) + | For { bound_var; from_value; to_value; direction; body; } -> + let new_body = aux body in + if new_body == body then + tree + else + For { bound_var; from_value; to_value; direction; + body = new_body; } + in + f exp + and aux_done_something expr done_something = + let new_expr = aux expr in + if not (new_expr == expr) then begin + done_something := true + end; + new_expr + and aux_named (id : Variable.t) (named : Flambda.named) = + let named : Flambda.named = + match named with + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Project_closure _ | Move_within_set_of_closures _ | Project_var _ + | Prim _ | Read_symbol_field _ -> named + | Set_of_closures ({ function_decls; free_vars; specialised_args; + direct_call_surrogates }) -> + if toplevel then named + else begin + let done_something = ref false in + let funs = + Variable.Map.map (fun (func_decl : Flambda.function_declaration) -> + let new_body = aux func_decl.body in + if new_body == func_decl.body then begin + func_decl + end else begin + done_something := true; + Flambda.create_function_declaration + ~params:func_decl.params + ~body:new_body + ~stub:func_decl.stub + ~dbg:func_decl.dbg + ~inline:func_decl.inline + ~specialise:func_decl.specialise + ~is_a_functor:func_decl.is_a_functor + end) + function_decls.funs + in + if not !done_something then + named + else + let function_decls = + Flambda.update_function_declarations function_decls ~funs + in + let set_of_closures = + Flambda.create_set_of_closures ~function_decls ~free_vars + ~specialised_args ~direct_call_surrogates + in + Set_of_closures set_of_closures + end + | Expr expr -> + let new_expr = aux expr in + if new_expr == expr then named + else Expr new_expr + in + f_named id named + and aux_named_done_something id named done_something = + let new_named = aux_named id named in + if not (new_named == named) then begin + done_something := true + end; + new_named + in + aux tree + +let iter_apply_on_program program ~f = + iter_exprs_at_toplevel_of_program program ~f:(fun expr -> + iter (function + | Apply apply -> f apply + | _ -> ()) + (fun _ -> ()) + expr) + +let map f f_named tree = + map_general ~toplevel:false f (fun _ n -> f_named n) tree +let map_expr f tree = map f (fun named -> named) tree +let map_named f_named tree = map (fun expr -> expr) f_named tree +let map_named_with_id f_named tree = + map_general ~toplevel:false (fun expr -> expr) f_named tree +let map_toplevel f f_named tree = + map_general ~toplevel:true f (fun _ n -> f_named n) tree +let map_toplevel_expr f_expr tree = + map_toplevel f_expr (fun named -> named) tree +let map_toplevel_named f_named tree = + map_toplevel (fun tree -> tree) f_named tree + +let map_symbols tree ~f = + map_named (function + | (Symbol sym) as named -> + let new_sym = f sym in + if new_sym == sym then + named + else + Symbol new_sym + | ((Read_symbol_field (sym, field)) as named) -> + let new_sym = f sym in + if new_sym == sym then + named + else + Read_symbol_field (new_sym, field) + | (Const _ | Allocated_const _ | Set_of_closures _ | Read_mutable _ + | Project_closure _ | Move_within_set_of_closures _ | Project_var _ + | Prim _ | Expr _) as named -> named) + tree + +let map_symbols_on_set_of_closures + ({ Flambda.function_decls; free_vars; specialised_args; + direct_call_surrogates; } as + set_of_closures) + ~f = + let done_something = ref false in + let funs = + Variable.Map.map (fun (func_decl : Flambda.function_declaration) -> + let body = map_symbols func_decl.body ~f in + if not (body == func_decl.body) then begin + done_something := true; + end; + Flambda.create_function_declaration + ~params:func_decl.params + ~body + ~stub:func_decl.stub + ~dbg:func_decl.dbg + ~inline:func_decl.inline + ~specialise:func_decl.specialise + ~is_a_functor:func_decl.is_a_functor) + function_decls.funs + in + if not !done_something then + set_of_closures + else + let function_decls = + Flambda.update_function_declarations function_decls ~funs + in + Flambda.create_set_of_closures ~function_decls ~free_vars + ~specialised_args ~direct_call_surrogates + +let map_toplevel_sets_of_closures tree ~f = + map_toplevel_named (function + | (Set_of_closures set_of_closures) as named -> + let new_set_of_closures = f set_of_closures in + if new_set_of_closures == set_of_closures then + named + else + Set_of_closures new_set_of_closures + | (Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ + | Project_closure _ | Move_within_set_of_closures _ | Project_var _ + | Prim _ | Expr _) as named -> named) + tree + +let map_apply tree ~f = + map (function + | (Apply apply) as expr -> + let new_apply = f apply in + if new_apply == apply then + expr + else + Apply new_apply + | expr -> expr) + (fun named -> named) + tree + +let map_sets_of_closures tree ~f = + map_named (function + | (Set_of_closures set_of_closures) as named -> + let new_set_of_closures = f set_of_closures in + if new_set_of_closures == set_of_closures then + named + else + Set_of_closures new_set_of_closures + | (Symbol _ | Const _ | Allocated_const _ | Project_closure _ + | Move_within_set_of_closures _ | Project_var _ + | Prim _ | Expr _ | Read_mutable _ + | Read_symbol_field _) as named -> named) + tree + +let map_project_var_to_expr_opt tree ~f = + map_named (function + | (Project_var project_var) as named -> + begin match f project_var with + | None -> named + | Some expr -> Expr expr + end + | (Symbol _ | Const _ | Allocated_const _ + | Set_of_closures _ | Project_closure _ | Move_within_set_of_closures _ + | Prim _ | Expr _ | Read_mutable _ | Read_symbol_field _) + as named -> named) + tree + +let map_project_var_to_named_opt tree ~f = + map_named (function + | (Project_var project_var) as named -> + begin match f project_var with + | None -> named + | Some named -> named + end + | (Symbol _ | Const _ | Allocated_const _ + | Set_of_closures _ | Project_closure _ | Move_within_set_of_closures _ + | Prim _ | Expr _ | Read_mutable _ | Read_symbol_field _) + as named -> named) + tree + +let map_function_bodies (set_of_closures : Flambda.set_of_closures) ~f = + let done_something = ref false in + let funs = + Variable.Map.map (fun (function_decl : Flambda.function_declaration) -> + let new_body = f function_decl.body in + if new_body == function_decl.body then + function_decl + else begin + done_something := true; + Flambda.create_function_declaration ~body:new_body + ~params:function_decl.params + ~stub:function_decl.stub + ~dbg:function_decl.dbg + ~inline:function_decl.inline + ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + end) + set_of_closures.function_decls.funs + in + if not !done_something then + set_of_closures + else + let function_decls = + Flambda.update_function_declarations set_of_closures.function_decls ~funs + in + Flambda.create_set_of_closures + ~function_decls + ~free_vars:set_of_closures.free_vars + ~specialised_args:set_of_closures.specialised_args + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + +let map_sets_of_closures_of_program (program : Flambda.program) + ~(f : Flambda.set_of_closures -> Flambda.set_of_closures) = + let rec loop (program : Flambda.program_body) : Flambda.program_body = + let map_constant_set_of_closures (set_of_closures:Flambda.set_of_closures) = + let done_something = ref false in + let function_decls = + let funs = + Variable.Map.map (fun + (function_decl : Flambda.function_declaration) -> + let body = map_sets_of_closures ~f function_decl.body in + if body == function_decl.body then + function_decl + else begin + done_something := true; + Flambda.create_function_declaration ~body + ~params:function_decl.params + ~stub:function_decl.stub + ~dbg:function_decl.dbg + ~inline:function_decl.inline + ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + end) + set_of_closures.function_decls.funs + in + if not !done_something then + set_of_closures.function_decls + else + Flambda.update_function_declarations set_of_closures.function_decls + ~funs + in + let new_set_of_closures = f set_of_closures in + if new_set_of_closures == set_of_closures then + set_of_closures + else + Flambda.create_set_of_closures ~function_decls + ~free_vars:set_of_closures.free_vars + ~specialised_args:set_of_closures.specialised_args + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + match program with + | Let_symbol (symbol, Set_of_closures set_of_closures, program') -> + let new_set_of_closures = map_constant_set_of_closures set_of_closures in + let new_program' = loop program' in + if new_set_of_closures == set_of_closures + && new_program' == program' then + program + else + Let_symbol (symbol, Set_of_closures new_set_of_closures, new_program') + | Let_symbol (symbol, const, program') -> + let new_program' = loop program' in + if new_program' == program' then + program + else + Let_symbol (symbol, const, new_program') + | Let_rec_symbol (defs, program') -> + let done_something = ref false in + let defs = + List.map (function + | (var, Flambda.Set_of_closures set_of_closures) -> + let new_set_of_closures = + map_constant_set_of_closures set_of_closures + in + if not (new_set_of_closures == set_of_closures) then begin + done_something := true + end; + var, Flambda.Set_of_closures new_set_of_closures + | def -> def) + defs + in + let new_program' = loop program' in + if new_program' == program' && not !done_something then + program + else + Let_rec_symbol (defs, loop program') + | Initialize_symbol (symbol, tag, fields, program') -> + let done_something = ref false in + let fields = + List.map (fun field -> + let new_field = map_sets_of_closures field ~f in + if not (new_field == field) then begin + done_something := true + end; + new_field) + fields + in + let new_program' = loop program' in + if new_program' == program' && not !done_something then + program + else + Initialize_symbol (symbol, tag, fields, new_program') + | Effect (expr, program') -> + let new_expr = map_sets_of_closures expr ~f in + let new_program' = loop program' in + if new_expr == expr && new_program' == program' then + program + else + Effect (new_expr, new_program') + | End _ -> program + in + { program with + program_body = loop program.program_body; + } + +let map_exprs_at_toplevel_of_program (program : Flambda.program) + ~(f : Flambda.t -> Flambda.t) = + let rec loop (program : Flambda.program_body) : Flambda.program_body = + let map_constant_set_of_closures (set_of_closures:Flambda.set_of_closures) = + let done_something = ref false in + let funs = + Variable.Map.map (fun (function_decl : Flambda.function_declaration) -> + let body = f function_decl.body in + if body == function_decl.body then + function_decl + else begin + done_something := true; + Flambda.create_function_declaration ~body + ~params:function_decl.params + ~stub:function_decl.stub + ~dbg:function_decl.dbg + ~inline:function_decl.inline + ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + end) + set_of_closures.function_decls.funs + in + if not !done_something then + set_of_closures + else + let function_decls = + Flambda.update_function_declarations set_of_closures.function_decls + ~funs + in + Flambda.create_set_of_closures ~function_decls + ~free_vars:set_of_closures.free_vars + ~specialised_args:set_of_closures.specialised_args + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + (* CR-soon mshinwell: code very similar to the above function *) + match program with + | Let_symbol (symbol, Set_of_closures set_of_closures, program') -> + let new_set_of_closures = map_constant_set_of_closures set_of_closures in + let new_program' = loop program' in + if new_set_of_closures == set_of_closures + && new_program' == program' then + program + else + Let_symbol (symbol, Set_of_closures new_set_of_closures, new_program') + | Let_symbol (symbol, const, program') -> + let new_program' = loop program' in + if new_program' == program' then + program + else + Let_symbol (symbol, const, new_program') + | Let_rec_symbol (defs, program') -> + let done_something = ref false in + let defs = + List.map (function + | (var, Flambda.Set_of_closures set_of_closures) -> + let new_set_of_closures = + map_constant_set_of_closures set_of_closures + in + if not (new_set_of_closures == set_of_closures) then begin + done_something := true + end; + var, Flambda.Set_of_closures new_set_of_closures + | def -> def) + defs + in + let new_program' = loop program' in + if new_program' == program' && not !done_something then + program + else + Let_rec_symbol (defs, new_program') + | Initialize_symbol (symbol, tag, fields, program') -> + let done_something = ref false in + let fields = + List.map (fun field -> + let new_field = f field in + if not (new_field == field) then begin + done_something := true + end; + new_field) + fields + in + let new_program' = loop program' in + if new_program' == program' && not !done_something then + program + else + Initialize_symbol (symbol, tag, fields, new_program') + | Effect (expr, program') -> + let new_expr = f expr in + let new_program' = loop program' in + if new_expr == expr && new_program' == program' then + program + else + Effect (new_expr, new_program') + | End _ -> program + in + { program with + program_body = loop program.program_body; + } + +let map_named_of_program (program : Flambda.program) + ~(f : Variable.t -> Flambda.named -> Flambda.named) : Flambda.program = + map_exprs_at_toplevel_of_program program + ~f:(fun expr -> map_named_with_id f expr) + +let map_all_immutable_let_and_let_rec_bindings (expr : Flambda.t) + ~(f : Variable.t -> Flambda.named -> Flambda.named) : Flambda.t = + map_named_with_id f expr + +let fold_function_decls_ignoring_stubs + (set_of_closures : Flambda.set_of_closures) ~init ~f = + Variable.Map.fold (fun fun_var function_decl acc -> + f ~fun_var ~function_decl acc) + set_of_closures.function_decls.funs + init diff --git a/middle_end/flambda_iterators.mli b/middle_end/flambda_iterators.mli new file mode 100644 index 00000000..02fe6850 --- /dev/null +++ b/middle_end/flambda_iterators.mli @@ -0,0 +1,227 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-soon mshinwell: we need to document whether these iterators follow any + particular order. *) + +(** Apply the given functions to the immediate subexpressions of the given + Flambda expression. For avoidance of doubt, if a subexpression is + [Expr], it is passed to the function taking [Flambda.named], rather + than being followed and passed to the function taking [Flambda.t]. *) +val apply_on_subexpressions + : (Flambda.t -> unit) + -> (Flambda.named -> unit) + -> Flambda.t + -> unit + +val map_subexpressions + : (Flambda.t -> Flambda.t) + -> (Variable.t -> Flambda.named -> Flambda.named) + -> Flambda.t + -> Flambda.t + +(* CR-soon lwhite: add comment to clarify that these recurse unlike the + ones above *) +val iter + : (Flambda.t -> unit) + -> (Flambda.named -> unit) + -> Flambda.t + -> unit + +val iter_expr + : (Flambda.t -> unit) + -> Flambda.t + -> unit + +val iter_on_named + : (Flambda.t -> unit) + -> (Flambda.named -> unit) + -> Flambda.named + -> unit + +(* CR-someday mshinwell: we might need to add the corresponding variable to + the parameters of the user function for [iter_named] *) +val iter_named + : (Flambda.named -> unit) + -> Flambda.t + -> unit + +(* CR-someday lwhite: These names are pretty indecipherable, perhaps + create submodules for the normal and "on_named" variants of each + function. *) + +val iter_named_on_named + : (Flambda.named -> unit) + -> Flambda.named + -> unit + +(** [iter_toplevel f t] applies [f] on every toplevel subexpression of [t]. + In particular, it never applies [f] to the body of a function (which + will always be contained within an [Set_of_closures] expression). *) +val iter_toplevel + : (Flambda.t -> unit) + -> (Flambda.named -> unit) + -> Flambda.t + -> unit + +val iter_named_toplevel + : (Flambda.t -> unit) + -> (Flambda.named -> unit) + -> Flambda.named + -> unit + +val iter_on_sets_of_closures + : (Flambda.set_of_closures -> unit) + -> Flambda.t + -> unit + +val iter_on_set_of_closures_of_program + : Flambda.program + -> f:(constant:bool -> Flambda.set_of_closures -> unit) + -> unit + +val iter_all_immutable_let_and_let_rec_bindings + : Flambda.t + -> f:(Variable.t -> Flambda.named -> unit) + -> unit + +val iter_all_toplevel_immutable_let_and_let_rec_bindings + : Flambda.t + -> f:(Variable.t -> Flambda.named -> unit) + -> unit + +val iter_exprs_at_toplevel_of_program + : Flambda.program + -> f:(Flambda.t -> unit) + -> unit + +val iter_named_of_program + : Flambda.program + -> f:(Flambda.named -> unit) + -> unit + +val iter_constant_defining_values_on_program + : Flambda.program + -> f:(Flambda.constant_defining_value -> unit) + -> unit + +val iter_apply_on_program + : Flambda.program + -> f:(Flambda.apply -> unit) + -> unit + +val map + : (Flambda.t -> Flambda.t) + -> (Flambda.named -> Flambda.named) + -> Flambda.t + -> Flambda.t + +val map_expr + : (Flambda.t -> Flambda.t) + -> Flambda.t + -> Flambda.t + +val map_named + : (Flambda.named -> Flambda.named) + -> Flambda.t + -> Flambda.t + +val map_toplevel + : (Flambda.t -> Flambda.t) + -> (Flambda.named -> Flambda.named) + -> Flambda.t + -> Flambda.t + +val map_toplevel_expr + : (Flambda.t -> Flambda.t) + -> Flambda.t + -> Flambda.t + +val map_toplevel_named + : (Flambda.named -> Flambda.named) + -> Flambda.t + -> Flambda.t + +val map_symbols + : Flambda.t + -> f:(Symbol.t -> Symbol.t) + -> Flambda.t + +val map_symbols_on_set_of_closures + : Flambda.set_of_closures + -> f:(Symbol.t -> Symbol.t) + -> Flambda.set_of_closures + +val map_toplevel_sets_of_closures + : Flambda.t + -> f:(Flambda.set_of_closures -> Flambda.set_of_closures) + -> Flambda.t + +val map_apply + : Flambda.t + -> f:(Flambda.apply -> Flambda.apply) + -> Flambda.t + +val map_function_bodies + : Flambda.set_of_closures + -> f:(Flambda.t -> Flambda.t) + -> Flambda.set_of_closures + +val map_sets_of_closures + : Flambda.t + -> f:(Flambda.set_of_closures -> Flambda.set_of_closures) + -> Flambda.t + +val map_sets_of_closures_of_program + : Flambda.program + -> f:(Flambda.set_of_closures -> Flambda.set_of_closures) + -> Flambda.program + +val map_project_var_to_expr_opt + : Flambda.t + -> f:(Flambda.project_var -> Flambda.t option) + -> Flambda.t + +val map_project_var_to_named_opt + : Flambda.t + -> f:(Flambda.project_var -> Flambda.named option) + -> Flambda.t + +val map_exprs_at_toplevel_of_program + : Flambda.program + -> f:(Flambda.t -> Flambda.t) + -> Flambda.program + +val map_named_of_program + : Flambda.program + -> f:(Variable.t -> Flambda.named -> Flambda.named) + -> Flambda.program + +val map_all_immutable_let_and_let_rec_bindings + : Flambda.t + -> f:(Variable.t -> Flambda.named -> Flambda.named) + -> Flambda.t + +val fold_function_decls_ignoring_stubs + : Flambda.set_of_closures + -> init:'a + -> f:(fun_var:Variable.t + -> function_decl:Flambda.function_declaration + -> 'a + -> 'a) + -> 'a diff --git a/middle_end/flambda_utils.ml b/middle_end/flambda_utils.ml new file mode 100644 index 00000000..3f97455f --- /dev/null +++ b/middle_end/flambda_utils.ml @@ -0,0 +1,836 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let name_expr (named : Flambda.named) ~name : Flambda.t = + let var = + Variable.create + ~current_compilation_unit:(Compilation_unit.get_current_exn ()) + name + in + Flambda.create_let var named (Var var) + +let find_declaration cf ({ funs } : Flambda.function_declarations) = + Variable.Map.find (Closure_id.unwrap cf) funs + +let find_declaration_variable cf ({ funs } : Flambda.function_declarations) = + let var = Closure_id.unwrap cf in + if not (Variable.Map.mem var funs) + then raise Not_found + else var + +let find_free_variable cv ({ free_vars } : Flambda.set_of_closures) = + let var : Flambda.specialised_to = + Variable.Map.find (Var_within_closure.unwrap cv) free_vars + in + var.var + +let function_arity (f : Flambda.function_declaration) = List.length f.params + +let variables_bound_by_the_closure cf + (decls : Flambda.function_declarations) = + let func = find_declaration cf decls in + let params = Variable.Set.of_list func.params in + let functions = Variable.Map.keys decls.funs in + Variable.Set.diff + (Variable.Set.diff func.free_variables params) + functions + +let description_of_toplevel_node (expr : Flambda.t) = + match expr with + | Var id -> Format.asprintf "var %a" Variable.print id + | Apply _ -> "apply" + | Assign _ -> "assign" + | Send _ -> "send" + | Proved_unreachable -> "unreachable" + | Let { var; _ } -> Format.asprintf "let %a" Variable.print var + | Let_mutable _ -> "let_mutable" + | Let_rec _ -> "letrec" + | If_then_else _ -> "if" + | Switch _ -> "switch" + | String_switch _ -> "stringswitch" + | Static_raise _ -> "staticraise" + | Static_catch _ -> "catch" + | Try_with _ -> "trywith" + | While _ -> "while" + | For _ -> "for" + +let compare_const (c1 : Flambda.const) (c2 : Flambda.const) = + match c1, c2 with + | Int v1, Int v2 -> compare v1 v2 + | Char v1, Char v2 -> compare v1 v2 + | Const_pointer v1, Const_pointer v2 -> compare v1 v2 + | Int _, _ -> -1 + | _, Int _ -> 1 + | Char _, _ -> -1 + | _, Char _ -> 1 + +let rec same (l1 : Flambda.t) (l2 : Flambda.t) = + l1 == l2 || (* it is ok for the string case: if they are physically the same, + it is the same original branch *) + match (l1, l2) with + | Var v1 , Var v2 -> Variable.equal v1 v2 + | Var _, _ | _, Var _ -> false + | Apply a1 , Apply a2 -> + a1.kind = a2.kind + && Variable.equal a1.func a2.func + && Misc.Stdlib.List.equal Variable.equal a1.args a2.args + | Apply _, _ | _, Apply _ -> false + | Let { var = var1; defining_expr = defining_expr1; body = body1; _ }, + Let { var = var2; defining_expr = defining_expr2; body = body2; _ } -> + Variable.equal var1 var2 && same_named defining_expr1 defining_expr2 + && same body1 body2 + | Let _, _ | _, Let _ -> false + | Let_mutable (mv1, v1, b1), Let_mutable (mv2, v2, b2) -> + Mutable_variable.equal mv1 mv2 + && Variable.equal v1 v2 + && same b1 b2 + | Let_mutable _, _ | _, Let_mutable _ -> false + | Let_rec (bl1, a1), Let_rec (bl2, a2) -> + Misc.Stdlib.List.equal samebinding bl1 bl2 && same a1 a2 + | Let_rec _, _ | _, Let_rec _ -> false + | Switch (a1, s1), Switch (a2, s2) -> + Variable.equal a1 a2 && sameswitch s1 s2 + | Switch _, _ | _, Switch _ -> false + | String_switch (a1, s1, d1), String_switch (a2, s2, d2) -> + Variable.equal a1 a2 + && Misc.Stdlib.List.equal + (fun (s1, e1) (s2, e2) -> s1 = s2 && same e1 e2) s1 s2 + && Misc.Stdlib.Option.equal same d1 d2 + | String_switch _, _ | _, String_switch _ -> false + | Static_raise (e1, a1), Static_raise (e2, a2) -> + Static_exception.equal e1 e2 && Misc.Stdlib.List.equal Variable.equal a1 a2 + | Static_raise _, _ | _, Static_raise _ -> false + | Static_catch (s1, v1, a1, b1), Static_catch (s2, v2, a2, b2) -> + Static_exception.equal s1 s2 + && Misc.Stdlib.List.equal Variable.equal v1 v2 + && same a1 a2 + && same b1 b2 + | Static_catch _, _ | _, Static_catch _ -> false + | Try_with (a1, v1, b1), Try_with (a2, v2, b2) -> + same a1 a2 && Variable.equal v1 v2 && same b1 b2 + | Try_with _, _ | _, Try_with _ -> false + | If_then_else (a1, b1, c1), If_then_else (a2, b2, c2) -> + Variable.equal a1 a2 && same b1 b2 && same c1 c2 + | If_then_else _, _ | _, If_then_else _ -> false + | While (a1, b1), While (a2, b2) -> + same a1 a2 && same b1 b2 + | While _, _ | _, While _ -> false + | For { bound_var = bound_var1; from_value = from_value1; + to_value = to_value1; direction = direction1; body = body1; }, + For { bound_var = bound_var2; from_value = from_value2; + to_value = to_value2; direction = direction2; body = body2; } -> + Variable.equal bound_var1 bound_var2 + && Variable.equal from_value1 from_value2 + && Variable.equal to_value1 to_value2 + && direction1 = direction2 + && same body1 body2 + | For _, _ | _, For _ -> false + | Assign { being_assigned = being_assigned1; new_value = new_value1; }, + Assign { being_assigned = being_assigned2; new_value = new_value2; } -> + Mutable_variable.equal being_assigned1 being_assigned2 + && Variable.equal new_value1 new_value2 + | Assign _, _ | _, Assign _ -> false + | Send { kind = kind1; meth = meth1; obj = obj1; args = args1; dbg = _; }, + Send { kind = kind2; meth = meth2; obj = obj2; args = args2; dbg = _; } -> + kind1 = kind2 + && Variable.equal meth1 meth2 + && Variable.equal obj1 obj2 + && Misc.Stdlib.List.equal Variable.equal args1 args2 + | Send _, _ | _, Send _ -> false + | Proved_unreachable, Proved_unreachable -> true + +and same_named (named1 : Flambda.named) (named2 : Flambda.named) = + match named1, named2 with + | Symbol s1 , Symbol s2 -> Symbol.equal s1 s2 + | Symbol _, _ | _, Symbol _ -> false + | Const c1, Const c2 -> compare_const c1 c2 = 0 + | Const _, _ | _, Const _ -> false + | Allocated_const c1, Allocated_const c2 -> + Allocated_const.compare c1 c2 = 0 + | Allocated_const _, _ | _, Allocated_const _ -> false + | Read_mutable mv1, Read_mutable mv2 -> Mutable_variable.equal mv1 mv2 + | Read_mutable _, _ | _, Read_mutable _ -> false + | Read_symbol_field (s1, i1), Read_symbol_field (s2, i2) -> + Symbol.equal s1 s2 && i1 = i2 + | Read_symbol_field _, _ | _, Read_symbol_field _ -> false + | Set_of_closures s1, Set_of_closures s2 -> same_set_of_closures s1 s2 + | Set_of_closures _, _ | _, Set_of_closures _ -> false + | Project_closure f1, Project_closure f2 -> same_project_closure f1 f2 + | Project_closure _, _ | _, Project_closure _ -> false + | Project_var v1, Project_var v2 -> + Variable.equal v1.closure v2.closure + && Closure_id.equal v1.closure_id v2.closure_id + && Var_within_closure.equal v1.var v2.var + | Project_var _, _ | _, Project_var _ -> false + | Move_within_set_of_closures m1, Move_within_set_of_closures m2 -> + same_move_within_set_of_closures m1 m2 + | Move_within_set_of_closures _, _ | _, Move_within_set_of_closures _ -> + false + | Prim (p1, al1, _), Prim (p2, al2, _) -> + p1 = p2 && Misc.Stdlib.List.equal Variable.equal al1 al2 + | Prim _, _ | _, Prim _ -> false + | Expr e1, Expr e2 -> same e1 e2 + +and sameclosure (c1 : Flambda.function_declaration) + (c2 : Flambda.function_declaration) = + Misc.Stdlib.List.equal Variable.equal c1.params c2.params + && same c1.body c2.body + +and same_set_of_closures (c1 : Flambda.set_of_closures) + (c2 : Flambda.set_of_closures) = + Variable.Map.equal sameclosure c1.function_decls.funs c2.function_decls.funs + && Variable.Map.equal Flambda.equal_specialised_to + c1.free_vars c2.free_vars + && Variable.Map.equal Flambda.equal_specialised_to c1.specialised_args + c2.specialised_args + +and same_project_closure (s1 : Flambda.project_closure) + (s2 : Flambda.project_closure) = + Variable.equal s1.set_of_closures s2.set_of_closures + && Closure_id.equal s1.closure_id s2.closure_id + +and same_move_within_set_of_closures (m1 : Flambda.move_within_set_of_closures) + (m2 : Flambda.move_within_set_of_closures) = + Variable.equal m1.closure m2.closure + && Closure_id.equal m1.start_from m2.start_from + && Closure_id.equal m1.move_to m2.move_to + +and samebinding (v1, n1) (v2, n2) = + Variable.equal v1 v2 && same_named n1 n2 + +and sameswitch (fs1 : Flambda.switch) (fs2 : Flambda.switch) = + let samecase (n1, a1) (n2, a2) = n1 = n2 && same a1 a2 in + fs1.numconsts = fs2.numconsts + && fs1.numblocks = fs2.numblocks + && Misc.Stdlib.List.equal samecase fs1.consts fs2.consts + && Misc.Stdlib.List.equal samecase fs1.blocks fs2.blocks + && Misc.Stdlib.Option.equal same fs1.failaction fs2.failaction + +let can_be_merged = same + +(* CR-soon mshinwell: this should use the explicit ignore functions *) +let toplevel_substitution sb tree = + let sb' = sb in + let sb v = try Variable.Map.find v sb with Not_found -> v in + let aux (flam : Flambda.t) : Flambda.t = + match flam with + | Var var -> + let var = sb var in + Var var + | Let_mutable (mut_var, var, body) -> + let var = sb var in + Let_mutable (mut_var, var, body) + | Assign { being_assigned; new_value; } -> + let new_value = sb new_value in + Assign { being_assigned; new_value; } + | Apply { func; args; kind; dbg; inline; specialise; } -> + let func = sb func in + let args = List.map sb args in + Apply { func; args; kind; dbg; inline; specialise; } + | If_then_else (cond, e1, e2) -> + let cond = sb cond in + If_then_else (cond, e1, e2) + | Switch (cond, sw) -> + let cond = sb cond in + Switch (cond, sw) + | String_switch (cond, branches, def) -> + let cond = sb cond in + String_switch (cond, branches, def) + | Send { kind; meth; obj; args; dbg } -> + let meth = sb meth in + let obj = sb obj in + let args = List.map sb args in + Send { kind; meth; obj; args; dbg } + | For { bound_var; from_value; to_value; direction; body } -> + let from_value = sb from_value in + let to_value = sb to_value in + For { bound_var; from_value; to_value; direction; body } + | Static_raise (static_exn, args) -> + let args = List.map sb args in + Static_raise (static_exn, args) + | Static_catch _ | Try_with _ | While _ + | Let _ | Let_rec _ | Proved_unreachable -> flam + in + let aux_named (named : Flambda.named) : Flambda.named = + match named with + | Symbol _ | Const _ | Expr _ -> named + | Allocated_const _ | Read_mutable _ -> named + | Read_symbol_field _ -> named + | Set_of_closures set_of_closures -> + let set_of_closures = + Flambda.create_set_of_closures + ~function_decls:set_of_closures.function_decls + ~free_vars: + (Variable.Map.map (fun (spec_to : Flambda.specialised_to) -> + { spec_to with var = sb spec_to.var; }) + set_of_closures.free_vars) + ~specialised_args: + (Variable.Map.map (fun (spec_to : Flambda.specialised_to) -> + { spec_to with var = sb spec_to.var; }) + set_of_closures.specialised_args) + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + Set_of_closures set_of_closures + | Project_closure project_closure -> + Project_closure { + project_closure with + set_of_closures = sb project_closure.set_of_closures; + } + | Move_within_set_of_closures move_within_set_of_closures -> + Move_within_set_of_closures { + move_within_set_of_closures with + closure = sb move_within_set_of_closures.closure; + } + | Project_var project_var -> + Project_var { + project_var with + closure = sb project_var.closure; + } + | Prim (prim, args, dbg) -> + Prim (prim, List.map sb args, dbg) + in + if Variable.Map.is_empty sb' then tree + else Flambda_iterators.map_toplevel aux aux_named tree + +(* CR-someday mshinwell: Fix [Flambda_iterators] so this can be implemented + properly. *) +let toplevel_substitution_named sb named = + let expr = name_expr named ~name:"toplevel_substitution_named" in + match toplevel_substitution sb expr with + | Let let_expr -> let_expr.defining_expr + | _ -> assert false + +let make_closure_declaration ~id ~body ~params ~stub : Flambda.t = + let free_variables = Flambda.free_variables body in + let param_set = Variable.Set.of_list params in + if not (Variable.Set.subset param_set free_variables) then begin + Misc.fatal_error "Flambda_utils.make_closure_declaration" + end; + let sb = + Variable.Set.fold + (fun id sb -> Variable.Map.add id (Variable.rename id) sb) + free_variables Variable.Map.empty + in + (* CR-soon mshinwell: try to eliminate this [toplevel_substitution]. This + function is only called from [Inline_and_simplify], so we should be able + to do something similar to what happens in [Inlining_transforms] now. *) + let body = toplevel_substitution sb body in + let subst id = Variable.Map.find id sb in + let function_declaration = + Flambda.create_function_declaration ~params:(List.map subst params) + ~body ~stub ~dbg:Debuginfo.none ~inline:Default_inline + ~specialise:Default_specialise ~is_a_functor:false + in + assert (Variable.Set.equal (Variable.Set.map subst free_variables) + function_declaration.free_variables); + let free_vars = + Variable.Map.fold (fun id id' fv' -> + let spec_to : Flambda.specialised_to = + { var = id; + projection = None; + } + in + Variable.Map.add id' spec_to fv') + (Variable.Map.filter + (fun id _ -> not (Variable.Set.mem id param_set)) + sb) + Variable.Map.empty + in + let compilation_unit = Compilation_unit.get_current_exn () in + let set_of_closures_var = + Variable.create "set_of_closures" + ~current_compilation_unit:compilation_unit + in + let set_of_closures = + let function_decls = + Flambda.create_function_declarations + ~funs:(Variable.Map.singleton id function_declaration) + in + Flambda.create_set_of_closures ~function_decls ~free_vars + ~specialised_args:Variable.Map.empty + ~direct_call_surrogates:Variable.Map.empty + in + let project_closure : Flambda.named = + Project_closure { + set_of_closures = set_of_closures_var; + closure_id = Closure_id.wrap id; + } + in + let project_closure_var = + Variable.create "project_closure" + ~current_compilation_unit:compilation_unit + in + Flambda.create_let set_of_closures_var (Set_of_closures set_of_closures) + (Flambda.create_let project_closure_var project_closure + (Var (project_closure_var))) + +let bind ~bindings ~body = + List.fold_left (fun expr (var, var_def) -> + Flambda.create_let var var_def expr) + body bindings + +let all_lifted_constants (program : Flambda.program) = + let rec loop (program : Flambda.program_body) = + match program with + | Let_symbol (symbol, decl, program) -> (symbol, decl) :: (loop program) + | Let_rec_symbol (decls, program) -> + List.fold_left (fun l (symbol, decl) -> (symbol, decl) :: l) + (loop program) + decls + | Initialize_symbol (_, _, _, program) + | Effect (_, program) -> loop program + | End _ -> [] + in + loop program.program_body + +let all_lifted_constants_as_map program = + Symbol.Map.of_list (all_lifted_constants program) + +let initialize_symbols (program : Flambda.program) = + let rec loop (program : Flambda.program_body) = + match program with + | Initialize_symbol (symbol, tag, fields, program) -> + (symbol, tag, fields) :: (loop program) + | Effect (_, program) + | Let_symbol (_, _, program) + | Let_rec_symbol (_, program) -> loop program + | End _ -> [] + in + loop program.program_body + +let imported_symbols (program : Flambda.program) = + program.imported_symbols + +let needed_import_symbols (program : Flambda.program) = + let dependencies = Flambda.free_symbols_program program in + let defined_symbol = + Symbol.Set.union + (Symbol.Set.of_list + (List.map fst (all_lifted_constants program))) + (Symbol.Set.of_list + (List.map (fun (s, _, _) -> s) (initialize_symbols program))) + in + Symbol.Set.diff dependencies defined_symbol + +let introduce_needed_import_symbols program : Flambda.program = + { program with + imported_symbols = needed_import_symbols program; + } + +let root_symbol (program : Flambda.program) = + let rec loop (program : Flambda.program_body) = + match program with + | Effect (_, program) + | Let_symbol (_, _, program) + | Let_rec_symbol (_, program) + | Initialize_symbol (_, _, _, program) -> loop program + | End root -> + root + in + loop program.program_body + +let might_raise_static_exn flam stexn = + try + Flambda_iterators.iter_on_named + (function + | Flambda.Static_raise (ex, _) when Static_exception.equal ex stexn -> + raise Exit + | _ -> ()) + (fun _ -> ()) + flam; + false + with Exit -> true + +let make_closure_map program = + let map = ref Closure_id.Map.empty in + let add_set_of_closures ~constant:_ : Flambda.set_of_closures -> unit = fun + { function_decls } -> + Variable.Map.iter (fun var _ -> + let closure_id = Closure_id.wrap var in + map := Closure_id.Map.add closure_id function_decls !map) + function_decls.funs + in + Flambda_iterators.iter_on_set_of_closures_of_program + program + ~f:add_set_of_closures; + !map + +let make_closure_map' input = + let map = ref Closure_id.Map.empty in + let add_set_of_closures _ (function_decls : Flambda.function_declarations) = + Variable.Map.iter (fun var _ -> + let closure_id = Closure_id.wrap var in + map := Closure_id.Map.add closure_id function_decls !map) + function_decls.funs + in + Set_of_closures_id.Map.iter add_set_of_closures input; + !map + +let all_lifted_constant_sets_of_closures program = + let set = ref Set_of_closures_id.Set.empty in + List.iter (function + | (_, Flambda.Set_of_closures { + function_decls = { set_of_closures_id } }) -> + set := Set_of_closures_id.Set.add set_of_closures_id !set + | _ -> ()) + (all_lifted_constants program); + !set + +let all_sets_of_closures program = + let list = ref [] in + Flambda_iterators.iter_on_set_of_closures_of_program program + ~f:(fun ~constant:_ set_of_closures -> + list := set_of_closures :: !list); + !list + +let all_sets_of_closures_map program = + let r = ref Set_of_closures_id.Map.empty in + Flambda_iterators.iter_on_set_of_closures_of_program program + ~f:(fun ~constant:_ set_of_closures -> + r := Set_of_closures_id.Map.add + set_of_closures.function_decls.set_of_closures_id + set_of_closures !r); + !r + +let all_function_decls_indexed_by_set_of_closures_id program = + Set_of_closures_id.Map.map + (fun { Flambda. function_decls; _ } -> function_decls) + (all_sets_of_closures_map program) + +let all_function_decls_indexed_by_closure_id program = + let aux_fun function_decls fun_var _ map = + let closure_id = Closure_id.wrap fun_var in + Closure_id.Map.add closure_id function_decls map + in + let aux _ ({ function_decls; _ } : Flambda.set_of_closures) map = + Variable.Map.fold (aux_fun function_decls) function_decls.funs map + in + Set_of_closures_id.Map.fold aux (all_sets_of_closures_map program) + Closure_id.Map.empty + +let make_variable_symbol var = + Symbol.create (Compilation_unit.get_current_exn ()) + (Linkage_name.create + (Variable.unique_name (Variable.rename var))) + +let make_variables_symbol vars = + let name = + String.concat "_and_" + (List.map (fun var -> Variable.unique_name (Variable.rename var)) vars) + in + Symbol.create (Compilation_unit.get_current_exn ()) (Linkage_name.create name) + +let substitute_read_symbol_field_for_variables + (substitution : (Symbol.t * int list) Variable.Map.t) + (expr : Flambda.t) = + let bind var fresh_var (expr:Flambda.t) : Flambda.t = + let symbol, path = Variable.Map.find var substitution in + let rec make_named (path:int list) : Flambda.named = + match path with + | [] -> Symbol symbol + | [i] -> Read_symbol_field (symbol, i) + | h :: t -> + let block = Variable.create "symbol_field_block" in + let field = Variable.create "get_symbol_field" in + Expr ( + Flambda.create_let block (make_named t) + (Flambda.create_let field + (Prim (Pfield h, [block], Debuginfo.none)) + (Var field))) + in + Flambda.create_let fresh_var (make_named path) expr + in + let substitute_named bindings (named:Flambda.named) : Flambda.named = + let sb to_substitute = + try Variable.Map.find to_substitute bindings with + | Not_found -> + to_substitute + in + match named with + | Symbol _ | Const _ | Expr _ -> named + | Allocated_const _ | Read_mutable _ -> named + | Read_symbol_field _ -> named + | Set_of_closures set_of_closures -> + let set_of_closures = + Flambda.create_set_of_closures + ~function_decls:set_of_closures.function_decls + ~free_vars: + (Variable.Map.map (fun (spec_to : Flambda.specialised_to) -> + { spec_to with var = sb spec_to.var; }) + set_of_closures.free_vars) + ~specialised_args: + (Variable.Map.map (fun (spec_to : Flambda.specialised_to) -> + { spec_to with var = sb spec_to.var; }) + set_of_closures.specialised_args) + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + Set_of_closures set_of_closures + | Project_closure project_closure -> + Project_closure { + project_closure with + set_of_closures = sb project_closure.set_of_closures; + } + | Move_within_set_of_closures move_within_set_of_closures -> + Move_within_set_of_closures { + move_within_set_of_closures with + closure = sb move_within_set_of_closures.closure; + } + | Project_var project_var -> + Project_var { + project_var with + closure = sb project_var.closure; + } + | Prim (prim, args, dbg) -> + Prim (prim, List.map sb args, dbg) + in + let make_var_subst var = + if Variable.Map.mem var substitution then + let fresh = Variable.rename var in + fresh, (fun expr -> bind var fresh expr) + else + var, (fun x -> x) + in + let f (expr:Flambda.t) : Flambda.t = + match expr with + | Var v when Variable.Map.mem v substitution -> + let fresh = Variable.rename v in + bind v fresh (Var fresh) + | Var _ -> expr + | Let ({ var = v; defining_expr = named; _ } as let_expr) -> + let to_substitute = + Variable.Set.filter + (fun v -> Variable.Map.mem v substitution) + (Flambda.free_variables_named named) + in + if Variable.Set.is_empty to_substitute then + expr + else + let bindings = + Variable.Map.of_set (fun var -> Variable.rename var) to_substitute + in + let named = + substitute_named bindings named + in + let expr = + let module W = Flambda.With_free_variables in + W.create_let_reusing_body v named (W.of_body_of_let let_expr) + in + Variable.Map.fold (fun to_substitute fresh expr -> + bind to_substitute fresh expr) + bindings expr + | Let_mutable (mut_var, var, body) when Variable.Map.mem var substitution -> + let fresh = Variable.rename var in + bind var fresh (Let_mutable (mut_var, fresh, body)) + | Let_mutable (_mut_var, _var, _body) -> + expr + | Let_rec (defs, body) -> + let free_variables_of_defs = + List.fold_left (fun set (_, named) -> + Variable.Set.union set (Flambda.free_variables_named named)) + Variable.Set.empty defs + in + let to_substitute = + Variable.Set.filter + (fun v -> Variable.Map.mem v substitution) + free_variables_of_defs + in + if Variable.Set.is_empty to_substitute then + expr + else begin + let bindings = + Variable.Map.of_set (fun var -> Variable.rename var) to_substitute + in + let defs = + List.map (fun (var, named) -> + var, substitute_named bindings named) + defs + in + let expr = + Flambda.Let_rec (defs, body) + in + Variable.Map.fold (fun to_substitute fresh expr -> + bind to_substitute fresh expr) + bindings expr + end + | If_then_else (cond, ifso, ifnot) + when Variable.Map.mem cond substitution -> + let fresh = Variable.rename cond in + bind cond fresh (If_then_else (fresh, ifso, ifnot)) + | If_then_else _ -> + expr + | Switch (cond, sw) when Variable.Map.mem cond substitution -> + let fresh = Variable.rename cond in + bind cond fresh (Switch (fresh, sw)) + | Switch _ -> + expr + | String_switch (cond, sw, def) when Variable.Map.mem cond substitution -> + let fresh = Variable.rename cond in + bind cond fresh (String_switch (fresh, sw, def)) + | String_switch _ -> + expr + | Assign { being_assigned; new_value } + when Variable.Map.mem new_value substitution -> + let fresh = Variable.rename new_value in + bind new_value fresh (Assign { being_assigned; new_value = fresh }) + | Assign _ -> + expr + | Static_raise (exn, args) -> + let args, bind_args = + List.split (List.map make_var_subst args) + in + List.fold_right (fun f expr -> f expr) bind_args @@ + Flambda.Static_raise (exn, args) + | For { bound_var; from_value; to_value; direction; body } -> + let from_value, bind_from_value = make_var_subst from_value in + let to_value, bind_to_value = make_var_subst to_value in + bind_from_value @@ + bind_to_value @@ + Flambda.For { bound_var; from_value; to_value; direction; body } + | Apply { func; args; kind; dbg; inline; specialise } -> + let func, bind_func = make_var_subst func in + let args, bind_args = + List.split (List.map make_var_subst args) + in + bind_func @@ + List.fold_right (fun f expr -> f expr) bind_args @@ + Flambda.Apply { func; args; kind; dbg; inline; specialise } + | Send { kind; meth; obj; args; dbg } -> + let meth, bind_meth = make_var_subst meth in + let obj, bind_obj = make_var_subst obj in + let args, bind_args = + List.split (List.map make_var_subst args) + in + bind_meth @@ + bind_obj @@ + List.fold_right (fun f expr -> f expr) bind_args @@ + Flambda.Send { kind; meth; obj; args; dbg } + | Proved_unreachable + | While _ + | Try_with _ + | Static_catch _ -> + (* No variables directly used in those expressions *) + expr + in + Flambda_iterators.map_toplevel f (fun v -> v) expr + +(* CR-soon mshinwell: implement this so that sharing can occur in + matches. Should probably leave this for the first release. *) +type sharing_key = unit +let make_key _ = None + +module Switch_storer = + Switch.Store + (struct + type t = Flambda.t + type key = sharing_key + let make_key = make_key + end) + +let fun_vars_referenced_in_decls + (function_decls : Flambda.function_declarations) ~backend = + let fun_vars = Variable.Map.keys function_decls.funs in + let symbols_to_fun_vars = + let module Backend = (val backend : Backend_intf.S) in + Variable.Set.fold (fun fun_var symbols_to_fun_vars -> + let closure_id = Closure_id.wrap fun_var in + let symbol = Backend.closure_symbol closure_id in + Symbol.Map.add symbol fun_var symbols_to_fun_vars) + fun_vars + Symbol.Map.empty + in + Variable.Map.map (fun (func_decl : Flambda.function_declaration) -> + let from_symbols = + Symbol.Set.fold (fun symbol fun_vars' -> + match Symbol.Map.find symbol symbols_to_fun_vars with + | exception Not_found -> fun_vars' + | fun_var -> + assert (Variable.Set.mem fun_var fun_vars); + Variable.Set.add fun_var fun_vars') + func_decl.free_symbols + Variable.Set.empty + in + let from_variables = + Variable.Set.inter func_decl.free_variables fun_vars + in + Variable.Set.union from_symbols from_variables) + function_decls.funs + +let closures_required_by_entry_point ~(entry_point : Closure_id.t) ~backend + (function_decls : Flambda.function_declarations) = + let dependencies = + fun_vars_referenced_in_decls function_decls ~backend + in + let set = ref Variable.Set.empty in + let queue = Queue.create () in + let add v = + if not (Variable.Set.mem v !set) then begin + set := Variable.Set.add v !set; + Queue.push v queue + end + in + add (Closure_id.unwrap entry_point); + while not (Queue.is_empty queue) do + let fun_var = Queue.pop queue in + match Variable.Map.find fun_var dependencies with + | exception Not_found -> () + | fun_dependencies -> + Variable.Set.iter (fun dep -> + if Variable.Map.mem dep function_decls.funs then + add dep) + fun_dependencies + done; + !set + +let all_functions_parameters (function_decls : Flambda.function_declarations) = + Variable.Map.fold (fun _ ({ params } : Flambda.function_declaration) set -> + Variable.Set.union set (Variable.Set.of_list params)) + function_decls.funs Variable.Set.empty + +let all_free_symbols (function_decls : Flambda.function_declarations) = + Variable.Map.fold (fun _ (function_decl : Flambda.function_declaration) + syms -> + Symbol.Set.union syms function_decl.free_symbols) + function_decls.funs Symbol.Set.empty + +let contains_stub (fun_decls : Flambda.function_declarations) = + let number_of_stub_functions = + Variable.Map.cardinal + (Variable.Map.filter (fun _ { Flambda.stub } -> stub) + fun_decls.funs) + in + number_of_stub_functions > 0 + +let clean_projections ~which_variables = + Variable.Map.map (fun (spec_to : Flambda.specialised_to) -> + match spec_to.projection with + | None -> spec_to + | Some projection -> + let from = Projection.projecting_from projection in + if Variable.Map.mem from which_variables then + spec_to + else + ({ spec_to with projection = None; } : Flambda.specialised_to)) + which_variables + +let projection_to_named (projection : Projection.t) : Flambda.named = + match projection with + | Project_var project_var -> Project_var project_var + | Project_closure project_closure -> Project_closure project_closure + | Move_within_set_of_closures move -> Move_within_set_of_closures move + | Field (field_index, var) -> + Prim (Pfield field_index, [var], Debuginfo.none) diff --git a/middle_end/flambda_utils.mli b/middle_end/flambda_utils.mli new file mode 100644 index 00000000..aba0bdb1 --- /dev/null +++ b/middle_end/flambda_utils.mli @@ -0,0 +1,216 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Utility functions for the Flambda intermediate language. *) + +(** Access functions *) + +(** [find_declaration f decl] raises [Not_found] if [f] is not in [decl]. *) +val find_declaration : + Closure_id.t -> Flambda.function_declarations -> Flambda.function_declaration + +(** [find_declaration_variable f decl] raises [Not_found] if [f] is not in + [decl]. *) +val find_declaration_variable : + Closure_id.t -> Flambda.function_declarations -> Variable.t + +(** [find_free_variable v clos] raises [Not_found] if [c] is not in [clos]. *) +val find_free_variable : + Var_within_closure.t -> Flambda.set_of_closures -> Variable.t + +(** Utility functions *) + +val function_arity : Flambda.function_declaration -> int + +(** Variables "bound by a closure" are those variables free in the + corresponding function's body that are neither: + - bound as parameters of that function; nor + - bound by the [let] binding that introduces the function declaration(s). + In particular, if [f], [g] and [h] are being introduced by a + simultaneous, possibly mutually-recursive [let] binding then none of + [f], [g] or [h] are bound in any of the closures for [f], [g] and [h]. +*) +val variables_bound_by_the_closure : + Closure_id.t -> Flambda.function_declarations -> Variable.Set.t + +(** If [can_be_merged f1 f2] is [true], it is safe to merge switch + branches containing [f1] and [f2]. *) +val can_be_merged : Flambda.t -> Flambda.t -> bool + +val description_of_toplevel_node : Flambda.t -> string + +(** Sharing key, used for coalescing switch cases. *) +type sharing_key +val make_key : Flambda.t -> sharing_key option + +(* Given an expression, freshen all variables within it, and form a function + whose body is the resulting expression. The variables specified by + [params] will become the parameters of the function; the closure will be + identified by [id]. [params] must only reference variables that are + free variables of [body]. *) +(* CR-soon mshinwell: consider improving name and names of arguments + lwhite: the params restriction seems odd, perhaps give a reason + in the comment. *) +val make_closure_declaration + : id:Variable.t + -> body:Flambda.t + -> params:Variable.t list + -> stub:bool + -> Flambda.t + +val toplevel_substitution + : Variable.t Variable.Map.t + -> Flambda.expr + -> Flambda.expr + +val toplevel_substitution_named + : Variable.t Variable.Map.t + -> Flambda.named + -> Flambda.named + +(** [bind [var1, expr1; ...; varN, exprN] body] binds using + [Immutable] [Let] expressions the given [(var, expr)] pairs around the + body. *) +val bind + : bindings:(Variable.t * Flambda.named) list + -> body:Flambda.t + -> Flambda.t + +val name_expr : Flambda.named -> name:string -> Flambda.t + +val compare_const : Flambda.const -> Flambda.const -> int + +val initialize_symbols + : Flambda.program + -> (Symbol.t * Tag.t * Flambda.t list) list + +val imported_symbols : Flambda.program -> Symbol.Set.t + +val needed_import_symbols : Flambda.program -> Symbol.Set.t + +val introduce_needed_import_symbols : Flambda.program -> Flambda.program + +val root_symbol : Flambda.program -> Symbol.t + +(** Returns [true] iff the given term might raise the given static + exception. *) +val might_raise_static_exn : Flambda.named -> Static_exception.t -> bool + +(** Creates a map from closure IDs to function declarations by iterating over + all sets of closures in the given program. *) +val make_closure_map + : Flambda.program + -> Flambda.function_declarations Closure_id.Map.t + +(** Like [make_closure_map], but takes a mapping from set of closures IDs to + function declarations, instead of a [program]. *) +val make_closure_map' + : Flambda.function_declarations Set_of_closures_id.Map.t + -> Flambda.function_declarations Closure_id.Map.t + +(** The definitions of all constants that have been lifted out to [Let_symbol] + or [Let_rec_symbol] constructions. *) +val all_lifted_constants + : Flambda.program + -> (Symbol.t * Flambda.constant_defining_value) list + +(** Like [all_lifted_constant_symbols], but returns a map instead of a list. *) +val all_lifted_constants_as_map + : Flambda.program + -> Flambda.constant_defining_value Symbol.Map.t + +(** The identifiers of all constant sets of closures that have been lifted out + to [Let_symbol] or [Let_rec_symbol] constructions. *) +val all_lifted_constant_sets_of_closures + : Flambda.program + -> Set_of_closures_id.Set.t + +(** All sets of closures in the given program (whether or not bound to a + symbol.) *) +val all_sets_of_closures : Flambda.program -> Flambda.set_of_closures list + +val all_sets_of_closures_map + : Flambda.program + -> Flambda.set_of_closures Set_of_closures_id.Map.t + +val all_function_decls_indexed_by_set_of_closures_id + : Flambda.program + -> Flambda.function_declarations Set_of_closures_id.Map.t + +val all_function_decls_indexed_by_closure_id + : Flambda.program + -> Flambda.function_declarations Closure_id.Map.t + +val make_variable_symbol : Variable.t -> Symbol.t +val make_variables_symbol : Variable.t list -> Symbol.t + +(* CR-someday pchambart: A more general version of this function might + take a [named] instead of a symbol and be called with + [Read_symbol_field (symbol, 0)]. *) +val substitute_read_symbol_field_for_variables + : (Symbol.t * int list) Variable.Map.t + -> Flambda.t + -> Flambda.t + +(** For the compilation of switch statements. *) +module Switch_storer : sig + val mk_store : unit -> Flambda.t Switch.t_store +end + +(** Within a set of function declarations there is a set of function bodies, + each of which may (or may not) reference one of the other functions in + the same set. Initially such intra-set references are by [Var]s (known + as "fun_var"s) but if the function is lifted by [Lift_constants] then the + references will be translated to [Symbol]s. This means that optimization + passes that need to identify whether a given "fun_var" (i.e. a key in the + [funs] map in a value of type [function_declarations]) is used in one of + the function bodies need to examine the [free_symbols] as well as the + [free_variables] members of [function_declarations]. This function makes + that process easier by computing all used "fun_var"s in the bodies of + the given set of function declarations, including the cases where the + references are [Symbol]s. The returned value is a map from "fun_var"s + to the "fun_var"s (if any) used in the body of the function associated + with that "fun_var". +*) +val fun_vars_referenced_in_decls + : Flambda.function_declarations + -> backend:(module Backend_intf.S) + -> Variable.Set.t Variable.Map.t + +(** Computes the set of closure_id in the set of closures that are + required used (transitively) the entry_point *) +val closures_required_by_entry_point + : entry_point:Closure_id.t + -> backend:(module Backend_intf.S) + -> Flambda.function_declarations + -> Variable.Set.t + +val all_functions_parameters : Flambda.function_declarations -> Variable.Set.t + +val all_free_symbols : Flambda.function_declarations -> Symbol.Set.t + +val contains_stub : Flambda.function_declarations -> bool + +(* Ensure that projection information is suitably erased from + free_vars and specialised_args if we have deleted the variable being + projected from. *) +val clean_projections + : which_variables : Flambda.specialised_to Variable.Map.t + -> Flambda.specialised_to Variable.Map.t + +val projection_to_named : Projection.t -> Flambda.named diff --git a/middle_end/freshening.ml b/middle_end/freshening.ml new file mode 100644 index 00000000..796531c2 --- /dev/null +++ b/middle_end/freshening.ml @@ -0,0 +1,444 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type tbl = { + sb_var : Variable.t Variable.Map.t; + sb_mutable_var : Mutable_variable.t Mutable_variable.Map.t; + sb_exn : Static_exception.t Static_exception.Map.t; + (* Used to handle substitution sequences: we cannot call the substitution + recursively because there can be name clashes. *) + back_var : Variable.t list Variable.Map.t; + back_mutable_var : Mutable_variable.t list Mutable_variable.Map.t; +} + +type t = + | Inactive + | Active of tbl + +type subst = t + +let empty_tbl = { + sb_var = Variable.Map.empty; + sb_mutable_var = Mutable_variable.Map.empty; + sb_exn = Static_exception.Map.empty; + back_var = Variable.Map.empty; + back_mutable_var = Mutable_variable.Map.empty; +} + +let print ppf = function + | Inactive -> Format.fprintf ppf "Inactive" + | Active tbl -> + Format.fprintf ppf "Active:@ "; + Variable.Map.iter (fun var1 var2 -> + Format.fprintf ppf "%a -> %a@ " + Variable.print var1 + Variable.print var2) + tbl.sb_var; + Mutable_variable.Map.iter (fun mut_var1 mut_var2 -> + Format.fprintf ppf "(mutable) %a -> %a@ " + Mutable_variable.print mut_var1 + Mutable_variable.print mut_var2) + tbl.sb_mutable_var; + Variable.Map.iter (fun var vars -> + Format.fprintf ppf "%a -> %a@ " + Variable.print var + Variable.Set.print (Variable.Set.of_list vars)) + tbl.back_var; + Mutable_variable.Map.iter (fun mut_var mut_vars -> + Format.fprintf ppf "(mutable) %a -> %a@ " + Mutable_variable.print mut_var + Mutable_variable.Set.print (Mutable_variable.Set.of_list mut_vars)) + tbl.back_mutable_var + +let empty = Inactive + +let empty_preserving_activation_state = function + | Inactive -> Inactive + | Active _ -> Active empty_tbl + +let activate = function + | Inactive -> Active empty_tbl + | Active _ as t -> t + +let rec add_sb_var sb id id' = + let sb = { sb with sb_var = Variable.Map.add id id' sb.sb_var } in + let sb = + try let pre_vars = Variable.Map.find id sb.back_var in + List.fold_left (fun sb pre_id -> add_sb_var sb pre_id id') sb pre_vars + with Not_found -> sb in + let back_var = + let l = try Variable.Map.find id' sb.back_var with Not_found -> [] in + Variable.Map.add id' (id :: l) sb.back_var in + { sb with back_var } + +let rec add_sb_mutable_var sb id id' = + let sb = + { sb with + sb_mutable_var = Mutable_variable.Map.add id id' sb.sb_mutable_var; + } + in + let sb = + try + let pre_vars = Mutable_variable.Map.find id sb.back_mutable_var in + List.fold_left (fun sb pre_id -> add_sb_mutable_var sb pre_id id') + sb pre_vars + with Not_found -> sb in + let back_mutable_var = + let l = + try Mutable_variable.Map.find id' sb.back_mutable_var + with Not_found -> [] + in + Mutable_variable.Map.add id' (id :: l) sb.back_mutable_var + in + { sb with back_mutable_var } + +let apply_static_exception t i = + match t with + | Inactive -> + i + | Active t -> + try Static_exception.Map.find i t.sb_exn + with Not_found -> i + +let add_static_exception t i = + match t with + | Inactive -> i, t + | Active t -> + let i' = Static_exception.create () in + let sb_exn = + Static_exception.Map.add i i' t.sb_exn + in + i', Active { t with sb_exn; } + +let active_add_variable t id = + let id' = Variable.rename id in + let t = add_sb_var t id id' in + id', t + +let add_variable t id = + match t with + | Inactive -> id, t + | Active t -> + let id', t = active_add_variable t id in + id', Active t + +let active_add_variables' t ids = + List.fold_right (fun id (ids, t) -> + let id', t = active_add_variable t id in + id' :: ids, t) ids ([], t) + +let add_variables t defs = + List.fold_right (fun (id, data) (defs, t) -> + let id', t = add_variable t id in + (id', data) :: defs, t) defs ([], t) + +let add_variables' t ids = + List.fold_right (fun id (ids, t) -> + let id', t = add_variable t id in + id' :: ids, t) ids ([], t) + +let active_add_mutable_variable t id = + let id' = Mutable_variable.freshen id in + let t = add_sb_mutable_var t id id' in + id', t + +let add_mutable_variable t id = + match t with + | Inactive -> id, t + | Active t -> + let id', t = active_add_mutable_variable t id in + id', Active t + +let active_find_var_exn t id = + try Variable.Map.find id t.sb_var with + | Not_found -> + Misc.fatal_error (Format.asprintf "find_var: can't find %a@." + Variable.print id) + +let apply_variable t var = + match t with + | Inactive -> var + | Active t -> + try Variable.Map.find var t.sb_var with + | Not_found -> var + +let apply_mutable_variable t mut_var = + match t with + | Inactive -> mut_var + | Active t -> + try Mutable_variable.Map.find mut_var t.sb_mutable_var with + | Not_found -> mut_var + +let rewrite_recursive_calls_with_symbols t + (function_declarations : Flambda.function_declarations) + ~make_closure_symbol = + match t with + | Inactive -> function_declarations + | Active _ -> + let all_free_symbols = + Flambda_utils.all_free_symbols function_declarations + in + let closure_symbols_used = ref false in + let closure_symbols = + Variable.Map.fold (fun var _ map -> + let closure_id = Closure_id.wrap var in + let sym = make_closure_symbol closure_id in + if Symbol.Set.mem sym all_free_symbols then begin + closure_symbols_used := true; + Symbol.Map.add sym var map + end else begin + map + end) + function_declarations.funs Symbol.Map.empty + in + if not !closure_symbols_used then begin + (* Don't waste time rewriting the function declaration(s) if there + are no occurrences of any of the closure symbols. *) + function_declarations + end else begin + let funs = + Variable.Map.map (fun (ffun : Flambda.function_declaration) -> + let body = + Flambda_iterators.map_toplevel_named + (* CR-someday pchambart: This may be worth deep substituting + below the closures, but that means that we need to take care + of functions' free variables. *) + (function + | Symbol sym when Symbol.Map.mem sym closure_symbols -> + Expr (Var (Symbol.Map.find sym closure_symbols)) + | e -> e) + ffun.body + in + Flambda.create_function_declaration ~params:ffun.params + ~body ~stub:ffun.stub ~dbg:ffun.dbg ~inline:ffun.inline + ~specialise:ffun.specialise ~is_a_functor:ffun.is_a_functor) + function_declarations.funs + in + Flambda.update_function_declarations function_declarations ~funs + end + +module Project_var = struct + type t = + { vars_within_closure : Var_within_closure.t Var_within_closure.Map.t; + closure_id : Closure_id.t Closure_id.Map.t } + + let empty = + { vars_within_closure = Var_within_closure.Map.empty; + closure_id = Closure_id.Map.empty; + } + + let print ppf t = + Format.fprintf ppf "{ vars_within_closure %a, closure_id %a }" + (Var_within_closure.Map.print Var_within_closure.print) + t.vars_within_closure + (Closure_id.Map.print Closure_id.print) + t.closure_id + + let new_subst_fv t id subst = + match subst with + | Inactive -> id, subst, t + | Active subst -> + let id' = Variable.rename id in + let subst = add_sb_var subst id id' in + let off = Var_within_closure.wrap id in + let off' = Var_within_closure.wrap id' in + let off_sb = Var_within_closure.Map.add off off' t.vars_within_closure in + id', Active subst, { t with vars_within_closure = off_sb; } + + let new_subst_fun t id subst = + let id' = Variable.rename id in + let subst = add_sb_var subst id id' in + let off = Closure_id.wrap id in + let off' = Closure_id.wrap id' in + let off_sb = Closure_id.Map.add off off' t.closure_id in + id', subst, { t with closure_id = off_sb; } + + (** Returns : + * The map of new_identifiers -> expression + * The new environment with added substitution + * a fresh ffunction_subst with only the substitution of free variables + *) + let subst_free_vars fv subst ~only_freshen_parameters + : (Flambda.specialised_to * _) Variable.Map.t * _ * _ = + Variable.Map.fold (fun id lam (fv, subst, t) -> + let id, subst, t = + if only_freshen_parameters then + id, subst, t + else + new_subst_fv t id subst + in + Variable.Map.add id lam fv, subst, t) + fv + (Variable.Map.empty, subst, empty) + + (** Returns : + * The function_declaration with renamed function identifiers + * The new environment with added substitution + * The ffunction_subst completed with function substitution + + subst_free_vars must have been used to build off_sb + *) + let func_decls_subst t (subst : subst) + (func_decls : Flambda.function_declarations) + ~only_freshen_parameters = + match subst with + | Inactive -> func_decls, subst, t + | Active subst -> + let subst_func_decl _fun_id (func_decl : Flambda.function_declaration) + subst = + let params, subst = active_add_variables' subst func_decl.params in + (* Since all parameters are distinct, even between functions, we can + just use a single substitution. *) + let body = + Flambda_utils.toplevel_substitution subst.sb_var func_decl.body + in + let function_decl = + Flambda.create_function_declaration ~params + ~body ~stub:func_decl.stub ~dbg:func_decl.dbg + ~inline:func_decl.inline ~specialise:func_decl.specialise + ~is_a_functor:func_decl.is_a_functor + in + function_decl, subst + in + let subst, t = + if only_freshen_parameters then + subst, t + else + Variable.Map.fold (fun orig_id _func_decl (subst, t) -> + let _id, subst, t = new_subst_fun t orig_id subst in + subst, t) + func_decls.funs + (subst, t) + in + let funs, subst = + Variable.Map.fold (fun orig_id func_decl (funs, subst) -> + let func_decl, subst = subst_func_decl orig_id func_decl subst in + let id = + if only_freshen_parameters then orig_id + else active_find_var_exn subst orig_id + in + let funs = Variable.Map.add id func_decl funs in + funs, subst) + func_decls.funs + (Variable.Map.empty, subst) + in + let function_decls = + Flambda.update_function_declarations func_decls ~funs + in + function_decls, Active subst, t + + let apply_closure_id t closure_id = + try Closure_id.Map.find closure_id t.closure_id + with Not_found -> closure_id + + let apply_var_within_closure t var_in_closure = + try Var_within_closure.Map.find var_in_closure t.vars_within_closure + with Not_found -> var_in_closure + + module Compose (T : Identifiable.S) = struct + let compose ~earlier ~later = + if (T.Map.equal T.equal) earlier later + || T.Map.cardinal later = 0 + then + earlier + else + T.Map.mapi (fun src_var var -> + if T.Map.mem src_var later then begin + Misc.fatal_errorf "Freshening.Project_var.compose: domains \ + of substitutions must be disjoint. earlier=%a later=%a" + (T.Map.print T.print) earlier + (T.Map.print T.print) later + end; + match T.Map.find var later with + | exception Not_found -> var + | var -> var) + earlier + end + + module V = Compose (Var_within_closure) + module C = Compose (Closure_id) + + let compose ~earlier ~later : t = + { vars_within_closure = + V.compose ~earlier:earlier.vars_within_closure + ~later:later.vars_within_closure; + closure_id = + C.compose ~earlier:earlier.closure_id + ~later:later.closure_id; + } +end + +let apply_function_decls_and_free_vars t fv func_decls + ~only_freshen_parameters = + let module I = Project_var in + let fv, t, of_closures = I.subst_free_vars fv t ~only_freshen_parameters in + let func_decls, t, of_closures = + I.func_decls_subst of_closures t func_decls ~only_freshen_parameters + in + fv, func_decls, t, of_closures + +let does_not_freshen t vars = + match t with + | Inactive -> true + | Active subst -> + not (List.exists (fun var -> Variable.Map.mem var subst.sb_var) vars) + +let freshen_projection (projection : Projection.t) ~freshening + ~closure_freshening : Projection.t = + match projection with + | Project_var { closure; closure_id; var; } -> + Project_var { + closure = apply_variable freshening closure; + closure_id = Project_var.apply_closure_id closure_freshening closure_id; + var = Project_var.apply_var_within_closure closure_freshening var; + } + | Project_closure { set_of_closures; closure_id; } -> + Project_closure { + set_of_closures = apply_variable freshening set_of_closures; + closure_id = Project_var.apply_closure_id closure_freshening closure_id; + } + | Move_within_set_of_closures { closure; start_from; move_to; } -> + Move_within_set_of_closures { + closure = apply_variable freshening closure; + start_from = Project_var.apply_closure_id closure_freshening start_from; + move_to = Project_var.apply_closure_id closure_freshening move_to; + } + | Field (field_index, var) -> + Field (field_index, apply_variable freshening var) + +let freshen_projection_relation relation ~freshening ~closure_freshening = + Variable.Map.map (fun (spec_to : Flambda.specialised_to) -> + let projection = + match spec_to.projection with + | None -> None + | Some projection -> + Some (freshen_projection projection ~freshening ~closure_freshening) + in + { spec_to with projection; }) + relation + +let freshen_projection_relation' relation ~freshening ~closure_freshening = + Variable.Map.map (fun ((spec_to : Flambda.specialised_to), data) -> + let projection = + match spec_to.projection with + | None -> None + | Some projection -> + Some (freshen_projection projection ~freshening ~closure_freshening) + in + { spec_to with projection; }, data) + relation diff --git a/middle_end/freshening.mli b/middle_end/freshening.mli new file mode 100644 index 00000000..6af21415 --- /dev/null +++ b/middle_end/freshening.mli @@ -0,0 +1,165 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Freshening of various identifiers. *) + +(** A table used for freshening variables and static exception identifiers. *) +type t +type subst = t + +(** The freshening that does nothing. This is the unique inactive + freshening. *) +val empty : t + +(** Activate the freshening. Without activation, operations to request + freshenings have no effect (cf. the documentation below for + [add_variable]). As such, the inactive renaming is unique. *) +val activate : t -> t + +(** Given the inactive freshening, return the same; otherwise, return an + empty active freshening. *) +val empty_preserving_activation_state : t -> t + +(** [add_variable t var] + If [t] is active: + It returns a fresh variable [new_var] and adds [var] -> [new_var] + to the freshening. + If a renaming [other_var] -> [var] or [symbol] -> [var] was already + present in [t], it will also add [other_var] -> [new_var] and + [symbol] -> [new_var]. + If [t] is inactive, this is the identity. +*) +val add_variable : t -> Variable.t -> Variable.t * t + +(** Like [add_variable], but for multiple variables, each freshened + separately. *) +val add_variables' + : t + -> Variable.t list + -> Variable.t list * t + +(** Like [add_variables'], but passes through the second component of the + input list unchanged. *) +val add_variables + : t + -> (Variable.t * 'a) list + -> (Variable.t * 'a) list * t + +(** Like [add_variable], but for mutable variables. *) +val add_mutable_variable : t -> Mutable_variable.t -> Mutable_variable.t * t + +(** As for [add_variable], but for static exception identifiers. *) +val add_static_exception : t -> Static_exception.t -> Static_exception.t * t + +(** [apply_variable t var] applies the freshening [t] to [var]. + If no renaming is specified in [t] for [var] it is returned unchanged. *) +val apply_variable : t -> Variable.t -> Variable.t + +(** As for [apply_variable], but for mutable variables. *) +val apply_mutable_variable : t -> Mutable_variable.t -> Mutable_variable.t + +(** As for [apply_variable], but for static exception identifiers. *) +val apply_static_exception : t -> Static_exception.t -> Static_exception.t + +(** Replace recursive accesses to the closures in the set through + [Symbol] by the corresponding [Var]. This is used to recover + the recursive call when importing code from another compilation unit. + + If the renaming is inactive, this is the identity. +*) +val rewrite_recursive_calls_with_symbols + : t + -> Flambda.function_declarations + -> make_closure_symbol:(Closure_id.t -> Symbol.t) + -> Flambda.function_declarations + +(* CR-soon mshinwell for mshinwell: maybe inaccurate module name, it freshens + closure IDs as well. Check use points though *) +module Project_var : sig + (** A table used for freshening of identifiers in [Project_closure] and + [Move_within_set_of_closures] ("ids of closures"); and [Project_var] + ("bound vars of closures") expressions. + + This information is propagated bottom up and populated when inlining a + function containing a closure declaration. + + For instance, + [let f x = + let g y = ... x ... in + ... g.x ... (Project_var x) + ... g 1 ... (Apply (Project_closure g ...)) + ] + + If f is inlined, g is renamed. The approximation of g will carry this + table such that later the access to the field x of g and selection of + g in the closure can be substituted. + *) + type t + + (* The freshening that does nothing. *) + val empty : t + + (** Composition of two freshenings. *) + val compose : earlier:t -> later:t -> t + + (** Freshen a closure ID based on the given renaming. The same ID is + returned if the renaming does not affect it. + If dealing with approximations, you probably want to use + [Simple_value_approx.freshen_and_check_closure_id] instead of this + function. + *) + val apply_closure_id : t -> Closure_id.t -> Closure_id.t + + (** Like [apply_closure_id], but for variables within closures. *) + val apply_var_within_closure + : t + -> Var_within_closure.t + -> Var_within_closure.t + + val print : Format.formatter -> t -> unit +end + +(* CR-soon mshinwell for mshinwell: add comment *) +val apply_function_decls_and_free_vars + : t + -> (Flambda.specialised_to * 'a) Variable.Map.t + -> Flambda.function_declarations + -> only_freshen_parameters:bool + -> (Flambda.specialised_to * 'a) Variable.Map.t + * Flambda.function_declarations + * t + * Project_var.t + +val does_not_freshen : t -> Variable.t list -> bool + +val print : Format.formatter -> t -> unit + +(** N.B. This does not freshen the domain of the supplied map, only the + range. *) +(* CR-someday mshinwell: consider fixing that *) +val freshen_projection_relation + : Flambda.specialised_to Variable.Map.t + -> freshening:t + -> closure_freshening:Project_var.t + -> Flambda.specialised_to Variable.Map.t + +val freshen_projection_relation' + : (Flambda.specialised_to * 'a) Variable.Map.t + -> freshening:t + -> closure_freshening:Project_var.t + -> (Flambda.specialised_to * 'a) Variable.Map.t diff --git a/middle_end/inconstant_idents.ml b/middle_end/inconstant_idents.ml new file mode 100644 index 00000000..04921800 --- /dev/null +++ b/middle_end/inconstant_idents.ml @@ -0,0 +1,494 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* This cannot be done in a single simple pass due to expressions like: + + let rec ... = + ... + let rec f1 x = + let f2 y = + f1 rec_list + in + f2 v + and rec_list = f1 :: rec_list in + ... + + and v = ... + + f1, f2 and rec_list are constants iff v is a constant. + + To handle this we populate both a 'not constant' set NC and a set of + implications between variables. + + For example, the above code would generate the implications: + + f1 in NC => rec_list in NC + f2 in NC => f1 in NC + rec_list in NC => f2 in NC + v in NC => f1 in NC + + then if v is found to be in NC this will be propagated to place + f1, f2 and rec_list in NC as well. + +*) + +(* CR-someday lwhite: I think this pass could be combined with + alias_analysis and other parts of lift_constants into a single + type-based anaylsis which infers a "type" for each variable that is + either an allocated_constant expression or "not constant". Recursion + would be handled with unification variables. *) + +module Int = Numbers.Int +module Symbol_field = struct + type t = Symbol.t * Int.t + include Identifiable.Make (Identifiable.Pair (Symbol) (Int)) +end + +type dep = + | Closure of Set_of_closures_id.t + | Var of Variable.t + | Symbol of Symbol.t + | Symbol_field of Symbol_field.t + +type state = + | Not_constant + | Implication of dep list + +type result = { + id : state Variable.Tbl.t; + closure : state Set_of_closures_id.Tbl.t; +} + +module type Param = sig + val program : Flambda.program + val compilation_unit : Compilation_unit.t +end + +(* CR-soon mshinwell: consider removing functor *) +module Inconstants (P:Param) (Backend:Backend_intf.S) = struct + let program = P.program + let compilation_unit = P.compilation_unit + let imported_symbols = Flambda_utils.imported_symbols program + + (* Sets representing NC *) + let variables : state Variable.Tbl.t = Variable.Tbl.create 42 + let closures : state Set_of_closures_id.Tbl.t = + Set_of_closures_id.Tbl.create 42 + let symbols : state Symbol.Tbl.t = Symbol.Tbl.create 42 + let symbol_fields : state Symbol_field.Tbl.t = Symbol_field.Tbl.create 42 + + let mark_queue = Queue.create () + + (* CR-soon pchambart: We could probably improve that quite a lot by adding + (the future annotation) [@unrolled] at the right call sites. Or more + directly mark mark_dep as [@inline] and call it instead of mark_curr in + some situations. + *) + + (* adds 'dep in NC' *) + let rec mark_dep = function + | Var id -> begin + match Variable.Tbl.find variables id with + | Not_constant -> () + | Implication deps -> + Variable.Tbl.replace variables id Not_constant; + Queue.push deps mark_queue + | exception Not_found -> + Variable.Tbl.add variables id Not_constant + end + | Closure cl -> begin + match Set_of_closures_id.Tbl.find closures cl with + | Not_constant -> () + | Implication deps -> + Set_of_closures_id.Tbl.replace closures cl Not_constant; + Queue.push deps mark_queue + | exception Not_found -> + Set_of_closures_id.Tbl.add closures cl Not_constant + end + | Symbol s -> begin + match Symbol.Tbl.find symbols s with + | Not_constant -> () + | Implication deps -> + Symbol.Tbl.replace symbols s Not_constant; + Queue.push deps mark_queue + | exception Not_found -> + Symbol.Tbl.add symbols s Not_constant + end + | Symbol_field s -> begin + match Symbol_field.Tbl.find symbol_fields s with + | Not_constant -> () + | Implication deps -> + Symbol_field.Tbl.replace symbol_fields s Not_constant; + Queue.push deps mark_queue + | exception Not_found -> + Symbol_field.Tbl.add symbol_fields s Not_constant + end + + and mark_deps deps = + List.iter mark_dep deps + + and complete_marking () = + while not (Queue.is_empty mark_queue) do + let deps = + try + Queue.take mark_queue + with Not_found -> [] + in + mark_deps deps; + done + + (* adds 'curr in NC' *) + let mark_curr curr = + mark_deps curr; + complete_marking () + + (* adds in the tables 'dep in NC => curr in NC' *) + let register_implication ~in_nc:dep ~implies_in_nc:curr = + match dep with + | Var id -> begin + match Variable.Tbl.find variables id with + | Not_constant -> + mark_deps curr; + complete_marking (); + | Implication deps -> + let deps = List.rev_append curr deps in + Variable.Tbl.replace variables id (Implication deps) + | exception Not_found -> + Variable.Tbl.add variables id (Implication curr); + end + | Closure cl -> begin + match Set_of_closures_id.Tbl.find closures cl with + | Not_constant -> + mark_deps curr; + complete_marking (); + | Implication deps -> + let deps = List.rev_append curr deps in + Set_of_closures_id.Tbl.replace closures cl (Implication deps) + | exception Not_found -> + Set_of_closures_id.Tbl.add closures cl (Implication curr); + end + | Symbol symbol -> begin + match Symbol.Tbl.find symbols symbol with + | Not_constant -> + mark_deps curr; + complete_marking (); + | Implication deps -> + let deps = List.rev_append curr deps in + Symbol.Tbl.replace symbols symbol (Implication deps) + | exception Not_found -> + Symbol.Tbl.add symbols symbol (Implication curr); + end + | Symbol_field ((symbol, _) as field) -> begin + match Symbol_field.Tbl.find symbol_fields field with + | Not_constant -> + mark_deps curr; + complete_marking (); + | Implication deps -> + let deps = List.rev_append curr deps in + Symbol_field.Tbl.replace symbol_fields field (Implication deps) + | exception Not_found -> + (* There is no information available about the contents of imported + symbols, so we must consider all their fields as inconstant. *) + (* CR-someday pchambart: recover that from the cmx information *) + if Symbol.Set.mem symbol imported_symbols then begin + Symbol_field.Tbl.add symbol_fields field Not_constant; + mark_deps curr; + complete_marking (); + end else begin + Symbol_field.Tbl.add symbol_fields field (Implication curr) + end + end + + (* First loop: iterates on the tree to mark dependencies. + + curr is the variables or closures to wich we add constraints like + '... in NC => curr in NC' or 'curr in NC' + + It can be empty when no constraint can be added like in the toplevel + expression or in the body of a function. + *) + let rec mark_loop ~toplevel (curr : dep list) (flam : Flambda.t) = + match flam with + | Let { var; defining_expr = lam; body; _ } -> + mark_named ~toplevel [Var var] lam; + (* adds 'var in NC => curr in NC' + This is not really necessary, but compiling this correctly is + trickier than eliminating that earlier. *) + mark_var var curr; + mark_loop ~toplevel curr body + | Let_mutable (_mut_var, var, body) -> + mark_var var curr; + mark_loop ~toplevel curr body + | Let_rec(defs, body) -> + List.iter (fun (var, def) -> + mark_named ~toplevel [Var var] def; + (* adds 'var in NC => curr in NC' same remark as let case *) + mark_var var curr) + defs; + mark_loop ~toplevel curr body + | Var var -> mark_var var curr + (* Not constant cases: we mark directly 'curr in NC' and mark + bound variables as in NC also *) + | Assign _ -> + mark_curr curr + | Try_with (f1,id,f2) -> + mark_curr [Var id]; + mark_curr curr; + mark_loop ~toplevel [] f1; + mark_loop ~toplevel [] f2 + | Static_catch (_,ids,f1,f2) -> + List.iter (fun id -> mark_curr [Var id]) ids; + mark_curr curr; + mark_loop ~toplevel [] f1; + mark_loop ~toplevel [] f2 + (* CR-someday pchambart: If recursive staticcatch is introduced: + this becomes ~toplevel:false *) + | For { bound_var; from_value; to_value; direction = _; body; } -> + mark_curr [Var bound_var]; + mark_var from_value curr; + mark_var to_value curr; + mark_curr curr; + mark_loop ~toplevel:false [] body + | While (f1,body) -> + mark_curr curr; + mark_loop ~toplevel [] f1; + mark_loop ~toplevel:false [] body + | If_then_else (f1,f2,f3) -> + mark_curr curr; + mark_curr [Var f1]; + mark_loop ~toplevel [] f2; + mark_loop ~toplevel [] f3 + | Static_raise (_,l) -> + mark_curr curr; + List.iter (fun v -> mark_var v curr) l + | Apply ({func; args; _ }) -> + mark_curr curr; + mark_var func curr; + mark_vars args curr; + | Switch (arg,sw) -> + mark_curr curr; + mark_var arg curr; + List.iter (fun (_,l) -> mark_loop ~toplevel [] l) sw.consts; + List.iter (fun (_,l) -> mark_loop ~toplevel [] l) sw.blocks; + Misc.may (fun l -> mark_loop ~toplevel [] l) sw.failaction + | String_switch (arg,sw,def) -> + mark_curr curr; + mark_var arg curr; + List.iter (fun (_,l) -> mark_loop ~toplevel [] l) sw; + Misc.may (fun l -> mark_loop ~toplevel [] l) def + | Send { kind = _; meth; obj; args; dbg = _; } -> + mark_curr curr; + mark_var meth curr; + mark_var obj curr; + List.iter (fun arg -> mark_var arg curr) args + | Proved_unreachable -> + mark_curr curr + + and mark_named ~toplevel curr (named : Flambda.named) = + match named with + | Set_of_closures (set_of_closures) -> + mark_loop_set_of_closures ~toplevel curr set_of_closures + | Const _ | Allocated_const _ -> () + | Read_mutable _ -> mark_curr curr + | Symbol symbol -> begin + let current_unit = Compilation_unit.get_current_exn () in + if Compilation_unit.equal current_unit (Symbol.compilation_unit symbol) + then + () + else + match (Backend.import_symbol symbol).descr with + | Value_unresolved _ -> + (* Constant when 'for_clambda' means: can be a symbol (which is + obviously the case here) with a known approximation. If this + condition is not satisfied we mark as inconstant to reflect + the fact that the symbol's contents are unknown and thus + prevent attempts to examine it. (This is a bit of a hack.) *) + mark_curr curr + | _ -> + () + end + | Read_symbol_field (symbol, index) -> + register_implication ~in_nc:(Symbol_field (symbol, index)) + ~implies_in_nc:curr + (* Globals are symbols: handle like symbols *) + | Prim (Lambda.Pgetglobal _id, [], _) -> () + (* Constant constructors: those expressions are constant if all their + parameters are: + - makeblock is compiled to a constant block + - offset is compiled to a pointer inside a constant closure. + See Cmmgen for the details + + makeblock(Mutable) can be a 'constant' if it is allocated at + toplevel: if this expression is evaluated only once. + *) + | Prim (Lambda.Pmakeblock (_tag, Asttypes.Immutable), args, _dbg) -> + mark_vars args curr +(* (* CR-someday pchambart: If global mutables are allowed: *) + | Prim(Lambda.Pmakeblock(_tag, Asttypes.Mutable), args, _dbg, _) + when toplevel -> + List.iter (mark_loop ~toplevel curr) args +*) + | Prim (Pmakearray (Pfloatarray, Immutable), args, _) -> + mark_vars args curr + | Prim (Pmakearray (Pfloatarray, Mutable), args, _) -> + if toplevel then mark_vars args curr + else mark_curr curr + | Prim (Pduparray (Pfloatarray, Immutable), [arg], _) -> + mark_var arg curr + | Prim (Pduparray (Pfloatarray, Mutable), [arg], _) -> + if toplevel then mark_var arg curr + else mark_curr curr + | Prim (Pduparray _, _, _) -> + (* See Lift_constants *) + mark_curr curr + | Project_closure ({ set_of_closures; closure_id; }) -> + if Closure_id.in_compilation_unit closure_id compilation_unit then + mark_var set_of_closures curr + else + mark_curr curr + | Move_within_set_of_closures ({ closure; start_from; move_to; }) -> + (* CR-someday mshinwell: We should be able to deem these projections + (same for the cases below) as constant when from another + compilation unit, but there isn't code to handle this yet. (Note + that for Project_var we cannot yet generate a projection from a + closure in another compilation unit, since we only lift closed + closures.) *) + if Closure_id.in_compilation_unit start_from compilation_unit then begin + assert (Closure_id.in_compilation_unit move_to compilation_unit); + mark_var closure curr + end else begin + mark_curr curr + end + | Project_var ({ closure; closure_id; var = _ }) -> + if Closure_id.in_compilation_unit closure_id compilation_unit then + mark_var closure curr + else + mark_curr curr + | Prim (Lambda.Pfield _, [f1], _) -> + mark_curr curr; + mark_var f1 curr + | Prim (_, args, _) -> + mark_curr curr; + mark_vars args curr + | Expr flam -> + mark_loop ~toplevel curr flam + + and mark_var var curr = + (* adds 'id in NC => curr in NC' *) + register_implication ~in_nc:(Var var) ~implies_in_nc:curr + + and mark_vars vars curr = + (* adds 'id in NC => curr in NC' *) + List.iter (fun var -> mark_var var curr) vars + + (* [toplevel] is intended for allowing static allocations of mutable + blocks. This feature should be available in a future release once the + necessary GC changes have been merged. (See GPR#178.) *) + and mark_loop_set_of_closures ~toplevel:_ curr + { Flambda. function_decls; free_vars; specialised_args } = + (* If a function in the set of closures is specialised, do not consider + it constant, unless all specialised args are also constant. *) + Variable.Map.iter (fun _ (spec_arg : Flambda.specialised_to) -> + register_implication + ~in_nc:(Var spec_arg.var) + ~implies_in_nc:[Closure function_decls.set_of_closures_id]) + specialised_args; + (* adds 'function_decls in NC => curr in NC' *) + register_implication ~in_nc:(Closure function_decls.set_of_closures_id) + ~implies_in_nc:curr; + (* a closure is constant if its free variables are constants. *) + Variable.Map.iter (fun inner_id (var : Flambda.specialised_to) -> + register_implication ~in_nc:(Var var.var) + ~implies_in_nc:[ + Var inner_id; + Closure function_decls.set_of_closures_id + ]) + free_vars; + Variable.Map.iter (fun fun_id (ffunc : Flambda.function_declaration) -> + (* for each function f in a closure c 'c in NC => f' *) + register_implication ~in_nc:(Closure function_decls.set_of_closures_id) + ~implies_in_nc:[Var fun_id]; + (* function parameters are in NC unless specialised *) + List.iter (fun param -> + match Variable.Map.find param specialised_args with + | exception Not_found -> mark_curr [Var param] + | outer_var -> + register_implication ~in_nc:(Var outer_var.var) + ~implies_in_nc:[Var param]) + ffunc.params; + mark_loop ~toplevel:false [] ffunc.body) + function_decls.funs + + let mark_constant_defining_value (const:Flambda.constant_defining_value) = + match const with + | Allocated_const _ + | Block _ + | Project_closure _ -> () + | Set_of_closures set_of_closure -> + mark_loop_set_of_closures ~toplevel:true [] set_of_closure + + let mark_program (program : Flambda.program) = + let rec loop (program : Flambda.program_body) = + match program with + | End _ -> () + | Initialize_symbol (symbol,_tag,fields,program) -> + List.iteri (fun i field -> + mark_loop ~toplevel:true + [Symbol symbol; Symbol_field (symbol,i)] field) + fields; + loop program + | Effect (expr, program) -> + mark_loop ~toplevel:true [] expr; + loop program + | Let_symbol (_, def, program) -> + mark_constant_defining_value def; + loop program + | Let_rec_symbol (defs, program) -> + List.iter (fun (_, def) -> mark_constant_defining_value def) defs; + loop program + in + loop program.program_body + + let res = + mark_program program; + { id = variables; + closure = closures; + } +end + +let inconstants_on_program ~compilation_unit ~backend + (program : Flambda.program) = + let module P = struct + let program = program + let compilation_unit = compilation_unit + end in + let module Backend = (val backend : Backend_intf.S) in + let module I = Inconstants (P) (Backend) in + I.res + +let variable var { id; _ } = + match Variable.Tbl.find id var with + | Not_constant -> true + | Implication _ -> false + | exception Not_found -> false + +let closure cl { closure; _ } = + match Set_of_closures_id.Tbl.find closure cl with + | Not_constant -> true + | Implication _ -> false + | exception Not_found -> false diff --git a/middle_end/inconstant_idents.mli b/middle_end/inconstant_idents.mli new file mode 100644 index 00000000..2c5309e0 --- /dev/null +++ b/middle_end/inconstant_idents.mli @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type result + +(** [inconstants_on_program] finds those variables and set-of-closures + identifiers that cannot be compiled to constants by [Flambda_to_clambda]. +*) +val inconstants_on_program + : compilation_unit:Compilation_unit.t + -> backend:(module Backend_intf.S) + -> Flambda.program + -> result + +(** [variable var res] returns [true] if [var] is marked as inconstant + in [res]. *) +val variable : Variable.t -> result -> bool + +(** [closure cl res] returns [true] if [cl] is marked as inconstant + in [res]. *) +val closure : Set_of_closures_id.t -> result -> bool diff --git a/middle_end/initialize_symbol_to_let_symbol.ml b/middle_end/initialize_symbol_to_let_symbol.ml new file mode 100644 index 00000000..634c68ad --- /dev/null +++ b/middle_end/initialize_symbol_to_let_symbol.ml @@ -0,0 +1,56 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let constant_field (expr:Flambda.t) + : Flambda.constant_defining_value_block_field option = + match expr with + | Let { var; defining_expr = Const c; body = Var var' ; _ } -> + assert(Variable.equal var var'); + (* This must be true since var is the only variable in scope *) + Some (Flambda.Const c) + | Let { var; defining_expr = Symbol s; body = Var var' ; _ } -> + assert(Variable.equal var var'); + Some (Flambda.Symbol s) + | _ -> + None + +let rec loop (program : Flambda.program_body) : Flambda.program_body = + match program with + | Initialize_symbol (symbol, tag, fields, program) -> + let constant_fields = List.map constant_field fields in + begin + match Misc.Stdlib.List.some_if_all_elements_are_some constant_fields + with + | None -> + Initialize_symbol (symbol, tag, fields, loop program) + | Some fields -> + Let_symbol (symbol, Block (tag, fields), loop program) + end + | Let_symbol (symbol, const, program) -> + Let_symbol (symbol, const, loop program) + | Let_rec_symbol (defs, program) -> + Let_rec_symbol (defs, loop program) + | Effect (expr, program) -> + Effect (expr, loop program) + | End symbol -> + End symbol + +let run (program : Flambda.program) = + { program with + program_body = loop program.program_body; + } diff --git a/middle_end/initialize_symbol_to_let_symbol.mli b/middle_end/initialize_symbol_to_let_symbol.mli new file mode 100644 index 00000000..c431156b --- /dev/null +++ b/middle_end/initialize_symbol_to_let_symbol.mli @@ -0,0 +1,21 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Transform Initialize_symbol with only constant fields to + let_symbol construction. *) +val run : Flambda.program -> Flambda.program diff --git a/middle_end/inline_and_simplify.ml b/middle_end/inline_and_simplify.ml new file mode 100644 index 00000000..1ce8fe2b --- /dev/null +++ b/middle_end/inline_and_simplify.ml @@ -0,0 +1,1595 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module B = Inlining_cost.Benefit +module E = Inline_and_simplify_aux.Env +module R = Inline_and_simplify_aux.Result + +(** Values of two types hold the information propagated during simplification: + - [E.t] "environments", top-down, almost always called "env"; + - [R.t] "results", bottom-up approximately following the evaluation order, + almost always called "r". These results come along with rewritten + Flambda terms. + The environments map variables to approximations, which enable various + simplifications to be performed; for example, some variable may be known + to always hold a particular constant. +*) + +let ret = R.set_approx + +type simplify_variable_result = + | No_binding of Variable.t + | Binding of Variable.t * (Flambda.named Flambda.With_free_variables.t) + +let simplify_free_variable_internal env original_var = + let var = Freshening.apply_variable (E.freshening env) original_var in + let original_var = var in + (* In the case where an approximation is useful, we introduce a [let] + to bind (e.g.) the constant or symbol replacing [var], unless this + would introduce a useless [let] as a consequence of [var] already being + in the current scope. + + Even when the approximation is not useful, this simplification helps. + In particular, it squashes aliases of the form: + let var1 = var2 in ... var2 ... + by replacing [var2] in the body with [var1]. Simplification can then + eliminate the [let]. + *) + let var = + let approx = E.find_exn env var in + match approx.var with + | Some var when E.mem env var -> var + | Some _ | None -> var + in + (* CR-soon mshinwell: Should we update [r] when we *add* code? + Aside from that, it looks like maybe we don't need [r] in this function, + because the approximation within it wouldn't be used by any of the + call sites. *) + match E.find_with_scope_exn env var with + | Current, approx -> No_binding var, approx (* avoid useless [let] *) + | Outer, approx -> + match A.simplify_var approx with + | None -> No_binding var, approx + | Some (named, approx) -> + let module W = Flambda.With_free_variables in + Binding (original_var, W.of_named named), approx + +let simplify_free_variable env var ~f : Flambda.t * R.t = + match simplify_free_variable_internal env var with + | No_binding var, approx -> f env var approx + | Binding (var, named), approx -> + let module W = Flambda.With_free_variables in + let var = Variable.rename var in + let env = E.add env var approx in + let body, r = f env var approx in + (W.create_let_reusing_defining_expr var named body), r + +let simplify_free_variables env vars ~f : Flambda.t * R.t = + let rec collect_bindings vars env bound_vars approxs : Flambda.t * R.t = + match vars with + | [] -> f env (List.rev bound_vars) (List.rev approxs) + | var::vars -> + match simplify_free_variable_internal env var with + | No_binding var, approx -> + collect_bindings vars env (var::bound_vars) (approx::approxs) + | Binding (var, named), approx -> + let module W = Flambda.With_free_variables in + let var = Variable.rename var in + let env = E.add env var approx in + let body, r = + collect_bindings vars env (var::bound_vars) (approx::approxs) + in + (W.create_let_reusing_defining_expr var named body), r + in + collect_bindings vars env [] [] + +let simplify_free_variables_named env vars ~f : Flambda.named * R.t = + let rec collect_bindings vars env bound_vars approxs + : Flambda.maybe_named * R.t = + match vars with + | [] -> + let named, r = f env (List.rev bound_vars) (List.rev approxs) in + Is_named named, r + | var::vars -> + match simplify_free_variable_internal env var with + | No_binding var, approx -> + collect_bindings vars env (var::bound_vars) (approx::approxs) + | Binding (var, named), approx -> + let module W = Flambda.With_free_variables in + let var = Variable.rename var in + let env = E.add env var approx in + let body, r = + collect_bindings vars env (var::bound_vars) (approx::approxs) + in + let body = + match body with + | Is_named body -> Flambda_utils.name_expr body ~name:"simplify_fv" + | Is_expr body -> body + in + Is_expr (W.create_let_reusing_defining_expr var named body), r + in + let named_or_expr, r = collect_bindings vars env [] [] in + match named_or_expr with + | Is_named named -> named, r + | Is_expr expr -> Expr expr, r + +(* CR-soon mshinwell: tidy this up *) +let simplify_free_variable_named env var ~f : Flambda.named * R.t = + simplify_free_variables_named env [var] ~f:(fun env vars vars_approxs -> + match vars, vars_approxs with + | [var], [approx] -> f env var approx + | _ -> assert false) + +let simplify_named_using_approx r lam approx = + let lam, _summary, approx = A.simplify_named approx lam in + lam, R.set_approx r approx + +let simplify_using_approx_and_env env r original_lam approx = + let lam, summary, approx = + A.simplify_using_env approx ~is_present_in_env:(E.mem env) original_lam + in + let r = + let r = ret r approx in + match summary with + (* CR-soon mshinwell: Why is [r] not updated with the cost of adding the + new code? + mshinwell: similar to CR above *) + | Replaced_term -> R.map_benefit r (B.remove_code original_lam) + | Nothing_done -> r + in + lam, r + +let simplify_named_using_approx_and_env env r original_named approx = + let named, summary, approx = + A.simplify_named_using_env approx ~is_present_in_env:(E.mem env) + original_named + in + let r = + let r = ret r approx in + match summary with + | Replaced_term -> R.map_benefit r (B.remove_code_named original_named) + | Nothing_done -> r + in + named, r + +let simplify_const (const : Flambda.const) = + match const with + | Int i -> A.value_int i + | Char c -> A.value_char c + | Const_pointer i -> A.value_constptr i + +let approx_for_allocated_const (const : Allocated_const.t) = + match const with + | String s -> A.value_string (String.length s) None + | Immutable_string s -> A.value_string (String.length s) (Some s) + | Int32 i -> A.value_boxed_int Int32 i + | Int64 i -> A.value_boxed_int Int64 i + | Nativeint i -> A.value_boxed_int Nativeint i + | Float f -> A.value_float f + | Float_array a -> A.value_mutable_float_array ~size:(List.length a) + | Immutable_float_array a -> + A.value_immutable_float_array + (Array.map (fun x -> Some x) (Array.of_list a)) + +(* Determine whether a given closure ID corresponds directly to a variable + (bound to a closure) in the given environment. This happens when the body + of a [let rec]-bound function refers to another in the same set of closures. + If we succeed in this process, we can change [Project_closure] + expressions into [Var] expressions, thus sharing closure projections. *) +let reference_recursive_function_directly env closure_id = + let closure_id = Closure_id.unwrap closure_id in + match E.find_opt env closure_id with + | None -> None + | Some approx -> Some (Flambda.Expr (Var closure_id), approx) + +(* Simplify an expression that takes a set of closures and projects an + individual closure from it. *) +let simplify_project_closure env r ~(project_closure : Flambda.project_closure) + : Flambda.named * R.t = + simplify_free_variable_named env project_closure.set_of_closures + ~f:(fun _env set_of_closures set_of_closures_approx -> + match A.check_approx_for_set_of_closures set_of_closures_approx with + | Wrong -> + Misc.fatal_errorf "Wrong approximation when projecting closure: %a" + Flambda.print_project_closure project_closure + | Unresolved symbol -> + (* 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) + | Unknown -> + (* CR-soon mshinwell: see CR comment in e.g. simple_value_approx.ml + [check_approx_for_closure_allowing_unresolved] *) + Project_closure { + set_of_closures; + closure_id = project_closure.closure_id; + }, ret r (A.value_unknown Other) + | Unknown_because_of_unresolved_symbol symbol -> + Project_closure { + set_of_closures; + closure_id = project_closure.closure_id; + }, ret r (A.value_unknown (Unresolved_symbol symbol)) + | Ok (set_of_closures_var, value_set_of_closures) -> + let closure_id = + A.freshen_and_check_closure_id value_set_of_closures + project_closure.closure_id + in + let projecting_from = + match set_of_closures_var with + | None -> None + | Some set_of_closures_var -> + let projection : Projection.t = + Project_closure { + set_of_closures = set_of_closures_var; + closure_id; + } + in + match E.find_projection env ~projection with + | None -> None + | Some var -> Some (var, projection) + in + match projecting_from with + | Some (var, projection) -> + simplify_free_variable_named env var ~f:(fun _env var var_approx -> + let r = R.map_benefit r (B.remove_projection projection) in + Expr (Var var), ret r var_approx) + | None -> + match reference_recursive_function_directly env closure_id with + | Some (flam, approx) -> flam, ret r approx + | None -> + let set_of_closures_var = + match set_of_closures_var with + | Some set_of_closures_var' when E.mem env set_of_closures_var' -> + set_of_closures_var + | Some _ | None -> None + in + let approx = + A.value_closure ?set_of_closures_var value_set_of_closures + closure_id + in + Project_closure { set_of_closures; closure_id; }, ret r approx) + +(* Simplify an expression that, given one closure within some set of + closures, returns another closure (possibly the same one) within the + same set. *) +let simplify_move_within_set_of_closures env r + ~(move_within_set_of_closures : Flambda.move_within_set_of_closures) + : Flambda.named * R.t = + simplify_free_variable_named env move_within_set_of_closures.closure + ~f:(fun _env closure closure_approx -> + match A.check_approx_for_closure_allowing_unresolved closure_approx with + | Wrong -> + Misc.fatal_errorf "Wrong approximation when moving within set of \ + closures. Approximation: %a Term: %a" + A.print closure_approx + Flambda.print_move_within_set_of_closures move_within_set_of_closures + | Unresolved sym -> + Move_within_set_of_closures { + closure; + start_from = move_within_set_of_closures.start_from; + move_to = move_within_set_of_closures.move_to; + }, + ret r (A.value_unresolved sym) + | Unknown -> + Move_within_set_of_closures { + closure; + start_from = move_within_set_of_closures.start_from; + move_to = move_within_set_of_closures.move_to; + }, + ret r (A.value_unknown Other) + | Unknown_because_of_unresolved_symbol sym -> + (* For example: a move upon a (move upon a closure whose .cmx file + is missing). *) + Move_within_set_of_closures { + closure; + 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)) + | Ok (_value_closure, set_of_closures_var, set_of_closures_symbol, + value_set_of_closures) -> + let freshen = + (* CR-soon mshinwell: potentially misleading name---not freshening with + new names, but with previously fresh names *) + A.freshen_and_check_closure_id value_set_of_closures + in + let move_to = freshen move_within_set_of_closures.move_to in + let start_from = freshen move_within_set_of_closures.start_from in + let projection : Projection.t = + Move_within_set_of_closures { + closure; + start_from; + move_to; + } + in + match E.find_projection env ~projection with + | Some var -> + simplify_free_variable_named env var ~f:(fun _env var var_approx -> + let r = R.map_benefit r (B.remove_projection projection) in + Expr (Var var), ret r var_approx) + | None -> + match reference_recursive_function_directly env move_to with + | Some (flam, approx) -> flam, ret r approx + | None -> + if Closure_id.equal start_from move_to then + (* Moving from one closure to itself is a no-op. We can return an + [Var] since we already have a variable bound to the closure. *) + Expr (Var closure), ret r closure_approx + else + match set_of_closures_var with + | Some set_of_closures_var when E.mem env set_of_closures_var -> + (* A variable bound to the set of closures is in scope, + meaning we can rewrite the [Move_within_set_of_closures] to a + [Project_closure]. *) + let project_closure : Flambda.project_closure = + { set_of_closures = set_of_closures_var; + closure_id = move_to; + } + in + let approx = + A.value_closure ~set_of_closures_var value_set_of_closures + move_to + in + Project_closure project_closure, ret r approx + | Some _ | None -> + match set_of_closures_symbol with + | Some set_of_closures_symbol -> + let set_of_closures_var = Variable.create "symbol" in + let project_closure : Flambda.project_closure = + { set_of_closures = set_of_closures_var; + closure_id = move_to; + } + in + let project_closure_var = Variable.create "project_closure" in + let let1 = + Flambda.create_let project_closure_var + (Project_closure project_closure) + (Var project_closure_var) + in + let expr = + Flambda.create_let set_of_closures_var + (Symbol set_of_closures_symbol) + let1 + in + let approx = + A.value_closure ~set_of_closures_var ~set_of_closures_symbol + value_set_of_closures move_to + in + Expr expr, ret r approx + | None -> + (* The set of closures is not available in scope, and we + have no other information by which to simplify the move. *) + let move_within : Flambda.move_within_set_of_closures = + { closure; start_from; move_to; } + in + let approx = A.value_closure value_set_of_closures move_to in + Move_within_set_of_closures move_within, ret r approx) + +(* Transform an expression denoting an access to a variable bound in + a closure. Variables in the closure ([project_var.closure]) may + have been freshened since [expr] was constructed; as such, we + must ensure the same happens to [expr]. The renaming information is + contained within the approximation deduced from [closure] (as + such, that approximation *must* identify which closure it is). + + For instance in some imaginary syntax for flambda: + + [let f x = + let g y ~closure:{a} = a + y in + let closure = { a = x } in + g 12 ~closure] + + when [f] is traversed, [g] can be inlined, resulting in the + expression + + [let f z = + let g y ~closure:{a} = a + y in + let closure = { a = x } in + closure.a + 12] + + [closure.a] being a notation for: + + [Project_var{closure = closure; closure_id = g; var = a}] + + If [f] is inlined later, the resulting code will be + + [let x = ... in + let g' y' ~closure':{a'} = a' + y' in + let closure' = { a' = x } in + closure'.a' + 12] + + in particular the field [a] of the closure has been alpha renamed to [a']. + This information must be carried from the declaration to the use. + + If the function is declared outside of the alpha renamed part, there is + no need for renaming in the [Ffunction] and [Project_var]. + This is not usualy the case, except when the closure declaration is a + symbol. + + What ensures that this information is available at [Project_var] + point is that those constructions can only be introduced by inlining, + which requires that same information. For this to still be valid, + other transformation must avoid transforming the information flow in + a way that the inline function can't propagate it. +*) +let rec simplify_project_var env r ~(project_var : Flambda.project_var) + : Flambda.named * R.t = + simplify_free_variable_named env project_var.closure + ~f:(fun _env closure approx -> + match A.check_approx_for_closure_allowing_unresolved approx with + | Ok (value_closure, _set_of_closures_var, _set_of_closures_symbol, + value_set_of_closures) -> + let module F = Freshening.Project_var in + let freshening = value_set_of_closures.freshening in + let var = F.apply_var_within_closure freshening project_var.var in + let closure_id = F.apply_closure_id freshening project_var.closure_id in + let closure_id_in_approx = value_closure.closure_id in + if not (Closure_id.equal closure_id closure_id_in_approx) then begin + Misc.fatal_errorf "When simplifying [Project_var], the closure ID %a \ + in the approximation of the set of closures did not match the \ + closure ID %a in the [Project_var] term. Approximation: %a@. \ + Var-within-closure being projected: %a@." + Closure_id.print closure_id_in_approx + Closure_id.print closure_id + Simple_value_approx.print approx + Var_within_closure.print var + end; + let projection : Projection.t = + Project_var { + closure; + closure_id; + var; + } + in + begin match E.find_projection env ~projection with + | Some var -> + simplify_free_variable_named env var ~f:(fun _env var var_approx -> + let r = R.map_benefit r (B.remove_projection projection) in + Expr (Var var), ret r var_approx) + | None -> + let approx = A.approx_for_bound_var value_set_of_closures var in + let expr : Flambda.named = Project_var { closure; closure_id; var; } in + let unwrapped = Var_within_closure.unwrap var in + let expr = + if E.mem env unwrapped then + Flambda.Expr (Var unwrapped) + else + expr + in + simplify_named_using_approx_and_env env r expr approx + end + | Unresolved symbol -> + (* This value comes from a symbol for which we couldn't find any + approximation, telling us that names within the closure couldn't + have been renamed. So we don't need to change the variable or + closure ID in the [Project_var] expression. *) + Project_var { project_var with closure }, + ret r (A.value_unresolved symbol) + | Unknown -> + Project_var { project_var with closure }, + ret r (A.value_unknown Other) + | Unknown_because_of_unresolved_symbol symbol -> + Project_var { project_var with closure }, + ret r (A.value_unknown (Unresolved_symbol symbol)) + | Wrong -> + (* We must have the correct approximation of the value to ensure + we take account of all freshenings. *) + Misc.fatal_errorf "[Project_var] from a value with wrong \ + approximation: %a@.closure=%a@.approx of closure=%a@." + Flambda.print_project_var project_var + Variable.print closure + Simple_value_approx.print approx) + +(* Transforms closure definitions by applying [loop] on the code of every + one of the set and on the expressions of the free variables. + If the substitution is activated, alpha renaming also occur on everything + defined by the set of closures: + * Variables bound by a closure of the set + * closure identifiers + * parameters + + The rewriting occurs in a clean environment without any of the variables + defined outside reachable. This helps increase robustness against + accidental, potentially unsound simplification of variable accesses by + [simplify_using_approx_and_env]. + + The rewriting occurs in an environment filled with: + * The approximation of the free variables + * An explicitely unknown approximation for function parameters, + except for those where it is known to be safe: those present in the + [specialised_args] set. + * An approximation for the closures in the set. It contains the code of + the functions before rewriting. + + The approximation of the currently defined closures is available to + allow marking recursives calls as direct and in some cases, allow + inlining of one closure from the set inside another one. For this to + be correct an alpha renaming is first applied on the expressions by + [apply_function_decls_and_free_vars]. + + For instance when rewriting the declaration + + [let rec f_1 x_1 = + let y_1 = x_1 + 1 in + g_1 y_1 + and g_1 z_1 = f_1 (f_1 z_1)] + + When rewriting this function, the first substitution will contain + some mapping: + { f_1 -> f_2; + g_1 -> g_2; + x_1 -> x_2; + z_1 -> z_2 } + + And the approximation for the closure will contain + + { f_2: + fun x_2 -> + let y_1 = x_2 + 1 in + g_2 y_1 + g_2: + fun z_2 -> f_2 (f_2 z_2) } + + Note that no substitution is applied to the let-bound variable [y_1]. + If [f_2] where to be inlined inside [g_2], we known that a new substitution + will be introduced in the current scope for [y_1] each time. + + + If the function where a recursive one comming from another compilation + unit, the code already went through [Flambdasym] that could have + replaced the function variable by the symbol identifying the function + (this occur if the function contains only constants in its closure). + To handle that case, we first replace those symbols by the original + variable. +*) +and simplify_set_of_closures original_env r + (set_of_closures : Flambda.set_of_closures) + : Flambda.set_of_closures * R.t * Freshening.Project_var.t = + let function_decls = + let module Backend = (val (E.backend original_env) : Backend_intf.S) in + (* CR-soon mshinwell: Does this affect + [reference_recursive_function_directly]? + mshinwell: This should be thought about as part of the wider issue of + references to functions via symbols or variables. *) + Freshening.rewrite_recursive_calls_with_symbols (E.freshening original_env) + set_of_closures.function_decls + ~make_closure_symbol:Backend.closure_symbol + in + let env = E.increase_closure_depth original_env in + let free_vars, specialised_args, function_decls, parameter_approximations, + internal_value_set_of_closures, set_of_closures_env = + Inline_and_simplify_aux.prepare_to_simplify_set_of_closures ~env + ~set_of_closures ~function_decls ~only_for_function_decl:None + ~freshen:true + in + let simplify_function fun_var (function_decl : Flambda.function_declaration) + (funs, used_params, r) + : Flambda.function_declaration Variable.Map.t * Variable.Set.t * R.t = + let closure_env = + Inline_and_simplify_aux.prepare_to_simplify_closure ~function_decl + ~free_vars ~specialised_args ~parameter_approximations + ~set_of_closures_env + in + let body, r = + E.enter_closure closure_env ~closure_id:(Closure_id.wrap fun_var) + ~inline_inside: + (Inlining_decision.should_inline_inside_declaration function_decl) + ~debuginfo:function_decl.dbg + ~f:(fun body_env -> simplify body_env r function_decl.body) + in + let inline : Lambda.inline_attribute = + match function_decl.inline with + | Default_inline -> + if !Clflags.classic_inlining && not function_decl.stub then + (* In classic-inlining mode, the inlining decision is taken at + definition site (here). If the function is small enough + (below the -inline threshold) it will always be inlined. *) + let inlining_threshold = + Inline_and_simplify_aux.initial_inlining_threshold + ~round:(E.round env) + in + if Inlining_cost.can_inline body inlining_threshold ~bonus:0 + then + Always_inline + else + Default_inline + else + Default_inline + | inline -> + inline + in + let function_decl = + Flambda.create_function_declaration ~params:function_decl.params + ~body ~stub:function_decl.stub ~dbg:function_decl.dbg + ~inline ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + in + let used_params' = Flambda.used_params function_decl in + Variable.Map.add fun_var function_decl funs, + Variable.Set.union used_params used_params', r + in + let funs, _used_params, r = + Variable.Map.fold simplify_function function_decls.funs + (Variable.Map.empty, Variable.Set.empty, r) + in + let function_decls = + Flambda.update_function_declarations function_decls ~funs + in + let invariant_params = + lazy (Invariant_params.invariant_params_in_recursion function_decls + ~backend:(E.backend env)) + in + let value_set_of_closures = + A.create_value_set_of_closures ~function_decls + ~bound_vars:internal_value_set_of_closures.bound_vars + ~invariant_params + ~specialised_args:internal_value_set_of_closures.specialised_args + ~freshening:internal_value_set_of_closures.freshening + ~direct_call_surrogates: + internal_value_set_of_closures.direct_call_surrogates + in + let direct_call_surrogates = + Closure_id.Map.fold (fun existing surrogate surrogates -> + Variable.Map.add (Closure_id.unwrap existing) + (Closure_id.unwrap surrogate) surrogates) + internal_value_set_of_closures.direct_call_surrogates + Variable.Map.empty + in + let set_of_closures = + Flambda.create_set_of_closures ~function_decls + ~free_vars:(Variable.Map.map fst free_vars) + ~specialised_args + ~direct_call_surrogates + in + let r = ret r (A.value_set_of_closures value_set_of_closures) in + set_of_closures, r, value_set_of_closures.freshening + +and simplify_apply env r ~(apply : Flambda.apply) : Flambda.t * R.t = + let { + Flambda. func = lhs_of_application; args; kind = _; dbg; + inline = inline_requested; specialise = specialise_requested; + } = apply in + simplify_free_variable env lhs_of_application + ~f:(fun env lhs_of_application lhs_of_application_approx -> + simplify_free_variables env args ~f:(fun env args args_approxs -> + (* By using the approximation of the left-hand side of the + application, attempt to determine which function is being applied + (even if the application is currently [Indirect]). If + successful---in which case we then have a direct + application---consider inlining. *) + match A.check_approx_for_closure lhs_of_application_approx with + | Ok (value_closure, set_of_closures_var, + set_of_closures_symbol, value_set_of_closures) -> + let lhs_of_application, closure_id_being_applied, + value_set_of_closures, env, wrap = + let closure_id_being_applied = value_closure.closure_id in + (* If the call site is a direct call to a function that has a + "direct call surrogate" (see inline_and_simplify_aux.mli), + repoint the call to the surrogate. *) + let surrogates = value_set_of_closures.direct_call_surrogates in + match Closure_id.Map.find closure_id_being_applied surrogates with + | exception Not_found -> + lhs_of_application, closure_id_being_applied, + value_set_of_closures, env, (fun expr -> expr) + | surrogate -> + let rec find_transitively surrogate = + match Closure_id.Map.find surrogate surrogates with + | exception Not_found -> surrogate + | surrogate -> find_transitively surrogate + in + let surrogate = find_transitively surrogate in + let surrogate_var = + Variable.rename lhs_of_application ~append:"_surrogate" + in + let move_to_surrogate : Projection.move_within_set_of_closures = + { closure = lhs_of_application; + start_from = closure_id_being_applied; + move_to = surrogate; + } + in + let approx_for_surrogate = + A.value_closure ~closure_var:surrogate_var + ?set_of_closures_var ?set_of_closures_symbol + value_set_of_closures surrogate + in + let env = E.add env surrogate_var approx_for_surrogate in + let wrap expr = + Flambda.create_let surrogate_var + (Move_within_set_of_closures move_to_surrogate) + expr + in + surrogate_var, surrogate, value_set_of_closures, env, wrap + in + let function_decls = value_set_of_closures.function_decls in + let function_decl = + try + Flambda_utils.find_declaration closure_id_being_applied + function_decls + with + | Not_found -> + Misc.fatal_errorf "When handling application expression, \ + approximation references non-existent closure %a@." + Closure_id.print closure_id_being_applied + in + let r = + match apply.kind with + | Indirect -> + R.map_benefit r Inlining_cost.Benefit.direct_call_of_indirect + | Direct _ -> r + in + let nargs = List.length args in + let arity = Flambda_utils.function_arity function_decl in + let result, r = + if nargs = arity then + simplify_full_application env r ~function_decls + ~lhs_of_application ~closure_id_being_applied ~function_decl + ~value_set_of_closures ~args ~args_approxs ~dbg + ~inline_requested ~specialise_requested + else if nargs > arity then + simplify_over_application env r ~args ~args_approxs + ~function_decls ~lhs_of_application ~closure_id_being_applied + ~function_decl ~value_set_of_closures ~dbg ~inline_requested + ~specialise_requested + else if nargs > 0 && nargs < arity then + simplify_partial_application env r ~lhs_of_application + ~closure_id_being_applied ~function_decl ~args ~dbg + ~inline_requested ~specialise_requested + else + Misc.fatal_errorf "Function with arity %d when simplifying \ + application expression: %a" + arity Flambda.print (Flambda.Apply apply) + in + wrap result, r + | Wrong -> (* Insufficient approximation information to simplify. *) + Apply ({ func = lhs_of_application; args; kind = Indirect; dbg; + inline = inline_requested; specialise = specialise_requested; }), + ret r (A.value_unknown Other))) + +and simplify_full_application env r ~function_decls ~lhs_of_application + ~closure_id_being_applied ~function_decl ~value_set_of_closures ~args + ~args_approxs ~dbg ~inline_requested ~specialise_requested = + Inlining_decision.for_call_site ~env ~r ~function_decls + ~lhs_of_application ~closure_id_being_applied ~function_decl + ~value_set_of_closures ~args ~args_approxs ~dbg ~simplify + ~inline_requested ~specialise_requested + +and simplify_partial_application env r ~lhs_of_application + ~closure_id_being_applied ~function_decl ~args ~dbg + ~inline_requested ~specialise_requested = + let arity = Flambda_utils.function_arity function_decl in + assert (arity > List.length args); + (* For simplicity, we disallow [@inline] attributes on partial + applications. The user may always write an explicit wrapper instead + with such an attribute. *) + (* CR-someday mshinwell: Pierre noted that we might like a function to be + inlined when applied to its first set of arguments, e.g. for some kind + of type class like thing. *) + begin match (inline_requested : Lambda.inline_attribute) with + | Always_inline | Never_inline -> + Location.prerr_warning (Debuginfo.to_location dbg) + (Warnings.Inlining_impossible "[@inlined] attributes may not be used \ + on partial applications") + | Unroll _ -> + Location.prerr_warning (Debuginfo.to_location dbg) + (Warnings.Inlining_impossible "[@unroll] attributes may not be used \ + on partial applications") + | Default_inline -> () + end; + begin match (specialise_requested : Lambda.specialise_attribute) with + | Always_specialise | Never_specialise -> + Location.prerr_warning (Debuginfo.to_location dbg) + (Warnings.Inlining_impossible "[@specialised] attributes may not be used \ + on partial applications") + | Default_specialise -> () + end; + let freshened_params = + List.map (fun id -> Variable.rename id) function_decl.Flambda.params + in + let applied_args, remaining_args = + Misc.Stdlib.List.map2_prefix (fun arg id' -> id', arg) + args freshened_params + in + let wrapper_accepting_remaining_args = + let body : Flambda.t = + Apply { + func = lhs_of_application; + args = freshened_params; + kind = Direct closure_id_being_applied; + dbg; + inline = Default_inline; + specialise = Default_specialise; + } + in + let closure_variable = + Variable.rename + ~append:"_partial_fun" + (Closure_id.unwrap closure_id_being_applied) + in + Flambda_utils.make_closure_declaration ~id:closure_variable + ~body + ~params:remaining_args + ~stub:true + in + let with_known_args = + Flambda_utils.bind + ~bindings:(List.map (fun (var, arg) -> + var, Flambda.Expr (Var arg)) applied_args) + ~body:wrapper_accepting_remaining_args + in + simplify env r with_known_args + +and simplify_over_application env r ~args ~args_approxs ~function_decls + ~lhs_of_application ~closure_id_being_applied ~function_decl + ~value_set_of_closures ~dbg ~inline_requested ~specialise_requested = + let arity = Flambda_utils.function_arity function_decl in + assert (arity < List.length args); + assert (List.length args = List.length args_approxs); + let full_app_args, remaining_args = + Misc.Stdlib.List.split_at arity args + in + let full_app_approxs, _ = + Misc.Stdlib.List.split_at arity args_approxs + in + let expr, r = + simplify_full_application env r ~function_decls ~lhs_of_application + ~closure_id_being_applied ~function_decl ~value_set_of_closures + ~args:full_app_args ~args_approxs:full_app_approxs ~dbg + ~inline_requested ~specialise_requested + in + let func_var = Variable.create "full_apply" in + let expr : Flambda.t = + Flambda.create_let func_var (Expr expr) + (Apply { func = func_var; args = remaining_args; kind = Indirect; dbg; + inline = inline_requested; specialise = specialise_requested; }) + in + let expr = Lift_code.lift_lets_expr expr ~toplevel:true in + simplify (E.set_never_inline env) r expr + +and simplify_named env r (tree : Flambda.named) : Flambda.named * R.t = + match tree with + | Symbol sym -> + (* New Symbol construction could have been introduced during + transformation (by simplify_named_using_approx_and_env). + When this comes from another compilation unit, we must load it. *) + let approx = E.find_or_load_symbol env sym in + simplify_named_using_approx r tree approx + | Const cst -> tree, ret r (simplify_const cst) + | Allocated_const cst -> tree, ret r (approx_for_allocated_const cst) + | Read_mutable mut_var -> + (* See comment on the [Assign] case. *) + let mut_var = + Freshening.apply_mutable_variable (E.freshening env) mut_var + in + Read_mutable mut_var, ret r (A.value_unknown Other) + | Read_symbol_field (symbol, field_index) -> + let approx = E.find_or_load_symbol env symbol in + begin match A.get_field approx ~field_index with + (* CR-someday mshinwell: Think about [Unreachable] vs. [Value_bottom]. *) + | Unreachable -> (Flambda.Expr Proved_unreachable), r + | Ok approx -> + let approx = A.augment_with_symbol_field approx symbol field_index in + simplify_named_using_approx_and_env env r tree approx + end + | Set_of_closures set_of_closures -> begin + let backend = E.backend env in + let set_of_closures, r, first_freshening = + simplify_set_of_closures env r set_of_closures + in + let simplify env r expr ~pass_name : Flambda.named * R.t = + (* If simplifying a set of closures more than once during any given round + of simplification, the [Freshening.Project_var] substitutions arising + from each call to [simplify_set_of_closures] must be composed. + Note that this function only composes with [first_freshening] owing + to the structure of the code below (this new [simplify] is always + in tail position). *) + (* CR-someday mshinwell: It was mooted that maybe we could try + structurally-typed closures (i.e. where we would never rename the + closure elements), or something else, to try to remove + the "closure freshening" thing in the approximation which is hard + to deal with. *) + let expr, r = simplify (E.set_never_inline env) r expr in + let approx = R.approx r in + let value_set_of_closures = + match A.strict_check_approx_for_set_of_closures approx with + | Wrong -> + Misc.fatal_errorf "Unexpected approximation returned from \ + simplification of [%s] result: %a" + pass_name A.print approx + | Ok (_var, value_set_of_closures) -> + let freshening = + Freshening.Project_var.compose ~earlier:first_freshening + ~later:value_set_of_closures.freshening + in + A.update_freshening_of_value_set_of_closures value_set_of_closures + ~freshening + in + Expr expr, (ret r (A.value_set_of_closures value_set_of_closures)) + in + (* This does the actual substitutions of specialised args introduced + by [Unbox_closures] for free variables. (Apart from simplifying + the [Unbox_closures] output, this also prevents applying + [Unbox_closures] over and over.) *) + let set_of_closures = + match Remove_free_vars_equal_to_args.run set_of_closures with + | None -> set_of_closures + | Some set_of_closures -> set_of_closures + in + (* Do [Unbox_closures] next to try to decide which things are + free variables and which things are specialised arguments before + unboxing them. *) + match + Unbox_closures.rewrite_set_of_closures ~env + ~duplicate_function ~set_of_closures + with + | Some (expr, benefit) -> + let r = R.add_benefit r benefit in + simplify env r expr ~pass_name:"Unbox_closures" + | None -> + match Unbox_free_vars_of_closures.run ~env ~set_of_closures with + | Some (expr, benefit) -> + let r = R.add_benefit r benefit in + simplify env r expr ~pass_name:"Unbox_free_vars_of_closures" + | None -> + (* CR-soon mshinwell: should maybe add one allocation for the stub *) + match + Unbox_specialised_args.rewrite_set_of_closures ~env + ~duplicate_function ~set_of_closures + with + | Some (expr, benefit) -> + let r = R.add_benefit r benefit in + simplify env r expr ~pass_name:"Unbox_specialised_args" + | None -> + match + Remove_unused_arguments. + separate_unused_arguments_in_set_of_closures + set_of_closures ~backend + with + | Some set_of_closures -> + let expr = + Flambda_utils.name_expr (Set_of_closures set_of_closures) + ~name:"remove_unused_arguments" + in + simplify env r expr ~pass_name:"Remove_unused_arguments" + | None -> + Set_of_closures set_of_closures, r + end + | Project_closure project_closure -> + simplify_project_closure env r ~project_closure + | Project_var project_var -> simplify_project_var env r ~project_var + | Move_within_set_of_closures move_within_set_of_closures -> + simplify_move_within_set_of_closures env r ~move_within_set_of_closures + | Prim (prim, args, dbg) -> + simplify_free_variables_named env args ~f:(fun env args args_approxs -> + let tree = Flambda.Prim (prim, args, dbg) in + begin match prim, args, args_approxs with + | Pgetglobal _, _, _ -> + Misc.fatal_error "Pgetglobal is forbidden in Inline_and_simplify" + | Pfield field_index, [arg], [arg_approx] -> + let projection : Projection.t = Field (field_index, arg) in + begin match E.find_projection env ~projection with + | Some var -> + simplify_free_variable_named env var ~f:(fun _env var var_approx -> + let r = R.map_benefit r (B.remove_projection projection) in + Expr (Var var), ret r var_approx) + | None -> + begin match A.get_field arg_approx ~field_index with + | Unreachable -> (Flambda.Expr Proved_unreachable, r) + | Ok approx -> + let tree, approx = + match arg_approx.symbol with + (* If the [Pfield] is projecting directly from a symbol, rewrite + the expression to [Read_symbol_field]. *) + | Some (symbol, None) -> + let approx = + A.augment_with_symbol_field approx symbol field_index + in + Flambda.Read_symbol_field (symbol, field_index), approx + | None | Some (_, Some _ ) -> + (* This [Pfield] is either not projecting from a symbol at all, + or it is the projection of a projection from a symbol. *) + let module Backend = (val (E.backend env) : Backend_intf.S) in + let approx' = Backend.really_import_approx approx in + tree, approx' + in + simplify_named_using_approx_and_env env r tree approx + end + end + | Pfield _, _, _ -> Misc.fatal_error "Pfield arity error" + | (Psetfield _ | Parraysetu _ | Parraysets _), + _block::_, block_approx::_ -> + if A.is_definitely_immutable block_approx then begin + Location.prerr_warning (Debuginfo.to_location dbg) + Warnings.Assignment_to_non_mutable_value + end; + tree, ret r (A.value_unknown Other) + | (Psetfield _ | Parraysetu _ | Parraysets _), _, _ -> + Misc.fatal_error "Psetfield / Parraysetu / Parraysets arity error" + | (Psequand | Psequor), _, _ -> + Misc.fatal_error "Psequand and Psequor must be expanded (see handling \ + in closure_conversion.ml)" + | p, args, args_approxs -> + let expr, approx, benefit = + let module Backend = (val (E.backend env) : Backend_intf.S) in + Simplify_primitives.primitive p (args, args_approxs) tree dbg + ~size_int:Backend.size_int ~big_endian:Backend.big_endian + in + let r = R.map_benefit r (B.(+) benefit) in + let approx = + match p with + | Popaque -> A.value_unknown Other + | _ -> approx + in + expr, ret r approx + end) + | Expr expr -> + let expr, r = simplify env r expr in + Expr expr, r + +and simplify env r (tree : Flambda.t) : Flambda.t * R.t = + match tree with + | Var var -> + let var = Freshening.apply_variable (E.freshening env) var in + (* If from the approximations we can simplify [var], then we will be + forced to insert [let]-expressions (done using [name_expr], in + [Simple_value_approx]) to bind a [named]. This has an important + consequence: it brings bindings of constants closer to their use + points. *) + simplify_using_approx_and_env env r (Var var) (E.find_exn env var) + | Apply apply -> + simplify_apply env r ~apply + | Let _ -> + let for_defining_expr (env, r) var defining_expr = + let defining_expr, r = simplify_named env r defining_expr in + let var, sb = Freshening.add_variable (E.freshening env) var in + let env = E.set_freshening env sb in + let env = E.add env var (R.approx r) in + (env, r), var, defining_expr + in + let for_last_body (env, r) body = + simplify env r body + in + let filter_defining_expr r var defining_expr free_vars_of_body = + if Variable.Set.mem var free_vars_of_body then + r, var, Some defining_expr + else if Effect_analysis.no_effects_named defining_expr then + let r = R.map_benefit r (B.remove_code_named defining_expr) in + r, var, None + else + r, var, Some defining_expr + in + Flambda.fold_lets_option tree + ~init:(env, r) + ~for_defining_expr + ~for_last_body + ~filter_defining_expr + | Let_mutable (mut_var, var, body) -> + (* CR-someday mshinwell: add the dead let elimination, as above. *) + simplify_free_variable env var ~f:(fun env var _var_approx -> + let mut_var, sb = + Freshening.add_mutable_variable (E.freshening env) mut_var + in + let env = E.set_freshening env sb in + let body, r = + simplify (E.add_mutable env mut_var (A.value_unknown Other)) r body + in + Flambda.Let_mutable (mut_var, var, body), r) + | Let_rec (defs, body) -> + let defs, sb = Freshening.add_variables (E.freshening env) defs in + let env = E.set_freshening env sb in + let def_env = + List.fold_left (fun env_acc (id, _lam) -> + E.add env_acc id (A.value_unknown Other)) + env defs + in + let defs, body_env, r = + List.fold_right (fun (id, lam) (defs, env_acc, r) -> + let lam, r = simplify_named def_env r lam in + let defs = (id, lam) :: defs in + let env_acc = E.add env_acc id (R.approx r) in + defs, env_acc, r) + defs ([], env, r) + in + let body, r = simplify body_env r body in + Let_rec (defs, body), r + | Static_raise (i, args) -> + let i = Freshening.apply_static_exception (E.freshening env) i in + simplify_free_variables env args ~f:(fun _env args _args_approxs -> + let r = R.use_static_exception r i in + Static_raise (i, args), ret r A.value_bottom) + | Static_catch (i, vars, body, handler) -> + begin + match body with + | Let { var; defining_expr = def; body; _ } + when not (Flambda_utils.might_raise_static_exn def i) -> + simplify env r + (Flambda.create_let var def (Static_catch (i, vars, body, handler))) + | _ -> + let i, sb = Freshening.add_static_exception (E.freshening env) i in + let env = E.set_freshening env sb in + let body, r = simplify env r body in + (* CR-soon mshinwell: for robustness, R.used_static_exceptions should + maybe be removed. *) + if not (Static_exception.Set.mem i (R.used_static_exceptions r)) then + (* If the static exception is not used, we can drop the declaration *) + body, r + else begin + match (body : Flambda.t) with + | Static_raise (j, args) -> + assert (Static_exception.equal i j); + let handler = + List.fold_left2 (fun body var arg -> + Flambda.create_let var (Expr (Var arg)) body) + handler vars args + in + let r = R.exit_scope_catch r i in + simplify env r handler + | _ -> + let vars, sb = Freshening.add_variables' (E.freshening env) vars in + let env = + List.fold_left (fun env id -> + E.add env id (A.value_unknown Other)) + (E.set_freshening env sb) vars + in + let env = E.inside_branch env in + let handler, r = simplify env r handler in + let r = R.exit_scope_catch r i in + Static_catch (i, vars, body, handler), + ret r (A.value_unknown Other) + end + end + | Try_with (body, id, handler) -> + let body, r = simplify env r body in + let id, sb = Freshening.add_variable (E.freshening env) id in + let env = E.add (E.set_freshening env sb) id (A.value_unknown Other) in + let env = E.inside_branch env in + let handler, r = simplify env r handler in + Try_with (body, id, handler), ret r (A.value_unknown Other) + | If_then_else (arg, ifso, ifnot) -> + (* When arg is the constant false or true (or something considered + as true), we can drop the if and replace it by a sequence. + if arg is not effectful we can also drop it. *) + simplify_free_variable env arg ~f:(fun env arg arg_approx -> + begin match arg_approx.descr with + | Value_constptr 0 | Value_int 0 -> (* Constant [false]: keep [ifnot] *) + let ifnot, r = simplify env r ifnot in + ifnot, R.map_benefit r B.remove_branch + | Value_constptr _ | Value_int _ + | Value_block _ -> (* Constant [true]: keep [ifso] *) + let ifso, r = simplify env r ifso in + ifso, R.map_benefit r B.remove_branch + | _ -> + let env = E.inside_branch env in + let ifso, r = simplify env r ifso in + let ifso_approx = R.approx r in + let ifnot, r = simplify env r ifnot in + let ifnot_approx = R.approx r in + If_then_else (arg, ifso, ifnot), + ret r (A.meet ifso_approx ifnot_approx) + end) + | While (cond, body) -> + let cond, r = simplify env r cond in + let body, r = simplify env r body in + While (cond, body), ret r (A.value_unknown Other) + | Send { kind; meth; obj; args; dbg; } -> + simplify_free_variable env meth ~f:(fun env meth _meth_approx -> + simplify_free_variable env obj ~f:(fun env obj _obj_approx -> + simplify_free_variables env args ~f:(fun _env args _args_approx -> + Send { kind; meth; obj; args; dbg; }, + ret r (A.value_unknown Other)))) + | For { bound_var; from_value; to_value; direction; body; } -> + simplify_free_variable env from_value ~f:(fun env from_value _approx -> + simplify_free_variable env to_value ~f:(fun env to_value _approx -> + let bound_var, sb = + Freshening.add_variable (E.freshening env) bound_var + in + let env = + E.add (E.set_freshening env sb) bound_var + (A.value_unknown Other) + in + let body, r = simplify env r body in + For { bound_var; from_value; to_value; direction; body; }, + ret r (A.value_unknown Other))) + | Assign { being_assigned; new_value; } -> + (* No need to use something like [simplify_free_variable]: the + approximation of [being_assigned] is always unknown. *) + let being_assigned = + Freshening.apply_mutable_variable (E.freshening env) being_assigned + in + simplify_free_variable env new_value ~f:(fun _env new_value _approx -> + Assign { being_assigned; new_value; }, ret r (A.value_unknown Other)) + | Switch (arg, sw) -> + (* When [arg] is known to be a variable whose approximation is that of a + block with a fixed tag or a fixed integer, we can eliminate the + [Switch]. (This should also make the [Let] that binds [arg] redundant, + meaning that it too can be eliminated.) *) + simplify_free_variable env arg ~f:(fun env arg arg_approx -> + let get_failaction () : Flambda.t = + (* If the switch is applied to a statically-known value that does not + match any case: + * if there is a default action take that case; + * otherwise this is something that is guaranteed not to + be reachable by the type checker. For example: + [type 'a t = Int : int -> int t | Float : float -> float t + match Int 1 with + | Int _ -> ... + | Float f as v -> + match v with <-- This match is unreachable + | Float f -> ...] + *) + match sw.failaction with + | None -> Proved_unreachable + | Some f -> f + in + begin match arg_approx.descr with + | Value_int i + | Value_constptr i -> + let lam = + try List.assoc i sw.consts + with Not_found -> get_failaction () + in + let lam, r = simplify env r lam in + lam, R.map_benefit r B.remove_branch + | Value_block (tag, _) -> + let tag = Tag.to_int tag in + let lam = + try List.assoc tag sw.blocks + with Not_found -> get_failaction () + in + let lam, r = simplify env r lam in + lam, R.map_benefit r B.remove_branch + | _ -> + let env = E.inside_branch env in + let f (i, v) (acc, r) = + let approx = R.approx r in + let lam, r = simplify env r v in + ((i, lam)::acc, R.set_approx r (A.meet (R.approx r) approx)) + in + let r = R.set_approx r A.value_bottom in + let consts, r = List.fold_right f sw.consts ([], r) in + let blocks, r = List.fold_right f sw.blocks ([], r) in + let failaction, r = + match sw.failaction with + | None -> None, r + | Some l -> + let approx = R.approx r in + let l, r = simplify env r l in + Some l, R.set_approx r (A.meet (R.approx r) approx) + in + let sw = { sw with failaction; consts; blocks; } in + Switch (arg, sw), r + end) + | String_switch (arg, sw, def) -> + simplify_free_variable env arg ~f:(fun env arg _arg_approx -> + let sw, r = + List.fold_right (fun (str, lam) (sw, r) -> + let lam, r = simplify env r lam in + (str, lam)::sw, r) + sw + ([], r) + in + let def, r = + match def with + | None -> def, r + | Some def -> + let def, r = simplify env r def in + Some def, r + in + String_switch (arg, sw, def), ret r (A.value_unknown Other)) + | Proved_unreachable -> tree, ret r A.value_bottom + +and simplify_list env r l = + match l with + | [] -> [], [], r + | h::t -> + let t', approxs, r = simplify_list env r t in + let h', r = simplify env r h in + let approxs = (R.approx r) :: approxs in + if t' == t && h' == h + then l, approxs, r + else h' :: t', approxs, r + +and duplicate_function ~env ~(set_of_closures : Flambda.set_of_closures) + ~fun_var = + let function_decl = + match Variable.Map.find fun_var set_of_closures.function_decls.funs with + | exception Not_found -> + Misc.fatal_errorf "duplicate_function: cannot find function %a" + Variable.print fun_var + | function_decl -> function_decl + in + let env = E.activate_freshening (E.set_never_inline env) in + let free_vars, specialised_args, function_decls, parameter_approximations, + _internal_value_set_of_closures, set_of_closures_env = + Inline_and_simplify_aux.prepare_to_simplify_set_of_closures ~env + ~set_of_closures ~function_decls:set_of_closures.function_decls + ~freshen:false ~only_for_function_decl:(Some function_decl) + in + let function_decl = + match Variable.Map.find fun_var function_decls.funs with + | exception Not_found -> + Misc.fatal_errorf "duplicate_function: cannot find function %a (2)" + Variable.print fun_var + | function_decl -> function_decl + in + let closure_env = + Inline_and_simplify_aux.prepare_to_simplify_closure ~function_decl + ~free_vars ~specialised_args ~parameter_approximations + ~set_of_closures_env + in + let body, _r = + E.enter_closure closure_env + ~closure_id:(Closure_id.wrap fun_var) + ~inline_inside:false + ~debuginfo:function_decl.dbg + ~f:(fun body_env -> + simplify body_env (R.create ()) function_decl.body) + in + let function_decl = + Flambda.create_function_declaration ~params:function_decl.params + ~body ~stub:function_decl.stub ~dbg:function_decl.dbg + ~inline:function_decl.inline ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + in + function_decl, specialised_args + +let constant_defining_value_approx + env + (constant_defining_value:Flambda.constant_defining_value) = + match constant_defining_value with + | Allocated_const const -> + approx_for_allocated_const const + | Block (tag, fields) -> + let fields = + List.map + (function + | Flambda.Symbol sym -> begin + match E.find_symbol_opt env sym with + | Some approx -> approx + | None -> A.value_unresolved sym + end + | Flambda.Const cst -> simplify_const cst) + fields + in + A.value_block tag (Array.of_list fields) + | Set_of_closures { function_decls; free_vars; specialised_args } -> + (* At toplevel, there is no freshening currently happening (this + cannot be the body of a currently inlined function), so we can + keep the original set_of_closures in the approximation. *) + assert(E.freshening env = Freshening.empty); + assert(Variable.Map.is_empty free_vars); + assert(Variable.Map.is_empty specialised_args); + let invariant_params = + lazy (Invariant_params.invariant_params_in_recursion function_decls + ~backend:(E.backend env)) + in + let value_set_of_closures = + A.create_value_set_of_closures ~function_decls + ~bound_vars:Var_within_closure.Map.empty + ~invariant_params + ~specialised_args:Variable.Map.empty + ~freshening:Freshening.Project_var.empty + ~direct_call_surrogates:Closure_id.Map.empty + in + A.value_set_of_closures value_set_of_closures + | 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 + | Some set_of_closures_approx -> + let checked_approx = + A.check_approx_for_set_of_closures set_of_closures_approx + in + match checked_approx with + | Ok (_, value_set_of_closures) -> + let closure_id = + A.freshen_and_check_closure_id value_set_of_closures closure_id + in + 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) + | Wrong -> + Misc.fatal_errorf "Wrong approximation for [Project_closure] \ + when being used as a [constant_defining_value]: %a" + Flambda.print_constant_defining_value constant_defining_value + end + +(* See documentation on [Let_rec_symbol] in flambda.mli. *) +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)) + env defs + in + let rec loop times env = + if times <= 0 then + env + else + let env = + List.fold_left (fun env (symbol, constant_defining_value) -> + let approx = + constant_defining_value_approx env constant_defining_value + in + E.redefine_symbol env symbol approx) + env defs + in + loop (times-1) env + in + loop 2 env + +let simplify_constant_defining_value + env r symbol + (constant_defining_value:Flambda.constant_defining_value) = + let r, constant_defining_value, approx = + match constant_defining_value with + (* No simplifications are possible for [Allocated_const] or [Block]. *) + | Allocated_const const -> + r, constant_defining_value, approx_for_allocated_const const + | Block (tag, fields) -> + let fields = List.map + (function + | Flambda.Symbol sym -> E.find_symbol_exn env sym + | Flambda.Const cst -> simplify_const cst) + fields + in + r, constant_defining_value, A.value_block tag (Array.of_list fields) + | Set_of_closures set_of_closures -> + if Variable.Map.cardinal set_of_closures.free_vars <> 0 then begin + Misc.fatal_errorf "Set of closures bound by [Let_symbol] is not \ + closed: %a" + Flambda.print_set_of_closures set_of_closures + end; + let set_of_closures, r, _freshening = + simplify_set_of_closures env r set_of_closures + in + r, ((Set_of_closures set_of_closures) : Flambda.constant_defining_value), + R.approx r + | Project_closure (set_of_closures_symbol, closure_id) -> + (* No simplifications are necessary here. *) + let set_of_closures_approx = + E.find_symbol_exn env set_of_closures_symbol + in + let closure_approx = + match A.check_approx_for_set_of_closures set_of_closures_approx with + | Ok (_, value_set_of_closures) -> + let closure_id = + A.freshen_and_check_closure_id value_set_of_closures closure_id + in + 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) + | Wrong -> + Misc.fatal_errorf "Wrong approximation for [Project_closure] \ + when being used as a [constant_defining_value]: %a" + Flambda.print_constant_defining_value constant_defining_value + in + r, constant_defining_value, closure_approx + in + let approx = A.augment_with_symbol approx symbol in + let r = ret r approx in + r, constant_defining_value, approx + +let rec simplify_program_body env r (program : Flambda.program_body) + : Flambda.program_body * R.t = + match program with + | Let_rec_symbol (defs, program) -> + let env = define_let_rec_symbol_approx env defs in + let env, r, defs = + List.fold_left (fun (env, r, defs) (symbol, def) -> + let r, def, approx = + simplify_constant_defining_value env r symbol def + in + let approx = A.augment_with_symbol approx symbol in + let env = E.redefine_symbol env symbol approx in + (env, r, (symbol, def) :: defs)) + (env, r, []) defs + in + let program, r = simplify_program_body env r program in + Let_rec_symbol (defs, program), r + | Let_symbol (symbol, constant_defining_value, program) -> + let r, constant_defining_value, approx = + simplify_constant_defining_value env r symbol constant_defining_value + in + let approx = A.augment_with_symbol approx symbol in + let env = E.add_symbol env symbol approx in + let program, r = simplify_program_body env r program in + Let_symbol (symbol, constant_defining_value, program), r + | Initialize_symbol (symbol, tag, fields, program) -> + let fields, approxs, r = simplify_list env r fields in + let approx = + A.augment_with_symbol (A.value_block tag (Array.of_list approxs)) symbol + in + let module Backend = (val (E.backend env) : Backend_intf.S) in + let env = E.add_symbol env symbol approx in + let program, r = simplify_program_body env r program in + Initialize_symbol (symbol, tag, fields, program), r + | Effect (expr, program) -> + let expr, r = simplify env r expr in + let program, r = simplify_program_body env r program in + Effect (expr, program), r + | End root -> End root, r + +let simplify_program env r (program : Flambda.program) = + let env, r = + Symbol.Set.fold (fun symbol (env, r) -> + let env, approx = + match E.find_symbol_exn env symbol with + | exception Not_found -> + let module Backend = (val (E.backend env) : Backend_intf.S) in + (* CR-someday mshinwell for mshinwell: Is there a reason we cannot + use [simplify_named_using_approx_and_env] here? *) + let approx = Backend.import_symbol symbol in + E.add_symbol env symbol approx, approx + | approx -> env, approx + in + env, ret r approx) + program.imported_symbols + (env, r) + in + let program_body, r = simplify_program_body env r program.program_body in + let program = { program with program_body; } in + program, r + +let add_predef_exns_to_environment ~env ~backend = + let module Backend = (val backend : Backend_intf.S) in + List.fold_left (fun env predef_exn -> + assert (Ident.is_predef_exn predef_exn); + let symbol = Backend.symbol_for_global' predef_exn in + let name = Ident.name predef_exn in + let approx = + A.value_block Tag.object_tag + [| A.value_string (String.length name) (Some name); + A.value_unknown Other; + |] + in + E.add_symbol env symbol (A.augment_with_symbol approx symbol)) + env + Predef.all_predef_exns + +let run ~never_inline ~backend ~prefixname ~round program = + let r = R.create () in + let report = !Clflags.inlining_report in + if never_inline then Clflags.inlining_report := false; + let initial_env = + add_predef_exns_to_environment + ~env:(E.create ~never_inline ~backend ~round) + ~backend + in + let result, r = simplify_program initial_env r program in + let result = Flambda_utils.introduce_needed_import_symbols result in + if not (Static_exception.Set.is_empty (R.used_static_exceptions r)) + then begin + Misc.fatal_error (Format.asprintf "remaining static exceptions: %a@.%a@." + Static_exception.Set.print (R.used_static_exceptions r) + Flambda.print_program result) + end; + assert (Static_exception.Set.is_empty (R.used_static_exceptions r)); + if !Clflags.inlining_report then begin + let output_prefix = Printf.sprintf "%s.%d" prefixname round in + Inlining_stats.save_then_forget_decisions ~output_prefix + end; + Clflags.inlining_report := report; + result diff --git a/middle_end/inline_and_simplify.mli b/middle_end/inline_and_simplify.mli new file mode 100644 index 00000000..a4ddf475 --- /dev/null +++ b/middle_end/inline_and_simplify.mli @@ -0,0 +1,38 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Simplification of Flambda programs combined with function inlining: + for the most part a beta-reduction pass. + + Readers interested in the inlining strategy should read the + [Inlining_decision] module first. +*) +val run + : never_inline:bool + -> backend:(module Backend_intf.S) + -> prefixname:string + -> round:int + -> Flambda.program + -> Flambda.program + +val duplicate_function + : env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> fun_var:Variable.t + -> Flambda.function_declaration + * Flambda.specialised_to Variable.Map.t (* new specialised arguments *) diff --git a/middle_end/inline_and_simplify_aux.ml b/middle_end/inline_and_simplify_aux.ml new file mode 100644 index 00000000..4f49a2fc --- /dev/null +++ b/middle_end/inline_and_simplify_aux.ml @@ -0,0 +1,680 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Env = struct + type scope = Current | Outer + + type t = { + backend : (module Backend_intf.S); + round : int; + approx : (scope * Simple_value_approx.t) Variable.Map.t; + approx_mutable : Simple_value_approx.t Mutable_variable.Map.t; + approx_sym : Simple_value_approx.t Symbol.Map.t; + projections : Variable.t Projection.Map.t; + current_functions : Set_of_closures_origin.Set.t; + (* The functions currently being declared: used to avoid inlining + recursively *) + inlining_level : int; + (* Number of times "inline" has been called recursively *) + inside_branch : int; + freshening : Freshening.t; + never_inline : bool ; + never_inline_inside_closures : bool; + never_inline_outside_closures : bool; + unroll_counts : int Set_of_closures_origin.Map.t; + inlining_counts : int Closure_id.Map.t; + actively_unrolling : int Set_of_closures_origin.Map.t; + closure_depth : int; + inlining_stats_closure_stack : Inlining_stats.Closure_stack.t; + } + + let create ~never_inline ~backend ~round = + { backend; + round; + approx = Variable.Map.empty; + approx_mutable = Mutable_variable.Map.empty; + approx_sym = Symbol.Map.empty; + projections = Projection.Map.empty; + current_functions = Set_of_closures_origin.Set.empty; + inlining_level = 0; + inside_branch = 0; + freshening = Freshening.empty; + never_inline; + never_inline_inside_closures = false; + never_inline_outside_closures = false; + unroll_counts = Set_of_closures_origin.Map.empty; + inlining_counts = Closure_id.Map.empty; + actively_unrolling = Set_of_closures_origin.Map.empty; + closure_depth = 0; + inlining_stats_closure_stack = + Inlining_stats.Closure_stack.create (); + } + + let backend t = t.backend + let round t = t.round + + let local env = + { env with + approx = Variable.Map.empty; + projections = Projection.Map.empty; + freshening = Freshening.empty_preserving_activation_state env.freshening; + } + + let inlining_level_up env = + let max_level = + Clflags.Int_arg_helper.get ~key:(env.round) !Clflags.inline_max_depth + in + if (env.inlining_level + 1) > max_level then + Misc.fatal_error "Inlining level increased above maximum"; + { env with inlining_level = env.inlining_level + 1 } + + let print ppf t = + Format.fprintf ppf + "Environment maps: %a@.Projections: %a@.Freshening: %a@." + Variable.Set.print (Variable.Map.keys t.approx) + (Projection.Map.print Variable.print) t.projections + Freshening.print t.freshening + + let mem t var = Variable.Map.mem var t.approx + + let add_internal t var (approx : Simple_value_approx.t) ~scope = + let approx = + (* The semantics of this [match] are what preserve the property + described at the top of simple_value_approx.mli, namely that when a + [var] is mem on an approximation (amongst many possible [var]s), + it is the one with the outermost scope. *) + match approx.var with + | Some var when mem t var -> approx + | _ -> Simple_value_approx.augment_with_variable approx var + in + { t with approx = Variable.Map.add var (scope, approx) t.approx } + + let add t var approx = add_internal t var approx ~scope:Current + let add_outer_scope t var approx = add_internal t var approx ~scope:Outer + + let add_mutable t mut_var approx = + { t with approx_mutable = + Mutable_variable.Map.add mut_var approx t.approx_mutable; + } + + let really_import_approx t approx = + let module Backend = (val (t.backend) : Backend_intf.S) in + Backend.really_import_approx approx + + let really_import_approx_with_scope t (scope, approx) = + scope, really_import_approx t approx + + let find_symbol_exn t symbol = + really_import_approx t + (Symbol.Map.find symbol t.approx_sym) + + let find_symbol_opt t symbol = + try Some (really_import_approx t + (Symbol.Map.find symbol t.approx_sym)) + with Not_found -> None + + let find_symbol_fatal t symbol = + match find_symbol_exn t symbol with + | exception Not_found -> + Misc.fatal_errorf "Symbol %a is unbound. Maybe there is a missing \ + [Let_symbol], [Import_symbol] or similar?" + Symbol.print symbol + | approx -> approx + + let find_or_load_symbol t symbol = + match find_symbol_exn t symbol with + | exception Not_found -> + if Compilation_unit.equal + (Compilation_unit.get_current_exn ()) + (Symbol.compilation_unit symbol) + then + Misc.fatal_errorf "Symbol %a from the current compilation unit is \ + unbound. Maybe there is a missing [Let_symbol] or similar?" + Symbol.print symbol; + let module Backend = (val (t.backend) : Backend_intf.S) in + Backend.import_symbol symbol + | approx -> approx + + let add_projection t ~projection ~bound_to = + { t with + projections = + Projection.Map.add projection bound_to t.projections; + } + + let find_projection t ~projection = + match Projection.Map.find projection t.projections with + | exception Not_found -> None + | var -> Some var + + let does_not_bind t vars = + not (List.exists (mem t) vars) + + let does_not_freshen t vars = + Freshening.does_not_freshen t.freshening vars + + let add_symbol t symbol approx = + match find_symbol_exn t symbol with + | exception Not_found -> + { t with + approx_sym = Symbol.Map.add symbol approx t.approx_sym; + } + | _ -> + Misc.fatal_errorf "Attempt to redefine symbol %a (to %a) in environment \ + for [Inline_and_simplify]" + Symbol.print symbol + Simple_value_approx.print approx + + let redefine_symbol t symbol approx = + match find_symbol_exn t symbol with + | exception Not_found -> + assert false + | _ -> + { t with + approx_sym = Symbol.Map.add symbol approx t.approx_sym; + } + + let find_with_scope_exn t id = + try + really_import_approx_with_scope t + (Variable.Map.find id t.approx) + with Not_found -> + Misc.fatal_errorf "Env.find_with_scope_exn: Unbound variable \ + %a@.%s@. Environment: %a@." + Variable.print id + (Printexc.raw_backtrace_to_string (Printexc.get_callstack max_int)) + print t + + let find_exn t id = + snd (find_with_scope_exn t id) + + let find_mutable_exn t mut_var = + try Mutable_variable.Map.find mut_var t.approx_mutable + with Not_found -> + Misc.fatal_errorf "Env.find_mutable_exn: Unbound variable \ + %a@.%s@. Environment: %a@." + Mutable_variable.print mut_var + (Printexc.raw_backtrace_to_string (Printexc.get_callstack max_int)) + print t + + let find_list_exn t vars = + List.map (fun var -> find_exn t var) vars + + let find_opt t id = + try Some (really_import_approx t + (snd (Variable.Map.find id t.approx))) + with Not_found -> None + + let activate_freshening t = + { t with freshening = Freshening.activate t.freshening } + + let enter_set_of_closures_declaration origin t = + { t with + current_functions = + Set_of_closures_origin.Set.add origin t.current_functions; } + + let inside_set_of_closures_declaration origin t = + Set_of_closures_origin.Set.mem origin t.current_functions + + let at_toplevel t = + t.closure_depth = 0 + + let is_inside_branch env = env.inside_branch > 0 + + let branch_depth env = env.inside_branch + + let inside_branch t = + { t with inside_branch = t.inside_branch + 1 } + + let set_freshening t freshening = + { t with freshening; } + + let increase_closure_depth t = + let approx = + Variable.Map.map (fun (_scope, approx) -> Outer, approx) t.approx + in + { t with + approx; + closure_depth = t.closure_depth + 1; + } + + let set_never_inline t = + if t.never_inline then t + else { t with never_inline = true } + + let set_never_inline_inside_closures t = + if t.never_inline_inside_closures then t + else { t with never_inline_inside_closures = true } + + let unset_never_inline_inside_closures t = + if t.never_inline_inside_closures then + { t with never_inline_inside_closures = false } + else t + + let set_never_inline_outside_closures t = + if t.never_inline_outside_closures then t + else { t with never_inline_outside_closures = true } + + let unset_never_inline_outside_closures t = + if t.never_inline_outside_closures then + { t with never_inline_outside_closures = false } + else t + + let actively_unrolling t origin = + match Set_of_closures_origin.Map.find origin t.actively_unrolling with + | count -> Some count + | exception Not_found -> None + + let start_actively_unrolling t origin i = + let actively_unrolling = + Set_of_closures_origin.Map.add origin i t.actively_unrolling + in + { t with actively_unrolling } + + let continue_actively_unrolling t origin = + let unrolling = + try + Set_of_closures_origin.Map.find origin t.actively_unrolling + with Not_found -> + Misc.fatal_error "Unexpected actively unrolled function"; + in + let actively_unrolling = + Set_of_closures_origin.Map.add origin (unrolling - 1) t.actively_unrolling + in + { t with actively_unrolling } + + let unrolling_allowed t origin = + let unroll_count = + try + Set_of_closures_origin.Map.find origin t.unroll_counts + with Not_found -> + Clflags.Int_arg_helper.get + ~key:t.round !Clflags.inline_max_unroll + in + unroll_count > 0 + + let inside_unrolled_function t origin = + let unroll_count = + try + Set_of_closures_origin.Map.find origin t.unroll_counts + with Not_found -> + Clflags.Int_arg_helper.get + ~key:t.round !Clflags.inline_max_unroll + in + let unroll_counts = + Set_of_closures_origin.Map.add + origin (unroll_count - 1) t.unroll_counts + in + { t with unroll_counts } + + let inlining_allowed t id = + let inlining_count = + try + Closure_id.Map.find id t.inlining_counts + with Not_found -> + max 1 (Clflags.Int_arg_helper.get + ~key:t.round !Clflags.inline_max_unroll) + in + inlining_count > 0 + + let inside_inlined_function t id = + let inlining_count = + try + Closure_id.Map.find id t.inlining_counts + with Not_found -> + max 1 (Clflags.Int_arg_helper.get + ~key:t.round !Clflags.inline_max_unroll) + in + let inlining_counts = + Closure_id.Map.add id (inlining_count - 1) t.inlining_counts + in + { t with inlining_counts } + + let inlining_level t = t.inlining_level + let freshening t = t.freshening + let never_inline t = t.never_inline || t.never_inline_outside_closures + + let note_entering_closure t ~closure_id ~debuginfo = + if t.never_inline then t + else + { t with + inlining_stats_closure_stack = + Inlining_stats.Closure_stack.note_entering_closure + t.inlining_stats_closure_stack ~closure_id ~debuginfo; + } + + let note_entering_call t ~closure_id ~debuginfo = + if t.never_inline then t + else + { t with + inlining_stats_closure_stack = + Inlining_stats.Closure_stack.note_entering_call + t.inlining_stats_closure_stack ~closure_id ~debuginfo; + } + + let note_entering_inlined t = + if t.never_inline then t + else + { t with + inlining_stats_closure_stack = + Inlining_stats.Closure_stack.note_entering_inlined + t.inlining_stats_closure_stack; + } + + let note_entering_specialised t ~closure_ids = + if t.never_inline then t + else + { t with + inlining_stats_closure_stack = + Inlining_stats.Closure_stack.note_entering_specialised + t.inlining_stats_closure_stack ~closure_ids; + } + + let enter_closure t ~closure_id ~inline_inside ~debuginfo ~f = + let t = + if inline_inside && not t.never_inline_inside_closures then t + else set_never_inline t + in + let t = unset_never_inline_outside_closures t in + f (note_entering_closure t ~closure_id ~debuginfo) + + let record_decision t decision = + Inlining_stats.record_decision decision + ~closure_stack:t.inlining_stats_closure_stack +end + +let initial_inlining_threshold ~round : Inlining_cost.Threshold.t = + let unscaled = + Clflags.Float_arg_helper.get ~key:round !Clflags.inline_threshold + in + (* CR-soon pchambart: Add a warning if this is too big + mshinwell: later *) + Can_inline_if_no_larger_than + (int_of_float + (unscaled *. float_of_int Inlining_cost.scale_inline_threshold_by)) + +let initial_inlining_toplevel_threshold ~round : Inlining_cost.Threshold.t = + let ordinary_threshold = + Clflags.Float_arg_helper.get ~key:round !Clflags.inline_threshold + in + let toplevel_threshold = + Clflags.Int_arg_helper.get ~key:round !Clflags.inline_toplevel_threshold + in + let unscaled = + (int_of_float ordinary_threshold) + toplevel_threshold + in + (* CR-soon pchambart: Add a warning if this is too big + mshinwell: later *) + Can_inline_if_no_larger_than + (unscaled * Inlining_cost.scale_inline_threshold_by) + +module Result = struct + module Int = Numbers.Int + + type t = + { approx : Simple_value_approx.t; + used_static_exceptions : Static_exception.Set.t; + inlining_threshold : Inlining_cost.Threshold.t option; + benefit : Inlining_cost.Benefit.t; + num_direct_applications : int; + } + + let create () = + { approx = Simple_value_approx.value_unknown Other; + used_static_exceptions = Static_exception.Set.empty; + inlining_threshold = None; + benefit = Inlining_cost.Benefit.zero; + num_direct_applications = 0; + } + + let approx t = t.approx + let set_approx t approx = { t with approx } + + let use_static_exception t i = + { t with + used_static_exceptions = + Static_exception.Set.add i t.used_static_exceptions; + } + + let used_static_exceptions t = t.used_static_exceptions + + let exit_scope_catch t i = + { t with + used_static_exceptions = + Static_exception.Set.remove i t.used_static_exceptions; + } + + let map_benefit t f = + { t with benefit = f t.benefit } + + let add_benefit t b = + { t with benefit = Inlining_cost.Benefit.(+) t.benefit b } + + let benefit t = t.benefit + + let reset_benefit t = + { t with benefit = Inlining_cost.Benefit.zero; } + + let set_inlining_threshold t inlining_threshold = + { t with inlining_threshold } + + let add_inlining_threshold t j = + match t.inlining_threshold with + | None -> t + | Some i -> + let inlining_threshold = Some (Inlining_cost.Threshold.add i j) in + { t with inlining_threshold } + + let sub_inlining_threshold t j = + match t.inlining_threshold with + | None -> t + | Some i -> + let inlining_threshold = Some (Inlining_cost.Threshold.sub i j) in + { t with inlining_threshold } + + let inlining_threshold t = t.inlining_threshold + + let seen_direct_application t = + { t with num_direct_applications = t.num_direct_applications + 1; } + + let num_direct_applications t = + t.num_direct_applications +end + +module A = Simple_value_approx +module E = Env + +let prepare_to_simplify_set_of_closures ~env + ~(set_of_closures : Flambda.set_of_closures) + ~function_decls ~freshen + ~(only_for_function_decl : Flambda.function_declaration option) = + let free_vars = + Variable.Map.map (fun (external_var : Flambda.specialised_to) -> + let var = + let var = + Freshening.apply_variable (E.freshening env) external_var.var + in + match + A.simplify_var_to_var_using_env (E.find_exn env var) + ~is_present_in_env:(fun var -> E.mem env var) + with + | None -> var + | Some var -> var + in + let approx = E.find_exn env var in + (* The projections are freshened below in one step, once we know + the closure freshening substitution. *) + let projection = external_var.projection in + ({ var; projection; } : Flambda.specialised_to), approx) + set_of_closures.free_vars + in + let specialised_args = + Variable.Map.filter_map set_of_closures.specialised_args + ~f:(fun param (spec_to : Flambda.specialised_to) -> + let keep = + match only_for_function_decl with + | None -> true + | Some function_decl -> + Variable.Set.mem param (Variable.Set.of_list function_decl.params) + in + if not keep then None + else + let external_var = spec_to.var in + let var = + Freshening.apply_variable (E.freshening env) external_var + in + let var = + match + A.simplify_var_to_var_using_env (E.find_exn env var) + ~is_present_in_env:(fun var -> E.mem env var) + with + | None -> var + | Some var -> var + in + let projection = spec_to.projection in + Some ({ var; projection; } : Flambda.specialised_to)) + in + let environment_before_cleaning = env in + (* [E.local] helps us to catch bugs whereby variables escape their scope. *) + let env = E.local env in + let free_vars, function_decls, sb, freshening = + Freshening.apply_function_decls_and_free_vars (E.freshening env) free_vars + function_decls ~only_freshen_parameters:(not freshen) + in + let env = E.set_freshening env sb in + let free_vars = + Freshening.freshen_projection_relation' free_vars + ~freshening:(E.freshening env) + ~closure_freshening:freshening + in + let specialised_args = + let specialised_args = + Variable.Map.map_keys (Freshening.apply_variable (E.freshening env)) + specialised_args + in + Freshening.freshen_projection_relation specialised_args + ~freshening:(E.freshening env) + ~closure_freshening:freshening + in + let parameter_approximations = + (* Approximations of parameters that are known to always hold the same + argument throughout the body of the function. *) + Variable.Map.map_keys (Freshening.apply_variable (E.freshening env)) + (Variable.Map.mapi (fun _id' (spec_to : Flambda.specialised_to) -> + E.find_exn environment_before_cleaning spec_to.var) + specialised_args) + in + let direct_call_surrogates = + Variable.Map.fold (fun existing surrogate surrogates -> + let existing = + Freshening.Project_var.apply_closure_id freshening + (Closure_id.wrap existing) + in + let surrogate = + Freshening.Project_var.apply_closure_id freshening + (Closure_id.wrap surrogate) + in + assert (not (Closure_id.Map.mem existing surrogates)); + Closure_id.Map.add existing surrogate surrogates) + set_of_closures.direct_call_surrogates + Closure_id.Map.empty + in + let env = + E.enter_set_of_closures_declaration + function_decls.set_of_closures_origin env + in + (* we use the previous closure for evaluating the functions *) + let internal_value_set_of_closures = + let bound_vars = + Variable.Map.fold (fun id (_, desc) map -> + Var_within_closure.Map.add (Var_within_closure.wrap id) desc map) + free_vars Var_within_closure.Map.empty + in + A.create_value_set_of_closures ~function_decls ~bound_vars + ~invariant_params:(lazy Variable.Map.empty) ~specialised_args + ~freshening ~direct_call_surrogates + in + (* Populate the environment with the approximation of each closure. + This part of the environment is shared between all of the closures in + the set of closures. *) + let set_of_closures_env = + Variable.Map.fold (fun closure _ env -> + let approx = + A.value_closure ~closure_var:closure internal_value_set_of_closures + (Closure_id.wrap closure) + in + E.add env closure approx + ) + function_decls.funs env + in + free_vars, specialised_args, function_decls, parameter_approximations, + internal_value_set_of_closures, set_of_closures_env + +(* This adds only the minimal set of approximations to the closures. + It is not strictly necessary to have this restriction, but it helps + to catch potential substitution bugs. *) +let populate_closure_approximations + ~(function_decl : Flambda.function_declaration) + ~(free_vars : (_ * A.t) Variable.Map.t) + ~(parameter_approximations : A.t Variable.Map.t) + ~set_of_closures_env = + (* Add approximations of free variables *) + let env = + Variable.Map.fold (fun id (_, desc) env -> + E.add_outer_scope env id desc) + free_vars set_of_closures_env + in + (* Add known approximations of function parameters *) + let env = + List.fold_left (fun env id -> + let approx = + try Variable.Map.find id parameter_approximations + with Not_found -> (A.value_unknown Other) + in + E.add env id approx) + env function_decl.params + in + env + +let prepare_to_simplify_closure ~(function_decl : Flambda.function_declaration) + ~free_vars ~specialised_args ~parameter_approximations + ~set_of_closures_env = + let closure_env = + populate_closure_approximations ~function_decl ~free_vars + ~parameter_approximations ~set_of_closures_env + in + (* Add definitions of known projections to the environment. *) + let add_projections ~closure_env ~which_variables ~map = + Variable.Map.fold (fun inner_var spec_arg env -> + let (spec_arg : Flambda.specialised_to) = map spec_arg in + match spec_arg.projection with + | None -> env + | Some projection -> + let from = Projection.projecting_from projection in + if Variable.Set.mem from function_decl.free_variables then + E.add_projection env ~projection ~bound_to:inner_var + else + env) + which_variables + closure_env + in + let closure_env = + add_projections ~closure_env ~which_variables:specialised_args + ~map:(fun spec_to -> spec_to) + in + add_projections ~closure_env ~which_variables:free_vars + ~map:(fun (spec_to, _approx) -> spec_to) diff --git a/middle_end/inline_and_simplify_aux.mli b/middle_end/inline_and_simplify_aux.mli new file mode 100644 index 00000000..a3a581d9 --- /dev/null +++ b/middle_end/inline_and_simplify_aux.mli @@ -0,0 +1,344 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Environments and result structures used during inlining and + simplification. (See inline_and_simplify.ml.) *) + +module Env : sig + (** Environments follow the lexical scopes of the program. *) + type t + + (** Create a new environment. If [never_inline] is true then the returned + environment will prevent [Inline_and_simplify] from inlining. The + [backend] parameter is used for passing information about the compiler + backend being used. + Newly-created environments have inactive [Freshening]s (see below) and do + not initially hold any approximation information. *) + val create + : never_inline:bool + -> backend:(module Backend_intf.S) + -> round:int + -> t + + (** Obtain the first-class module that gives information about the + compiler backend being used for compilation. *) + val backend : t -> (module Backend_intf.S) + + (** Which simplification round we are currently in. *) + val round : t -> int + + (** Add the approximation of a variable---that is to say, some knowledge + about the value(s) the variable may take on at runtime---to the + environment. *) + val add : t -> Variable.t -> Simple_value_approx.t -> t + + val add_outer_scope : t -> Variable.t -> Simple_value_approx.t -> t + + (** Like [add], but for mutable variables. *) + val add_mutable : t -> Mutable_variable.t -> Simple_value_approx.t -> t + + (** Find the approximation of a given variable, raising a fatal error if + the environment does not know about the variable. Use [find_opt] + instead if you need to catch the failure case. *) + val find_exn : t -> Variable.t -> Simple_value_approx.t + + (** Like [find_exn], but for mutable variables. *) + val find_mutable_exn : t -> Mutable_variable.t -> Simple_value_approx.t + + type scope = Current | Outer + + val find_with_scope_exn : t -> Variable.t -> scope * Simple_value_approx.t + + (** Like [find_exn], but intended for use where the "not present in + environment" case is to be handled by the caller. *) + val find_opt : t -> Variable.t -> Simple_value_approx.t option + + (** Like [find_exn], but for a list of variables. *) + val find_list_exn : t -> Variable.t list -> Simple_value_approx.t list + + val does_not_bind : t -> Variable.t list -> bool + + val does_not_freshen : t -> Variable.t list -> bool + + val add_symbol : t -> Symbol.t -> Simple_value_approx.t -> t + val redefine_symbol : t -> Symbol.t -> Simple_value_approx.t -> t + val find_symbol_exn : t -> Symbol.t -> Simple_value_approx.t + val find_symbol_opt : t -> Symbol.t -> Simple_value_approx.t option + val find_symbol_fatal : t -> Symbol.t -> Simple_value_approx.t + + (* Like [find_symbol_exn], but load the symbol approximation using + the backend if not available in the environment. *) + val find_or_load_symbol : t -> Symbol.t -> Simple_value_approx.t + + (** Note that the given [bound_to] holds the given [projection]. *) + val add_projection + : t + -> projection:Projection.t + -> bound_to:Variable.t + -> t + + (** Determine if the environment knows about a variable that is bound + to the given [projection]. *) + val find_projection + : t + -> projection:Projection.t + -> Variable.t option + + (** Whether the environment has an approximation for the given variable. *) + val mem : t -> Variable.t -> bool + + (** Return the freshening that should be applied to variables when + rewriting code (in [Inline_and_simplify], etc.) using the given + environment. *) + val freshening : t -> Freshening.t + + (** Set the freshening that should be used as per [freshening], above. *) + val set_freshening : t -> Freshening.t -> t + + (** Causes every bound variable in code rewritten during inlining and + simplification, using the given environment, to be freshened. This is + used when descending into subexpressions substituted into existing + expressions. *) + val activate_freshening : t -> t + + (** Erase all variable approximation information and freshening information + from the given environment. However, the freshening activation state + is preserved. This function is used when rewriting inside a function + declaration, to avoid (due to a compiler bug) accidental use of + variables from outer scopes that are not accessible. *) + val local : t -> t + + (** Note that the inliner is descending into a function body from the given + set of closures. A set of such descents is maintained. *) + (* CR-someday mshinwell: consider changing name to remove "declaration". + Also, isn't this the inlining stack? Maybe we can use that instead. *) + val enter_set_of_closures_declaration : Set_of_closures_origin.t -> t -> t + + (** Determine whether the inliner is currently inside a function body from + the given set of closures. This is used to detect whether a given + function call refers to a function which exists somewhere on the current + inlining stack. *) + val inside_set_of_closures_declaration : Set_of_closures_origin.t -> t -> bool + + (** Not inside a closure declaration. + Toplevel code is the one evaluated when the compilation unit is + loaded *) + val at_toplevel : t -> bool + + val is_inside_branch : t -> bool + val branch_depth : t -> int + val inside_branch : t -> t + + val increase_closure_depth : t -> t + + (** Mark that call sites contained within code rewritten using the given + environment should never be replaced by inlined (or unrolled) versions + of the callee(s). *) + val set_never_inline : t -> t + + (** Equivalent to [set_never_inline] but only applies to code inside + a set of closures. *) + val set_never_inline_inside_closures : t -> t + + (** Unset the restriction from [set_never_inline_inside_closures] *) + val unset_never_inline_inside_closures : t -> t + + (** Equivalent to [set_never_inline] but does not apply to code inside + a set of closures. *) + val set_never_inline_outside_closures : t -> t + + (** Unset the restriction from [set_never_inline_outside_closures] *) + val unset_never_inline_outside_closures : t -> t + + (** Return whether [set_never_inline] is currently in effect on the given + environment. *) + val never_inline : t -> bool + + val inlining_level : t -> int + + (** Mark that this environment is used to rewrite code for inlining. This is + used by the inlining heuristics to decide wether to continue. + Unconditionally inlined does not take this into account. *) + val inlining_level_up : t -> t + + (** Whether we are actively unrolling a given function. *) + val actively_unrolling : t -> Set_of_closures_origin.t -> int option + + (** Start actively unrolling a given function [n] times. *) + val start_actively_unrolling : t -> Set_of_closures_origin.t -> int -> t + + (** Unroll a function currently actively being unrolled. *) + val continue_actively_unrolling : t -> Set_of_closures_origin.t -> t + + (** Whether it is permissible to unroll a call to a recursive function + in the given environment. *) + val unrolling_allowed : t -> Set_of_closures_origin.t -> bool + + (** Whether the given environment is currently being used to rewrite the + body of an unrolled recursive function. *) + val inside_unrolled_function : t -> Set_of_closures_origin.t -> t + + (** Whether it is permissible to inline a call to a function in the given + environment. *) + val inlining_allowed : t -> Closure_id.t -> bool + + (** Whether the given environment is currently being used to rewrite the + body of an inlined function. *) + val inside_inlined_function : t -> Closure_id.t -> t + + (** If collecting inlining statistics, record that the inliner is about to + descend into [closure_id]. This information enables us to produce a + stack of closures that form a kind of context around an inlining + decision point. *) + val note_entering_closure + : t + -> closure_id:Closure_id.t + -> debuginfo:Debuginfo.t + -> t + + (** If collecting inlining statistics, record that the inliner is about to + descend into a call to [closure_id]. This information enables us to + produce a stack of closures that form a kind of context around an + inlining decision point. *) + val note_entering_call + : t + -> closure_id:Closure_id.t + -> debuginfo:Debuginfo.t + -> t + + (** If collecting inlining statistics, record that the inliner is about to + descend into an inlined function call. This requires that the inliner + has already entered the call with [note_entering_call]. *) + val note_entering_inlined : t -> t + + (** If collecting inlining statistics, record that the inliner is about to + descend into a specialised function definition. This requires that the + inliner has already entered the call with [note_entering_call]. *) + val note_entering_specialised : t -> closure_ids:Closure_id.Set.t -> t + + (** Update a given environment to record that the inliner is about to + descend into [closure_id] and pass the resulting environment to [f]. + If [inline_inside] is [false] then the environment passed to [f] will be + marked as [never_inline] (see above). *) + val enter_closure + : t + -> closure_id:Closure_id.t + -> inline_inside:bool + -> debuginfo:Debuginfo.t + -> f:(t -> 'a) + -> 'a + + (** If collecting inlining statistics, record an inlining decision for the + call at the top of the closure stack stored inside the given + environment. *) + val record_decision + : t + -> Inlining_stats_types.Decision.t + -> unit + + (** Print a human-readable version of the given environment. *) + val print : Format.formatter -> t -> unit +end + +module Result : sig + (** Result structures approximately follow the evaluation order of the + program. They are returned by the simplification algorithm acting on + an Flambda subexpression. *) + type t + + val create : unit -> t + + (** The approximation of the subexpression that has just been + simplified. *) + val approx : t -> Simple_value_approx.t + + (** Set the approximation of the subexpression that has just been + simplified. Typically used just before returning from a case of the + simplification algorithm. *) + val set_approx : t -> Simple_value_approx.t -> t + + (** All static exceptions for which [use_staticfail] has been called on + the given result structure. *) + val used_static_exceptions : t -> Static_exception.Set.t + + (** Mark that the given static exception has been used. *) + val use_static_exception : t -> Static_exception.t -> t + + (** Mark that we are moving up out of the scope of a static-catch block + that catches the given static exception identifier. This has the effect + of removing the identifier from the [used_staticfail] set. *) + val exit_scope_catch : t -> Static_exception.t -> t + + (** The benefit to be gained by inlining the subexpression whose + simplification yielded the given result structure. *) + val benefit : t -> Inlining_cost.Benefit.t + + (** Apply a transformation to the inlining benefit stored within the + given result structure. *) + val map_benefit + : t + -> (Inlining_cost.Benefit.t -> Inlining_cost.Benefit.t) + -> t + + (** Add some benefit to the inlining benefit stored within the + given result structure. *) + val add_benefit : t -> Inlining_cost.Benefit.t -> t + + (** Set the benefit of inlining the subexpression corresponding to the + given result structure to zero. *) + val reset_benefit : t -> t + + val set_inlining_threshold : + t -> Inlining_cost.Threshold.t option -> t + val add_inlining_threshold : + t -> Inlining_cost.Threshold.t -> t + val sub_inlining_threshold : + t -> Inlining_cost.Threshold.t -> t + val inlining_threshold : t -> Inlining_cost.Threshold.t option + + val seen_direct_application : t -> t + val num_direct_applications : t -> int +end + +(** Command line argument -inline *) +val initial_inlining_threshold : round:int -> Inlining_cost.Threshold.t + +(** Command line argument -inline-toplevel *) +val initial_inlining_toplevel_threshold + : round:int -> Inlining_cost.Threshold.t + +val prepare_to_simplify_set_of_closures + : env:Env.t + -> set_of_closures:Flambda.set_of_closures + -> function_decls:Flambda.function_declarations + -> freshen:bool + -> only_for_function_decl:Flambda.function_declaration option + -> (Flambda.specialised_to * Simple_value_approx.t) Variable.Map.t (* fvs *) + * Flambda.specialised_to Variable.Map.t (* specialised arguments *) + * Flambda.function_declarations + * Simple_value_approx.t Variable.Map.t (* parameter approximations *) + * Simple_value_approx.value_set_of_closures + * Env.t + +val prepare_to_simplify_closure + : function_decl:Flambda.function_declaration + -> free_vars:(Flambda.specialised_to * Simple_value_approx.t) Variable.Map.t + -> specialised_args:Flambda.specialised_to Variable.Map.t + -> parameter_approximations:Simple_value_approx.t Variable.Map.t + -> set_of_closures_env:Env.t + -> Env.t diff --git a/middle_end/inlining_cost.ml b/middle_end/inlining_cost.ml new file mode 100644 index 00000000..27f0f58e --- /dev/null +++ b/middle_end/inlining_cost.ml @@ -0,0 +1,684 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* Simple approximation of the space cost of a primitive. *) + +let prim_size (prim : Lambda.primitive) args = + match prim with + | Pidentity -> 0 + | Pgetglobal _ -> 1 + | Psetglobal _ -> 1 + | Pmakeblock _ -> 5 + List.length args + | Pfield _ -> 1 + | Psetfield (_, isptr, init) -> + begin match init with + | Initialization -> 1 (* never causes a write barrier hit *) + | Assignment -> + match isptr with + | Pointer -> 4 + | Immediate -> 1 + end + | Pfloatfield _ -> 1 + | Psetfloatfield _ -> 1 + | Pduprecord _ -> 10 + List.length args + | Pccall p -> (if p.Primitive.prim_alloc then 10 else 4) + List.length args + | Praise _ -> 4 + | Pstringlength -> 5 + | Pstringrefs | Pstringsets -> 6 + | Pmakearray _ -> 5 + List.length args + | Parraylength Pgenarray -> 6 + | Parraylength _ -> 2 + | Parrayrefu Pgenarray -> 12 + | Parrayrefu _ -> 2 + | Parraysetu Pgenarray -> 16 + | Parraysetu _ -> 4 + | Parrayrefs Pgenarray -> 18 + | Parrayrefs _ -> 8 + | Parraysets Pgenarray -> 22 + | Parraysets _ -> 10 + | Pbittest -> 3 + | Pbigarrayref (_, ndims, _, _) -> 4 + ndims * 6 + | Pbigarrayset (_, ndims, _, _) -> 4 + ndims * 6 + | Psequand | Psequor -> + Misc.fatal_error "Psequand and Psequor are not allowed in Prim \ + expressions; translate out instead (cf. closure_conversion.ml)" + (* CR-soon mshinwell: This match must be made exhaustive. + mshinwell: Let's do this when we have the new size computation. *) + | _ -> 2 (* arithmetic and comparisons *) + +(* Simple approximation of the space cost of an Flambda expression. *) + +(* CR-soon mshinwell: Investigate revised size numbers. *) + +let direct_call_size = 4 +let project_size = 1 + +let lambda_smaller' lam ~than:threshold = + let size = ref 0 in + let rec lambda_size (lam : Flambda.t) = + if !size > threshold then raise Exit; + match lam with + | Var _ -> () + | Apply ({ func = _; args = _; kind = direct }) -> + let call_cost = + match direct with Indirect -> 6 | Direct _ -> direct_call_size + in + size := !size + call_cost + | Assign _ -> incr size + | Send _ -> size := !size + 8 + | Proved_unreachable -> () + | Let { defining_expr; body; _ } -> + lambda_named_size defining_expr; + lambda_size body + | Let_mutable (_, _, body) -> lambda_size body + | Let_rec (bindings, body) -> + List.iter (fun (_, lam) -> lambda_named_size lam) bindings; + lambda_size body + | Switch (_, sw) -> + let aux = function _::_::_ -> size := !size + 5 | _ -> () in + aux sw.consts; aux sw.blocks; + List.iter (fun (_, lam) -> lambda_size lam) sw.consts; + List.iter (fun (_, lam) -> lambda_size lam) sw.blocks; + Misc.Stdlib.Option.iter lambda_size sw.failaction + | String_switch (_, sw, def) -> + List.iter (fun (_, lam) -> + size := !size + 2; + lambda_size lam) + sw; + Misc.may lambda_size def + | Static_raise _ -> () + | Static_catch (_, _, body, handler) -> + incr size; lambda_size body; lambda_size handler + | Try_with (body, _, handler) -> + size := !size + 8; lambda_size body; lambda_size handler + | If_then_else (_, ifso, ifnot) -> + size := !size + 2; + lambda_size ifso; lambda_size ifnot + | While (cond, body) -> + size := !size + 2; lambda_size cond; lambda_size body + | For { body; _ } -> + size := !size + 4; lambda_size body + and lambda_named_size (named : Flambda.named) = + if !size > threshold then raise Exit; + match named with + | Symbol _ | Read_mutable _ -> () + | Const _ | Allocated_const _ -> incr size + | Read_symbol_field _ -> incr size + | Set_of_closures ({ function_decls = ffuns }) -> + Variable.Map.iter (fun _ (ffun : Flambda.function_declaration) -> + lambda_size ffun.body) + ffuns.funs + | Project_closure _ | Project_var _ -> + size := !size + project_size + | Move_within_set_of_closures _ -> + incr size + | Prim (prim, args, _) -> + size := !size + prim_size prim args + | Expr expr -> lambda_size expr + in + try + lambda_size lam; + if !size <= threshold then Some !size + else None + with Exit -> + None + +let lambda_size lam = + match lambda_smaller' lam ~than:max_int with + | Some size -> + size + | None -> + (* There is no way that an expression of size max_int could fit in + memory. *) + assert false + +module Threshold = struct + + type t = + | Never_inline + | Can_inline_if_no_larger_than of int + + let add t1 t2 = + match t1, t2 with + | Never_inline, t -> t + | t, Never_inline -> t + | Can_inline_if_no_larger_than i1, Can_inline_if_no_larger_than i2 -> + Can_inline_if_no_larger_than (i1 + i2) + + let sub t1 t2 = + match t1, t2 with + | Never_inline, _ -> Never_inline + | t, Never_inline -> t + | Can_inline_if_no_larger_than i1, Can_inline_if_no_larger_than i2 -> + if i1 > i2 then Can_inline_if_no_larger_than (i1 - i2) + else Never_inline + + let min t1 t2 = + match t1, t2 with + | Never_inline, _ -> Never_inline + | _, Never_inline -> Never_inline + | Can_inline_if_no_larger_than i1, Can_inline_if_no_larger_than i2 -> + Can_inline_if_no_larger_than (min i1 i2) + +end + +let can_try_inlining lam inlining_threshold ~number_of_arguments + ~size_from_approximation = + match inlining_threshold with + | Threshold.Never_inline -> Threshold.Never_inline + | Threshold.Can_inline_if_no_larger_than inlining_threshold -> + let bonus = + (* removing a call will reduce the size by at least the number + of arguments *) + number_of_arguments + in + let size = + let than = inlining_threshold + bonus in + match size_from_approximation with + | Some size -> if size <= than then Some size else None + | None -> lambda_smaller' lam ~than + in + match size with + | None -> Threshold.Never_inline + | Some size -> + Threshold.Can_inline_if_no_larger_than + (inlining_threshold - size + bonus) + +let lambda_smaller lam ~than = + lambda_smaller' lam ~than <> None + +let can_inline lam inlining_threshold ~bonus = + match inlining_threshold with + | Threshold.Never_inline -> false + | Threshold.Can_inline_if_no_larger_than inlining_threshold -> + lambda_smaller + lam + ~than:(inlining_threshold + bonus) + +let cost (flag : Clflags.Int_arg_helper.parsed) ~round = + Clflags.Int_arg_helper.get ~key:round flag + +let benefit_factor = 1 + +module Benefit = struct + type t = { + remove_call : int; + remove_alloc : int; + remove_prim : int; + remove_branch : int; + (* CR-someday pchambart: branch_benefit : t list; *) + direct_call_of_indirect : int; + requested_inline : int; + (* Benefit to compensate the size of functions marked for inlining *) + } + + let zero = { + remove_call = 0; + remove_alloc = 0; + remove_prim = 0; + remove_branch = 0; + direct_call_of_indirect = 0; + requested_inline = 0; + } + + let remove_call t = { t with remove_call = t.remove_call + 1; } + let remove_alloc t = { t with remove_alloc = t.remove_alloc + 1; } + let remove_prim t = { t with remove_prim = t.remove_prim + 1; } + let remove_prims t n = { t with remove_prim = t.remove_prim + n; } + let remove_branch t = { t with remove_branch = t.remove_branch + 1; } + let direct_call_of_indirect t = + { t with direct_call_of_indirect = t.direct_call_of_indirect + 1; } + let requested_inline t ~size_of = + let size = lambda_size size_of in + { t with requested_inline = t.requested_inline + size; } + + let remove_code_helper b (flam : Flambda.t) = + match flam with + | Assign _ -> b := remove_prim !b + | Switch _ | String_switch _ | Static_raise _ | Try_with _ + | If_then_else _ | While _ | For _ -> b := remove_branch !b + | Apply _ | Send _ -> b := remove_call !b + | Let _ | Let_mutable _ | Let_rec _ | Proved_unreachable | Var _ + | Static_catch _ -> () + + let remove_code_helper_named b (named : Flambda.named) = + match named with + | Set_of_closures _ + | Prim ((Pmakearray _ | Pmakeblock _ | Pduprecord _), _, _) -> + b := remove_alloc !b + (* CR-soon pchambart: should we consider that boxed integer and float + operations are allocations ? *) + | Prim _ | Project_closure _ | Project_var _ + | Move_within_set_of_closures _ + | Read_symbol_field _ -> b := remove_prim !b + | Symbol _ | Read_mutable _ | Allocated_const _ | Const _ | Expr _ -> () + + let remove_code lam b = + let b = ref b in + Flambda_iterators.iter_toplevel (remove_code_helper b) + (remove_code_helper_named b) lam; + !b + + let remove_code_named lam b = + let b = ref b in + Flambda_iterators.iter_named_toplevel (remove_code_helper b) + (remove_code_helper_named b) lam; + !b + + let remove_projection (_proj : Projection.t) b = + (* They are all primitives for the moment. The [Projection.t] argument + is here for future expansion. *) + remove_prim b + + let print ppf b = + Format.fprintf ppf "@[remove_call: %i@ remove_alloc: %i@ \ + remove_prim: %i@ remove_branch: %i@ \ + direct: %i@ requested: %i@]" + b.remove_call + b.remove_alloc + b.remove_prim + b.remove_branch + b.direct_call_of_indirect + b.requested_inline + + let evaluate t ~round : int = + benefit_factor * + (t.remove_call * (cost !Clflags.inline_call_cost ~round) + + t.remove_alloc * (cost !Clflags.inline_alloc_cost ~round) + + t.remove_prim * (cost !Clflags.inline_prim_cost ~round) + + t.remove_branch * (cost !Clflags.inline_branch_cost ~round) + + (t.direct_call_of_indirect + * (cost !Clflags.inline_indirect_cost ~round))) + + t.requested_inline + + let (+) t1 t2 = { + remove_call = t1.remove_call + t2.remove_call; + remove_alloc = t1.remove_alloc + t2.remove_alloc; + remove_prim = t1.remove_prim + t2.remove_prim; + remove_branch = t1.remove_branch + t2.remove_branch; + direct_call_of_indirect = + t1.direct_call_of_indirect + t2.direct_call_of_indirect; + requested_inline = t1.requested_inline + t2.requested_inline; + } + + let (-) t1 t2 = { + remove_call = t1.remove_call - t2.remove_call; + remove_alloc = t1.remove_alloc - t2.remove_alloc; + remove_prim = t1.remove_prim - t2.remove_prim; + remove_branch = t1.remove_branch - t2.remove_branch; + direct_call_of_indirect = + t1.direct_call_of_indirect - t2.direct_call_of_indirect; + requested_inline = t1.requested_inline - t2.requested_inline; + } + + let max ~round t1 t2 = + let c1 = evaluate ~round t1 in + let c2 = evaluate ~round t2 in + if c1 > c2 then t1 else t2 + + let add_code lam b = + b - (remove_code lam zero) + + let add_code_named lam b = + b - (remove_code_named lam zero) + + let add_projection proj b = + b - (remove_projection proj zero) + + (* Print out a benefit as a table *) + + let benefit_table = + [ "Calls", (fun b -> b.remove_call); + "Allocs", (fun b -> b.remove_alloc); + "Prims", (fun b -> b.remove_prim); + "Branches", (fun b -> b.remove_branch); + "Indirect calls", (fun b -> b.direct_call_of_indirect); + ] + + let benefits_table = + lazy begin + List.map + (fun (header, accessor) -> (header, accessor, String.length header)) + benefit_table + end + + let table_line = + lazy begin + let benefits_table = Lazy.force benefits_table in + let dashes = + List.map (fun (_, _, n) -> String.make n '-') benefits_table + in + "|-" ^ String.concat "-+-" dashes ^ "-|" + end + + let table_headers = + lazy begin + let benefits_table = Lazy.force benefits_table in + let headers = List.map (fun (head, _, _) -> head) benefits_table in + "| " ^ String.concat " | " headers ^ " |" + end + + let print_table_values ppf b = + let rec loop ppf = function + | [] -> Format.fprintf ppf "|" + | (_, accessor, width) :: rest -> + Format.fprintf ppf "| %*d %a" width (accessor b) loop rest + in + loop ppf (Lazy.force benefits_table) + + let print_table ppf b = + let table_line = Lazy.force table_line in + let table_headers = Lazy.force table_headers in + Format.fprintf ppf + "@[@[%s@]@;@[%s@]@;@[%s@]@;@[%a@]@;@[%s@]@]" + table_line table_headers table_line + print_table_values b + table_line +end + +module Whether_sufficient_benefit = struct + type t = { + round : int; + benefit : Benefit.t; + toplevel : bool; + branch_depth : int; + lifting : bool; + original_size : int; + new_size : int; + evaluated_benefit : int; + estimate : bool; + } + + let create ~original ~toplevel ~branch_depth lam ~benefit ~lifting ~round = + let evaluated_benefit = Benefit.evaluate benefit ~round in + { round; benefit; toplevel; branch_depth; lifting; + original_size = lambda_size original; + new_size = lambda_size lam; + evaluated_benefit; + estimate = false; + } + + let create_estimate ~original_size ~toplevel ~branch_depth ~new_size + ~benefit ~lifting ~round = + let evaluated_benefit = Benefit.evaluate benefit ~round in + { round; benefit; toplevel; branch_depth; lifting; original_size; + new_size; evaluated_benefit; estimate = true; + } + + let correct_branch_factor f = + f = f (* is not nan *) + && f >= 0. + + let estimated_benefit t = + if t.toplevel && t.lifting && t.branch_depth = 0 then begin + let lifting_benefit = + Clflags.Int_arg_helper.get ~key:t.round !Clflags.inline_lifting_benefit + in + float (t.evaluated_benefit + lifting_benefit) + end else begin + (* The estimated benefit is the evaluated benefit times an + estimation of the probability that the branch does actually matter + for performance (i.e. is hot). The probability is very roughly + estimated by considering that under every branch the + sub-expressions have the same [1 / (1 + factor)] probability + [p] of being hot. Hence the probability for the current + call to be hot is [p ^ number of nested branches]. + The probability is expressed as [1 / (1 + factor)] rather + than letting the user directly provide [p], since for every + positive value of [factor] [p] is in [0, 1]. *) + let branch_taken_estimated_probability = + let inline_branch_factor = + let factor = + Clflags.Float_arg_helper.get ~key:t.round + !Clflags.inline_branch_factor + in + if not (factor = factor) (* nan *) then + Clflags.default_inline_branch_factor + else if factor < 0. then + 0. + else + factor + in + assert (correct_branch_factor inline_branch_factor); + 1. /. (1. +. inline_branch_factor) + in + let call_estimated_probability = + branch_taken_estimated_probability ** float t.branch_depth + in + float t.evaluated_benefit *. call_estimated_probability + end + + let evaluate t = + float t.new_size -. estimated_benefit t <= float t.original_size + + let to_string t = + let lifting = t.toplevel && t.lifting && t.branch_depth = 0 in + let evaluated_benefit = + if lifting then + let lifting_benefit = + Clflags.Int_arg_helper.get ~key:t.round + !Clflags.inline_lifting_benefit + in + t.evaluated_benefit + lifting_benefit + else t.evaluated_benefit + in + let estimate = if t.estimate then "<" else "=" in + Printf.sprintf "{benefit%s{call=%d,alloc=%d,prim=%i,branch=%i,\ + indirect=%i,req=%i,\ + lifting=%b}, orig_size=%d,new_size=%d,eval_size=%d,\ + eval_benefit%s%d,\ + branch_depth=%d}=%s" + estimate + t.benefit.remove_call + t.benefit.remove_alloc + t.benefit.remove_prim + t.benefit.remove_branch + t.benefit.direct_call_of_indirect + t.benefit.requested_inline + lifting + t.original_size + t.new_size + (t.original_size - t.new_size) + estimate + evaluated_benefit + t.branch_depth + (if evaluate t then "yes" else "no") + + let print_description ~subfunctions ppf t = + let pr_intro ppf = + let estimate = if t.estimate then " at most" else "" in + Format.pp_print_text ppf + "Specialisation of the function body"; + if subfunctions then + Format.pp_print_text ppf + ", including speculative inlining of other functions,"; + Format.pp_print_text ppf " removed"; + Format.pp_print_text ppf estimate; + Format.pp_print_text ppf " the following operations:" + in + let lifting = t.toplevel && t.lifting && t.branch_depth = 0 in + let requested = t.benefit.requested_inline in + let pr_requested ppf = + if requested > 0 then begin + Format.pp_open_box ppf 0; + Format.pp_print_text ppf + "and inlined user-annotated functions worth "; + Format.fprintf ppf "%d." requested; + Format.pp_close_box ppf (); + Format.pp_print_cut ppf (); + Format.pp_print_cut ppf () + end + in + let pr_lifting ppf = + if lifting then begin + Format.pp_open_box ppf 0; + Format.pp_print_text ppf + "Inlining the function would also \ + lift some definitions to toplevel."; + Format.pp_close_box ppf (); + Format.pp_print_cut ppf (); + Format.pp_print_cut ppf () + end + in + let total_benefit = + if lifting then + let lifting_benefit = + Clflags.Int_arg_helper.get ~key:t.round + !Clflags.inline_lifting_benefit + in + t.evaluated_benefit + lifting_benefit + else t.evaluated_benefit + in + let expected_benefit = estimated_benefit t in + let size_change = t.new_size - t.original_size in + let result = if evaluate t then "less" else "greater" in + let pr_conclusion ppf = + Format.pp_print_text ppf "This gives a total benefit of "; + Format.pp_print_int ppf total_benefit; + Format.pp_print_text ppf ". At a branch depth of "; + Format.pp_print_int ppf t.branch_depth; + Format.pp_print_text ppf " this produces an expected benefit of "; + Format.fprintf ppf "%.1f" expected_benefit; + Format.pp_print_text ppf ". The new code has size "; + Format.pp_print_int ppf t.new_size; + Format.pp_print_text ppf ", giving a change in code size of "; + Format.pp_print_int ppf size_change; + Format.pp_print_text ppf ". The change in code size is "; + Format.pp_print_text ppf result; + Format.pp_print_text ppf " than the expected benefit." + in + Format.fprintf ppf "%t@,@[@[@;%a@]@;@;%t%t@]%t" + pr_intro Benefit.print_table t.benefit pr_requested pr_lifting + pr_conclusion +end + +let scale_inline_threshold_by = 8 + +let default_toplevel_multiplier = 8 + + (* CR-soon mshinwell for mshinwell: hastily-written comment, to review *) + (* We may in [Inlining_decision] need to measure the size of functions + that are below the inlining threshold. We also need to measure with + regard to benefit (see [Inlining_decision.inline_non_recursive). The + intuition for having a cached size in the second case is as follows. + If a function's body exceeds some maximum size and its argument + approximations are unknown (meaning that we cannot materially simplify + it further), we can infer without examining the function's body that + it cannot be inlined. The aim is to speed up [Inlining_decision]. + + The "original size" is [Inlining_cost.direct_call_size]. The "new size" is + the size of the function's body plus [Inlining_cost.project_size] for each + free variable and mutually recursive function accessed through the closure. + + To be inlined we need: + + body_size + + (closure_accesses * project_size) <= direct_call_size + - (evaluated_benefit * call_prob) + + i.e.: + + body_size <= direct_call_size + + (evaluated_benefit * call_prob) + - (closure_accesses * project_size) + + In this case we would be removing a single call and a projection for each + free variable that can be accessed directly (i.e. not via the closure + or the internal variable). + + evaluated_benefit = + benefit_factor + * (inline_call_cost + + ((free_variables - indirect_accesses) * inline_prim_cost)) + + (For [inline_call_cost] and [inline_prim_cost], we use the maximum these + might be across any round.) + + Substituting: + + body_size <= direct_call_size + + (benefit_factor + * (inline_call_cost + + ((free_variables - indirect_accesses) + * inline_prim_cost))) + * call_prob + - (closure_accesses * project_size) + + Rearranging: + + body_size <= direct_call_size + + (inline_call_cost * benefit_factor * call_prob) + + (free_variables * inline_prim_cost + * benefit_factor * call_prob) + - (indirect_accesses * inline_prim_cost + * benefit_factor * call_prob) + - (closure_accesses * project_size) + + The upper bound for the right-hand side is when call_prob = 1.0, + indirect_accesses = 0 and closure_accesses = 0, giving: + + direct_call_size + + (inline_call_cost * benefit_factor) + + (free_variables * inline_prim_cost * benefit_factor) + + So we should measure all functions at or below this size, but also record + the size discovered, so we can later re-check (without examining the body) + when we know [call_prob], [indirect_accesses] and [closure_accesses]. + + This number is split into parts dependent and independent of the + number of free variables: + + base = direct_call_size + (inline_call_cost * benefit_factor) + + multiplier = inline_prim_cost * benefit_factor + + body_size <= base + free_variables * multiplier + + *) +let maximum_interesting_size_of_function_body_base = + lazy begin + let max_cost = ref 0 in + for round = 0 to (Clflags.rounds ()) - 1 do + let max_size = + let inline_call_cost = cost !Clflags.inline_call_cost ~round in + direct_call_size + (inline_call_cost * benefit_factor) + in + max_cost := max !max_cost max_size + done; + !max_cost + end + +let maximum_interesting_size_of_function_body_multiplier = + lazy begin + let max_cost = ref 0 in + for round = 0 to (Clflags.rounds ()) - 1 do + let max_size = + let inline_prim_cost = cost !Clflags.inline_prim_cost ~round in + inline_prim_cost * benefit_factor + in + max_cost := max !max_cost max_size + done; + !max_cost + end + +let maximum_interesting_size_of_function_body num_free_variables = + let base = Lazy.force maximum_interesting_size_of_function_body_base in + let multiplier = + Lazy.force maximum_interesting_size_of_function_body_multiplier + in + base + (num_free_variables * multiplier) diff --git a/middle_end/inlining_cost.mli b/middle_end/inlining_cost.mli new file mode 100644 index 00000000..72327602 --- /dev/null +++ b/middle_end/inlining_cost.mli @@ -0,0 +1,141 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Measurement of the cost (including cost in space) of Flambda terms + in the context of inlining. *) + +module Threshold : sig + + (** The maximum size, in some abstract measure of space cost, that an + Flambda expression may be in order to be inlined. *) + type t = + | Never_inline + | Can_inline_if_no_larger_than of int + + val add : t -> t -> t + val sub : t -> t -> t + val min : t -> t -> t + +end + +(* Determine whether the given Flambda expression has a sufficiently low space + cost so as to fit under the given [inlining_threshold]. The [bonus] is + added to the threshold before evaluation. *) +val can_inline + : Flambda.t + -> Threshold.t + -> bonus:int + -> bool + +(* CR-soon mshinwell for pchambart: I think the name of this function might be + misleading. It should probably reflect the functionality it provides, + not the use to which it is put in another module. *) +(* As for [can_inline], but returns the decision as an inlining threshold. + If [Never_inline] is returned, the expression was too large for the + input [inlining_threshold]. Otherwise, [Can_inline_if_no_larger_than] is + returned, with the constructor argument being the measured estimated size + of the expression. *) +val can_try_inlining + : Flambda.t + -> Threshold.t + -> number_of_arguments:int + -> size_from_approximation:int option + -> Threshold.t + +module Benefit : sig + (* A model of the benefit we gain by removing a particular combination + of operations. Such removals are typically performed by inlining (for + example, [remove_call]) and simplification (for example, [remove_alloc]) + passes. *) + + type t + + val zero : t + val (+) : t -> t -> t + val max : round:int -> t -> t -> t + + val remove_call : t -> t + (* CR-soon mshinwell: [remove_alloc] should take the size of the block + (to account for removal of initializing writes). *) + val remove_alloc : t -> t + val remove_prim : t -> t + val remove_prims : t -> int -> t + val remove_branch : t -> t + val direct_call_of_indirect : t -> t + val requested_inline : t -> size_of:Flambda.t -> t + + val remove_code : Flambda.t -> t -> t + val remove_code_named : Flambda.named -> t -> t + val remove_projection : Projection.t -> t -> t + + val add_code : Flambda.t -> t -> t + val add_code_named : Flambda.named -> t -> t + val add_projection : Projection.t -> t -> t + + val print : Format.formatter -> t -> unit +end + +module Whether_sufficient_benefit : sig + (* Evaluation of the benefit of removing certain operations against an + inlining threshold. *) + + type t + + val create + : original:Flambda.t + -> toplevel:bool + -> branch_depth:int + -> Flambda.t + -> benefit:Benefit.t + -> lifting:bool + -> round:int + -> t + + val create_estimate + : original_size:int + -> toplevel:bool + -> branch_depth: int + -> new_size:int + -> benefit:Benefit.t + -> lifting:bool + -> round:int + -> t + + val evaluate : t -> bool + + val to_string : t -> string + + val print_description : subfunctions:bool -> Format.formatter -> t -> unit +end + +val scale_inline_threshold_by : int + +val default_toplevel_multiplier : int + +val direct_call_size : int + +(** If a function body exceeds this size, we can make a fast decision not + to inline it (see [Inlining_decision]). *) +val maximum_interesting_size_of_function_body : int -> int + +(** Measure the given expression to determine whether its size is at or + below the given threshold. [None] is returned if it is too big; otherwise + [Some] is returned with the measured size. *) +val lambda_smaller' : Flambda.expr -> than:int -> int option + +val lambda_size : Flambda.expr -> int diff --git a/middle_end/inlining_decision.ml b/middle_end/inlining_decision.ml new file mode 100644 index 00000000..f9cf8859 --- /dev/null +++ b/middle_end/inlining_decision.ml @@ -0,0 +1,662 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module E = Inline_and_simplify_aux.Env +module R = Inline_and_simplify_aux.Result +module U = Flambda_utils +module W = Inlining_cost.Whether_sufficient_benefit +module T = Inlining_cost.Threshold +module S = Inlining_stats_types +module D = S.Decision + +type ('a, 'b) inlining_result = + | Changed of (Flambda.t * R.t) * 'a + | Original of 'b + +type 'b good_idea = + | Try_it + | Don't_try_it of 'b + +let inline env r ~lhs_of_application + ~(function_decls : Flambda.function_declarations) + ~closure_id_being_applied ~(function_decl : Flambda.function_declaration) + ~value_set_of_closures ~only_use_of_function ~original ~recursive + ~(args : Variable.t list) ~size_from_approximation ~simplify + ~(inline_requested : Lambda.inline_attribute) + ~(specialise_requested : Lambda.specialise_attribute) + ~self_call ~fun_cost ~inlining_threshold = + let toplevel = E.at_toplevel env in + let branch_depth = E.branch_depth env in + let unrolling, always_inline, never_inline, env = + let unrolling = + E.actively_unrolling env function_decls.set_of_closures_origin + in + match unrolling with + | Some count -> + if count > 0 then + let env = + E.continue_actively_unrolling + env function_decls.set_of_closures_origin + in + true, true, false, env + else false, false, true, env + | None -> begin + let inline_annotation = + (* Merge call site annotation and function annotation. + The call site annotation takes precedence *) + match (inline_requested : Lambda.inline_attribute) with + | Always_inline | Never_inline | Unroll _ -> inline_requested + | Default_inline -> function_decl.inline + in + match inline_annotation with + | Always_inline -> false, true, false, env + | Never_inline -> false, false, true, env + | Default_inline -> false, false, false, env + | Unroll count -> + if count > 0 then + let env = + E.start_actively_unrolling + env function_decls.set_of_closures_origin (count - 1) + in + true, true, false, env + else false, false, true, env + end + in + let remaining_inlining_threshold : Inlining_cost.Threshold.t = + if always_inline then inlining_threshold + else Lazy.force fun_cost + in + let try_inlining = + if unrolling then + Try_it + else if self_call then + Don't_try_it S.Not_inlined.Self_call + else if not (E.inlining_allowed env closure_id_being_applied) then + Don't_try_it S.Not_inlined.Unrolling_depth_exceeded + else if only_use_of_function || always_inline then + Try_it + else if never_inline then + Don't_try_it S.Not_inlined.Annotation + else if !Clflags.classic_inlining then + Don't_try_it S.Not_inlined.Classic_mode + else if not (E.unrolling_allowed env function_decls.set_of_closures_origin) + && (Lazy.force recursive) then + Don't_try_it S.Not_inlined.Unrolling_depth_exceeded + else if remaining_inlining_threshold = T.Never_inline then + let threshold = + match inlining_threshold with + | 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) + 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, + then we cannot materially simplify the function. As such, we know + what the benefit of inlining it would be: just removing the call. + In this case we may be able to prove the function cannot be inlined + without traversing its body. + Note that if the function is sufficiently small, we still have to call + [simplify], because the body needs freshening before substitution. + *) + (* CR-someday mshinwell: (from GPR#8): pchambart writes: + + We may need to think a bit about that. I can't see a lot of + meaningful examples right now, but there are some cases where some + optimisation can happen even if we don't know anything about the + shape of the arguments. + + For instance + + let f x y = x + + let g x = + let y = (x,x) in + f x y + let f x y = + if x = y then ... else ... + + let g x = f x x + *) + match size_from_approximation with + | Some body_size -> + let wsb = + let benefit = Inlining_cost.Benefit.zero in + let benefit = Inlining_cost.Benefit.remove_call benefit in + let benefit = + Variable.Set.fold (fun v acc -> + try + let t = + Var_within_closure.Map.find (Var_within_closure.wrap v) + value_set_of_closures.A.bound_vars + in + match t.A.var with + | Some v -> + if (E.mem env v) then Inlining_cost.Benefit.remove_prim acc + else acc + | None -> acc + with Not_found -> acc) + function_decl.free_variables benefit + in + W.create_estimate + ~original_size:Inlining_cost.direct_call_size + ~new_size:body_size + ~toplevel:(E.at_toplevel env) + ~branch_depth:(E.branch_depth env) + ~lifting:function_decl.Flambda.is_a_functor + ~round:(E.round env) + ~benefit + in + if (not (W.evaluate wsb)) then begin + Don't_try_it + (S.Not_inlined.Without_subfunctions wsb) + end else Try_it + | None -> + (* The function is definitely too large to inline given that we don't + have any approximations for its arguments. Further, the body + 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 + else begin + (* There are useful approximations, so we should simplify. *) + Try_it + end + in + match try_inlining with + | Don't_try_it decision -> Original decision + | Try_it -> + let r = + R.set_inlining_threshold r (Some remaining_inlining_threshold) + in + let body, r_inlined = + (* First we construct the code that would result from copying the body of + the function, without doing any further inlining upon it, to the call + site. *) + Inlining_transforms.inline_by_copying_function_body ~env + ~r:(R.reset_benefit r) ~function_decls ~lhs_of_application + ~closure_id_being_applied ~specialise_requested ~inline_requested + ~function_decl ~args ~simplify + in + let num_direct_applications_seen = + (R.num_direct_applications r_inlined) - (R.num_direct_applications r) + in + assert (num_direct_applications_seen >= 0); + let keep_inlined_version decision = + (* Inlining the body of the function was sufficiently beneficial that we + will keep it, replacing the call site. We continue by allowing + further inlining within the inlined copy of the body. *) + let r_inlined = + (* The meaning of requesting inlining is that the user ensure + that the function has a benefit of at least its size. It is not + added to the benefit exposed by the inlining because the user should + have taken that into account before annotating the function. *) + if always_inline then + R.map_benefit r_inlined + (Inlining_cost.Benefit.max ~round:(E.round env) + Inlining_cost.Benefit.(requested_inline ~size_of:body zero)) + else r_inlined + in + let r = + R.map_benefit r_inlined (Inlining_cost.Benefit.(+) (R.benefit r)) + in + let env = E.note_entering_inlined env in + let env = + (* We decrement the unrolling count even if the function is not + recursive to avoid having to check whether or not it is recursive *) + E.inside_unrolled_function env function_decls.set_of_closures_origin + in + let env = E.inside_inlined_function env closure_id_being_applied in + let env = + if E.inlining_level env = 0 + (* If the function was considered for inlining without considering + its sub-functions, and it is not below another inlining choice, + then we are certain that this code will be kept. *) + then env + else E.inlining_level_up env + in + Changed ((simplify env r body), decision) + in + if always_inline then + keep_inlined_version S.Inlined.Annotation + else if only_use_of_function then + keep_inlined_version S.Inlined.Decl_local_to_application + else begin + let wsb = + W.create ~original body + ~toplevel:(E.at_toplevel env) + ~branch_depth:(E.branch_depth env) + ~lifting:function_decl.Flambda.is_a_functor + ~round:(E.round env) + ~benefit:(R.benefit r_inlined) + in + if W.evaluate wsb then + keep_inlined_version (S.Inlined.Without_subfunctions wsb) + else if num_direct_applications_seen < 1 then begin + (* Inlining the body of the function did not appear sufficiently + beneficial; however, it may become so if we inline within the body + first. We try that next, unless it is known that there are were + no direct applications in the simplified body computed above, meaning + no opportunities for inlining. *) + Original (S.Not_inlined.Without_subfunctions wsb) + end else begin + let env = E.inlining_level_up env in + let env = E.note_entering_inlined env in + let env = + (* We decrement the unrolling count even if the function is recursive + to avoid having to check whether or not it is recursive *) + E.inside_unrolled_function env function_decls.set_of_closures_origin + in + let body, r_inlined = simplify env r_inlined body in + let wsb_with_subfunctions = + W.create ~original body + ~toplevel:(E.at_toplevel env) + ~branch_depth:(E.branch_depth env) + ~lifting:function_decl.Flambda.is_a_functor + ~round:(E.round env) + ~benefit:(R.benefit r_inlined) + in + if W.evaluate wsb_with_subfunctions then begin + let res = + (body, R.map_benefit r_inlined + (Inlining_cost.Benefit.(+) (R.benefit r))) + in + let decision = + S.Inlined.With_subfunctions (wsb, wsb_with_subfunctions) + in + Changed (res, decision) + end + else begin + (* r_inlined contains an approximation that may be invalid for the + untransformed expression: it may reference functions that only + exists if the body of the function is in fact inlined. + If the function approximation contained an approximation that + does not depend on the actual values of its arguments, it + could be returned instead of [A.value_unknown]. *) + let decision = + S.Not_inlined.With_subfunctions (wsb, wsb_with_subfunctions) + in + Original decision + end + end + end + +let specialise env r ~lhs_of_application + ~(function_decls : Flambda.function_declarations) + ~(function_decl : Flambda.function_declaration) + ~closure_id_being_applied + ~(value_set_of_closures : Simple_value_approx.value_set_of_closures) + ~args ~args_approxs ~dbg ~simplify ~original ~recursive ~self_call + ~inlining_threshold ~fun_cost + ~inline_requested ~specialise_requested = + let bound_vars = + lazy + (let closures_required = + Flambda_utils.closures_required_by_entry_point + ~entry_point:closure_id_being_applied + ~backend:(E.backend env) + function_decls + in + let bound_vars_required = + Variable.Set.fold (fun fun_var bound_vars_required -> + let bound_vars = + Flambda_utils.variables_bound_by_the_closure + (Closure_id.wrap fun_var) + function_decls + in + Variable.Set.union bound_vars bound_vars_required) + closures_required + Variable.Set.empty + in + Var_within_closure.Map.filter (fun var _approx -> + Variable.Set.mem (Var_within_closure.unwrap var) bound_vars_required) + value_set_of_closures.bound_vars) + in + let invariant_params = value_set_of_closures.invariant_params in + let has_no_useful_approxes = + lazy + (List.for_all2 + (fun id approx -> + not ((A.useful approx) + && Variable.Map.mem id (Lazy.force invariant_params))) + function_decl.params args_approxs) + in + let always_specialise, never_specialise = + (* Merge call site annotation and function annotation. + The call site annotation takes precedence *) + match (specialise_requested : Lambda.specialise_attribute) with + | Always_specialise -> true, false + | Never_specialise -> false, true + | Default_specialise -> begin + match (function_decl.specialise : Lambda.specialise_attribute) with + | Always_specialise -> true, false + | Never_specialise -> false, true + | Default_specialise -> false, false + end + in + let remaining_inlining_threshold : Inlining_cost.Threshold.t = + if always_specialise then inlining_threshold + else Lazy.force fun_cost + in + let try_specialising = + (* Try specialising if the function: + - is recursive; and + - is closed (it and all other members of the set of closures on which + it depends); and + - has useful approximations for some invariant parameters. *) + if !Clflags.classic_inlining then + Don't_try_it S.Not_specialised.Classic_mode + else if always_specialise && not (Lazy.force has_no_useful_approxes) then + Try_it + else if never_specialise then + Don't_try_it S.Not_specialised.Annotation + else if self_call then + Don't_try_it S.Not_specialised.Self_call + else if remaining_inlining_threshold = T.Never_inline then + let threshold = + match inlining_threshold with + | 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) + 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 + Don't_try_it S.Not_specialised.Not_recursive + else if Variable.Map.is_empty (Lazy.force invariant_params) then + Don't_try_it S.Not_specialised.No_invariant_parameters + else if Lazy.force has_no_useful_approxes then + Don't_try_it S.Not_specialised.No_useful_approximations + else Try_it + in + match try_specialising with + | Don't_try_it decision -> Original decision + | Try_it -> begin + let r = + R.set_inlining_threshold r (Some remaining_inlining_threshold) + in + let copied_function_declaration = + Inlining_transforms.inline_by_copying_function_declaration ~env + ~r:(R.reset_benefit r) ~lhs_of_application + ~function_decls ~closure_id_being_applied ~function_decl + ~args ~args_approxs + ~invariant_params:value_set_of_closures.invariant_params + ~specialised_args:value_set_of_closures.specialised_args + ~direct_call_surrogates:value_set_of_closures.direct_call_surrogates + ~dbg ~simplify ~inline_requested + in + match copied_function_declaration with + | Some (expr, r_inlined) -> + let wsb = + W.create ~original expr + ~toplevel:false + ~branch_depth:(E.branch_depth env) + ~lifting:false + ~round:(E.round env) + ~benefit:(R.benefit r_inlined) + in + let env = + (* CR-someday lwhite: could avoid calculating this if stats is turned + off *) + let closure_ids = + Closure_id.Set.of_list ( + List.map Closure_id.wrap + (Variable.Set.elements (Variable.Map.keys function_decls.funs))) + in + E.note_entering_specialised env ~closure_ids + in + if always_specialise || W.evaluate wsb then begin + let r_inlined = + if always_specialise then + R.map_benefit r_inlined + (Inlining_cost.Benefit.max ~round:(E.round env) + Inlining_cost.Benefit.(requested_inline ~size_of:expr zero)) + else r_inlined + in + let r = + R.map_benefit r_inlined (Inlining_cost.Benefit.(+) (R.benefit r)) + in + let closure_env = + let env = + if E.inlining_level env = 0 + (* If the function was considered for specialising without + considering its sub-functions, and it is not below another + inlining choice, then we are certain that this code will + be kept. *) + then env + else E.inlining_level_up env + in + E.set_never_inline_outside_closures env + in + let application_env = E.set_never_inline_inside_closures env in + let expr, r = simplify closure_env r expr in + let res = simplify application_env r expr in + let decision = + if always_specialise then S.Specialised.Annotation + else S.Specialised.Without_subfunctions wsb + in + Changed (res, decision) + end else begin + let closure_env = + let env = E.inlining_level_up env in + E.set_never_inline_outside_closures env + in + let expr, r_inlined = simplify closure_env r_inlined expr in + let wsb_with_subfunctions = + W.create ~original expr + ~toplevel:false + ~branch_depth:(E.branch_depth env) + ~lifting:false + ~round:(E.round env) + ~benefit:(R.benefit r_inlined) + in + if W.evaluate wsb_with_subfunctions then begin + let r = + R.map_benefit r_inlined + (Inlining_cost.Benefit.(+) (R.benefit r)) + in + let application_env = E.set_never_inline_inside_closures env in + let res = simplify application_env r expr in + let decision = + S.Specialised.With_subfunctions (wsb, wsb_with_subfunctions) + in + Changed (res, decision) + end else begin + let decision = + S.Not_specialised.Not_beneficial (wsb, wsb_with_subfunctions) + in + Original decision + end + end + | None -> + let decision = S.Not_specialised.No_useful_approximations in + Original decision + end + +let for_call_site ~env ~r ~(function_decls : Flambda.function_declarations) + ~lhs_of_application ~closure_id_being_applied + ~(function_decl : Flambda.function_declaration) + ~(value_set_of_closures : Simple_value_approx.value_set_of_closures) + ~args ~args_approxs ~dbg ~simplify ~inline_requested + ~specialise_requested = + if List.length args <> List.length args_approxs then begin + Misc.fatal_error "Inlining_decision.for_call_site: inconsistent lengths \ + of [args] and [args_approxs]" + end; + (* Remove unroll attributes from functions we are already actively + unrolling, otherwise they'll be unrolled again next round. *) + let inline_requested : Lambda.inline_attribute = + match (inline_requested : Lambda.inline_attribute) with + | Unroll _ -> begin + let unrolling = + E.actively_unrolling env function_decls.set_of_closures_origin + in + match unrolling with + | Some _ -> Default_inline + | None -> inline_requested + end + | Always_inline | Default_inline | Never_inline -> inline_requested + in + let original = + Flambda.Apply { + func = lhs_of_application; + args; + kind = Direct closure_id_being_applied; + dbg; + inline = inline_requested; + specialise = specialise_requested; + } + in + let original_r = + R.set_approx (R.seen_direct_application r) (A.value_unknown Other) + in + if function_decl.stub then + let body, r = + Inlining_transforms.inline_by_copying_function_body ~env ~r + ~function_decls ~lhs_of_application ~closure_id_being_applied + ~inline_requested ~specialise_requested ~function_decl ~args ~simplify + in + simplify env r body + else if E.never_inline env then + (* This case only occurs when examining the body of a stub function + but not in the context of inlining said function. As such, there + is nothing to do here (and no decision to report). *) + original, original_r + else begin + let env = E.unset_never_inline_inside_closures env in + let env = + E.note_entering_call env + ~closure_id:closure_id_being_applied ~debuginfo:dbg + in + let max_level = + Clflags.Int_arg_helper.get ~key:(E.round env) !Clflags.inline_max_depth + in + let raw_inlining_threshold = R.inlining_threshold r in + let max_inlining_threshold = + if E.at_toplevel env then + Inline_and_simplify_aux.initial_inlining_toplevel_threshold + ~round:(E.round env) + else + Inline_and_simplify_aux.initial_inlining_threshold ~round:(E.round env) + in + let unthrottled_inlining_threshold = + match raw_inlining_threshold with + | None -> max_inlining_threshold + | Some inlining_threshold -> inlining_threshold + in + let inlining_threshold = + T.min unthrottled_inlining_threshold max_inlining_threshold + in + let inlining_threshold_diff = + T.sub unthrottled_inlining_threshold inlining_threshold + in + let inlining_prevented = + match inlining_threshold with + | Never_inline -> true + | Can_inline_if_no_larger_than _ -> false + in + let simpl = + if inlining_prevented then + Original (D.Prevented Function_prevented_from_inlining) + else if E.inlining_level env >= max_level then + Original (D.Prevented Level_exceeded) + else begin + let self_call = + E.inside_set_of_closures_declaration + function_decls.set_of_closures_origin env + in + let fun_cost = + lazy + (Inlining_cost.can_try_inlining function_decl.body + inlining_threshold + ~number_of_arguments:(List.length function_decl.params) + (* CR-someday mshinwell: for the moment, this is None, since + the Inlining_cost code isn't checking sizes up to the max + inlining threshold---this seems to take too long. *) + ~size_from_approximation:None) + in + let fun_var = + U.find_declaration_variable closure_id_being_applied function_decls + in + let recursive = + lazy + (Variable.Set.mem fun_var + ((Find_recursive_functions.in_function_declarations + function_decls + ~backend:(E.backend env)))) + in + let specialise_result = + specialise env r ~lhs_of_application ~function_decls ~recursive + ~closure_id_being_applied ~function_decl ~value_set_of_closures + ~args ~args_approxs ~dbg ~simplify ~original ~inline_requested + ~specialise_requested ~fun_cost ~self_call ~inlining_threshold + in + match specialise_result with + | Changed (res, spec_reason) -> + Changed (res, D.Specialised spec_reason) + | Original spec_reason -> + let only_use_of_function = false in + (* If we didn't specialise then try inlining *) + let size_from_approximation = + match + Variable.Map.find fun_var (Lazy.force value_set_of_closures.size) + with + | size -> size + | exception Not_found -> + Misc.fatal_errorf "Approximation does not give a size for the \ + function having fun_var %a. value_set_of_closures: %a" + Variable.print fun_var + A.print_value_set_of_closures value_set_of_closures + in + let inline_result = + inline env r ~function_decls ~lhs_of_application + ~closure_id_being_applied ~function_decl ~value_set_of_closures + ~only_use_of_function ~original ~recursive + ~inline_requested ~specialise_requested ~args + ~size_from_approximation ~simplify ~fun_cost ~self_call + ~inlining_threshold + in + match inline_result with + | Changed (res, inl_reason) -> + Changed (res, D.Inlined (spec_reason, inl_reason)) + | Original inl_reason -> + Original (D.Unchanged (spec_reason, inl_reason)) + end + in + let res, decision = + match simpl with + | Original decision -> (original, original_r), decision + | Changed ((expr, r), decision) -> + let res = + if E.inlining_level env = 0 + then expr, R.set_inlining_threshold r raw_inlining_threshold + else expr, R.add_inlining_threshold r inlining_threshold_diff + in + res, decision + in + E.record_decision env decision; + res + end + +(* We do not inline inside stubs, which are always inlined at their call site. + Inlining inside the declaration of a stub could result in more code than + expected being inlined (e.g. the body of a function that was transformed + by adding the stub). *) +let should_inline_inside_declaration (decl : Flambda.function_declaration) = + not decl.stub diff --git a/middle_end/inlining_decision.mli b/middle_end/inlining_decision.mli new file mode 100644 index 00000000..40cb4f66 --- /dev/null +++ b/middle_end/inlining_decision.mli @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** See the Flambda manual chapter for an explanation in prose of the + inlining decision procedure. *) + +(** Try to inline a full application of a known function, guided by various + heuristics. *) +val for_call_site + : env:Inline_and_simplify_aux.Env.t + -> r:Inline_and_simplify_aux.Result.t + -> function_decls:Flambda.function_declarations + -> lhs_of_application:Variable.t + -> closure_id_being_applied:Closure_id.t + -> function_decl:Flambda.function_declaration + -> value_set_of_closures:Simple_value_approx.value_set_of_closures + -> args:Variable.t list + -> args_approxs:Simple_value_approx.t list + -> dbg:Debuginfo.t + -> simplify:Inlining_decision_intf.simplify + -> inline_requested:Lambda.inline_attribute + -> specialise_requested:Lambda.specialise_attribute + -> Flambda.t * Inline_and_simplify_aux.Result.t + +(** When a function declaration is encountered by [for_call_site], the body + may be subject to inlining immediately, thus changing the declaration. + This function must return [true] for that to be able to happen. *) +val should_inline_inside_declaration : Flambda.function_declaration -> bool diff --git a/middle_end/inlining_decision_intf.mli b/middle_end/inlining_decision_intf.mli new file mode 100644 index 00000000..15a08031 --- /dev/null +++ b/middle_end/inlining_decision_intf.mli @@ -0,0 +1,49 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-someday mshinwell: name of this source file could now be improved *) + +type 'a by_copying_function_body = + env:Inline_and_simplify_aux.Env.t + -> r:Inline_and_simplify_aux.Result.t + -> clos:Flambda.function_declarations + -> lfunc:Flambda.t + -> fun_id:Closure_id.t + -> func:Flambda.function_declaration + -> args:Flambda.t list + -> Flambda.t * Inline_and_simplify_aux.Result.t + +type 'a by_copying_function_declaration = + env:Inline_and_simplify_aux.Env.t + -> r:Inline_and_simplify_aux.Result.t + -> funct:Flambda.t + -> clos:Flambda.function_declarations + -> fun_id:Closure_id.t + -> func:Flambda.function_declaration + -> args_with_approxs: + (Flambda.t list) * (Simple_value_approx.t list) + -> invariant_params:Variable.Set.t + -> specialised_args:Variable.Set.t + -> dbg:Debuginfo.t + -> (Flambda.t * Inline_and_simplify_aux.Result.t) option + +type simplify = + Inline_and_simplify_aux.Env.t + -> Inline_and_simplify_aux.Result.t + -> Flambda.t + -> Flambda.t * Inline_and_simplify_aux.Result.t diff --git a/middle_end/inlining_stats.ml b/middle_end/inlining_stats.ml new file mode 100644 index 00000000..d0d18fc8 --- /dev/null +++ b/middle_end/inlining_stats.ml @@ -0,0 +1,257 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Closure_stack = struct + type t = node list + + and node = + | Closure of Closure_id.t * Debuginfo.t + | Call of Closure_id.t * Debuginfo.t + | Inlined + | Specialised of Closure_id.Set.t + + let create () = [] + + let note_entering_closure t ~closure_id ~debuginfo = + if not !Clflags.inlining_report then t + else + match t with + | [] | (Closure _ | Inlined | Specialised _) :: _-> + (Closure (closure_id, debuginfo)) :: t + | (Call _) :: _ -> + Misc.fatal_errorf "note_entering_closure: unexpected Call node" + + (* CR-someday lwhite: since calls do not have a unique id it is possible + some calls will end up sharing nodes. *) + let note_entering_call t ~closure_id ~debuginfo = + if not !Clflags.inlining_report then t + else + match t with + | [] | (Closure _ | Inlined | Specialised _) :: _ -> + (Call (closure_id, debuginfo)) :: t + | (Call _) :: _ -> + Misc.fatal_errorf "note_entering_call: unexpected Call node" + + let note_entering_inlined t = + if not !Clflags.inlining_report then t + else + match t with + | [] | (Closure _ | Inlined | Specialised _) :: _-> + Misc.fatal_errorf "note_entering_inlined: missing Call node" + | (Call _) :: _ -> Inlined :: t + + let note_entering_specialised t ~closure_ids = + if not !Clflags.inlining_report then t + else + match t with + | [] | (Closure _ | Inlined | Specialised _) :: _ -> + Misc.fatal_errorf "note_entering_specialised: missing Call node" + | (Call _) :: _ -> Specialised closure_ids :: t + +end + +let log + : (Closure_stack.t * Inlining_stats_types.Decision.t) list ref + = ref [] + +let record_decision decision ~closure_stack = + if !Clflags.inlining_report then begin + match closure_stack with + | [] + | Closure_stack.Closure _ :: _ + | Closure_stack.Inlined :: _ + | Closure_stack.Specialised _ :: _ -> + Misc.fatal_errorf "record_decision: missing Call node" + | Closure_stack.Call _ :: _ -> + log := (closure_stack, decision) :: !log + end + +module Inlining_report = struct + + module Place = struct + type kind = + | Closure + | Call + + type t = Debuginfo.t * Closure_id.t * kind + + let compare ((d1, cl1, k1) : t) ((d2, cl2, k2) : t) = + let c = compare d1.dinfo_file d2.dinfo_file in + if c <> 0 then c else + let c = compare d1.dinfo_line d2.dinfo_line in + if c <> 0 then c else + let c = compare d1.dinfo_char_end d2.dinfo_char_end in + if c <> 0 then c else + let c = compare d1.dinfo_char_start d2.dinfo_char_start in + if c <> 0 then c else + let c = Closure_id.compare cl1 cl2 in + if c <> 0 then c else + match k1, k2 with + | Closure, Closure -> 0 + | Call, Call -> 0 + | Closure, Call -> 1 + | Call, Closure -> -1 + end + + module Place_map = Map.Make(Place) + + type t = node Place_map.t + + and node = + | Closure of t + | Call of call + + and call = + { decision: Inlining_stats_types.Decision.t option; + inlined: t option; + specialised: t option; } + + let empty_call = + { decision = None; + inlined = None; + specialised = None; } + + (* Prevented or unchanged decisions may be overridden by a later look at the + same call. Other decisions may also be "overridden" because calls are not + uniquely identified. *) + let add_call_decision call (decision : Inlining_stats_types.Decision.t) = + match call.decision, decision with + | None, _ -> { call with decision = Some decision } + | Some _, Prevented _ -> call + | Some (Prevented _), _ -> { call with decision = Some decision } + | Some (Specialised _), _ -> call + | Some _, Specialised _ -> { call with decision = Some decision } + | Some (Inlined _), _ -> call + | Some _, Inlined _ -> { call with decision = Some decision } + | Some Unchanged _, Unchanged _ -> call + + let add_decision t (stack, decision) = + let rec loop t : Closure_stack.t -> _ = function + | Closure(cl, dbg) :: rest -> + let key : Place.t = (dbg, cl, Closure) in + let v = + try + match Place_map.find key t with + | Closure v -> v + | Call _ -> assert false + with Not_found -> Place_map.empty + in + let v = loop v rest in + Place_map.add key (Closure v) t + | Call(cl, dbg) :: rest -> + let key : Place.t = (dbg, cl, Call) in + let v = + try + match Place_map.find key t with + | Call v -> v + | Closure _ -> assert false + with Not_found -> empty_call + in + let v = + match rest with + | [] -> add_call_decision v decision + | Inlined :: rest -> + let inlined = + match v.inlined with + | None -> Place_map.empty + | Some inlined -> inlined + in + let inlined = loop inlined rest in + { v with inlined = Some inlined } + | Specialised _ :: rest -> + let specialised = + match v.specialised with + | None -> Place_map.empty + | Some specialised -> specialised + in + let specialised = loop specialised rest in + { v with specialised = Some specialised } + | Call _ :: _ -> assert false + | Closure _ :: _ -> assert false + in + Place_map.add key (Call v) t + | [] -> assert false + | Inlined :: _ -> assert false + | Specialised _ :: _ -> assert false + in + loop t (List.rev stack) + + let build log = + List.fold_left add_decision Place_map.empty log + + let print_stars ppf n = + let s = String.make n '*' in + Format.fprintf ppf "%s" s + + let rec print ~depth ppf t = + Place_map.iter (fun (dbg, cl, _) v -> + match v with + | Closure t -> + Format.fprintf ppf "@[%a Definition of %a%s@]@." + print_stars (depth + 1) + Closure_id.print cl + (Debuginfo.to_string dbg); + print ppf ~depth:(depth + 1) t; + if depth = 0 then Format.pp_print_newline ppf () + | Call c -> + match c.decision with + | None -> + Misc.fatal_error "Inlining_report.print: missing call decision" + | Some decision -> + Format.pp_open_vbox ppf (depth + 2); + Format.fprintf ppf "@[%a Application of %a%s@]@;@;@[%a@]" + print_stars (depth + 1) + Closure_id.print cl + (Debuginfo.to_string dbg) + Inlining_stats_types.Decision.summary decision; + Format.pp_close_box ppf (); + Format.pp_print_newline ppf (); + Format.pp_print_newline ppf (); + Inlining_stats_types.Decision.calculation ~depth:(depth + 1) + ppf decision; + begin + match c.specialised with + | None -> () + | Some specialised -> + print ppf ~depth:(depth + 1) specialised + end; + begin + match c.inlined with + | None -> () + | Some inlined -> + print ppf ~depth:(depth + 1) inlined + end; + if depth = 0 then Format.pp_print_newline ppf ()) + t + + let print ppf t = print ~depth:0 ppf t + +end + +let really_save_then_forget_decisions ~output_prefix = + let report = Inlining_report.build !log in + let out_channel = open_out (output_prefix ^ ".inlining.org") in + let ppf = Format.formatter_of_out_channel out_channel in + Inlining_report.print ppf report; + close_out out_channel; + log := [] + +let save_then_forget_decisions ~output_prefix = + if !Clflags.inlining_report then begin + really_save_then_forget_decisions ~output_prefix + end diff --git a/middle_end/inlining_stats.mli b/middle_end/inlining_stats.mli new file mode 100644 index 00000000..b0716a2a --- /dev/null +++ b/middle_end/inlining_stats.mli @@ -0,0 +1,46 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Closure_stack : sig + type t + + val create : unit -> t + + val note_entering_closure + : t + -> closure_id:Closure_id.t + -> debuginfo:Debuginfo.t + -> t + + val note_entering_call + : t + -> closure_id:Closure_id.t + -> debuginfo:Debuginfo.t + -> t + + val note_entering_inlined : t -> t + val note_entering_specialised : t -> closure_ids:Closure_id.Set.t -> t + +end + +val record_decision + : Inlining_stats_types.Decision.t + -> closure_stack:Closure_stack.t + -> unit + +val save_then_forget_decisions : output_prefix:string -> unit diff --git a/middle_end/inlining_stats_types.ml b/middle_end/inlining_stats_types.ml new file mode 100644 index 00000000..568c5d83 --- /dev/null +++ b/middle_end/inlining_stats_types.ml @@ -0,0 +1,281 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Wsb = Inlining_cost.Whether_sufficient_benefit + +let print_stars ppf n = + let s = String.make n '*' in + Format.fprintf ppf "%s" s + +let print_calculation ~depth ~title ~subfunctions ppf wsb = + Format.pp_open_vbox ppf (depth + 2); + Format.fprintf ppf "@[%a %s@]@;@;@[%a@]" + print_stars (depth + 1) + title + (Wsb.print_description ~subfunctions) wsb; + Format.pp_close_box ppf (); + Format.pp_print_newline ppf (); + Format.pp_print_newline ppf () + +module Inlined = struct + + type t = + | Annotation + | Decl_local_to_application + | Without_subfunctions of Wsb.t + | With_subfunctions of Wsb.t * Wsb.t + + let summary ppf = function + | Annotation -> + Format.pp_print_text ppf + "This function was inlined because of an annotation." + | Decl_local_to_application -> + Format.pp_print_text ppf + "This function was inlined because it was local to this application." + | Without_subfunctions _ -> + Format.pp_print_text ppf + "This function was inlined because \ + the expected benefit outweighed the change in code size." + | With_subfunctions _ -> + Format.pp_print_text ppf + "This function was inlined because \ + the expected benefit outweighed the change in code size." + + let calculation ~depth ppf = function + | Annotation -> () + | Decl_local_to_application -> () + | Without_subfunctions wsb -> + print_calculation + ~depth ~title:"Inlining benefit calculation" + ~subfunctions:false ppf wsb + | With_subfunctions(_, wsb) -> + print_calculation + ~depth ~title:"Inlining benefit calculation" + ~subfunctions:true ppf wsb + +end + +module Not_inlined = struct + type t = + | Classic_mode + | Function_obviously_too_large of int + | Annotation + | Unspecialised + | Unrolling_depth_exceeded + | Self_call + | Without_subfunctions of Wsb.t + | With_subfunctions of Wsb.t * Wsb.t + + + let summary ppf = function + | Classic_mode -> + Format.pp_print_text ppf + "This function was prevented from inlining by `-Oclassic'." + | Function_obviously_too_large size -> + Format.pp_print_text ppf + "This function was not inlined because \ + it was obviously too large"; + Format.fprintf ppf "(%i)" size + | Annotation -> + Format.pp_print_text ppf + "This function was not inlined because \ + of an annotation." + | Unspecialised -> + Format.pp_print_text ppf + "This function was not inlined because \ + its parameters could not be specialised." + | Unrolling_depth_exceeded -> + Format.pp_print_text ppf + "This function was not inlined because \ + its unrolling depth was exceeded." + | Self_call -> + Format.pp_print_text ppf + "This function was not inlined because \ + it was a self call." + | Without_subfunctions _ -> + Format.pp_print_text ppf + "This function was not inlined because \ + the expected benefit did not outweigh the change in code size." + | With_subfunctions _ -> + Format.pp_print_text ppf + "This function was not inlined because \ + the expected benefit did not outweigh the change in code size." + + let calculation ~depth ppf = function + | Classic_mode + | Function_obviously_too_large _ + | Annotation + | Unspecialised + | Unrolling_depth_exceeded + | Self_call -> () + | Without_subfunctions wsb -> + print_calculation + ~depth ~title:"Inlining benefit calculation" + ~subfunctions:false ppf wsb + | With_subfunctions(_, wsb) -> + print_calculation + ~depth ~title:"Inlining benefit calculation" + ~subfunctions:true ppf wsb + +end + +module Specialised = struct + type t = + | Annotation + | Without_subfunctions of Wsb.t + | With_subfunctions of Wsb.t * Wsb.t + + let summary ppf = function + | Annotation -> + Format.pp_print_text ppf + "This function was specialised because of an annotation." + | Without_subfunctions _ -> + Format.pp_print_text ppf + "This function was specialised because the expected benefit \ + outweighed the change in code size." + | With_subfunctions _ -> + Format.pp_print_text ppf + "This function was specialised because the expected benefit \ + outweighed the change in code size." + + + let calculation ~depth ppf = function + | Annotation -> () + | Without_subfunctions wsb -> + print_calculation + ~depth ~title:"Specialising benefit calculation" + ~subfunctions:false ppf wsb + | With_subfunctions(_, wsb) -> + print_calculation + ~depth ~title:"Specialising benefit calculation" + ~subfunctions:true ppf wsb +end + +module Not_specialised = struct + type t = + | Classic_mode + | Function_obviously_too_large of int + | Annotation + | Not_recursive + | Not_closed + | No_invariant_parameters + | No_useful_approximations + | Self_call + | Not_beneficial of Wsb.t * Wsb.t + + let summary ppf = function + | Classic_mode -> + Format.pp_print_text ppf + "This function was prevented from specialising by \ + `-Oclassic'." + | Function_obviously_too_large size -> + Format.pp_print_text ppf + "This function was not specialised because \ + it was obviously too large"; + Format.fprintf ppf "(%i)" size + | Annotation -> + Format.pp_print_text ppf + "This function was not specialised because \ + of an annotation." + | Not_recursive -> + Format.pp_print_text ppf + "This function was not specialised because \ + it is not recursive." + | Not_closed -> + Format.pp_print_text ppf + "This function was not specialised because \ + it is not closed." + | No_invariant_parameters -> + Format.pp_print_text ppf + "This function was not specialised because \ + it has no invariant parameters." + | No_useful_approximations -> + Format.pp_print_text ppf + "This function was not specialised because \ + there was no useful information about any of its invariant \ + parameters." + | Self_call -> + Format.pp_print_text ppf + "This function was not specialised because \ + it was a self call." + | Not_beneficial _ -> + Format.pp_print_text ppf + "This function was not specialised because \ + the expected benefit did not outweigh the change in code size." + + let calculation ~depth ppf = function + | Classic_mode + | Function_obviously_too_large _ + | Annotation + | Not_recursive + | Not_closed + | No_invariant_parameters + | No_useful_approximations + | Self_call -> () + | Not_beneficial(_, wsb) -> + print_calculation + ~depth ~title:"Specialising benefit calculation" + ~subfunctions:true ppf wsb + +end + +module Prevented = struct + type t = + | Function_prevented_from_inlining + | Level_exceeded + + let summary ppf = function + | Function_prevented_from_inlining -> + Format.pp_print_text ppf + "This function was prevented from inlining or specialising." + | Level_exceeded -> + Format.pp_print_text ppf + "This function was prevented from inlining or specialising \ + because the inlining depth was exceeded." +end + +module Decision = struct + type t = + | Prevented of Prevented.t + | Specialised of Specialised.t + | Inlined of Not_specialised.t * Inlined.t + | Unchanged of Not_specialised.t * Not_inlined.t + + let summary ppf = function + | Prevented p -> + Prevented.summary ppf p + | Specialised s -> + Specialised.summary ppf s + | Inlined (s, i) -> + Format.fprintf ppf "@[@[%a@]@;@;@[%a@]@]" + Not_specialised.summary s Inlined.summary i + | Unchanged (s, i) -> + Format.fprintf ppf "@[@[%a@]@;@;@[%a@]@]" + Not_specialised.summary s Not_inlined.summary i + + let calculation ~depth ppf = function + | Prevented _ -> () + | Specialised s -> + Specialised.calculation ~depth ppf s + | Inlined (s, i) -> + Not_specialised.calculation ~depth ppf s; + Inlined.calculation ~depth ppf i + | Unchanged (s, i) -> + Not_specialised.calculation ~depth ppf s; + Not_inlined.calculation ~depth ppf i +end diff --git a/middle_end/inlining_stats_types.mli b/middle_end/inlining_stats_types.mli new file mode 100644 index 00000000..c0915228 --- /dev/null +++ b/middle_end/inlining_stats_types.mli @@ -0,0 +1,88 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* Types used for producing statistics about inlining. *) + +module Inlined : sig + type t = + | Annotation + | Decl_local_to_application + | Without_subfunctions of + Inlining_cost.Whether_sufficient_benefit.t + | With_subfunctions of + Inlining_cost.Whether_sufficient_benefit.t + * Inlining_cost.Whether_sufficient_benefit.t +end + +module Not_inlined : sig + type t = + | Classic_mode + | Function_obviously_too_large of int + | Annotation + | Unspecialised + | Unrolling_depth_exceeded + | Self_call + | Without_subfunctions of + Inlining_cost.Whether_sufficient_benefit.t + | With_subfunctions of + Inlining_cost.Whether_sufficient_benefit.t + * Inlining_cost.Whether_sufficient_benefit.t +end + +module Specialised : sig + type t = + | Annotation + | Without_subfunctions of + Inlining_cost.Whether_sufficient_benefit.t + | With_subfunctions of + Inlining_cost.Whether_sufficient_benefit.t + * Inlining_cost.Whether_sufficient_benefit.t +end + +module Not_specialised : sig + type t = + | Classic_mode + | Function_obviously_too_large of int + | Annotation + | Not_recursive + | Not_closed + | No_invariant_parameters + | No_useful_approximations + | Self_call + | Not_beneficial of + Inlining_cost.Whether_sufficient_benefit.t + * Inlining_cost.Whether_sufficient_benefit.t +end + +module Prevented : sig + type t = + | Function_prevented_from_inlining + | Level_exceeded +end + +module Decision : sig + + type t = + | Prevented of Prevented.t + | Specialised of Specialised.t + | Inlined of Not_specialised.t * Inlined.t + | Unchanged of Not_specialised.t * Not_inlined.t + + val summary : Format.formatter -> t -> unit + val calculation : depth:int -> Format.formatter -> t -> unit +end diff --git a/middle_end/inlining_transforms.ml b/middle_end/inlining_transforms.ml new file mode 100644 index 00000000..58c24421 --- /dev/null +++ b/middle_end/inlining_transforms.ml @@ -0,0 +1,380 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module B = Inlining_cost.Benefit +module E = Inline_and_simplify_aux.Env +module R = Inline_and_simplify_aux.Result + +let new_var name = + Variable.create name + ~current_compilation_unit:(Compilation_unit.get_current_exn ()) + +let which_function_parameters_can_we_specialise ~params ~args + ~args_approxs ~(invariant_params:Variable.Set.t Variable.Map.t lazy_t) + ~specialised_args = + assert (List.length params = List.length args); + assert (List.length args = List.length args_approxs); + List.fold_right2 (fun (var, arg) approx + (worth_specialising_args, spec_args, args, args_decl) -> + let spec_args = + if Variable.Map.mem var (Lazy.force invariant_params) || + Variable.Set.mem var specialised_args + then + Variable.Map.add var arg spec_args + else + spec_args + in + let worth_specialising_args = + if Simple_value_approx.useful approx + && Variable.Map.mem var (Lazy.force invariant_params) + then + Variable.Set.add var worth_specialising_args + else + worth_specialising_args + in + worth_specialising_args, spec_args, arg :: args, args_decl) + (List.combine params args) args_approxs + (Variable.Set.empty, Variable.Map.empty, [], []) + +(** Fold over all variables bound by the given closure, which is bound to the + variable [lhs_of_application], and corresponds to the given + [function_decls]. Each variable bound by the closure is passed to the + user-specified function as an [Flambda.named] value that projects the + variable from its closure. *) +let fold_over_projections_of_vars_bound_by_closure ~closure_id_being_applied + ~lhs_of_application ~function_decls ~init ~f = + Variable.Set.fold (fun var acc -> + let expr : Flambda.named = + Project_var { + closure = lhs_of_application; + closure_id = closure_id_being_applied; + var = Var_within_closure.wrap var; + } + in + f ~acc ~var ~expr) + (Flambda_utils.variables_bound_by_the_closure closure_id_being_applied + function_decls) + init + +let set_inline_attribute_on_all_apply body inline specialise = + Flambda_iterators.map_toplevel_expr (function + | Apply apply -> Apply { apply with inline; specialise } + | expr -> expr) + body + +(** Assign fresh names for a function's parameters and rewrite the body to + use these new names. *) +let copy_of_function's_body_with_freshened_params env + ~(function_decl : Flambda.function_declaration) = + let params = function_decl.params in + (* We cannot avoid the substitution in the case where we are inlining + inside the function itself. This can happen in two ways: either + (a) we are inlining the function itself directly inside its declaration; + or (b) we are inlining the function into an already-inlined copy. + For (a) we cannot short-cut the substitution by freshening since the + original [params] may still be referenced; for (b) we cannot do it + either since the freshening may already be renaming the parameters for + the first inlining of the function. *) + if E.does_not_bind env params + && E.does_not_freshen env params + then + params, function_decl.body + else + let freshened_params = List.map (fun var -> Variable.rename var) params in + let subst = Variable.Map.of_list (List.combine params freshened_params) in + let body = Flambda_utils.toplevel_substitution subst function_decl.body in + freshened_params, body + +(* CR-soon mshinwell: Add a note somewhere to explain why "bound by the closure" + does not include the function identifiers for other functions in the same + set of closures. + mshinwell: The terminology may be used inconsistently. *) + +(** Inline a function by copying its body into a context where it becomes + closed. That is to say, we bind the free variables of the body + (= "variables bound by the closure"), and any function identifiers + introduced by the corresponding set of closures. *) +let inline_by_copying_function_body ~env ~r + ~(function_decls : Flambda.function_declarations) + ~lhs_of_application + ~(inline_requested : Lambda.inline_attribute) + ~(specialise_requested : Lambda.specialise_attribute) + ~closure_id_being_applied + ~(function_decl : Flambda.function_declaration) ~args ~simplify = + assert (E.mem env lhs_of_application); + assert (List.for_all (E.mem env) args); + let r = + if function_decl.stub then r + else R.map_benefit r B.remove_call + in + let freshened_params, body = + copy_of_function's_body_with_freshened_params env ~function_decl + in + let body = + if function_decl.stub && + ((inline_requested <> Lambda.Default_inline) + || (specialise_requested <> Lambda.Default_specialise)) then + (* When the function inlined function is a stub, the annotation + is reported to the function applications inside the stub. + This allows to report the annotation to the application the + original programmer really intended: the stub is not visible + in the source. *) + set_inline_attribute_on_all_apply body + inline_requested specialise_requested + else + body + in + let bindings_for_params_to_args = + (* Bind the function's parameters to the arguments from the call site. *) + let args = List.map (fun arg -> Flambda.Expr (Var arg)) args in + Flambda_utils.bind ~body ~bindings:(List.combine freshened_params args) + in + (* Add bindings for the variables bound by the closure. *) + let bindings_for_vars_bound_by_closure_and_params_to_args = + fold_over_projections_of_vars_bound_by_closure ~closure_id_being_applied + ~lhs_of_application ~function_decls ~init:bindings_for_params_to_args + ~f:(fun ~acc:body ~var ~expr -> Flambda.create_let var expr body) + in + (* Add bindings for variables corresponding to the functions introduced by + the whole set of closures. Each such variable will be bound to a closure; + each such closure is in turn produced by moving from the closure being + applied to another closure in the same set. + *) + let expr = + Variable.Map.fold (fun another_closure_in_the_same_set _ expr -> + let used = + Variable.Set.mem another_closure_in_the_same_set + function_decl.free_variables + in + if used then + Flambda.create_let another_closure_in_the_same_set + (Move_within_set_of_closures { + closure = lhs_of_application; + start_from = closure_id_being_applied; + move_to = Closure_id.wrap another_closure_in_the_same_set; + }) + expr + else expr) + function_decls.funs + bindings_for_vars_bound_by_closure_and_params_to_args + in + let env = E.activate_freshening (E.set_never_inline env) in + simplify env r expr + +let inline_by_copying_function_declaration ~env ~r + ~(function_decls : Flambda.function_declarations) + ~lhs_of_application + ~(inline_requested : Lambda.inline_attribute) + ~closure_id_being_applied + ~(function_decl : Flambda.function_declaration) + ~args ~args_approxs + ~(invariant_params:Variable.Set.t Variable.Map.t lazy_t) + ~(specialised_args : Flambda.specialised_to Variable.Map.t) + ~direct_call_surrogates ~dbg ~simplify = + let original_function_decls = function_decls in + let specialised_args_set = Variable.Map.keys specialised_args in + let worth_specialising_args, specialisable_args, args, args_decl = + which_function_parameters_can_we_specialise + ~params:function_decl.params ~args ~args_approxs + ~invariant_params + ~specialised_args:specialised_args_set + in + (* Arguments of functions that are not directly called but are + aliased to arguments of a directly called one may need to be + marked as specialiased. *) + let specialisable_args_with_aliases = + Variable.Map.fold (fun arg outside_var map -> + match Variable.Map.find arg (Lazy.force invariant_params) with + | exception Not_found -> map + | set -> + Variable.Set.fold (fun alias map -> + Variable.Map.add alias outside_var map) + set map) + specialisable_args specialisable_args + in + (* The other closures from the same set of closures may have + specialised arguments. Those refer to variables that may not be + bound anymore in the current environment. The only allowed + remaining specialised arguments after duplicating a function are + those that either comes from the free variables of set of + closures or the arguments of the closure being applied (and + propagated transitively to other functions). This is ensured by + the fact that no closure not directly required by the closure + being applied are kept in the set. If an argument of an other + function of the set does not come from the closure being applied + then, that function cannot be applied (unreachable from the one + being aplied). + + For specialised arguments of other function to reference a valid + value, they need to be rewritten accordingly to the ones of the + closure being applied. *) + let specialisable_renaming = + Variable.Map.fold (fun param outside_var map -> + match Variable.Map.find param specialised_args with + | exception Not_found -> + (* Newly specialised argument: no other function argument + may need renaming for that one *) + map + | original_spec_to -> + let original_outside_var = original_spec_to.var in + let spec_to = + { original_spec_to with var = outside_var; } + in + Variable.Map.add original_outside_var spec_to map) + specialisable_args_with_aliases Variable.Map.empty + in + if Variable.Set.subset worth_specialising_args specialised_args_set + then + (* Don't duplicate the function definition if we would make its + specialisation information worse. (Note that this judgement is made + based only on those arguments found to be invariant with known-useful + approximations, rather than on all invariant arguments.) *) + None + else + let set_of_closures_var = new_var "dup_set_of_closures" in + (* The free variable map for the duplicated declaration(s) maps the + "internal" names used within the function bodies to fresh names, + which in turn are bound to projections from the set of closures being + copied. We add these bindings using [Let] around the new + set-of-closures declaration. *) + let free_vars, free_vars_for_lets = + fold_over_projections_of_vars_bound_by_closure ~closure_id_being_applied + ~lhs_of_application ~function_decls ~init:(Variable.Map.empty, []) + ~f:(fun ~acc:(map, for_lets) ~var:internal_var ~expr -> + let from_closure : Flambda.specialised_to = + { var = new_var "from_closure"; + projection = None; + } + in + Variable.Map.add internal_var from_closure map, + (from_closure.var, expr)::for_lets) + in + let required_functions = + Flambda_utils.closures_required_by_entry_point ~backend:(E.backend env) + ~entry_point:closure_id_being_applied + function_decls + in + let funs = + Variable.Map.filter (fun func _ -> + Variable.Set.mem func required_functions) + function_decls.funs + in + let direct_call_surrogates = + Closure_id.Map.fold (fun existing surrogate surrogates -> + let existing = Closure_id.unwrap existing in + let surrogate = Closure_id.unwrap surrogate in + if Variable.Map.mem existing funs + && Variable.Map.mem surrogate funs + then + Variable.Map.add existing surrogate surrogates + else + surrogates) + direct_call_surrogates + Variable.Map.empty + in + let function_decls = + Flambda.update_function_declarations ~funs function_decls + in + let all_functions_parameters = + Flambda_utils.all_functions_parameters function_decls + in + let specialisable_args = + Variable.Map.merge (fun param v1 v2 -> + match v1, v2 with + | None, None -> None + | Some var, _ -> + (* New specialised argument being introduced. *) + let spec_to : Flambda.specialised_to = + { var; + projection = None; + } + in + Some spec_to + | None, Some (spec_to : Flambda.specialised_to) -> + (* Renaming an existing specialised argument. *) + if Variable.Set.mem param all_functions_parameters then + match Variable.Map.find spec_to.var specialisable_renaming with + | exception Not_found -> + Misc.fatal_errorf + "Missing renaming for specialised argument of a function \ + being duplicated but not directly applied: %a -> %a.@ \ + Closure ID being applied = %a.@ \ + required_functions = %a.@ \ + specialisable_renaming = %a@ \ + specialisable_args_with_aliases = %a@ \ + Original function declarations = %a@ \ + Filtered function declarations = %a@ \ + Original specialised args = %a" + Variable.print param + Flambda.print_specialised_to spec_to + Closure_id.print closure_id_being_applied + Variable.Set.print required_functions + (Variable.Map.print Flambda.print_specialised_to) + specialisable_renaming + (Variable.Map.print Variable.print) + specialisable_args_with_aliases + Flambda.print_function_declarations original_function_decls + Flambda.print_function_declarations function_decls + (Variable.Map.print Flambda.print_specialised_to) + specialised_args + | argument_from_the_current_application -> + Some argument_from_the_current_application + else + None) + specialisable_args_with_aliases specialised_args + in + let set_of_closures = + (* This is the new set of closures, with more precise specialisation + information than the one being copied. *) + Flambda.create_set_of_closures ~function_decls ~free_vars + ~specialised_args:specialisable_args + ~direct_call_surrogates + in + (* Generate a copy of the function application, including the function + declaration(s), but with variables (not yet bound) in place of the + arguments. *) + let duplicated_application : Flambda.t = + let project_closure : Flambda.project_closure = + { set_of_closures = set_of_closures_var; + closure_id = closure_id_being_applied; + } + in + let func = new_var "dup_func" in + let body : Flambda.t = + Flambda.create_let set_of_closures_var + (Set_of_closures set_of_closures) + (Flambda.create_let func (Project_closure project_closure) + (Apply { + func; + args; + kind = Direct closure_id_being_applied; + dbg; + inline = inline_requested; + specialise = Default_specialise; + })) + in + Flambda_utils.bind ~bindings:free_vars_for_lets ~body + in + (* Now bind the variables that will hold the arguments from the original + application. *) + let expr : Flambda.t = + Flambda_utils.bind ~body:duplicated_application ~bindings:args_decl + in + let env = E.activate_freshening (E.set_never_inline env) in + Some (simplify env r expr) diff --git a/middle_end/inlining_transforms.mli b/middle_end/inlining_transforms.mli new file mode 100644 index 00000000..3995a975 --- /dev/null +++ b/middle_end/inlining_transforms.mli @@ -0,0 +1,102 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Source code transformations used during inlining. *) + +(** Inline a function by substituting its body (which may be subject to + further transformation) at a call site. The function's declaration is + not copied. + + This transformation is used when: + - inlining a call to a non-recursive function; + - inlining a call, within a recursive or mutually-recursive function, to + the same or another function being defined simultaneously ("unrolling"). + The maximum depth of unrolling is bounded (see [E.unrolling_allowed]). + + In both cases, the body of the function is copied, within a sequence of + [let]s that bind the function parameters, the variables "bound by the + closure" (see flambda.mli), and any function identifiers introduced by the + set of closures. These stages are delimited below by comments. + + As an example, suppose we are inlining the following function: + + let f x = x + y + ... + let p = f, f in + (fst p) 42 + + The call site [ (fst p) 42] will be transformed to: + + let clos_id = fst p in (* must eventually yield a closure *) + let y = in + let x' = 42 in + let x = x' in + x + y + + When unrolling a recursive function we rename the arguments to the + recursive call in order to avoid clashes with existing bindings. For + example, suppose we are inlining the following call to [f], which lies + within its own declaration: + + let rec f x y = + f (fst x) (y + snd x) + + This will be transformed to: + + let rec f x y = + let clos_id = f in (* not used this time, since [f] has no free vars *) + let x' = fst x in + let y' = y + snd x in + f (fst x') (y' + snd x') (* body of [f] with parameters freshened *) +*) +val inline_by_copying_function_body + : env:Inline_and_simplify_aux.Env.t + -> r:Inline_and_simplify_aux.Result.t + -> function_decls:Flambda.function_declarations + -> lhs_of_application:Variable.t + -> inline_requested:Lambda.inline_attribute + -> specialise_requested:Lambda.specialise_attribute + -> closure_id_being_applied:Closure_id.t + -> function_decl:Flambda.function_declaration + -> args:Variable.t list + -> simplify:Inlining_decision_intf.simplify + -> Flambda.t * Inline_and_simplify_aux.Result.t + +(** Inlining of recursive function(s) yields a copy of the functions' + definitions (not just their bodies, unlike the non-recursive case) and + a direct application of the new body. + Note: the function really does need to be recursive (but possibly only via + some mutual recursion) to end up in here; a simultaneous binding [that is + non-recursive] is not sufficient. +*) +val inline_by_copying_function_declaration + : env:Inline_and_simplify_aux.Env.t + -> r:Inline_and_simplify_aux.Result.t + -> function_decls:Flambda.function_declarations + -> lhs_of_application:Variable.t + -> inline_requested:Lambda.inline_attribute + -> closure_id_being_applied:Closure_id.t + -> function_decl:Flambda.function_declaration + -> args:Variable.t list + -> args_approxs:Simple_value_approx.t list + -> invariant_params:Variable.Set.t Variable.Map.t lazy_t + -> specialised_args:Flambda.specialised_to Variable.Map.t + -> direct_call_surrogates:Closure_id.t Closure_id.Map.t + -> dbg:Debuginfo.t + -> simplify:Inlining_decision_intf.simplify + -> (Flambda.t * Inline_and_simplify_aux.Result.t) option diff --git a/middle_end/invariant_params.ml b/middle_end/invariant_params.ml new file mode 100644 index 00000000..76e4b3e6 --- /dev/null +++ b/middle_end/invariant_params.ml @@ -0,0 +1,414 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-someday pchambart to pchambart: in fact partial application doesn't + work because there are no 'known' partial application left: they are + converted to applications new partial function declaration. + That can be improved (and many other cases) by keeping track of aliases in + closure of functions. *) + +(* These analyses are computed in two steps: + * accumulate the atomic <- relations + * compute the least-fixed point + + The <- relation is represented by the type + + t Variable.Pair.Map.t + + if [Variable.Pair.Map.find (f, x) relation = Top] then (f, x) <- Top + is in the relation. + + if [Variable.Pair.Map.find (f, x) relation = Implication s] and + [Variable.Pair.Set.mem (g, y) s] then (f, x) <- (g, y) is in the + relation. +*) + +type t = + | Top + | Implication of Variable.Pair.Set.t + +let _print ppf = function + | Top -> Format.fprintf ppf "Top" + | Implication args -> + Format.fprintf ppf "Implication: @[%a@]" + Variable.Pair.Set.print args + +let top relation p = + Variable.Pair.Map.add p Top relation + +let implies relation from to_ = + match Variable.Pair.Map.find to_ relation with + | Top -> relation + | Implication set -> + Variable.Pair.Map.add to_ + (Implication (Variable.Pair.Set.add from set)) + relation + | exception Not_found -> + Variable.Pair.Map.add to_ + (Implication (Variable.Pair.Set.singleton from)) + relation + +let transitive_closure state = + let union s1 s2 = + match s1, s2 with + | Top, _ | _, Top -> Top + | Implication s1, Implication s2 -> + Implication (Variable.Pair.Set.union s1 s2) + in + let equal s1 s2 = + match s1, s2 with + | Top, Implication _ | Implication _, Top -> false + | Top, Top -> true + | Implication s1, Implication s2 -> Variable.Pair.Set.equal s1 s2 + in + let update arg state = + let original_set = + try Variable.Pair.Map.find arg state with + | Not_found -> Implication Variable.Pair.Set.empty + in + match original_set with + | Top -> state + | Implication arguments -> + let set = + Variable.Pair.Set.fold + (fun orig acc-> + let set = + try Variable.Pair.Map.find orig state with + | Not_found -> Implication Variable.Pair.Set.empty in + union set acc) + arguments original_set + in + Variable.Pair.Map.add arg set state + in + let once state = + Variable.Pair.Map.fold (fun arg _ state -> update arg state) state state + in + let rec fp state = + let state' = once state in + if Variable.Pair.Map.equal equal state state' + then state + else fp state' + in + fp state + +(* CR-soon pchambart: to move to Flambda_utils and document + mshinwell: I think this calculation is basically the same as + [Flambda_utils.fun_vars_referenced_in_decls], so we should try + to share code. However let's defer until after 4.03. (And note CR + below.) +*) +(* Finds variables that represent the functions. + In a construction like: + let f x = + let g = Symbol f_closure in + .. + the variable g is bound to the symbol f_closure which + is the current closure. + The result of [function_variable_alias] will contain + the association [g -> f] +*) +let function_variable_alias + (function_decls : Flambda.function_declarations) + ~backend = + let fun_vars = Variable.Map.keys function_decls.funs in + let symbols_to_fun_vars = + let module Backend = (val backend : Backend_intf.S) in + Variable.Set.fold (fun fun_var symbols_to_fun_vars -> + let closure_id = Closure_id.wrap fun_var in + let symbol = Backend.closure_symbol closure_id in + Symbol.Map.add symbol fun_var symbols_to_fun_vars) + fun_vars + Symbol.Map.empty + in + let fun_var_bindings = ref Variable.Map.empty in + Variable.Map.iter (fun _ ( function_decl : Flambda.function_declaration ) -> + Flambda_iterators.iter_all_toplevel_immutable_let_and_let_rec_bindings + ~f:(fun var named -> + (* CR-soon mshinwell: consider having the body passed to this + function and using fv calculation instead of used_variables. + Need to be careful of "let rec" *) + match named with + | Symbol sym -> + begin match Symbol.Map.find sym symbols_to_fun_vars with + | exception Not_found -> () + | fun_var -> + fun_var_bindings := + Variable.Map.add var fun_var !fun_var_bindings + end + | _ -> ()) + function_decl.body) + function_decls.funs; + !fun_var_bindings + +let analyse_functions ~backend ~param_to_param + ~anything_to_param ~param_to_anywhere + (decls : Flambda.function_declarations) = + let function_variable_alias = function_variable_alias ~backend decls in + let param_indexes_by_fun_vars = + Variable.Map.map (fun (decl : Flambda.function_declaration) -> + Array.of_list decl.params) + decls.funs + in + let find_callee_arg ~callee ~callee_pos = + match Variable.Map.find callee param_indexes_by_fun_vars with + | exception Not_found -> None (* not a recursive call *) + | arr -> + (* Ignore overapplied parameters: they are applied to a different + function. *) + if callee_pos < Array.length arr then Some arr.(callee_pos) + else None + in + let escaping_functions = Variable.Tbl.create 13 in + let escaping_function fun_var = + let fun_var = + match Variable.Map.find fun_var function_variable_alias with + | exception Not_found -> fun_var + | fun_var -> fun_var + in + if Variable.Map.mem fun_var decls.funs + then Variable.Tbl.add escaping_functions fun_var (); + in + let used_variables = Variable.Tbl.create 42 in + let used_variable var = Variable.Tbl.add used_variables var () in + let relation = ref Variable.Pair.Map.empty in + (* If the called closure is in the current set of closures, record the + relation (callee, callee_arg) <- (caller, caller_arg) *) + let check_argument ~caller ~callee ~callee_pos ~caller_arg = + escaping_function caller_arg; + match find_callee_arg ~callee ~callee_pos with + | None -> used_variable caller_arg (* not a recursive call *) + | Some callee_arg -> + match Variable.Map.find caller decls.funs with + | exception Not_found -> + assert false + | { params } -> + let new_relation = + (* We only track dataflow for parameters of functions, not + arbitrary variables. *) + if List.mem caller_arg params then + param_to_param ~caller ~caller_arg ~callee ~callee_arg !relation + else begin + used_variable caller_arg; + anything_to_param ~callee ~callee_arg !relation + end + in + relation := new_relation + in + let arity ~callee = + match Variable.Map.find callee decls.funs with + | exception Not_found -> 0 + | func -> Flambda_utils.function_arity func + in + let check_expr ~caller (expr : Flambda.t) = + match expr with + | Apply { func; args } -> + used_variable func; + let callee = + match Variable.Map.find func function_variable_alias with + | exception Not_found -> func + | callee -> callee + in + let num_args = List.length args in + for callee_pos = num_args to (arity ~callee) - 1 do + (* If a function is partially applied, consider all missing + arguments as "anything". *) + match find_callee_arg ~callee ~callee_pos with + | None -> () + | Some callee_arg -> + relation := anything_to_param ~callee ~callee_arg !relation + done; + List.iteri (fun callee_pos caller_arg -> + check_argument ~caller ~callee ~callee_pos ~caller_arg) + args + | _ -> () + in + Variable.Map.iter (fun caller (decl : Flambda.function_declaration) -> + Flambda_iterators.iter (check_expr ~caller) + (fun (_ : Flambda.named) -> ()) + decl.body; + Variable.Set.iter + (fun var -> escaping_function var; used_variable var) + (* CR-soon mshinwell: we should avoid recomputing this, cache in + [function_declaration]. See also comment on + [only_via_symbols] in [Flambda_utils]. *) + (Flambda.free_variables ~ignore_uses_as_callee:() + ~ignore_uses_as_argument:() decl.body)) + decls.funs; + Variable.Map.iter + (fun func_var ({ params } : Flambda.function_declaration) -> + List.iter + (fun param -> + if Variable.Tbl.mem used_variables param then + relation := + param_to_anywhere ~caller:func_var ~caller_arg:param !relation; + if Variable.Tbl.mem escaping_functions func_var then + relation := + anything_to_param ~callee:func_var ~callee_arg:param !relation) + params) + decls.funs; + transitive_closure !relation + + +(* A parameter [x] of the function [f] is considered as unchanging if + during an 'external' (call from outside the set of closures) call of + [f], every recursive call of [f] all the instances of [x] are aliased + to the original one. This function computes an underapproximation of + that set by computing the flow of parameters between the different + functions of the set of closures. + + We record [(f, x) <- (g, y)] when the function g calls f and + the y parameter of g is used as argument for the x parameter of f. For + instance in + + let rec f x = ... + and g y = f x + + We record [(f, x) <- Top] when some unknown values can flow to a the + [y] parameter. + + let rec f x = f 1 + + We record also [(f, x) <- Top] if [f] could escape. This is over + approximated by considering that a function escape when its variable is used + for something else than an application: + + let rec f x = (f, f) + + [x] is not unchanging if either + (f, x) <- Top + or (f, x) <- (f, y) with x != y + + Notice that having (f, x) <- (g, a) and (f, x) <- (g, b) does not make + x not unchanging. This is because (g, a) and (g, b) represent necessarily + different values only if g is the externaly called function. If some + value where created during the execution of the function that could + flow to (g, a), then (g, a) <- Top, so (f, x) <- Top. + + *) + +let invariant_params_in_recursion (decls : Flambda.function_declarations) + ~backend = + let param_to_param ~caller ~caller_arg ~callee ~callee_arg relation = + implies relation (caller, caller_arg) (callee, callee_arg) + in + let anything_to_param ~callee ~callee_arg relation = + top relation (callee, callee_arg) + in + let param_to_anywhere ~caller:_ ~caller_arg:_ relation = relation in + let relation = + analyse_functions ~backend ~param_to_param + ~anything_to_param ~param_to_anywhere + decls + in + let not_unchanging = + Variable.Pair.Map.fold (fun (func, var) set not_unchanging -> + match set with + | Top -> Variable.Set.add var not_unchanging + | Implication set -> + if Variable.Pair.Set.exists (fun (func', var') -> + Variable.equal func func' && not (Variable.equal var var')) + set + then Variable.Set.add var not_unchanging + else not_unchanging) + relation Variable.Set.empty + in + let params = Variable.Map.fold (fun _ + ({ params } : Flambda.function_declaration) set -> + Variable.Set.union (Variable.Set.of_list params) set) + decls.funs Variable.Set.empty + in + let unchanging = Variable.Set.diff params not_unchanging in + let aliased_to = + Variable.Pair.Map.fold (fun (_, var) set aliases -> + match set with + | Implication set + when Variable.Set.mem var unchanging -> + Variable.Pair.Set.fold (fun (_, caller_args) aliases -> + if Variable.Set.mem caller_args unchanging then + let alias_set = + match Variable.Map.find caller_args aliases with + | exception Not_found -> + Variable.Set.singleton var + | alias_set -> + Variable.Set.add var alias_set + in + Variable.Map.add caller_args alias_set aliases + else + aliases) + set aliases + | Top | Implication _ -> aliases) + relation Variable.Map.empty + in + (* We complete the set of aliases such that there does not miss any + unchanging param *) + Variable.Map.of_set (fun var -> + match Variable.Map.find var aliased_to with + | exception Not_found -> Variable.Set.empty + | set -> set) + unchanging + +let invariant_param_sources decls ~backend = + let param_to_param ~caller ~caller_arg ~callee ~callee_arg relation = + implies relation (caller, caller_arg) (callee, callee_arg) + in + let anything_to_param ~callee:_ ~callee_arg:_ relation = relation in + let param_to_anywhere ~caller:_ ~caller_arg:_ relation = relation in + let relation = + analyse_functions ~backend ~param_to_param + ~anything_to_param ~param_to_anywhere + decls + in + Variable.Pair.Map.fold (fun (_, var) set relation -> + match set with + | Top -> relation + | Implication set -> Variable.Map.add var set relation) + relation Variable.Map.empty + +let pass_name = "unused-arguments" +let () = Clflags.all_passes := pass_name :: !Clflags.all_passes + +let unused_arguments (decls : Flambda.function_declarations) ~backend = + let dump = Clflags.dumped_pass pass_name in + let param_to_param ~caller ~caller_arg ~callee ~callee_arg relation = + implies relation (callee, callee_arg) (caller, caller_arg) + in + let anything_to_param ~callee:_ ~callee_arg:_ relation = relation in + let param_to_anywhere ~caller ~caller_arg relation = + top relation (caller, caller_arg) + in + let relation = + analyse_functions ~backend ~param_to_param + ~anything_to_param ~param_to_anywhere + decls + in + let arguments = + Variable.Map.fold + (fun fun_var decl acc -> + List.fold_left + (fun acc param -> + match Variable.Pair.Map.find (fun_var, param) relation with + | exception Not_found -> Variable.Set.add param acc + | Implication _ -> Variable.Set.add param acc + | Top -> acc) + acc decl.Flambda.params) + decls.funs Variable.Set.empty + in + if dump then begin + Format.printf "Unused arguments: %a@." Variable.Set.print arguments + end; + arguments diff --git a/middle_end/invariant_params.mli b/middle_end/invariant_params.mli new file mode 100644 index 00000000..c6851420 --- /dev/null +++ b/middle_end/invariant_params.mli @@ -0,0 +1,57 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* [invariant_params_in_recursion] calculates the set of parameters whose + values are known not to change during the execution of a recursive + function. As such, occurrences of the parameters may always be replaced + by the corresponding values. + + For example, [x] would be in [invariant_params] for both of the following + functions: + + let rec f x y = (f x y) + (f x (y+1)) + + let rec f x l = List.iter (f x) l + + For invariant parameters it also computes the set of parameters of functions + in the set of closures that are always aliased to it. For example in the set + of closures: + + let rec f x y = (f x y) + (f x (y+1)) + g x + and g z = z + 1 + + The map of aliases is + + x -> { x; z } +*) +val invariant_params_in_recursion + : Flambda.function_declarations + -> backend:(module Backend_intf.S) + -> Variable.Set.t Variable.Map.t + +val invariant_param_sources + : Flambda.function_declarations + -> backend:(module Backend_intf.S) + -> Variable.Pair.Set.t Variable.Map.t + +(* CR-soon mshinwell: think about whether this function should + be in this file. Should it be called "unused_parameters"? *) +val unused_arguments + : Flambda.function_declarations + -> backend:(module Backend_intf.S) + -> Variable.Set.t diff --git a/middle_end/lift_code.ml b/middle_end/lift_code.ml new file mode 100644 index 00000000..4098c23a --- /dev/null +++ b/middle_end/lift_code.ml @@ -0,0 +1,165 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module C = Inlining_cost + +type lifter = Flambda.program -> Flambda.program + +let rebuild_let + (defs : (Variable.t * Flambda.named Flambda.With_free_variables.t) list) + (body : Flambda.t) = + let module W = Flambda.With_free_variables in + List.fold_left (fun body (var, def) -> + W.create_let_reusing_defining_expr var def body) + body defs + +let rec extract_lets + (acc:(Variable.t * Flambda.named Flambda.With_free_variables.t) list) + (let_expr:Flambda.let_expr) : + (Variable.t * Flambda.named Flambda.With_free_variables.t) list * + Flambda.t Flambda.With_free_variables.t = + let module W = Flambda.With_free_variables in + match let_expr with + | { var = v1; defining_expr = Expr (Let let2); _ } -> + let acc, body2 = extract_lets acc let2 in + let acc = (v1, W.expr body2) :: acc in + let body = W.of_body_of_let let_expr in + extract acc body + | { var = v; _ } -> + let acc = (v, W.of_defining_expr_of_let let_expr) :: acc in + let body = W.of_body_of_let let_expr in + extract acc body + +and extract acc (expr : Flambda.t Flambda.With_free_variables.t) = + let module W = Flambda.With_free_variables in + match W.contents expr with + | Let let_expr -> + extract_lets acc let_expr + | _ -> + acc, expr + +let rec lift_lets_expr (expr:Flambda.t) ~toplevel : Flambda.t = + let module W = Flambda.With_free_variables in + match expr with + | Let let_expr -> + let defs, body = extract_lets [] let_expr in + let rev_defs = + List.rev_map (lift_lets_named_with_free_variables ~toplevel) defs + in + let body = lift_lets_expr (W.contents body) ~toplevel in + rebuild_let (List.rev rev_defs) body + | e -> + Flambda_iterators.map_subexpressions + (lift_lets_expr ~toplevel) + (lift_lets_named ~toplevel) + e + +and lift_lets_named_with_free_variables + ((var, named):Variable.t * Flambda.named Flambda.With_free_variables.t) + ~toplevel : Variable.t * Flambda.named Flambda.With_free_variables.t = + let module W = Flambda.With_free_variables in + match W.contents named with + | Expr e -> + var, W.expr (W.of_expr (lift_lets_expr e ~toplevel)) + | Set_of_closures set when not toplevel -> + var, + W.of_named + (Set_of_closures + (Flambda_iterators.map_function_bodies + ~f:(lift_lets_expr ~toplevel) set)) + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field (_, _) | Project_closure _ | Move_within_set_of_closures _ + | Project_var _ | Prim _ | Set_of_closures _ -> + var, named + +and lift_lets_named _var (named:Flambda.named) ~toplevel : Flambda.named = + let module W = Flambda.With_free_variables in + match named with + | Expr e -> + Expr (lift_lets_expr e ~toplevel) + | Set_of_closures set when not toplevel -> + Set_of_closures + (Flambda_iterators.map_function_bodies ~f:(lift_lets_expr ~toplevel) set) + | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field (_, _) | Project_closure _ | Move_within_set_of_closures _ + | Project_var _ | Prim _ | Set_of_closures _ -> + named + +module Sort_lets = Strongly_connected_components.Make (Variable) + +let rebuild_let_rec (defs:(Variable.t * Flambda.named) list) body = + let map = Variable.Map.of_list defs in + let graph = + Variable.Map.map + (fun named -> + Variable.Set.filter (fun v -> Variable.Map.mem v map) + (Flambda.free_variables_named named)) + map + in + let components = + Sort_lets.connected_components_sorted_from_roots_to_leaf graph + in + Array.fold_left (fun body (component:Sort_lets.component) -> + match component with + | No_loop v -> + let def = Variable.Map.find v map in + Flambda.create_let v def body + | Has_loop l -> + Flambda.Let_rec + (List.map (fun v -> v, Variable.Map.find v map) l, + body)) + body components + +let lift_let_rec program = + Flambda_iterators.map_exprs_at_toplevel_of_program program + ~f:(Flambda_iterators.map_expr + (fun expr -> match expr with + | Let_rec (defs, body) -> + rebuild_let_rec defs body + | expr -> expr)) + +let lift_lets program = + let program = lift_let_rec program in + Flambda_iterators.map_exprs_at_toplevel_of_program program + ~f:(lift_lets_expr ~toplevel:false) + +let lifting_helper exprs ~evaluation_order ~create_body ~name = + let vars, lets = + (* [vars] corresponds elementwise to [exprs]; the order is unchanged. *) + List.fold_right (fun (flam : Flambda.t) (vars, lets) -> + match flam with + | Var v -> + (* Note that [v] is (statically) always an immutable variable. *) + v::vars, lets + | expr -> + let v = + Variable.create name ~current_compilation_unit: + (Compilation_unit.get_current_exn ()) + in + v::vars, (v, expr)::lets) + exprs ([], []) + in + let lets = + match evaluation_order with + | `Right_to_left -> lets + | `Left_to_right -> List.rev lets + in + List.fold_left (fun body (v, expr) -> + Flambda.create_let v (Expr expr) body) + (create_body vars) lets diff --git a/middle_end/lift_code.mli b/middle_end/lift_code.mli new file mode 100644 index 00000000..9cbfa878 --- /dev/null +++ b/middle_end/lift_code.mli @@ -0,0 +1,43 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type lifter = Flambda.program -> Flambda.program + +(** Lift [let] bindings to attempt to increase the length of scopes, as an + aid to further optimizations. For example: + let c = let b = in b, b in fst c + would be transformed to: + let b = in let c = b, b in fst c + which is then clearly just: + +*) +val lift_lets : lifter + +val lift_lets_expr : Flambda.t -> toplevel:bool -> Flambda.t + +(* CR-someday mshinwell: Rename to [bind]? Also see Flambda_utils.bind. *) +(* [create_body] always receives the variables corresponding to [evaluate] + in the same order. However [evaluation_order] specifies in which order + the (possibly complex) expressions bound to those variables are + evaluated. *) +val lifting_helper + : Flambda.t list + -> evaluation_order:[ `Left_to_right | `Right_to_left ] + -> create_body:(Variable.t list -> Flambda.t) + -> name:string + -> Flambda.t diff --git a/middle_end/lift_constants.ml b/middle_end/lift_constants.ml new file mode 100644 index 00000000..d9b26d41 --- /dev/null +++ b/middle_end/lift_constants.ml @@ -0,0 +1,1033 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-someday mshinwell: move to Flambda_utils *) +let rec tail_variable : Flambda.t -> Variable.t option = function + | Var v -> Some v + | Let_rec (_, e) + | Let_mutable (_, _, e) + | Let { body = e; _ } -> tail_variable e + | _ -> None + +let closure_symbol ~(backend : (module Backend_intf.S)) closure_id = + let module Backend = (val backend) in + Backend.closure_symbol closure_id + +let make_variable_symbol prefix var = + Symbol.create (Compilation_unit.get_current_exn ()) + (Linkage_name.create + (prefix ^ Variable.unique_name (Variable.rename var))) + +(** Traverse the given expression assigning symbols to [let]- and [let rec]- + bound constant variables. At the same time collect the definitions of + such variables. *) +let assign_symbols_and_collect_constant_definitions + ~(backend : (module Backend_intf.S)) + ~(program : Flambda.program) + ~(inconstants : Inconstant_idents.result) = + let var_to_symbol_tbl = Variable.Tbl.create 42 in + let var_to_definition_tbl = Variable.Tbl.create 42 in + let module AA = Alias_analysis in + let assign_symbol var (named : Flambda.named) = + if not (Inconstant_idents.variable var inconstants) then begin + let assign_symbol () = + let symbol = make_variable_symbol "" var in + Variable.Tbl.add var_to_symbol_tbl var symbol + in + let assign_existing_symbol = Variable.Tbl.add var_to_symbol_tbl var in + let record_definition = Variable.Tbl.add var_to_definition_tbl var in + match named with + | Symbol symbol -> + assign_existing_symbol symbol; + record_definition (AA.Symbol symbol) + | Const const -> record_definition (AA.Const const) + | Allocated_const const -> + assign_symbol (); + record_definition (AA.Allocated_const (Normal const)) + | Read_mutable _ -> + (* [Inconstant_idents] always marks these expressions as + inconstant, so we should never get here. *) + assert false + | Prim (Pmakeblock (tag, _), fields, _) -> + assign_symbol (); + record_definition (AA.Block (Tag.create_exn tag, fields)) + | Read_symbol_field (symbol, field) -> + record_definition (AA.Symbol_field (symbol, field)) + | Set_of_closures ( + { function_decls = { funs; set_of_closures_id; _ }; + _ } as set) -> + assert (not (Inconstant_idents.closure set_of_closures_id + inconstants)); + assign_symbol (); + record_definition (AA.Set_of_closures set); + Variable.Map.iter (fun fun_var _ -> + let closure_id = Closure_id.wrap fun_var in + let closure_symbol = closure_symbol ~backend closure_id in + Variable.Tbl.add var_to_symbol_tbl fun_var closure_symbol; + let project_closure = + Alias_analysis.Project_closure + { set_of_closures = var; closure_id } + in + Variable.Tbl.add var_to_definition_tbl fun_var + project_closure) + funs + | Move_within_set_of_closures ({ closure = _; start_from = _; move_to; } + as move) -> + assign_existing_symbol (closure_symbol ~backend move_to); + record_definition (AA.Move_within_set_of_closures move) + | Project_closure ({ closure_id } as project_closure) -> + assign_existing_symbol (closure_symbol ~backend closure_id); + record_definition (AA.Project_closure project_closure) + | Prim (Pfield index, [block], _) -> + record_definition (AA.Field (block, index)) + | Prim (Pfield _, _, _) -> + Misc.fatal_errorf "[Pfield] with the wrong number of arguments" + Flambda.print_named named + | Prim (Pmakearray (Pfloatarray as kind, mutability), args, _) -> + assign_symbol (); + record_definition (AA.Allocated_const (Array (kind, mutability, args))) + | Prim (Pduparray (kind, mutability), [arg], _) -> + assign_symbol (); + record_definition (AA.Allocated_const ( + Duplicate_array (kind, mutability, arg))) + | Prim _ -> + Misc.fatal_errorf "Primitive not expected to be constant: @.%a@." + Flambda.print_named named + | Project_var project_var -> + record_definition (AA.Project_var project_var) + | Expr e -> + match tail_variable e with + | None -> assert false (* See [Inconstant_idents]. *) + | Some v -> record_definition (AA.Variable v) + end + in + let assign_symbol_program expr = + Flambda_iterators.iter_all_immutable_let_and_let_rec_bindings expr + ~f:assign_symbol + in + Flambda_iterators.iter_exprs_at_toplevel_of_program program + ~f:assign_symbol_program; + let let_symbol_to_definition_tbl = Symbol.Tbl.create 42 in + let initialize_symbol_to_definition_tbl = Symbol.Tbl.create 42 in + let rec collect_let_and_initialize_symbols (program : Flambda.program_body) = + match program with + | Let_symbol (symbol, decl, program) -> + Symbol.Tbl.add let_symbol_to_definition_tbl symbol decl; + collect_let_and_initialize_symbols program + | Let_rec_symbol (decls, program) -> + List.iter (fun (symbol, decl) -> + Symbol.Tbl.add let_symbol_to_definition_tbl symbol decl) + decls; + collect_let_and_initialize_symbols program + | Effect (_, program) -> collect_let_and_initialize_symbols program + | Initialize_symbol (symbol,_tag,fields,program) -> + collect_let_and_initialize_symbols program; + let fields = List.map tail_variable fields in + Symbol.Tbl.add initialize_symbol_to_definition_tbl symbol fields + | End _ -> () + in + collect_let_and_initialize_symbols program.program_body; + let record_set_of_closure_equalities + (set_of_closures : Flambda.set_of_closures) = + Variable.Map.iter (fun arg (var : Flambda.specialised_to) -> + if not (Inconstant_idents.variable arg inconstants) then + Variable.Tbl.add var_to_definition_tbl arg (AA.Variable var.var)) + set_of_closures.free_vars; + Variable.Map.iter (fun arg (spec_to : Flambda.specialised_to) -> + if not (Inconstant_idents.variable arg inconstants) then + Variable.Tbl.add var_to_definition_tbl arg + (AA.Variable spec_to.var)) + set_of_closures.specialised_args + in + Flambda_iterators.iter_on_set_of_closures_of_program program + ~f:(fun ~constant set_of_closures -> + record_set_of_closure_equalities set_of_closures; + if constant then begin + Variable.Map.iter (fun fun_var _ -> + let closure_id = Closure_id.wrap fun_var in + let closure_symbol = closure_symbol ~backend closure_id in + Variable.Tbl.add var_to_definition_tbl fun_var + (AA.Symbol closure_symbol); + Variable.Tbl.add var_to_symbol_tbl fun_var closure_symbol) + set_of_closures.Flambda.function_decls.funs + end); + var_to_symbol_tbl, var_to_definition_tbl, + let_symbol_to_definition_tbl, initialize_symbol_to_definition_tbl + +let variable_field_definition + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl : + Alias_analysis.constant_defining_value Variable.Tbl.t) + (var : Variable.t) : Flambda.constant_defining_value_block_field = + try + Symbol (Variable.Tbl.find var_to_symbol_tbl var) + with Not_found -> + match Variable.Tbl.find var_to_definition_tbl var with + | Const c -> Const c + | const_defining_value -> + Misc.fatal_errorf "Unexpected pattern for a constant: %a: %a" + Variable.print var + Alias_analysis.print_constant_defining_value const_defining_value + | exception Not_found -> + Misc.fatal_errorf "No associated symbol for the constant %a" + Variable.print var + +let resolve_variable + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl : + Alias_analysis.constant_defining_value Variable.Tbl.t) + (var : Variable.t) : Flambda.constant_defining_value_block_field = + match Variable.Map.find var aliases with + | exception Not_found -> + variable_field_definition var_to_symbol_tbl var_to_definition_tbl var + | Symbol s -> Symbol s + | Variable aliased_variable -> + variable_field_definition var_to_symbol_tbl var_to_definition_tbl + aliased_variable + +let translate_set_of_closures + (inconstants : Inconstant_idents.result) + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl: + Alias_analysis.constant_defining_value Variable.Tbl.t) + (set_of_closures : Flambda.set_of_closures) = + let f var (named : Flambda.named) : Flambda.named = + if Inconstant_idents.variable var inconstants then + named + else + let resolved = + resolve_variable + aliases + var_to_symbol_tbl + var_to_definition_tbl + var + in + match resolved with + | Symbol s -> Symbol s + | Const c -> Const c + in + Flambda_iterators.map_function_bodies set_of_closures + ~f:(Flambda_iterators.map_all_immutable_let_and_let_rec_bindings ~f) + +let translate_constant_set_of_closures + (inconstants : Inconstant_idents.result) + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl: + Alias_analysis.constant_defining_value Variable.Tbl.t) + (constant_defining_values : Flambda.constant_defining_value Symbol.Map.t) = + Symbol.Map.map (fun (const : Flambda.constant_defining_value) -> + match const with + | Flambda.Allocated_const _ + | Flambda.Block _ + | Flambda.Project_closure _ -> + const + | Flambda.Set_of_closures set_of_closures -> + let set_of_closures = + translate_set_of_closures + (inconstants : Inconstant_idents.result) + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl: + Alias_analysis.constant_defining_value Variable.Tbl.t) + (set_of_closures : Flambda.set_of_closures) + in + Flambda.Set_of_closures set_of_closures) + constant_defining_values + +let find_original_set_of_closure + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl: + Alias_analysis.constant_defining_value Variable.Tbl.t) + project_closure_map + var = + let rec loop var = + match Variable.Map.find var aliases with + | Variable var -> + begin match Variable.Tbl.find var_to_definition_tbl var with + | Project_closure { set_of_closures = var } + | Move_within_set_of_closures { closure = var } -> + loop var + | Set_of_closures _ -> begin + match Variable.Tbl.find var_to_symbol_tbl var with + | s -> + s + | exception Not_found -> + Format.eprintf "var: %a@." Variable.print var; + assert false + end + | _ -> assert false + end + | Symbol s -> + match Symbol.Map.find s project_closure_map with + | exception Not_found -> + Misc.fatal_errorf "find_original_set_of_closure: cannot find \ + symbol %a in the project-closure map" + Symbol.print s + | s -> s + in + loop var + +let translate_definition_and_resolve_alias inconstants + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl : + Alias_analysis.constant_defining_value Variable.Tbl.t) + (symbol_definition_map : Flambda.constant_defining_value Symbol.Map.t) + (project_closure_map : Symbol.t Symbol.Map.t) + (definition : Alias_analysis.constant_defining_value) + ~(backend : (module Backend_intf.S)) + : Flambda.constant_defining_value option = + let resolve_float_array_involving_variables + ~(mutability : Asttypes.mutable_flag) ~vars = + (* Resolve an [Allocated_const] of the form: + [Array (Pfloatarray, _, _)] + (which references its contents via variables; it does not contain + manifest floats). *) + let floats = + List.map (fun var -> + let var = + match Variable.Map.find var aliases with + | exception Not_found -> var + | Symbol _ -> + Misc.fatal_errorf + "Lift_constants.translate_definition_and_resolve_alias: \ + Array Pfloatarray %a with Symbol argument: %a" + Variable.print var + Alias_analysis.print_constant_defining_value definition + | Variable var -> var + in + match Variable.Tbl.find var_to_definition_tbl var with + | Allocated_const (Normal (Float f)) -> f + | const_defining_value -> + Misc.fatal_errorf "Bad definition for float array member %a: %a" + Variable.print var + Alias_analysis.print_constant_defining_value + const_defining_value) + vars + in + let const : Allocated_const.t = + match mutability with + | Immutable -> Immutable_float_array floats + | Mutable -> Float_array floats + in + Some (Flambda.Allocated_const const) + in + match definition with + | Block (tag, fields) -> + Some (Flambda.Block (tag, + List.map (resolve_variable aliases var_to_symbol_tbl + var_to_definition_tbl) + fields)) + | Allocated_const (Normal const) -> Some (Flambda.Allocated_const const) + | Allocated_const (Duplicate_array (Pfloatarray, mutability, var)) -> + (* CR-someday mshinwell: This next section could do with cleanup. + What happens is: + - Duplicate contains a variable, which is resolved to + a float array thing full of variables; + - We send that value back through this function again so the + individual members of that array are resolved from variables to + floats. + - Then we can build the Flambda.name term containing the + Allocated_const (full of floats). + We should maybe factor out the code from the + Allocated_const (Array (...)) case below so this function doesn't have + to be recursive. *) + let (constant_defining_value : Alias_analysis.constant_defining_value) = + match Variable.Map.find var aliases with + | exception Not_found -> + Variable.Tbl.find var_to_definition_tbl var + | Variable var -> + Variable.Tbl.find var_to_definition_tbl var + | Symbol sym -> + match Symbol.Map.find sym symbol_definition_map with + | Allocated_const ((Immutable_float_array _) as const) -> + Alias_analysis.Allocated_const (Normal const) + | (Allocated_const _ | Block _ | Set_of_closures _ + | Project_closure _) as wrong -> + Misc.fatal_errorf + "Lift_constants.translate_definition_and_resolve_alias: \ + Duplicate Pfloatarray %a with symbol %a mapping to \ + wrong constant defining value %a" + Variable.print var + Alias_analysis.print_constant_defining_value definition + Flambda.print_constant_defining_value wrong + | exception Not_found -> + let module Backend = (val backend) in + match (Backend.import_symbol sym).descr with + | Value_unresolved _ -> + Misc.fatal_errorf + "Lift_constants.translate_definition_and_resolve_alias: \ + Duplicate Pfloatarray %a with unknown symbol: %a" + Variable.print var + Alias_analysis.print_constant_defining_value definition + | Value_float_array { contents = Contents float_array } -> + let contents = + Array.fold_right (fun elt acc -> + match acc, elt with + | None, _ | _, None -> None + | Some acc, Some f -> + Some (f :: acc)) + float_array (Some []) + in + begin match contents with + | None -> + Misc.fatal_errorf + "Lift_constants.translate_definition_and_resolve_alias: \ + Duplicate Pfloatarray %a with not completely known float \ + array from symbol: %a" + Variable.print var + Alias_analysis.print_constant_defining_value definition + | Some l -> + Alias_analysis.Allocated_const (Normal (Immutable_float_array l)) + end + | wrong -> + (* CR-someday mshinwell: we might hit this if we ever duplicate + a mutable array across compilation units (e.g. "snapshotting" + an array). We do not currently generate such code. *) + Misc.fatal_errorf + "Lift_constants.translate_definition_and_resolve_alias: \ + Duplicate Pfloatarray %a with symbol %a that does not \ + have an export description of an immutable array" + Variable.print var + Alias_analysis.print_constant_defining_value definition + Simple_value_approx.print_descr wrong + in + begin match constant_defining_value with + | Allocated_const (Normal (Float_array _)) -> + (* This example from pchambart illustrates why we do not allow + the duplication of mutable arrays: + + {| + let_symbol a = Allocated_const (Immutable_float_array [|0.|]) + initialize_symbol b = Duparray(Mutable, a) + effect b.(0) <- 1. + initialize_symbol c = Duparray(Mutable, b) + |} + + This will be converted to: + {| + let_symbol a = Allocated_const (Immutable_float_array [|0.|]) + let_symbol b = Allocated_const (Float_array [|0.|]) + effect b.(0) <- 1. + let_symbol c = Allocated_const (Float_array [|0.|]) + |} + + We can't encounter that currently, but it's scary. + *) + Misc.fatal_error "Pduparray is not allowed on mutable arrays" + | Allocated_const (Normal (Immutable_float_array floats)) -> + let const : Allocated_const.t = + match mutability with + | Immutable -> Immutable_float_array floats + | Mutable -> Float_array floats + in + Some (Flambda.Allocated_const const) + | Allocated_const (Array (Pfloatarray, _, vars)) -> + (* Important: [mutability] is from the [Duplicate_array] + construction above. *) + resolve_float_array_involving_variables ~mutability ~vars + | const -> + Misc.fatal_errorf + "Lift_constants.translate_definition_and_resolve_alias: \ + Duplicate Pfloatarray %a with wrong argument: %a" + Variable.print var + Alias_analysis.print_constant_defining_value const + end + | Allocated_const (Duplicate_array (_, _, _)) -> + Misc.fatal_errorf "Lift_constants.translate_definition_and_resolve_alias: \ + Duplicate_array with non-Pfloatarray kind: %a" + Alias_analysis.print_constant_defining_value definition + | Allocated_const (Array (Pfloatarray, mutability, vars)) -> + resolve_float_array_involving_variables ~mutability ~vars + | Allocated_const (Array (_, _, _)) -> + Misc.fatal_errorf "Lift_constants.translate_definition_and_resolve_alias: \ + Array with non-Pfloatarray kind: %a" + Alias_analysis.print_constant_defining_value definition + | Project_closure { set_of_closures; closure_id } -> + begin match Variable.Map.find set_of_closures aliases with + | Symbol s -> + Some (Flambda.Project_closure (s, closure_id)) + (* If a closure projection is a constant, the set of closures must + be assigned to a symbol. *) + | exception Not_found -> + assert false + | Variable v -> + match Variable.Tbl.find var_to_symbol_tbl v with + | s -> + Some (Flambda.Project_closure (s, closure_id)) + | exception Not_found -> + Format.eprintf "var: %a@." Variable.print v; + assert false + end + | Move_within_set_of_closures { closure; move_to } -> + let set_of_closure_symbol = + find_original_set_of_closure + aliases + var_to_symbol_tbl + var_to_definition_tbl + project_closure_map + closure + in + Some (Flambda.Project_closure (set_of_closure_symbol, move_to)) + | Set_of_closures set_of_closures -> + let set_of_closures = + translate_set_of_closures + inconstants + aliases + var_to_symbol_tbl + var_to_definition_tbl + set_of_closures + in + Some (Flambda.Set_of_closures set_of_closures) + | Project_var _ -> None + | Field (_,_) | Symbol_field _ -> None + | Const _ -> None + | Symbol _ -> None + | Variable _ -> None + +let translate_definitions_and_resolve_alias + inconstants + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl: + Alias_analysis.constant_defining_value Variable.Tbl.t) + symbol_definition_map + project_closure_map + ~backend = + Variable.Tbl.fold (fun var def map -> + match + translate_definition_and_resolve_alias inconstants aliases ~backend + var_to_symbol_tbl var_to_definition_tbl symbol_definition_map + project_closure_map def + with + | None -> map + | Some def -> + let symbol = Variable.Tbl.find var_to_symbol_tbl var in + Symbol.Map.add symbol def map) + var_to_definition_tbl Symbol.Map.empty + +(* Resorting of graph including Initialize_symbol *) +let constant_dependencies ~backend:_ + (const : Flambda.constant_defining_value) = + match const with + | Allocated_const _ -> Symbol.Set.empty + | Block (_, fields) -> + let symbol_fields = + Misc.Stdlib.List.filter_map + (function + | (Symbol s : Flambda.constant_defining_value_block_field) -> Some s + | Flambda.Const _ -> None) + fields + in + Symbol.Set.of_list symbol_fields + | Set_of_closures set_of_closures -> + Flambda.free_symbols_named (Set_of_closures set_of_closures) + | Project_closure (s, _) -> + Symbol.Set.singleton s + +let program_graph ~backend imported_symbols symbol_to_constant + (initialize_symbol_tbl : + (Tag.t * Flambda.t list * Symbol.t option) Symbol.Tbl.t) + (effect_tbl : (Flambda.t * Symbol.t option) Symbol.Tbl.t) = + let expression_symbol_dependencies expr = Flambda.free_symbols expr in + let graph_with_only_constant_parts = + Symbol.Map.map (fun const -> + Symbol.Set.diff (constant_dependencies ~backend const) + imported_symbols) + symbol_to_constant + in + let graph_with_initialisation = + Symbol.Tbl.fold (fun sym (_tag, fields, previous) -> + let order_dep = + match previous with + | None -> Symbol.Set.empty + | Some previous -> Symbol.Set.singleton previous + in + let deps = List.fold_left (fun set field -> + Symbol.Set.union (expression_symbol_dependencies field) set) + order_dep fields + in + let deps = Symbol.Set.diff deps imported_symbols in + Symbol.Map.add sym deps) + initialize_symbol_tbl graph_with_only_constant_parts + in + let graph = + Symbol.Tbl.fold (fun sym (expr, previous) -> + let order_dep = + match previous with + | None -> Symbol.Set.empty + | Some previous -> Symbol.Set.singleton previous + in + let deps = + Symbol.Set.union (expression_symbol_dependencies expr) order_dep + in + let deps = Symbol.Set.diff deps imported_symbols in + Symbol.Map.add sym deps + ) + effect_tbl graph_with_initialisation + in + let module Symbol_SCC = Strongly_connected_components.Make (Symbol) in + let components = + Symbol_SCC.connected_components_sorted_from_roots_to_leaf + graph + in + components + +(* rebuilding the program *) +let add_definition_of_symbol constant_definitions + (initialize_symbol_tbl : + (Tag.t * Flambda.t list * Symbol.t option) Symbol.Tbl.t) + (effect_tbl : (Flambda.t * Symbol.t option) Symbol.Tbl.t) + (program : Flambda.program_body) component : Flambda.program_body = + let symbol_declaration sym = + (* A symbol declared through an Initialize_symbol construct + cannot be recursive, this is not allowed in the construction. + This also couldn't have been introduced by this pass, so we can + safely assert that this is not possible here *) + assert(not (Symbol.Tbl.mem initialize_symbol_tbl sym)); + (sym, Symbol.Map.find sym constant_definitions) + in + let module Symbol_SCC = Strongly_connected_components.Make (Symbol) in + match component with + | Symbol_SCC.Has_loop l -> + let l = List.map symbol_declaration l in + Let_rec_symbol (l, program) + | Symbol_SCC.No_loop sym -> + match Symbol.Tbl.find initialize_symbol_tbl sym with + | (tag, fields, _previous) -> + Initialize_symbol (sym, tag, fields, program) + | exception Not_found -> + match Symbol.Tbl.find effect_tbl sym with + | (expr, _previous) -> + Effect (expr, program) + | exception Not_found -> + let decl = Symbol.Map.find sym constant_definitions in + Let_symbol (sym, decl, program) + +let add_definitions_of_symbols constant_definitions initialize_symbol_tbl + effect_tbl program components = + Array.fold_left + (add_definition_of_symbol constant_definitions initialize_symbol_tbl + effect_tbl) + program components + +let introduce_free_variables_in_set_of_closures + (var_to_block_field_tbl : + Flambda.constant_defining_value_block_field Variable.Tbl.t) + ({ Flambda.function_decls; free_vars; specialised_args; + direct_call_surrogates; } + as set_of_closures) = + let add_definition_and_make_substitution var (expr, subst) = + let searched_var = + match Variable.Map.find var specialised_args with + | exception Not_found -> var + | external_var -> + (* specialised arguments bound to constant can be rewritten *) + external_var.var + in + match Variable.Tbl.find var_to_block_field_tbl searched_var with + | def -> + let fresh = Variable.rename var in + let named : Flambda.named = match def with + | Symbol sym -> Symbol sym + | Const c -> Const c + in + (Flambda.create_let fresh named expr), Variable.Map.add var fresh subst + | exception Not_found -> + (* The variable is bound by the closure or the arguments or not + constant. In either case it does not need to be bound *) + expr, subst + in + let done_something = ref false in + let function_decls : Flambda.function_declarations = + Flambda.update_function_declarations function_decls + ~funs:(Variable.Map.map + (fun (func_decl : Flambda.function_declaration) -> + let variables_to_bind = + (* Closures from the same set must not be bound. *) + Variable.Set.diff func_decl.free_variables + (Variable.Map.keys function_decls.funs) + in + let body, subst = + Variable.Set.fold add_definition_and_make_substitution + variables_to_bind + (func_decl.body, Variable.Map.empty) + in + if Variable.Map.is_empty subst then begin + func_decl + end else begin + done_something := true; + let body = Flambda_utils.toplevel_substitution subst body in + Flambda.create_function_declaration + ~params:func_decl.params + ~body + ~stub:func_decl.stub + ~dbg:func_decl.dbg + ~inline:func_decl.inline + ~specialise:func_decl.specialise + ~is_a_functor:func_decl.is_a_functor + end) + function_decls.funs) + in + let free_vars = + (* Keep only those that are not rewritten to constants. *) + Variable.Map.filter (fun v _ -> + let keep = not (Variable.Tbl.mem var_to_block_field_tbl v) in + if not keep then done_something := true; + keep) + free_vars + in + let free_vars = + Flambda_utils.clean_projections ~which_variables:free_vars + in + let specialised_args = + (* Keep only those that are not rewritten to constants. *) + Variable.Map.filter (fun _ (spec_to : Flambda.specialised_to) -> + let keep = + not (Variable.Tbl.mem var_to_block_field_tbl spec_to.var) + in + if not keep then begin + done_something := true + end; + keep) + specialised_args + in + let specialised_args = + Flambda_utils.clean_projections ~which_variables:specialised_args + in + if not !done_something then + set_of_closures + else + Flambda.create_set_of_closures ~function_decls ~free_vars + ~specialised_args ~direct_call_surrogates + +let rewrite_project_var + (var_to_block_field_tbl + : Flambda.constant_defining_value_block_field Variable.Tbl.t) + (project_var : Flambda.project_var) ~original : Flambda.named = + let var = Var_within_closure.unwrap project_var.var in + match Variable.Tbl.find var_to_block_field_tbl var with + | exception Not_found -> original + | Symbol sym -> Symbol sym + | Const const -> Const const + +let introduce_free_variables_in_sets_of_closures + (var_to_block_field_tbl: + Flambda.constant_defining_value_block_field Variable.Tbl.t) + (translate_definition : Flambda.constant_defining_value Symbol.Map.t) = + Symbol.Map.map (fun (def : Flambda.constant_defining_value) -> + match def with + | Allocated_const _ + | Block _ + | Project_closure _ -> def + | Set_of_closures set_of_closures -> + Flambda.Set_of_closures + (introduce_free_variables_in_set_of_closures + var_to_block_field_tbl + set_of_closures)) + translate_definition + +let var_to_block_field + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl : + Alias_analysis.constant_defining_value Variable.Tbl.t) = + let var_to_block_field_tbl = Variable.Tbl.create 42 in + Variable.Tbl.iter (fun var _ -> + let def = + resolve_variable aliases var_to_symbol_tbl var_to_definition_tbl var + in + Variable.Tbl.add var_to_block_field_tbl var def) + var_to_definition_tbl; + var_to_block_field_tbl + +let program_symbols ~backend (program : Flambda.program) = + let new_fake_symbol = + let r = ref 0 in + fun () -> + incr r; + Symbol.create (Compilation_unit.get_current_exn ()) + (Linkage_name.create ("fake_effect_symbol_" ^ string_of_int !r)) + in + let initialize_symbol_tbl = Symbol.Tbl.create 42 in + let effect_tbl = Symbol.Tbl.create 42 in + let symbol_definition_tbl = Symbol.Tbl.create 42 in + let add_project_closure_definitions def_symbol + (const : Flambda.constant_defining_value) = + match const with + | Set_of_closures { function_decls = { funs } } -> + Variable.Map.iter (fun fun_var _ -> + let closure_id = Closure_id.wrap fun_var in + let closure_symbol = closure_symbol ~backend closure_id in + let project_closure = + Flambda.Project_closure (def_symbol, closure_id) + in + Symbol.Tbl.add symbol_definition_tbl closure_symbol + project_closure) + funs + | Project_closure _ + | Allocated_const _ + | Block _ -> () + in + let rec loop (program : Flambda.program_body) previous_effect = + match program with + | Flambda.Let_symbol (symbol, def, program) -> + add_project_closure_definitions symbol def; + Symbol.Tbl.add symbol_definition_tbl symbol def; + loop program previous_effect + | Flambda.Let_rec_symbol (defs, program) -> + List.iter (fun (symbol, def) -> + add_project_closure_definitions symbol def; + Symbol.Tbl.add symbol_definition_tbl symbol def) + defs; + loop program previous_effect + | Flambda.Initialize_symbol (symbol, tag, fields, program) -> + (* previous_effect is used to keep the order of initialize and effect + values. Their effects order must be kept ordered. + it is used as an extra dependency when sorting the symbols. *) + (* CR-someday pchambart: if the fields expressions are pure, we could + drop this dependency + mshinwell: deferred CR *) + Symbol.Tbl.add initialize_symbol_tbl symbol + (tag, fields, previous_effect); + loop program (Some symbol) + | Flambda.Effect (expr, program) -> + (* Used to ensure that effects are correctly ordered *) + let fake_effect_symbol = new_fake_symbol () in + Symbol.Tbl.add effect_tbl fake_effect_symbol (expr, previous_effect); + loop program (Some fake_effect_symbol) + | Flambda.End _ -> () + in + loop program.program_body None; + initialize_symbol_tbl, symbol_definition_tbl, effect_tbl + +let replace_definitions_in_initialize_symbol_and_effects + (inconstants : Inconstant_idents.result) + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl : + Alias_analysis.constant_defining_value Variable.Tbl.t) + (initialize_symbol_tbl : + (Tag.t * Flambda.t list * Symbol.t option) Symbol.Tbl.t) + (effect_tbl : (Flambda.t * Symbol.t option) Symbol.Tbl.t) = + let rewrite_expr expr = + Flambda_iterators.map_all_immutable_let_and_let_rec_bindings expr + ~f:(fun var (named : Flambda.named) : Flambda.named -> + if Inconstant_idents.variable var inconstants then + named + else + let resolved = + resolve_variable + aliases + var_to_symbol_tbl + var_to_definition_tbl + var + in + match resolved with + | 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) *) + Symbol.Tbl.iter + (fun symbol (tag, fields, previous) -> + let fields = List.map rewrite_expr fields in + Symbol.Tbl.replace initialize_symbol_tbl symbol (tag, fields, previous)) + initialize_symbol_tbl; + Symbol.Tbl.iter + (fun symbol (expr, previous) -> + Symbol.Tbl.replace effect_tbl symbol (rewrite_expr expr, previous)) + effect_tbl + +(* CR-soon mshinwell: Update the name of [project_closure_map]. *) +let project_closure_map symbol_definition_map = + Symbol.Map.fold (fun sym (const : Flambda.constant_defining_value) acc -> + match const with + | Project_closure (set_of_closures, _) -> + Symbol.Map.add sym set_of_closures acc + | Set_of_closures _ -> + Symbol.Map.add sym sym acc + | Allocated_const _ + | Block _ -> acc) + symbol_definition_map + Symbol.Map.empty + +let the_dead_constant_index = ref 0 + +let lift_constants (program : Flambda.program) ~backend = + let the_dead_constant = + let index = !the_dead_constant_index in + incr the_dead_constant_index; + let name = Printf.sprintf "the_dead_constant_%d" index in + Symbol.create (Compilation_unit.get_current_exn ()) + (Linkage_name.create name) + in + let program_body : Flambda.program_body = + Let_symbol (the_dead_constant, Allocated_const (Nativeint 0n), + program.program_body) + in + let program : Flambda.program = + { program with program_body; } + in + let inconstants = + Inconstant_idents.inconstants_on_program program ~backend + ~compilation_unit:(Compilation_unit.get_current_exn ()) + in + let initialize_symbol_tbl, symbol_definition_tbl, effect_tbl = + program_symbols ~backend program + in + let var_to_symbol_tbl, var_to_definition_tbl, let_symbol_to_definition_tbl, + initialize_symbol_to_definition_tbl = + assign_symbols_and_collect_constant_definitions ~backend ~program + ~inconstants + in + let aliases = + Alias_analysis.run var_to_definition_tbl + initialize_symbol_to_definition_tbl + let_symbol_to_definition_tbl + ~the_dead_constant + in + replace_definitions_in_initialize_symbol_and_effects + (inconstants : Inconstant_idents.result) + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl + : Alias_analysis.constant_defining_value Variable.Tbl.t) + initialize_symbol_tbl + effect_tbl; + let symbol_definition_map = + translate_constant_set_of_closures + (inconstants : Inconstant_idents.result) + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl + : Alias_analysis.constant_defining_value Variable.Tbl.t) + (Symbol.Tbl.to_map symbol_definition_tbl) + in + let project_closure_map = project_closure_map symbol_definition_map in + let translated_definitions = + translate_definitions_and_resolve_alias + inconstants + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl + : Alias_analysis.constant_defining_value Variable.Tbl.t) + symbol_definition_map + project_closure_map + ~backend + in + let var_to_block_field_tbl = + var_to_block_field + (aliases : Alias_analysis.allocation_point Variable.Map.t) + (var_to_symbol_tbl : Symbol.t Variable.Tbl.t) + (var_to_definition_tbl + : Alias_analysis.constant_defining_value Variable.Tbl.t) + in + let translated_definitions = + introduce_free_variables_in_sets_of_closures var_to_block_field_tbl + translated_definitions + in + let constant_definitions = + (* Add previous Let_symbol to the newly discovered ones *) + Symbol.Map.union + (fun _sym + (c1:Flambda.constant_defining_value) + (c2:Flambda.constant_defining_value) -> + match c1, c2 with + | Project_closure (s1, closure_id1), + Project_closure (s2, closure_id2) when + Symbol.equal s1 s2 && + Closure_id.equal closure_id1 closure_id2 -> + Some c1 + | Project_closure (s1, closure_id1), + Project_closure (s2, closure_id2) -> + Format.eprintf "not equal project closure@. s %a %a@. cid %a %a@." + Symbol.print s1 Symbol.print s2 + Closure_id.print closure_id1 Closure_id.print closure_id2; + assert false + | _ -> + assert false + ) + symbol_definition_map + translated_definitions + in + (* Upon the [Initialize_symbol]s, the [Effect]s and the constant definitions, + do the following: + 1. Introduce [Let]s to bind variables that are going to be replaced + by constants. + 2. If a variable bound by a closure gets replaced by a symbol and + thus eliminated from the [free_vars] set of the closure, we need to + rewrite any subsequent [Project_var] expressions that project that + variable. *) + let rewrite_expr expr = + Flambda_iterators.map_named (function + | (Set_of_closures set_of_closures) as named -> + let new_set_of_closures = + introduce_free_variables_in_set_of_closures + var_to_block_field_tbl set_of_closures + in + if new_set_of_closures == set_of_closures then + named + else + Set_of_closures new_set_of_closures + | (Project_var project_var) as original -> + rewrite_project_var var_to_block_field_tbl project_var ~original + | (Symbol _ | Const _ | Allocated_const _ | Project_closure _ + | Move_within_set_of_closures _ | Prim _ | Expr _ + | Read_mutable _ | Read_symbol_field _) as named -> named) + expr + in + let constant_definitions = + Symbol.Map.map (fun (const : Flambda.constant_defining_value) -> + match const with + | Allocated_const _ | Block _ | Project_closure _ -> const + | Set_of_closures set_of_closures -> + let set_of_closures = + Flambda_iterators.map_function_bodies set_of_closures + ~f:rewrite_expr + in + Flambda.Set_of_closures + (introduce_free_variables_in_set_of_closures + var_to_block_field_tbl set_of_closures)) + constant_definitions + in + let effect_tbl = + Symbol.Tbl.map effect_tbl (fun (effect, dep) -> rewrite_expr effect, dep) + in + let initialize_symbol_tbl = + Symbol.Tbl.map initialize_symbol_tbl (fun (tag, fields, dep) -> + let fields = List.map rewrite_expr fields in + tag, fields, dep) + in + let imported_symbols = Flambda_utils.imported_symbols program in + let components = + program_graph ~backend imported_symbols constant_definitions + initialize_symbol_tbl effect_tbl + in + let program_body = + add_definitions_of_symbols constant_definitions + initialize_symbol_tbl + effect_tbl + (End (Flambda_utils.root_symbol program)) + components + in + Flambda_utils.introduce_needed_import_symbols { program with program_body; } diff --git a/middle_end/lift_constants.mli b/middle_end/lift_constants.mli new file mode 100644 index 00000000..464391aa --- /dev/null +++ b/middle_end/lift_constants.mli @@ -0,0 +1,65 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** The aim of this pass is to assign symbols to values known to be + constant (in other words, whose values we know at compile time), with + appropriate sharing of constants, and replace the occurrences of the + constants with their corresponding symbols. + + This pass uses the results of two other passes, [Inconstant_idents] and + [Alias_analysis]. The relationship between these two deserves some + attention. + + [Inconstant_idents] is a "backwards" analysis that propagates implications + about inconstantness of variables and set of closures IDs. + + [Alias_analysis] is a "forwards" analysis that is analagous to the + propagation of [Simple_value_approx.t] values during [Inline_and_simplify]. + It gives us information about relationships between values but not actually + about their constantness. + + Combining these two into a single pass has been attempted previously, + but was not thought to be successful; this experiment could be repeated in + the future. (If "constant" is considered as "top" and "inconstant" is + considered as "bottom", then [Alias_analysis] corresponds to a least fixed + point and [Inconstant_idents] corresponds to a greatest fixed point.) + + At a high level, this pass operates as follows. Symbols are assigned to + variables known to be constant and their defining expressions examined. + Based on the results of [Alias_analysis], we simplify the destructive + elements within the defining expressions (specifically, projection of + fields from blocks), to eventually yield [Flambda.constant_defining_value]s + that are entirely constructive. These will be bound to symbols in the + resulting program. + + Another approach to this pass could be to only use the results of + [Inconstant_idents] and then repeatedly lift constants and run + [Inline_and_simplify] until a fixpoint. It was thought more robust to + instead use [Alias_analysis], where the fixpointing involves a less + complicated function. + + We still run [Inline_and_simplify] once after this pass since the lifting + of constants may enable more functions to become closed; the simplification + pass provides an easy way of cleaning up (e.g. making sure [free_vars] + maps in sets of closures are correct). +*) + +val lift_constants + : Flambda.program + -> backend:(module Backend_intf.S) + -> Flambda.program diff --git a/middle_end/lift_let_to_initialize_symbol.ml b/middle_end/lift_let_to_initialize_symbol.ml new file mode 100644 index 00000000..337d0193 --- /dev/null +++ b/middle_end/lift_let_to_initialize_symbol.ml @@ -0,0 +1,294 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type ('a, 'b) kind = + | Initialisation of (Symbol.t * Tag.t * Flambda.t list) + | Effect of 'b + +let should_copy (named:Flambda.named) = + match named with + | Symbol _ | Read_symbol_field _ | Const _ -> true + | _ -> false + +type extracted = + | Expr of Variable.t * Flambda.t + | Exprs of Variable.t list * Flambda.t + | Block of Variable.t * Tag.t * Variable.t list + +type accumulated = { + copied_lets : (Variable.t * Flambda.named) list; + extracted_lets : extracted list; + terminator : Flambda.expr; +} + +let rec accumulate ~substitution ~copied_lets ~extracted_lets + (expr : Flambda.t) = + match expr with + | Let { var; body = Var var'; _ } | Let_rec ([var, _], Var var') + when Variable.equal var var' -> + { copied_lets; extracted_lets; + terminator = Flambda_utils.toplevel_substitution substitution expr; + } + (* If the pattern is what lifting let_rec generates, prevent it from being + lifted again. *) + | Let_rec (defs, + Let { var; body = Var var'; + defining_expr = Prim (Pmakeblock _, fields, _); }) + when + Variable.equal var var' + && List.for_all (fun field -> + List.exists (fun (def_var, _) -> Variable.equal def_var field) defs) + fields -> + { copied_lets; extracted_lets; + terminator = Flambda_utils.toplevel_substitution substitution expr; + } + | Let { var; defining_expr = Expr (Var alias); body; _ } + | Let_rec ([var, Expr (Var alias)], body) -> + let alias = + match Variable.Map.find alias substitution with + | exception Not_found -> alias + | original_alias -> original_alias + in + accumulate + ~substitution:(Variable.Map.add var alias substitution) + ~copied_lets + ~extracted_lets + body + | Let { var; defining_expr = named; body; _ } + | Let_rec ([var, named], body) + when should_copy named -> + accumulate body + ~substitution + ~copied_lets:((var, named)::copied_lets) + ~extracted_lets + | Let { var; defining_expr = named; body; _ } -> + let extracted = + let renamed = Variable.rename var in + match named with + | Prim (Pmakeblock (tag, Asttypes.Immutable), args, _dbg) -> + let tag = Tag.create_exn tag in + let args = + List.map (fun v -> + try Variable.Map.find v substitution + with Not_found -> v) + args + in + Block (var, tag, args) + | named -> + let expr = + Flambda_utils.toplevel_substitution substitution + (Flambda.create_let renamed named (Var renamed)) + in + Expr (var, expr) + in + accumulate body + ~substitution + ~copied_lets + ~extracted_lets:(extracted::extracted_lets) + | Let_rec ([var, named], body) -> + let renamed = Variable.rename var in + let def_substitution = Variable.Map.add var renamed substitution in + let expr = + Flambda_utils.toplevel_substitution def_substitution + (Let_rec ([renamed, named], Var renamed)) + in + let extracted = Expr (var, expr) in + accumulate body + ~substitution + ~copied_lets + ~extracted_lets:(extracted::extracted_lets) + | Let_rec (defs, body) -> + let renamed_defs, def_substitution = + List.fold_right (fun (var, def) (acc, substitution) -> + let new_var = Variable.rename var in + (new_var, def) :: acc, + Variable.Map.add var new_var substitution) + defs ([], substitution) + in + let extracted = + let expr = + Flambda_utils.toplevel_substitution def_substitution + (Let_rec (renamed_defs, + Flambda_utils.name_expr ~name:"lifted_let_rec_block" + (Prim (Pmakeblock (0, Immutable), + List.map fst renamed_defs, + Debuginfo.none)))) + in + Exprs (List.map fst defs, expr) + in + accumulate body + ~substitution + ~copied_lets + ~extracted_lets:(extracted::extracted_lets) + | _ -> + { copied_lets; + extracted_lets; + terminator = Flambda_utils.toplevel_substitution substitution expr; + } + +let rebuild_expr + ~(extracted_definitions : (Symbol.t * int list) Variable.Map.t) + ~(copied_definitions : Flambda.named Variable.Map.t) + ~(substitute : bool) + (expr : Flambda.t) = + let expr_with_read_symbols = + Flambda_utils.substitute_read_symbol_field_for_variables + extracted_definitions expr + in + let free_variables = Flambda.free_variables expr_with_read_symbols in + let substitution = + if substitute then + Variable.Map.of_set (fun x -> Variable.rename x) free_variables + else + Variable.Map.of_set (fun x -> x) free_variables + in + let expr_with_read_symbols = + Flambda_utils.toplevel_substitution substitution + expr_with_read_symbols + in + Variable.Map.fold (fun var declaration body -> + let definition = Variable.Map.find var copied_definitions in + Flambda.create_let declaration definition body) + substitution expr_with_read_symbols + +let rebuild (used_variables:Variable.Set.t) (accumulated:accumulated) = + let copied_definitions = Variable.Map.of_list accumulated.copied_lets in + let accumulated_extracted_lets = + List.map (fun decl -> + match decl with + | Block (var, _, _) | Expr (var, _) -> + Flambda_utils.make_variable_symbol var, decl + | Exprs (vars, _) -> + Flambda_utils.make_variables_symbol vars, decl) + accumulated.extracted_lets + in + let extracted_definitions = + (* Blocks are lifted to direct top-level Initialize_block: + accessing the value be done directly through the symbol. + Other let bound variables are initialized inside a size + one static block: + accessing the value is done directly through the field 0 + of the symbol. + let rec of size more than one is represented as a block of + all the bound variables allocated inside a size one static + block: + accessing the value is done directly through the right + field of the field 0 of the symbol. *) + List.fold_left (fun map (symbol, decl) -> + match decl with + | Block (var, _tag, _fields) -> + Variable.Map.add var (symbol, []) map + | Expr (var, _expr) -> + Variable.Map.add var (symbol, [0]) map + | Exprs (vars, _expr) -> + let map, _ = + List.fold_left (fun (map, field) var -> + Variable.Map.add var (symbol, [field; 0]) map, + field + 1) + (map, 0) vars + in + map) + Variable.Map.empty accumulated_extracted_lets + in + let extracted = + List.map (fun (symbol, decl) -> + match decl with + | Expr (var, decl) -> + let expr = + rebuild_expr ~extracted_definitions ~copied_definitions + ~substitute:true decl + in + if Variable.Set.mem var used_variables then + Initialisation + (symbol, + Tag.create_exn 0, + [expr]) + else + Effect expr + | Exprs (_vars, decl) -> + let expr = + rebuild_expr ~extracted_definitions ~copied_definitions + ~substitute:true decl + in + Initialisation (symbol, Tag.create_exn 0, [expr]) + | Block (_var, tag, fields) -> + let fields = + List.map (fun var -> + rebuild_expr ~extracted_definitions ~copied_definitions + ~substitute:true (Var var)) + fields + in + Initialisation (symbol, tag, fields)) + accumulated_extracted_lets + in + let terminator = + (* We don't need to substitute the variables in the terminator, we + suppose that we did for every other occurrence. Avoiding this + substitution allows this transformation to be idempotent. *) + rebuild_expr ~extracted_definitions ~copied_definitions + ~substitute:false accumulated.terminator + in + List.rev extracted, terminator + +let introduce_symbols expr = + let accumulated = + accumulate expr + ~substitution:Variable.Map.empty + ~copied_lets:[] ~extracted_lets:[] + in + let used_variables = Flambda.used_variables expr in + let extracted, terminator = rebuild used_variables accumulated in + extracted, terminator + +let add_extracted introduced program = + List.fold_right (fun extracted program -> + match extracted with + | Initialisation (symbol, tag, def) -> + Flambda.Initialize_symbol (symbol, tag, def, program) + | Effect effect -> + Flambda.Effect (effect, program)) + introduced program + +let rec split_program (program : Flambda.program_body) : Flambda.program_body = + match program with + | End s -> End s + | Let_symbol (s, def, program) -> + Let_symbol (s, def, split_program program) + | Let_rec_symbol (defs, program) -> + Let_rec_symbol (defs, split_program program) + | Effect (expr, program) -> + let program = split_program program in + let introduced, expr = introduce_symbols expr in + add_extracted introduced (Flambda.Effect (expr, program)) + | Initialize_symbol (symbol, tag, ((_::_::_) as fields), program) -> + (* CR-someday pchambart: currently the only initialize_symbol with more + than 1 field is the module block. This could evolve, in that case + this pattern should be handled properly. *) + Initialize_symbol (symbol, tag, fields, split_program program) + | Initialize_symbol (sym, tag, [], program) -> + Let_symbol (sym, Block (tag, []), split_program program) + | Initialize_symbol (symbol, tag, [field], program) -> + let program = split_program program in + let introduced, field = introduce_symbols field in + add_extracted introduced + (Flambda.Initialize_symbol (symbol, tag, [field], program)) + +let lift ~backend:_ (program : Flambda.program) = + { program with + program_body = split_program program.program_body; + } diff --git a/middle_end/lift_let_to_initialize_symbol.mli b/middle_end/lift_let_to_initialize_symbol.mli new file mode 100644 index 00000000..287cdcab --- /dev/null +++ b/middle_end/lift_let_to_initialize_symbol.mli @@ -0,0 +1,38 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Lift toplevel [Let]-expressions to Flambda [program] constructions such + that the results of evaluation of such expressions may be accessed + directly, through symbols, rather than through closures. The + [Let]-expressions typically come from the compilation of modules (using + the bytecode strategy) in [Translmod]. + + This means of compilation supercedes the old "transl_store_" methodology + for native code. + + An [Initialize_symbol] construction generated by this pass may be + subsequently rewritten to [Let_symbol] if it is discovered that the + initializer is in fact constant. (See [Initialize_symbol_to_let_symbol].) + + The [program] constructions generated by this pass will be joined by + others that arise from the lifting of constants (see [Lift_constants]). +*) +val lift + : backend:(module Backend_intf.S) + -> Flambda.program + -> Flambda.program diff --git a/middle_end/middle_end.ml b/middle_end/middle_end.ml new file mode 100644 index 00000000..c6646abf --- /dev/null +++ b/middle_end/middle_end.ml @@ -0,0 +1,183 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let _dump_function_sizes flam ~backend = + let module Backend = (val backend : Backend_intf.S) in + let than = max_int in + Flambda_iterators.iter_on_set_of_closures_of_program flam + ~f:(fun ~constant:_ (set_of_closures : Flambda.set_of_closures) -> + Variable.Map.iter (fun fun_var + (function_decl : Flambda.function_declaration) -> + let closure_id = Closure_id.wrap fun_var in + let symbol = Backend.closure_symbol closure_id in + match Inlining_cost.lambda_smaller' function_decl.body ~than with + | Some size -> Format.eprintf "%a %d\n" Symbol.print symbol size + | None -> assert false) + set_of_closures.function_decls.funs) + +let middle_end ppf ~source_provenance ~prefixname ~backend + ~size + ~filename + ~module_ident + ~module_initializer = + let pass_number = ref 0 in + let round_number = ref 0 in + let check flam = + if !Clflags.flambda_invariant_checks then begin + try Flambda_invariants.check_exn flam + with exn -> + Misc.fatal_errorf "After Flambda pass %d, round %d:@.%s:@.%a" + !pass_number !round_number (Printexc.to_string exn) + Flambda.print_program flam + end + in + let (+-+) flam (name, pass) = + incr pass_number; + if !Clflags.dump_flambda_verbose then begin + Format.fprintf ppf "@.PASS: %s@." name; + Format.fprintf ppf "Before pass %d, round %d:@ %a@." !pass_number + !round_number Flambda.print_program flam; + Format.eprintf "\n@?" + end; + let timing_pass = (Timings.Flambda_pass (name, source_provenance)) in + let flam = Timings.accumulate_time timing_pass pass flam in + if !Clflags.flambda_invariant_checks then begin + Timings.accumulate_time (Flambda_pass ("check", source_provenance)) + check flam + end; + flam + in + Timings.accumulate_time + (Flambda_pass ("middle_end", source_provenance)) (fun () -> + let flam = + let timing_pass = + Timings.Flambda_pass ("closure_conversion", source_provenance) + in + Timings.accumulate_time timing_pass (fun () -> + module_initializer + |> Closure_conversion.lambda_to_flambda ~backend ~module_ident + ~size ~filename) + () + in + if !Clflags.dump_rawflambda + then + Format.fprintf ppf "After closure conversion:@ %a@." + Flambda.print_program flam; + check flam; + let fast_mode flam = + pass_number := 0; + let round = 0 in + flam + +-+ ("lift_lets 1", Lift_code.lift_lets) + +-+ ("Lift_constants", Lift_constants.lift_constants ~backend) + +-+ ("Share_constants", Share_constants.share_constants) + +-+ ("Lift_let_to_initialize_symbol", + Lift_let_to_initialize_symbol.lift ~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) + +-+ ("Initialize_symbol_to_let_symbol", + Initialize_symbol_to_let_symbol.run) + in + let rec loop flam = + pass_number := 0; + let round = !round_number in + incr round_number; + if !round_number > (Clflags.rounds ()) then flam + else + flam + (* Beware: [Lift_constants] must be run before any pass that might + duplicate strings. *) + +-+ ("lift_lets 1", Lift_code.lift_lets) + +-+ ("Lift_constants", Lift_constants.lift_constants ~backend) + +-+ ("Share_constants", Share_constants.share_constants) + +-+ ("Remove_unused_program_constructs", + Remove_unused_program_constructs.remove_unused_program_constructs) + +-+ ("Lift_let_to_initialize_symbol", + Lift_let_to_initialize_symbol.lift ~backend) + +-+ ("lift_lets 2", Lift_code.lift_lets) + +-+ ("Remove_unused_closure_vars 1", + Remove_unused_closure_vars.remove_unused_closure_variables + ~remove_direct_call_surrogates:false) + +-+ ("Inline_and_simplify", + Inline_and_simplify.run ~never_inline:false ~backend + ~prefixname ~round) + +-+ ("Remove_unused_closure_vars 2", + 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) + +-+ ("Initialize_symbol_to_let_symbol", + Initialize_symbol_to_let_symbol.run) + |> loop + in + let back_end flam = + flam + +-+ ("Remove_unused_closure_vars", + Remove_unused_closure_vars.remove_unused_closure_variables + ~remove_direct_call_surrogates:true) + +-+ ("Lift_constants", Lift_constants.lift_constants ~backend) + +-+ ("Share_constants", Share_constants.share_constants) + +-+ ("Remove_unused_program_constructs", + Remove_unused_program_constructs.remove_unused_program_constructs) + in + let flam = + if !Clflags.classic_inlining then + fast_mode flam + else + loop flam + in + let flam = back_end flam in + (* Check that there aren't any unused "always inline" attributes. *) + Flambda_iterators.iter_apply_on_program flam ~f:(fun apply -> + match apply.inline with + | Default_inline | Never_inline -> () + | Always_inline -> + (* CR-someday mshinwell: consider a different error message if + this triggers as a result of the propagation of a user's + attribute into the second part of an over application + (inline_and_simplify.ml line 710). *) + Location.prerr_warning (Debuginfo.to_location apply.dbg) + (Warnings.Inlining_impossible "[@inlined] attribute was not \ + used on this function application (the optimizer did not \ + know what function was being applied)") + | Unroll _ -> + Location.prerr_warning (Debuginfo.to_location apply.dbg) + (Warnings.Inlining_impossible "[@unroll] attribute was not \ + used on this function application (the optimizer did not \ + know what function was being applied)")); + if !Clflags.dump_flambda + then + Format.fprintf ppf "End of middle end:@ %a@." + Flambda.print_program flam; + check flam; + (* CR-someday mshinwell: add -d... option for this *) + (* dump_function_sizes flam ~backend; *) + flam) (); diff --git a/middle_end/middle_end.mli b/middle_end/middle_end.mli new file mode 100644 index 00000000..ff8728a3 --- /dev/null +++ b/middle_end/middle_end.mli @@ -0,0 +1,30 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* Translate Lambda code to Flambda code and then optimize it. *) + +val middle_end + : Format.formatter + -> source_provenance:Timings.source_provenance + -> prefixname:string + -> backend:(module Backend_intf.S) + -> size:int + -> filename:string + -> module_ident:Ident.t + -> module_initializer:Lambda.lambda + -> Flambda.program diff --git a/middle_end/pass_wrapper.ml b/middle_end/pass_wrapper.ml new file mode 100644 index 00000000..0907583e --- /dev/null +++ b/middle_end/pass_wrapper.ml @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let register ~pass_name = + Clflags.all_passes := pass_name :: !Clflags.all_passes + +let with_dump ~pass_name ~f ~input ~print_input ~print_output = + let dump = Clflags.dumped_pass pass_name in + let result = f () in + match result with + | None -> + if dump then Format.eprintf "%s: no-op.\n\n%!" pass_name; + None + | Some result -> + if dump then begin + Format.eprintf "Before %s:@ %a@.@." pass_name print_input input; + Format.eprintf "After %s:@ %a@.@." pass_name print_output result + end; + Some result diff --git a/middle_end/pass_wrapper.mli b/middle_end/pass_wrapper.mli new file mode 100644 index 00000000..a6d3bf9d --- /dev/null +++ b/middle_end/pass_wrapper.mli @@ -0,0 +1,25 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +val register : pass_name:string -> unit + +val with_dump + : pass_name:string + -> f:(unit -> 'b option) + -> input:'a + -> print_input:(Format.formatter -> 'a -> unit) + -> print_output:(Format.formatter -> 'b -> unit) + -> 'b option diff --git a/middle_end/projection.ml b/middle_end/projection.ml new file mode 100644 index 00000000..deb86488 --- /dev/null +++ b/middle_end/projection.ml @@ -0,0 +1,169 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-someday mshinwell: Move these three types into their own modules. *) + +type project_closure = { + set_of_closures : Variable.t; + closure_id : Closure_id.t; +} + +type move_within_set_of_closures = { + closure : Variable.t; + start_from : Closure_id.t; + move_to : Closure_id.t; +} + +type project_var = { + closure : Variable.t; + closure_id : Closure_id.t; + var : Var_within_closure.t; +} + +let compare_project_var + ({ closure = closure1; closure_id = closure_id1; var = var1; } + : project_var) + ({ closure = closure2; closure_id = closure_id2; var = var2; } + : project_var) = + let c = Variable.compare closure1 closure2 in + if c <> 0 then c + else + let c = Closure_id.compare closure_id1 closure_id2 in + if c <> 0 then c + else + Var_within_closure.compare var1 var2 + +let compare_move_within_set_of_closures + ({ closure = closure1; start_from = start_from1; move_to = move_to1; } + : move_within_set_of_closures) + ({ closure = closure2; start_from = start_from2; move_to = move_to2; } + : move_within_set_of_closures) = + let c = Variable.compare closure1 closure2 in + if c <> 0 then c + else + let c = Closure_id.compare start_from1 start_from2 in + if c <> 0 then c + else + Closure_id.compare move_to1 move_to2 + +let compare_project_closure + ({ set_of_closures = set_of_closures1; closure_id = closure_id1; } + : project_closure) + ({ set_of_closures = set_of_closures2; closure_id = closure_id2; } + : project_closure) = + let c = Variable.compare set_of_closures1 set_of_closures2 in + if c <> 0 then c + else + Closure_id.compare closure_id1 closure_id2 + +let print_project_closure ppf (project_closure : project_closure) = + Format.fprintf ppf "@[<2>(project_closure@ %a@ from@ %a)@]" + Closure_id.print project_closure.closure_id + Variable.print project_closure.set_of_closures + +let print_move_within_set_of_closures ppf + (move_within_set_of_closures : move_within_set_of_closures) = + Format.fprintf ppf + "@[<2>(move_within_set_of_closures@ %a <-- %a@ (closure = %a))@]" + Closure_id.print move_within_set_of_closures.move_to + Closure_id.print move_within_set_of_closures.start_from + Variable.print move_within_set_of_closures.closure + +let print_project_var ppf (project_var : project_var) = + Format.fprintf ppf "@[<2>(project_var@ %a@ from %a=%a)@]" + Var_within_closure.print project_var.var + Closure_id.print project_var.closure_id + Variable.print project_var.closure + +type t = + | Project_var of project_var + | Project_closure of project_closure + | Move_within_set_of_closures of move_within_set_of_closures + | Field of int * Variable.t + +include Identifiable.Make (struct + type nonrec t = t + + let compare t1 t2 = + match t1, t2 with + | Project_var project_var1, Project_var project_var2 -> + compare_project_var project_var1 project_var2 + | Project_closure project_closure1, Project_closure project_closure2 -> + compare_project_closure project_closure1 project_closure2 + | Move_within_set_of_closures move1, Move_within_set_of_closures move2 -> + compare_move_within_set_of_closures move1 move2 + | Field (index1, var1), Field (index2, var2) -> + let c = compare index1 index2 in + if c <> 0 then c + else Variable.compare var1 var2 + | Project_var _, _ -> -1 + | _, Project_var _ -> 1 + | Project_closure _, _ -> -1 + | _, Project_closure _ -> 1 + | Move_within_set_of_closures _, _ -> -1 + | _, Move_within_set_of_closures _ -> -1 + + let equal t1 t2 = + (compare t1 t2) = 0 + + let hash = Hashtbl.hash + + let print ppf t = + match t with + | Project_closure (project_closure) -> + print_project_closure ppf project_closure + | Project_var (project_var) -> print_project_var ppf project_var + | Move_within_set_of_closures (move_within_set_of_closures) -> + print_move_within_set_of_closures ppf move_within_set_of_closures + | Field (field_index, var) -> + Format.fprintf ppf "Field %d of %a" field_index Variable.print var + + let output _ _ = failwith "Projection.output: not yet implemented" +end) + +let projecting_from t = + match t with + | Project_var { closure; _ } -> closure + | Project_closure { set_of_closures; _ } -> set_of_closures + | Move_within_set_of_closures { closure; _ } -> closure + | Field (_, var) -> var + +let map_projecting_from t ~f : t = + match t with + | Project_var project_var -> + let project_var : project_var = + { project_var with + closure = f project_var.closure; + } + in + Project_var project_var + | Project_closure project_closure -> + let project_closure : project_closure = + { project_closure with + set_of_closures = f project_closure.set_of_closures; + } + in + Project_closure project_closure + | Move_within_set_of_closures move -> + let move : move_within_set_of_closures = + { move with + closure = f move.closure; + } + in + Move_within_set_of_closures move + | Field (field_index, var) -> Field (field_index, f var) diff --git a/middle_end/projection.mli b/middle_end/projection.mli new file mode 100644 index 00000000..1b251ca2 --- /dev/null +++ b/middle_end/projection.mli @@ -0,0 +1,80 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +(** Representation of projections from closures and blocks. *) + +(** The selection of one closure given a set of closures, required before + a function defined by said set of closures can be applied. See more + detailed documentation below on [set_of_closures]. *) +type project_closure = { + set_of_closures : Variable.t; (** must yield a set of closures *) + closure_id : Closure_id.t; +} + +(** The selection of one closure given another closure in the same set of + closures. See more detailed documentation below on [set_of_closures]. + The [move_to] closure must be part of the free variables of + [start_from]. *) +type move_within_set_of_closures = { + closure : Variable.t; (** must yield a closure *) + start_from : Closure_id.t; + move_to : Closure_id.t; +} + +(** The selection from a closure of a variable bound by said closure. + In other words, access to a function's environment. Also see more + detailed documentation below on [set_of_closures]. *) +type project_var = { + closure : Variable.t; (** must yield a closure *) + closure_id : Closure_id.t; + var : Var_within_closure.t; +} + +val print_project_closure + : Format.formatter + -> project_closure + -> unit + +val print_move_within_set_of_closures + : Format.formatter + -> move_within_set_of_closures + -> unit + +val print_project_var + : Format.formatter + -> project_var + -> unit + +val compare_project_var : project_var -> project_var -> int +val compare_project_closure : project_closure -> project_closure -> int +val compare_move_within_set_of_closures + : move_within_set_of_closures + -> move_within_set_of_closures + -> int + +type t = + | Project_var of project_var + | Project_closure of project_closure + | Move_within_set_of_closures of move_within_set_of_closures + | Field of int * Variable.t + +include Identifiable.S with type t := t + +(** Return which variable the given projection projects from. *) +val projecting_from : t -> Variable.t + +(** Change the variable that the given projection projects from. *) +val map_projecting_from : t -> f:(Variable.t -> Variable.t) -> t diff --git a/middle_end/ref_to_variables.ml b/middle_end/ref_to_variables.ml new file mode 100644 index 00000000..0b79b1ca --- /dev/null +++ b/middle_end/ref_to_variables.ml @@ -0,0 +1,195 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let rename_var var = + Mutable_variable.create + (Variable.unique_name var) + (* Variable.rename var *) + (* ~current_compilation_unit:(Compilation_unit.get_current_exn ()) *) + +let variables_not_used_as_local_reference (tree:Flambda.t) = + let set = ref Variable.Set.empty in + let rec loop_named (flam : Flambda.named) = + match flam with + (* Directly used block: does not prevent use as a variable *) + | Prim(Pfield _, [_], _) + | Prim(Poffsetref _, [_], _) -> () + | Prim(Psetfield _, [_block; v], _) -> + (* block is not prevented to be used as a local reference, but v is *) + set := Variable.Set.add v !set + | Prim(_, _, _) + | Symbol _ |Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ | Project_closure _ + | Move_within_set_of_closures _ | Project_var _ -> + set := Variable.Set.union !set (Flambda.free_variables_named flam) + | Set_of_closures set_of_closures -> + set := Variable.Set.union !set (Flambda.free_variables_named flam); + Variable.Map.iter (fun _ (function_decl : Flambda.function_declaration) -> + loop function_decl.body) + set_of_closures.function_decls.funs + | Expr e -> + loop e + and loop (flam : Flambda.t) = + match flam with + | Let { defining_expr; body; _ } -> + loop_named defining_expr; + loop body + | Let_rec (defs, body) -> + List.iter (fun (_var, named) -> loop_named named) defs; + loop body + | Var v -> + set := Variable.Set.add v !set + | Let_mutable (_, v, body) -> + set := Variable.Set.add v !set; + loop body + | If_then_else (cond, ifso, ifnot) -> + set := Variable.Set.add cond !set; + loop ifso; + loop ifnot + | Switch (cond, { consts; blocks; failaction }) -> + set := Variable.Set.add cond !set; + List.iter (fun (_, branch) -> loop branch) consts; + List.iter (fun (_, branch) -> loop branch) blocks; + Misc.may loop failaction + | String_switch (cond, branches, default) -> + set := Variable.Set.add cond !set; + List.iter (fun (_, branch) -> loop branch) branches; + Misc.may loop default + | Static_catch (_, _, body, handler) -> + loop body; + loop handler + | Try_with (body, _, handler) -> + loop body; + loop handler + | While (cond, body) -> + loop cond; + loop body + | For { bound_var = _; from_value; to_value; direction = _; body; } -> + set := Variable.Set.add from_value !set; + set := Variable.Set.add to_value !set; + loop body + | Static_raise (_, args) -> + set := Variable.Set.union (Variable.Set.of_list args) !set + | Proved_unreachable | Apply _ | Send _ | Assign _ -> + set := Variable.Set.union !set (Flambda.free_variables flam) + in + loop tree; + !set + +let variables_containing_ref (flam:Flambda.t) = + let map = ref Variable.Map.empty in + let aux (flam : Flambda.t) = + match flam with + | Let { var; + defining_expr = Prim(Pmakeblock(0, Asttypes.Mutable), l, _); + } -> + map := Variable.Map.add var (List.length l) !map + | _ -> () + in + Flambda_iterators.iter aux (fun _ -> ()) flam; + !map + +let eliminate_ref_of_expr flam = + let variables_not_used_as_local_reference = + variables_not_used_as_local_reference flam + in + let convertible_variables = + Variable.Map.filter + (fun v _ -> + not (Variable.Set.mem v variables_not_used_as_local_reference)) + (variables_containing_ref flam) + in + if Variable.Map.cardinal convertible_variables = 0 then flam + else + let convertible_variables = + Variable.Map.mapi (fun v size -> + Array.init size (fun _ -> rename_var v)) + convertible_variables + in + let convertible_variable v = Variable.Map.mem v convertible_variables in + let get_variable v field = + let arr = try Variable.Map.find v convertible_variables + with Not_found -> assert false in + if Array.length arr <= field + then None (* This case could apply when inlining code containing GADTS *) + else Some (arr.(field), Array.length arr) + in + let aux (flam : Flambda.t) : Flambda.t = + match flam with + | Let { var; + defining_expr = Prim(Pmakeblock(0, Asttypes.Mutable), l, _); + body } + when convertible_variable var -> + let _, expr = + List.fold_left (fun (field,body) init -> + match get_variable var field with + | None -> assert false + | Some (field_var, _) -> + field+1, + ((Let_mutable (field_var, init, body)) : Flambda.t)) + (0,body) l in + expr + | Let _ | Let_mutable _ + | Assign _ | Var _ | Apply _ + | Let_rec _ | Switch _ | String_switch _ + | Static_raise _ | Static_catch _ + | Try_with _ | If_then_else _ + | While _ | For _ | Send _ | Proved_unreachable -> + flam + and aux_named (named : Flambda.named) : Flambda.named = + match named with + | Prim(Pfield field, [v], _) + when convertible_variable v -> + (match get_variable v field with + | None -> Expr Proved_unreachable + | Some (var,_) -> Read_mutable var) + | Prim(Poffsetref delta, [v], dbg) + when convertible_variable v -> + (match get_variable v 0 with + | None -> Expr Proved_unreachable + | Some (var,size) -> + if size = 1 + then begin + let mut = Variable.create "read_mutable" in + let new_value = Variable.create "offseted" in + let expr = + Flambda.create_let mut (Read_mutable var) + (Flambda.create_let new_value + (Prim(Poffsetint delta, [mut], dbg)) + (Assign { being_assigned = var; new_value })) + in + Expr expr + end + else + Expr Proved_unreachable) + | Prim(Psetfield (field, _, _), [v; new_value], _) + when convertible_variable v -> + (match get_variable v field with + | None -> Expr Proved_unreachable + | Some (being_assigned,_) -> + Expr (Assign { being_assigned; new_value })) + | Prim _ | Symbol _ | Const _ | Allocated_const _ | Read_mutable _ + | Read_symbol_field _ | Set_of_closures _ | Project_closure _ + | Move_within_set_of_closures _ | Project_var _ | Expr _ -> + named + in + Flambda_iterators.map aux aux_named flam + +let eliminate_ref (program:Flambda.program) = + Flambda_iterators.map_exprs_at_toplevel_of_program program + ~f:eliminate_ref_of_expr diff --git a/middle_end/ref_to_variables.mli b/middle_end/ref_to_variables.mli new file mode 100644 index 00000000..38d36889 --- /dev/null +++ b/middle_end/ref_to_variables.mli @@ -0,0 +1,23 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Transform [let]-bound references into variables. *) + +val eliminate_ref + : Flambda.program + -> Flambda.program diff --git a/middle_end/remove_free_vars_equal_to_args.ml b/middle_end/remove_free_vars_equal_to_args.ml new file mode 100644 index 00000000..d5df14bd --- /dev/null +++ b/middle_end/remove_free_vars_equal_to_args.ml @@ -0,0 +1,104 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let pass_name = "remove-free-vars-equal-to-args" +let () = Pass_wrapper.register ~pass_name + +let rewrite_one_function_decl ~(function_decl : Flambda.function_declaration) + ~back_free_vars ~specialised_args = + let params_for_equal_free_vars = + List.fold_left (fun subst param -> + match Variable.Map.find param specialised_args with + | exception Not_found -> + (* param is not specialised *) + subst + | (spec_to : Flambda.specialised_to) -> + let outside_var = spec_to.var in + match Variable.Map.find outside_var back_free_vars with + | exception Not_found -> + (* No free variables equal to the param *) + subst + | set -> + (* Replace the free variables equal to an parameter *) + Variable.Set.fold (fun free_var subst -> + Variable.Map.add free_var param subst) + set subst) + Variable.Map.empty function_decl.params + in + if Variable.Map.is_empty params_for_equal_free_vars then + function_decl + else + let body = + Flambda_utils.toplevel_substitution + params_for_equal_free_vars + function_decl.body + in + Flambda.create_function_declaration + ~params:function_decl.params + ~body:body + ~stub:function_decl.stub + ~dbg:function_decl.dbg + ~inline:function_decl.inline + ~specialise:function_decl.specialise + ~is_a_functor:function_decl.is_a_functor + +let rewrite_one_set_of_closures (set_of_closures : Flambda.set_of_closures) = + let back_free_vars = + Variable.Map.fold (fun var (outside_var : Flambda.specialised_to) map -> + let set = + match Variable.Map.find outside_var.var map with + | exception Not_found -> Variable.Set.singleton var + | set -> Variable.Set.add var set + in + Variable.Map.add outside_var.var set map) + set_of_closures.free_vars Variable.Map.empty + in + let done_something = ref false in + let funs = + Variable.Map.map (fun function_decl -> + let new_function_decl = + rewrite_one_function_decl ~function_decl ~back_free_vars + ~specialised_args:set_of_closures.specialised_args + in + if not (new_function_decl == function_decl) then begin + done_something := true + end; + new_function_decl) + set_of_closures.function_decls.funs + in + if not !done_something then + None + else + let function_decls = + Flambda.update_function_declarations + set_of_closures.function_decls ~funs + in + let set_of_closures = + Flambda.create_set_of_closures + ~function_decls + ~free_vars:set_of_closures.free_vars + ~specialised_args:set_of_closures.specialised_args + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + Some set_of_closures + +let run set_of_closures = + Pass_wrapper.with_dump ~pass_name ~input:set_of_closures + ~print_input:Flambda.print_set_of_closures + ~print_output:Flambda.print_set_of_closures + ~f:(fun () -> rewrite_one_set_of_closures set_of_closures) diff --git a/middle_end/remove_free_vars_equal_to_args.mli b/middle_end/remove_free_vars_equal_to_args.mli new file mode 100644 index 00000000..ae92d44d --- /dev/null +++ b/middle_end/remove_free_vars_equal_to_args.mli @@ -0,0 +1,20 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +(** Replace free variables in closures known to be equal to specialised + arguments of such closures with those specialised arguments. *) + +val run : Flambda.set_of_closures -> Flambda.set_of_closures option diff --git a/middle_end/remove_unused_arguments.ml b/middle_end/remove_unused_arguments.ml new file mode 100644 index 00000000..cfac16e3 --- /dev/null +++ b/middle_end/remove_unused_arguments.ml @@ -0,0 +1,231 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let pass_name = "remove-unused-arguments" +let () = Clflags.all_passes := pass_name :: !Clflags.all_passes + +let rename_var var = + Variable.rename var + ~current_compilation_unit:(Compilation_unit.get_current_exn ()) + +let remove_params unused (fun_decl: Flambda.function_declaration) = + let unused_params, used_params = + List.partition (fun v -> Variable.Set.mem v unused) fun_decl.params + in + let unused_params = List.filter (fun v -> + Variable.Set.mem v fun_decl.free_variables) unused_params + in + let body = + List.fold_left (fun body var -> + Flambda.create_let var (Const (Const_pointer 0)) body) + fun_decl.body + unused_params + in + Flambda.create_function_declaration ~params:used_params ~body + ~stub:fun_decl.stub ~dbg:fun_decl.dbg ~inline:fun_decl.inline + ~specialise:fun_decl.specialise ~is_a_functor:fun_decl.is_a_functor + +let make_stub unused var (fun_decl : Flambda.function_declaration) + ~specialised_args ~additional_specialised_args = + let renamed = rename_var var in + let args' = + List.map (fun var -> var, rename_var var) fun_decl.params + in + let used_args' = + List.filter (fun (var, _) -> not (Variable.Set.mem var unused)) args' + in + let args_renaming = Variable.Map.of_list args' in + let additional_specialised_args = + List.fold_left (fun additional_specialised_args (original_arg,arg) -> + match Variable.Map.find original_arg specialised_args with + | exception Not_found -> additional_specialised_args + | (outer_var : Flambda.specialised_to) -> + (* CR-soon mshinwell: share with Augment_specialised_args *) + let outer_var : Flambda.specialised_to = + match outer_var.projection with + | None -> outer_var + | Some projection -> + let projection = + Projection.map_projecting_from projection ~f:(fun var -> + match Variable.Map.find var args_renaming with + | exception Not_found -> + (* Must always be a parameter of this + [function_decl]. *) + assert false + | wrapper_arg -> wrapper_arg) + in + { outer_var with + projection = Some projection; + } + in + Variable.Map.add arg outer_var additional_specialised_args) + additional_specialised_args args' + in + let args = List.map (fun (_, var) -> var) used_args' in + let kind = Flambda.Direct (Closure_id.wrap renamed) in + let dbg = fun_decl.dbg in + let body : Flambda.t = + Apply { + func = renamed; + args; + kind; + dbg; + inline = Default_inline; + specialise = Default_specialise; + } + in + let function_decl = + Flambda.create_function_declaration ~params:(List.map snd args') ~body + ~stub:true ~dbg:fun_decl.dbg ~inline:Default_inline + ~specialise:Default_specialise ~is_a_functor:fun_decl.is_a_functor + in + function_decl, renamed, additional_specialised_args + +let separate_unused_arguments ~only_specialised + ~backend ~(set_of_closures : Flambda.set_of_closures) = + let function_decls = set_of_closures.function_decls in + let unused = Invariant_params.unused_arguments ~backend function_decls in + let non_stub_arguments = + Variable.Map.fold (fun _ (decl : Flambda.function_declaration) acc -> + if decl.stub then + acc + else + Variable.Set.union acc (Variable.Set.of_list decl.Flambda.params)) + function_decls.funs Variable.Set.empty + in + let unused = Variable.Set.inter non_stub_arguments unused in + let specialised_args = Variable.Map.keys set_of_closures.specialised_args in + let unused = + if only_specialised then Variable.Set.inter specialised_args unused + else unused + in + if Variable.Set.is_empty unused + then None + else begin + let funs, additional_specialised_args = + Variable.Map.fold (fun fun_id (fun_decl : Flambda.function_declaration) + (funs, additional_specialised_args) -> + if List.exists (fun v -> Variable.Set.mem v unused) fun_decl.params + then begin + let stub, renamed_fun_id, additional_specialised_args = + make_stub unused fun_id fun_decl + ~specialised_args:set_of_closures.specialised_args + ~additional_specialised_args + in + let cleaned = remove_params unused fun_decl in + Variable.Map.add fun_id stub + (Variable.Map.add renamed_fun_id cleaned funs), + additional_specialised_args + end + else + Variable.Map.add fun_id fun_decl funs, + additional_specialised_args + ) + function_decls.funs (Variable.Map.empty, Variable.Map.empty) + in + let specialised_args = + Variable.Map.disjoint_union additional_specialised_args + (Variable.Map.filter (fun param _ -> + not (Variable.Set.mem param unused)) + set_of_closures.specialised_args) + in + let specialised_args = + Flambda_utils.clean_projections ~which_variables:specialised_args + in + let function_decls = + Flambda.update_function_declarations function_decls ~funs + in + let set_of_closures = + Flambda.create_set_of_closures ~function_decls + ~free_vars:set_of_closures.free_vars ~specialised_args + (* CR-soon mshinwell: Use direct_call_surrogates for this + transformation. *) + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + Some set_of_closures + end + +(* Splitting is not always beneficial. For instance when a function + is only indirectly called, suppressing unused arguments does not + benefit, and introduce an useless intermediate call. Specialised + args should always be beneficial since they should not be used in + indirect calls. *) +let should_split_only_specialised_args + (fun_decls : Flambda.function_declarations) + ~backend = + if not !Clflags.remove_unused_arguments then begin + true + end else begin + let no_recursive_functions = + Variable.Set.is_empty + (Find_recursive_functions.in_function_declarations fun_decls ~backend) + in + let number_of_non_stub_functions = + Variable.Map.cardinal + (Variable.Map.filter (fun _ { Flambda.stub } -> not stub) + fun_decls.funs) + in + (* CR-soon lwhite: this criteria could use some justification. + mshinwell: pchambart cannot remember how these criteria arose, + but we're going to leave this as-is for 4.03. *) + no_recursive_functions && (number_of_non_stub_functions <= 1) + end + +let separate_unused_arguments_in_set_of_closures set_of_closures ~backend = + let dump = Clflags.dumped_pass pass_name in + let only_specialised = + should_split_only_specialised_args + set_of_closures.Flambda.function_decls + ~backend + in + match separate_unused_arguments + ~only_specialised ~backend ~set_of_closures with + | None -> + if dump then + Format.eprintf "No change for Remove_unused_arguments:@ %a@.@." + Flambda.print_set_of_closures set_of_closures; + None + | Some result -> + if dump then + Format.eprintf "Before Remove_unused_arguments:@ %a@.@.\ + After Remove_unused_arguments:@ %a@.@." + Flambda.print_set_of_closures set_of_closures + Flambda.print_set_of_closures result; + Some result + +let separate_unused_arguments_in_closures_expr tree ~backend = + let aux_named (named : Flambda.named) : Flambda.named = + match named with + | Set_of_closures set_of_closures -> begin + let only_specialised = + should_split_only_specialised_args + set_of_closures.function_decls + ~backend + in + match separate_unused_arguments + ~only_specialised ~backend ~set_of_closures with + | None -> named + | Some set_of_closures -> Set_of_closures set_of_closures + end + | e -> e + in + Flambda_iterators.map_named aux_named tree + +let separate_unused_arguments_in_closures program ~backend = + Flambda_iterators.map_exprs_at_toplevel_of_program program ~f:(fun expr -> + separate_unused_arguments_in_closures_expr expr ~backend) diff --git a/middle_end/remove_unused_arguments.mli b/middle_end/remove_unused_arguments.mli new file mode 100644 index 00000000..759b32f2 --- /dev/null +++ b/middle_end/remove_unused_arguments.mli @@ -0,0 +1,39 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Introduce a stub function to avoid depending on unused arguments. + + For instance, it turns + [let rec fact n unused = + if n = 0 then 1 + else n * fact (n-1) unused] + into + [let rec fact' n = + if n = 0 then 1 + else n * fact' (n-1) + and fact n unused = fact' n] +*) +val separate_unused_arguments_in_closures + : Flambda.program + -> backend:(module Backend_intf.S) + -> Flambda.program + +val separate_unused_arguments_in_set_of_closures + : Flambda.set_of_closures + -> backend:(module Backend_intf.S) + -> Flambda.set_of_closures option diff --git a/middle_end/remove_unused_closure_vars.ml b/middle_end/remove_unused_closure_vars.ml new file mode 100644 index 00000000..2f58d045 --- /dev/null +++ b/middle_end/remove_unused_closure_vars.ml @@ -0,0 +1,124 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** A variable in a closure can either be used by the closure itself + or by an inlined version of the function. *) +let remove_unused_closure_variables ~remove_direct_call_surrogates program = + let used_vars_within_closure, used_closure_ids = + let used = Var_within_closure.Tbl.create 13 in + let used_fun = Closure_id.Tbl.create 13 in + let aux_named (named : Flambda.named) = + match named with + | Project_closure { set_of_closures = _; closure_id } -> + Closure_id.Tbl.add used_fun closure_id () + | Project_var { closure_id; var } -> + Var_within_closure.Tbl.add used var (); + Closure_id.Tbl.add used_fun closure_id () + | Move_within_set_of_closures { closure = _; start_from; move_to } -> + Closure_id.Tbl.add used_fun start_from (); + Closure_id.Tbl.add used_fun move_to () + | Symbol _ | Const _ | Set_of_closures _ | Prim _ | Expr _ + | Allocated_const _ | Read_mutable _ | Read_symbol_field _ -> () + in + Flambda_iterators.iter_named_of_program ~f:aux_named program; + used, used_fun + in + let aux_named _ (named : Flambda.named) : Flambda.named = + match named with + | Set_of_closures ({ function_decls; free_vars; _ } as set_of_closures) -> + let direct_call_surrogates = + if remove_direct_call_surrogates then Variable.Set.empty + else + Variable.Set.of_list + (Variable.Map.data set_of_closures.direct_call_surrogates) + in + let rec add_needed needed_funs remaining_funs free_vars_of_kept_funs = + let new_needed_funs, remaining_funs = + (* Keep a function if it is used either by the rest of the code, + (in used_closure_ids), or by any other kept function + (in free_vars_of_kept_funs) *) + Variable.Map.partition (fun fun_id _ -> + Variable.Set.mem fun_id free_vars_of_kept_funs + || Closure_id.Tbl.mem used_closure_ids + (Closure_id.wrap fun_id) + || Variable.Set.mem fun_id direct_call_surrogates) + remaining_funs + in + if Variable.Map.is_empty new_needed_funs then + (* If no new function is needed, we reached fixpoint *) + needed_funs, free_vars_of_kept_funs + else begin + let needed_funs = + Variable.Map.disjoint_union needed_funs new_needed_funs + in + let free_vars_of_kept_funs = + Variable.Map.fold (fun _ { Flambda. free_variables } acc -> + Variable.Set.union free_variables acc) + new_needed_funs + free_vars_of_kept_funs + in + add_needed needed_funs remaining_funs free_vars_of_kept_funs + end + in + let funs, free_vars_of_kept_funs = + add_needed Variable.Map.empty function_decls.funs Variable.Set.empty + in + let free_vars = + Variable.Map.filter (fun id _var -> + Variable.Set.mem id free_vars_of_kept_funs + || Var_within_closure.Tbl.mem + used_vars_within_closure + (Var_within_closure.wrap id)) + free_vars + in + let function_decls = + Flambda.update_function_declarations function_decls ~funs + in + let specialised_args = + (* Remove specialised args that are used by removed functions *) + let all_remaining_arguments = + Variable.Map.fold (fun _ { Flambda.params } set -> + Variable.Set.union set (Variable.Set.of_list params)) + funs Variable.Set.empty + in + Variable.Map.filter (fun arg _ -> + Variable.Set.mem arg all_remaining_arguments) + set_of_closures.specialised_args + in + let free_vars = + Flambda_utils.clean_projections ~which_variables:free_vars + in + let direct_call_surrogates = + (* Remove direct call surrogates where either the existing function + or the surrogate has been eliminated. *) + Variable.Map.fold (fun existing surrogate surrogates -> + if not (Variable.Map.mem existing funs) + || not (Variable.Map.mem surrogate funs) + then surrogates + else Variable.Map.add existing surrogate surrogates) + set_of_closures.direct_call_surrogates + Variable.Map.empty + in + let set_of_closures = + Flambda.create_set_of_closures ~function_decls + ~free_vars ~specialised_args ~direct_call_surrogates + in + Set_of_closures set_of_closures + | e -> e + in + Flambda_iterators.map_named_of_program ~f:aux_named program diff --git a/middle_end/remove_unused_closure_vars.mli b/middle_end/remove_unused_closure_vars.mli new file mode 100644 index 00000000..225697a8 --- /dev/null +++ b/middle_end/remove_unused_closure_vars.mli @@ -0,0 +1,26 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* CR-soon mshinwell: Rename this module. *) + +(** Eliminate variables bound by sets of closures that are not required. + Also eliminate functions within sets of closures that are not required. *) +val remove_unused_closure_variables + : remove_direct_call_surrogates:bool + -> Flambda.program + -> Flambda.program diff --git a/middle_end/remove_unused_program_constructs.ml b/middle_end/remove_unused_program_constructs.ml new file mode 100644 index 00000000..6311a44a --- /dev/null +++ b/middle_end/remove_unused_program_constructs.ml @@ -0,0 +1,108 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +let dependency (expr:Flambda.t) = Flambda.free_symbols expr + +(* CR-soon pchambart: copied from lift_constant. Needs remerging *) +let constant_dependencies (const:Flambda.constant_defining_value) = + let closure_dependencies (set_of_closures:Flambda.set_of_closures) = + Flambda.free_symbols_named (Set_of_closures set_of_closures) + in + match const with + | Allocated_const _ -> Symbol.Set.empty + | Block (_, fields) -> + let symbol_fields = + Misc.Stdlib.List.filter_map (function + | (Symbol s : Flambda.constant_defining_value_block_field) -> + Some s + | Flambda.Const _ -> None) + fields + in + Symbol.Set.of_list symbol_fields + | Set_of_closures set_of_closures -> closure_dependencies set_of_closures + | Project_closure (s, _) -> Symbol.Set.singleton s + +let let_rec_dep defs dep = + let add_deps l dep = + List.fold_left (fun dep (sym, sym_dep) -> + if Symbol.Set.mem sym dep then Symbol.Set.union dep sym_dep + else dep) + dep l + in + let defs_deps = + List.map (fun (sym, def) -> sym, constant_dependencies def) defs + in + let rec fixpoint dep = + let new_dep = add_deps defs_deps dep in + if Symbol.Set.equal dep new_dep then dep + else fixpoint new_dep + in + fixpoint dep + +let rec loop (program : Flambda.program_body) + : Flambda.program_body * Symbol.Set.t = + match program with + | Let_symbol (sym, def, program) -> + let program, dep = loop program in + if Symbol.Set.mem sym dep then + Let_symbol (sym, def, program), + Symbol.Set.union dep (constant_dependencies def) + else + program, dep + | Let_rec_symbol (defs, program) -> + let program, dep = loop program in + let dep = let_rec_dep defs dep in + let defs = + List.filter (fun (sym, _) -> Symbol.Set.mem sym dep) defs + in + Let_rec_symbol (defs, program), dep + | Initialize_symbol (sym, tag, fields, program) -> + let program, dep = loop program in + if Symbol.Set.mem sym dep then + let dep = + List.fold_left (fun dep field -> + Symbol.Set.union dep (dependency field)) + dep fields + in + Initialize_symbol (sym, tag, fields, program), dep + else begin + List.fold_left + (fun (program, dep) field -> + if Effect_analysis.no_effects field then + program, dep + else + let new_dep = dependency field in + let dep = Symbol.Set.union new_dep dep in + Flambda.Effect (field, program), dep) + (program, dep) fields + end + | Effect (effect, program) -> + let program, dep = loop program in + if Effect_analysis.no_effects effect then begin + program, dep + end else begin + let new_dep = dependency effect in + let dep = Symbol.Set.union new_dep dep in + Effect (effect, program), dep + end + | End symbol -> program, Symbol.Set.singleton symbol + +let remove_unused_program_constructs (program : Flambda.program) = + { program with + program_body = fst (loop program.program_body); + } diff --git a/middle_end/remove_unused_program_constructs.mli b/middle_end/remove_unused_program_constructs.mli new file mode 100644 index 00000000..3a722011 --- /dev/null +++ b/middle_end/remove_unused_program_constructs.mli @@ -0,0 +1,24 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* Remove unused [Flambda.program] constructs from the given program. + - Symbols (whose defining expressions have no effects) are eliminated + if unused. + - [Effect] constructs that turn out to have no effects are eliminated. +*) +val remove_unused_program_constructs : Flambda.program -> Flambda.program diff --git a/middle_end/semantics_of_primitives.ml b/middle_end/semantics_of_primitives.ml new file mode 100644 index 00000000..b8b8c51d --- /dev/null +++ b/middle_end/semantics_of_primitives.ml @@ -0,0 +1,144 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +type effects = No_effects | Only_generative_effects | Arbitrary_effects +type coeffects = No_coeffects | Has_coeffects + +let for_primitive (prim : Lambda.primitive) = + match prim with + | Pignore | Pidentity -> 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. *) + | Pduparray (_, Mutable) | Pduprecord _ -> + 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 + | Plazyforce + | Pccall _ -> Arbitrary_effects, Has_coeffects + | Praise _ -> Arbitrary_effects, No_coeffects + | Pnot + | Pnegint + | Paddint + | Psubint + | Pmulint + | Pandint + | Porint + | Pxorint + | Plslint + | Plsrint + | Pasrint + | Pintcomp _ -> No_effects, No_coeffects + | Pdivint + | Pmodint -> + No_effects, No_coeffects (* Will not raise [Division_by_zero]. *) + | Poffsetint _ -> No_effects, No_coeffects + | Poffsetref _ -> Arbitrary_effects, Has_coeffects + | Pintoffloat + | Pfloatofint + | Pnegfloat + | Pabsfloat + | Paddfloat + | Psubfloat + | Pmulfloat + | Pdivfloat + | Pfloatcomp _ -> No_effects, No_coeffects + | Pstringlength + | Parraylength _ -> + No_effects, Has_coeffects (* That old chestnut: [Obj.truncate]. *) + | Pisint + | Pisout + | Pbittest + | Pbintofint _ + | Pintofbint _ + | Pcvtbint _ + | Pnegbint _ + | Paddbint _ + | Psubbint _ + | Pmulbint _ + | Pdivbint _ + | Pmodbint _ + | Pandbint _ + | Porbint _ + | Pxorbint _ + | Plslbint _ + | Plsrbint _ + | Pasrbint _ + | Pbintcomp _ -> No_effects, No_coeffects + | Pbigarraydim _ -> + No_effects, Has_coeffects (* Some people resize bigarrays in place. *) + | Pfield _ + | Pfloatfield _ + | Pgetglobal _ + | Parrayrefu _ + | Pstringrefu + | Pstring_load_16 true + | Pstring_load_32 true + | Pstring_load_64 true + | Pbigarrayref (true, _, _, _) + | Pbigstring_load_16 true + | Pbigstring_load_32 true + | Pbigstring_load_64 true -> + No_effects, Has_coeffects + | Parrayrefs _ + | Pstringrefs + | Pstring_load_16 false + | Pstring_load_32 false + | Pstring_load_64 false + | Pbigarrayref (false, _, _, _) + | Pbigstring_load_16 false + | Pbigstring_load_32 false + | Pbigstring_load_64 false -> + (* May trigger a bounds check exception. *) + Arbitrary_effects, Has_coeffects + | Psetfield _ + | Psetfloatfield _ + | Psetglobal _ + | Parraysetu _ + | Parraysets _ + | Pstringsetu + | Pstringsets + | Pstring_set_16 _ + | Pstring_set_32 _ + | Pstring_set_64 _ + | Pbigarrayset _ + | 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 + | 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]" + | Prevapply _ + | Pdirapply _ + | Psequand + | Psequor -> + Misc.fatal_errorf "The primitive %a should have been eliminated by the \ + [Closure_conversion] pass." + Printlambda.primitive prim diff --git a/middle_end/semantics_of_primitives.mli b/middle_end/semantics_of_primitives.mli new file mode 100644 index 00000000..65231733 --- /dev/null +++ b/middle_end/semantics_of_primitives.mli @@ -0,0 +1,65 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Description of the semantics of primitives, to be used for optimization + purposes. + + "No effects" means that the primitive does not change the observable state + of the world. For example, it must not write to any mutable storage, + call arbitrary external functions or change control flow (e.g. by raising + an exception). Note that allocation is not "No effects" (see below). + + It is assumed in the compiler that applications of primitives with no + effects, whose results are not used, may be eliminated. It is further + assumed that applications of primitives with no effects may be + duplicated (and thus possibly executed more than once). + + (Exceptions arising from allocation points, for example "out of memory" or + exceptions propagated from finalizers or signal handlers, are treated as + "effects out of the ether" and thus ignored for our determination here + of effectfulness. The same goes for floating point operations that may + cause hardware traps on some platforms.) + + "Only generative effects" means that a primitive does not change the + observable state of the world save for possibly affecting the state of + the garbage collector by performing an allocation. Applications of + primitives that only have generative effects and whose results are unused + may be eliminated by the compiler. However, unlike "No effects" + primitives, such applications will never be eligible for duplication. + + "Arbitrary effects" covers all other primitives. + + "No coeffects" means that the primitive does not observe the effects (in + the sense described above) of other expressions. For example, it must not + read from any mutable storage or call arbitrary external functions. + + It is assumed in the compiler that, subject to data dependencies, + expressions with neither effects nor coeffects may be reordered with + respect to other expressions. +*) + +type effects = No_effects | Only_generative_effects | Arbitrary_effects +type coeffects = No_coeffects | Has_coeffects + +(** Describe the semantics of a primitive. This does not take into account of + 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 diff --git a/middle_end/share_constants.ml b/middle_end/share_constants.ml new file mode 100644 index 00000000..2655d77c --- /dev/null +++ b/middle_end/share_constants.ml @@ -0,0 +1,129 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module Constant_defining_value = Flambda.Constant_defining_value + +let update_constant_for_sharing sharing_symbol_tbl const + : Flambda.constant_defining_value = + let substitute_symbol sym = + match Symbol.Tbl.find sharing_symbol_tbl sym with + | exception Not_found -> sym + | symbol -> symbol + in + match (const:Flambda.constant_defining_value) with + | Allocated_const _ -> const + | Block (tag, fields) -> + let subst_field (field:Flambda.constant_defining_value_block_field) : + Flambda.constant_defining_value_block_field = + match field with + | Const _ -> field + | Symbol sym -> + Symbol (substitute_symbol sym) + in + let fields = List.map subst_field fields in + Block (tag, fields) + | Set_of_closures set_of_closures -> + Set_of_closures ( + Flambda_iterators.map_symbols_on_set_of_closures + ~f:substitute_symbol set_of_closures + ) + | Project_closure (sym, closure_id) -> + Project_closure (substitute_symbol sym, closure_id) + +let cannot_share (const : Flambda.constant_defining_value) = + match const with + (* Strings and float arrays are mutable; we never share them. *) + | Allocated_const ((String _) | (Float_array _)) -> true + | Allocated_const _ | Set_of_closures _ | Project_closure _ | Block _ -> + false + +let share_definition constant_to_symbol_tbl sharing_symbol_tbl + symbol def end_symbol = + let def = update_constant_for_sharing sharing_symbol_tbl def in + if cannot_share def || Symbol.equal symbol end_symbol then + (* The symbol exported by the unit (end_symbol), cannot be removed + from the module. We prevent it from being shared to avoid that. *) + Some def + else + begin match Constant_defining_value.Tbl.find constant_to_symbol_tbl def with + | exception Not_found -> + Constant_defining_value.Tbl.add constant_to_symbol_tbl def symbol; + Some def + | equal_symbol -> + Symbol.Tbl.add sharing_symbol_tbl symbol equal_symbol; + None + end + +let rec end_symbol (program : Flambda.program_body) = + match program with + | End symbol -> symbol + | Let_symbol (_, _, program) + | Let_rec_symbol (_, program) + | Initialize_symbol (_, _, _, program) + | Effect (_, program) -> + end_symbol program + +let share_constants (program : Flambda.program) = + let end_symbol = end_symbol program.program_body in + let sharing_symbol_tbl = Symbol.Tbl.create 42 in + let constant_to_symbol_tbl = Constant_defining_value.Tbl.create 42 in + let rec loop (program : Flambda.program_body) : Flambda.program_body = + match program with + | Let_symbol (symbol,def,program) -> + begin match + share_definition constant_to_symbol_tbl sharing_symbol_tbl symbol + def end_symbol + with + | None -> + loop program + | Some def' -> + Let_symbol (symbol,def',loop program) + end + | Let_rec_symbol (defs,program) -> + let defs = + List.map (fun (symbol, def) -> + let def = update_constant_for_sharing sharing_symbol_tbl def in + symbol, def) + defs + in + Let_rec_symbol (defs, loop program) + | Initialize_symbol (symbol,tag,fields,program) -> + let fields = + List.map (fun field -> + Flambda_iterators.map_symbols + ~f:(fun symbol -> + try Symbol.Tbl.find sharing_symbol_tbl symbol with + | Not_found -> symbol) + field) + fields + in + Initialize_symbol (symbol,tag,fields,loop program) + | Effect (expr,program) -> + let expr = + Flambda_iterators.map_symbols + ~f:(fun symbol -> + try Symbol.Tbl.find sharing_symbol_tbl symbol with + | Not_found -> symbol) + expr + in + Effect (expr, loop program) + | End root -> End root + in + { program with + program_body = loop program.program_body; + } diff --git a/middle_end/share_constants.mli b/middle_end/share_constants.mli new file mode 100644 index 00000000..7fec22bc --- /dev/null +++ b/middle_end/share_constants.mli @@ -0,0 +1,22 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Share lifted constants that are eligible for sharing (e.g. not strings) + and have equal definitions. *) + +val share_constants : Flambda.program -> Flambda.program diff --git a/middle_end/simple_value_approx.ml b/middle_end/simple_value_approx.ml new file mode 100644 index 00000000..50de3181 --- /dev/null +++ b/middle_end/simple_value_approx.ml @@ -0,0 +1,719 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module U = Flambda_utils + +type 'a boxed_int = + | Int32 : int32 boxed_int + | Int64 : int64 boxed_int + | Nativeint : nativeint boxed_int + +type value_string = { + (* CR-soon mshinwell: use variant *) + contents : string option; (* None if unknown or mutable *) + size : int; +} + +type value_float_array_contents = + | Contents of float option array + | Unknown_or_mutable + +type value_float_array = { + contents : value_float_array_contents; + size : int; +} + +type unknown_because_of = + | Unresolved_symbol of Symbol.t + | Other + +type t = { + descr : descr; + var : Variable.t option; + symbol : (Symbol.t * int option) option; +} + +and descr = + | Value_block of Tag.t * t array + | Value_int of int + | Value_char of char + | Value_constptr of int + | Value_float of float + | Value_boxed_int : 'a boxed_int * 'a -> descr + | Value_set_of_closures of value_set_of_closures + | Value_closure of value_closure + | Value_string of value_string + | Value_float_array of value_float_array + | Value_unknown of unknown_because_of + | 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 *) + +and value_closure = { + set_of_closures : t; + closure_id : Closure_id.t; +} + +and value_set_of_closures = { + function_decls : Flambda.function_declarations; + bound_vars : t Var_within_closure.Map.t; + invariant_params : Variable.Set.t Variable.Map.t lazy_t; + size : int option Variable.Map.t lazy_t; + specialised_args : Flambda.specialised_to Variable.Map.t; + freshening : Freshening.Project_var.t; + direct_call_surrogates : Closure_id.t Closure_id.Map.t; +} + +let descr t = t.descr + +let print_value_set_of_closures ppf + { function_decls = { funs }; invariant_params; freshening; _ } = + Format.fprintf ppf "(set_of_closures:@ %a invariant_params=%a freshening=%a)" + (fun ppf -> Variable.Map.iter (fun id _ -> Variable.print ppf id)) funs + (Variable.Map.print Variable.Set.print) (Lazy.force invariant_params) + Freshening.Project_var.print freshening + +let rec print_descr ppf = function + | Value_int i -> Format.pp_print_int ppf i + | Value_char c -> Format.fprintf ppf "%c" c + | Value_constptr i -> Format.fprintf ppf "%ia" i + | Value_block (tag,fields) -> + let p ppf fields = + Array.iter (fun v -> Format.fprintf ppf "%a@ " print v) fields in + 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 + | Other -> Format.fprintf ppf "?" + end; + | Value_bottom -> Format.fprintf ppf "bottom" + | Value_extern id -> Format.fprintf ppf "_%a_" Export_id.print id + | Value_symbol sym -> Format.fprintf ppf "%a" Symbol.print sym + | Value_closure { set_of_closures; closure_id; } -> + Format.fprintf ppf "(closure:@ %a from@ %a)" Closure_id.print closure_id + 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_float f -> Format.pp_print_float ppf f + | Value_string { contents; size } -> begin + match contents with + | None -> + Format.fprintf ppf "string %i" size + | Some s -> + let s = + if size > 10 + then String.sub s 0 8 ^ "..." + else s + in + Format.fprintf ppf "string %i %S" size s + end + | Value_float_array float_array -> + begin match float_array.contents with + | Unknown_or_mutable -> + Format.fprintf ppf "float_array %i" float_array.size + | Contents _ -> + Format.fprintf ppf "float_array_imm %i" float_array.size + end + | Value_boxed_int (t, i) -> + match t with + | Int32 -> Format.fprintf ppf "%li" i + | Int64 -> Format.fprintf ppf "%Li" i + | Nativeint -> Format.fprintf ppf "%ni" i + +and print ppf { descr; var; symbol; } = + let print ppf = function + | None -> Symbol.print_opt ppf None + | Some (sym, None) -> Symbol.print ppf sym + | Some (sym, Some field) -> + Format.fprintf ppf "%a.(%i)" Symbol.print sym field + in + Format.fprintf ppf "{ descr=%a var=%a symbol=%a }" + print_descr descr + Variable.print_opt var + print symbol + +let approx descr = { descr; var = None; symbol = None } + +let augment_with_variable t var = { t with var = Some var } +let augment_with_symbol t symbol = { t with symbol = Some (symbol, None) } +let augment_with_symbol_field t symbol field = + match t.symbol with + | None -> { t with symbol = Some (symbol, Some field) } + | Some _ -> t +let replace_description t descr = { t with descr } + +let value_unknown reason = approx (Value_unknown reason) +let value_int i = approx (Value_int i) +let value_char i = approx (Value_char i) +let value_constptr i = approx (Value_constptr i) +let value_float f = approx (Value_float f) +let value_boxed_int bi i = approx (Value_boxed_int (bi,i)) + +let value_closure ?closure_var ?set_of_closures_var ?set_of_closures_symbol + value_set_of_closures closure_id = + let approx_set_of_closures = + { descr = Value_set_of_closures value_set_of_closures; + var = set_of_closures_var; + symbol = Misc.may_map (fun s -> s, None) set_of_closures_symbol; + } + in + let value_closure = + { set_of_closures = approx_set_of_closures; + closure_id; + } + in + { descr = Value_closure value_closure; + var = closure_var; + symbol = None; + } + +let create_value_set_of_closures + ~(function_decls : Flambda.function_declarations) ~bound_vars + ~invariant_params ~specialised_args ~freshening + ~direct_call_surrogates = + let size = + lazy ( + let functions = Variable.Map.keys function_decls.funs in + Variable.Map.map (fun (function_decl : Flambda.function_declaration) -> + let params = Variable.Set.of_list function_decl.params in + let free_vars = + Variable.Set.diff + (Variable.Set.diff function_decl.free_variables params) + functions + in + let num_free_vars = Variable.Set.cardinal free_vars in + let max_size = + Inlining_cost.maximum_interesting_size_of_function_body + num_free_vars + in + Inlining_cost.lambda_smaller' function_decl.body ~than:max_size) + function_decls.funs) + in + { function_decls; + bound_vars; + invariant_params; + size; + specialised_args; + freshening; + direct_call_surrogates; + } + +let update_freshening_of_value_set_of_closures value_set_of_closures + ~freshening = + (* CR-someday mshinwell: We could maybe check that [freshening] is + reasonable. *) + { value_set_of_closures with freshening; } + +let value_set_of_closures ?set_of_closures_var value_set_of_closures = + { descr = Value_set_of_closures value_set_of_closures; + var = set_of_closures_var; + symbol = None; + } + +let value_block t b = approx (Value_block (t, b)) +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_string size contents = approx (Value_string {size; contents }) +let value_mutable_float_array ~size = + approx (Value_float_array { contents = Unknown_or_mutable; size; } ) +let value_immutable_float_array contents = + let size = Array.length contents in + approx (Value_float_array { contents = Contents contents; size; } ) + +let name_expr_fst (named, thing) ~name = + (Flambda_utils.name_expr named ~name), thing + +let make_const_int_named n : Flambda.named * t = + Const (Int n), value_int n +let make_const_int (n : int) = + let name = + match n with + | 0 -> "const_zero" + | 1 -> "const_one" + | _ -> "const_int" + in + name_expr_fst (make_const_int_named n) ~name + +let make_const_char_named n : Flambda.named * t = + Const (Char n), value_char n +let make_const_char n = + name_expr_fst (make_const_char_named n) ~name:"const_char" + +let make_const_ptr_named n : Flambda.named * t = + Const (Const_pointer n), value_constptr n +let make_const_ptr (n : int) = + let name = + match n with + | 0 -> "const_ptr_zero" + | 1 -> "const_ptr_one" + | _ -> "const_ptr" + in + name_expr_fst (make_const_ptr_named n) ~name + +let make_const_bool_named b : Flambda.named * t = + make_const_ptr_named (if b then 1 else 0) +let make_const_bool b = + name_expr_fst (make_const_bool_named b) ~name:"const_bool" + +let make_const_float_named f : Flambda.named * t = + Allocated_const (Float f), value_float f +let make_const_float f = + name_expr_fst (make_const_float_named f) ~name:"const_float" + +let make_const_boxed_int_named (type bi) (t:bi boxed_int) (i:bi) + : Flambda.named * t = + let c : Allocated_const.t = + match t with + | Int32 -> Int32 i + | Int64 -> Int64 i + | Nativeint -> Nativeint i + in + Allocated_const c, value_boxed_int t i +let make_const_boxed_int t i = + name_expr_fst (make_const_boxed_int_named t i) ~name:"const_boxed_int" + +type simplification_summary = + | Nothing_done + | Replaced_term + +type simplification_result = Flambda.t * simplification_summary * t +type simplification_result_named = Flambda.named * simplification_summary * t + +let simplify t (lam : Flambda.t) : simplification_result = + if Effect_analysis.no_effects lam then + match t.descr with + | Value_int n -> + let const, approx = make_const_int n in + const, Replaced_term, approx + | Value_char n -> + let const, approx = make_const_char n in + const, Replaced_term, approx + | Value_constptr n -> + let const, approx = make_const_ptr n in + const, Replaced_term, approx + | Value_float f -> + let const, approx = make_const_float f in + const, Replaced_term, approx + | Value_boxed_int (t, i) -> + let const, approx = make_const_boxed_int t i in + const, Replaced_term, approx + | Value_symbol sym -> + U.name_expr (Symbol sym) ~name:"symbol", Replaced_term, t + | Value_string _ | Value_float_array _ + | Value_block _ | Value_set_of_closures _ | Value_closure _ + | Value_unknown _ | Value_bottom | Value_extern _ | Value_unresolved _ -> + lam, Nothing_done, t + else + lam, Nothing_done, t + +let simplify_named t (named : Flambda.named) : simplification_result_named = + if Effect_analysis.no_effects_named named then + match t.descr with + | Value_int n -> + let const, approx = make_const_int_named n in + const, Replaced_term, approx + | Value_char n -> + let const, approx = make_const_char_named n in + const, Replaced_term, approx + | Value_constptr n -> + let const, approx = make_const_ptr_named n in + const, Replaced_term, approx + | Value_float f -> + let const, approx = make_const_float_named f in + const, Replaced_term, approx + | Value_boxed_int (t, i) -> + let const, approx = make_const_boxed_int_named t i in + const, Replaced_term, approx + | Value_symbol sym -> + Symbol sym, Replaced_term, t + | Value_string _ | Value_float_array _ + | Value_block _ | Value_set_of_closures _ | Value_closure _ + | Value_unknown _ | Value_bottom | Value_extern _ | Value_unresolved _ -> + named, Nothing_done, t + else + named, Nothing_done, t + +(* CR-soon mshinwell: bad name. This function and its call site in + [Inline_and_simplify] is also messy. *) +let simplify_var t : (Flambda.named * t) option = + match t.descr with + | Value_int n -> Some (make_const_int_named n) + | Value_char n -> Some (make_const_char_named n) + | Value_constptr n -> Some (make_const_ptr_named n) + | Value_float f -> Some (make_const_float_named f) + | Value_boxed_int (t, i) -> Some (make_const_boxed_int_named t i) + | Value_symbol sym -> Some (Symbol sym, t) + | Value_string _ | Value_float_array _ + | Value_block _ | Value_set_of_closures _ | Value_closure _ + | Value_unknown _ | Value_bottom | Value_extern _ + | Value_unresolved _ -> + match t.symbol with + | Some (sym, None) -> Some (Symbol sym, t) + | Some (sym, Some field) -> Some (Read_symbol_field (sym, field), t) + | None -> None + +let join_summaries summary ~replaced_by_var_or_symbol = + match replaced_by_var_or_symbol, summary with + | true, Nothing_done + | true, Replaced_term + | false, Replaced_term -> Replaced_term + | false, Nothing_done -> Nothing_done + +let simplify_using_env t ~is_present_in_env flam = + let replaced_by_var_or_symbol, flam = + match t.var with + | Some var when is_present_in_env var -> true, Flambda.Var var + | _ -> + match t.symbol with + | Some (sym, None) -> true, + U.name_expr (Symbol sym) ~name:"symbol" + | Some (sym, Some field) -> + true, U.name_expr (Read_symbol_field (sym, field)) ~name:"symbol_field" + | None -> false, flam + in + let const, summary, approx = simplify t flam in + const, join_summaries summary ~replaced_by_var_or_symbol, approx + +let simplify_named_using_env t ~is_present_in_env named = + let replaced_by_var_or_symbol, named = + match t.var with + | Some var when is_present_in_env var -> + true, Flambda.Expr (Var var) + | _ -> + match t.symbol with + | Some (sym, None) -> true, (Flambda.Symbol sym:Flambda.named) + | Some (sym, Some field) -> + true, Flambda.Read_symbol_field (sym, field) + | None -> false, named + in + let const, summary, approx = simplify_named t named in + const, join_summaries summary ~replaced_by_var_or_symbol, approx + +let simplify_var_to_var_using_env t ~is_present_in_env = + match t.var with + | Some var when is_present_in_env var -> Some var + | _ -> None + +let known t = + match t.descr with + | Value_unresolved _ + | Value_unknown _ -> false + | Value_string _ | Value_float_array _ + | Value_bottom | Value_block _ | Value_int _ | Value_char _ + | Value_constptr _ | Value_set_of_closures _ | Value_closure _ + | Value_extern _ | Value_float _ | Value_boxed_int _ | Value_symbol _ -> true + +let useful t = + match t.descr with + | Value_unresolved _ | Value_unknown _ | Value_bottom -> false + | Value_string _ | Value_float_array _ | Value_block _ | Value_int _ + | Value_char _ | Value_constptr _ | Value_set_of_closures _ + | Value_float _ | Value_boxed_int _ | Value_closure _ | Value_extern _ + | Value_symbol _ -> true + +let all_not_useful ts = List.for_all (fun t -> not (useful t)) ts + +let is_definitely_immutable t = + match t.descr with + | Value_string { contents = Some _ } + | Value_block _ | Value_int _ | Value_char _ | Value_constptr _ + | Value_set_of_closures _ | Value_float _ | Value_boxed_int _ + | Value_closure _ -> true + | Value_string { contents = None } | Value_float_array _ + | Value_unresolved _ | Value_unknown _ | Value_bottom -> false + | Value_extern _ | Value_symbol _ -> assert false + +type get_field_result = + | Ok of t + | Unreachable + +let get_field t ~field_index:i : get_field_result = + match t.descr with + | Value_block (_tag, fields) -> + if i >= 0 && i < Array.length fields then begin + Ok fields.(i) + end else begin + (* This (unfortunately) cannot be a fatal error; it can happen if a + .cmx file is missing. However for debugging the compiler this can + be a useful point to put a [Misc.fatal_errorf]. *) + Unreachable + end + (* CR-someday mshinwell: This should probably return Unreachable in more + cases. I added a couple more. *) + | Value_bottom + | Value_int _ | Value_char _ | Value_constptr _ -> + (* Something seriously wrong is happening: either the user is doing + something exceptionally unsafe, or it is an unreachable branch. + We consider this as unreachable and mark the result accordingly. *) + Ok value_bottom + | Value_float_array _ -> + (* For the moment we return "unknown" even for immutable arrays, since + it isn't possible for user code to project from an immutable array. *) + (* CR-someday mshinwell: If Leo's array's patch lands, then we can + change this, although it's probably not Pfield that is used to + do the projection. *) + Ok (value_unknown Other) + | Value_string _ | Value_float _ | Value_boxed_int _ -> + (* The user is doing something unsafe. *) + Unreachable + | Value_set_of_closures _ | Value_closure _ + (* This is used by [CamlinternalMod]. *) + | Value_symbol _ | Value_extern _ -> + (* These should have been resolved. *) + Ok (value_unknown Other) + | Value_unknown reason -> + Ok (value_unknown reason) + | Value_unresolved sym -> + (* 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) + +type checked_approx_for_block = + | Wrong + | Ok of Tag.t * t array + +let check_approx_for_block t = + match t.descr with + | Value_block (tag, fields) -> + Ok (tag, fields) + | Value_bottom + | Value_int _ | Value_char _ | Value_constptr _ + | Value_float_array _ + | Value_string _ | Value_float _ | Value_boxed_int _ + | Value_set_of_closures _ | Value_closure _ + | Value_symbol _ | Value_extern _ + | Value_unknown _ + | Value_unresolved _ -> + Wrong + +let descrs approxs = List.map (fun v -> v.descr) approxs + +let equal_boxed_int (type t1) (type t2) + (bi1:t1 boxed_int) (i1:t1) + (bi2:t2 boxed_int) (i2:t2) = + match bi1, bi2 with + | Int32, Int32 -> Int32.equal i1 i2 + | Int64, Int64 -> Int64.equal i1 i2 + | Nativeint, Nativeint -> Nativeint.equal i1 i2 + | _ -> false + +(* Closures and set of closures descriptions cannot be merged. + + let f x = + let g y -> x + y in + g + in + let v = + if ... + then f 1 + else f 2 + in + v 3 + + The approximation for [f 1] and [f 2] could both contain the + description of [g]. But if [f] where inlined, a new [g] would + be created in each branch, leading to incompatible description. + And we must never make the descrition for a function less + precise that it used to be: its information are needed for + rewriting [Project_var] and [Project_closure] constructions + in [Flambdainline.loop] +*) +let rec meet_descr d1 d2 = match d1, d2 with + | Value_int i, Value_int j when i = j -> + d1 + | Value_constptr i, Value_constptr j when i = j -> + d1 + | Value_symbol s1, Value_symbol s2 when Symbol.equal s1 s2 -> + d1 + | Value_extern e1, Value_extern e2 when Export_id.equal e1 e2 -> + d1 + | Value_float i, Value_float j when i = j -> + d1 + | Value_boxed_int (bi1, i1), Value_boxed_int (bi2, i2) when + equal_boxed_int bi1 i1 bi2 i2 -> + d1 + | Value_block (tag1, a1), Value_block (tag2, a2) + when tag1 = tag2 && Array.length a1 = Array.length a2 -> + Value_block (tag1, Array.mapi (fun i v -> meet v a2.(i)) a1) + | _ -> Value_unknown Other + +and meet a1 a2 = + match a1, a2 with + | { descr = Value_bottom }, a + | a, { descr = Value_bottom } -> a + | _ -> + let var = + match a1.var, a2.var with + | None, _ | _, None -> None + | Some v1, Some v2 -> + if Variable.equal v1 v2 + then Some v1 + else None + in + let symbol = + match a1.symbol, a2.symbol with + | None, _ | _, None -> None + | Some (v1, field1), Some (v2, field2) -> + if Symbol.equal v1 v2 + then match field1, field2 with + | None, None -> a1.symbol + | Some f1, Some f2 when f1 = f2 -> + a1.symbol + | _ -> None + else None + in + { descr = meet_descr a1.descr a2.descr; + var; + symbol } + +(* Given a set-of-closures approximation and a closure ID, apply any + freshening specified in the approximation to the closure ID, and return + that new closure ID. A fatal error is produced if the new closure ID + does not correspond to a function declaration in the given approximation. *) +let freshen_and_check_closure_id + (value_set_of_closures : value_set_of_closures) closure_id = + let closure_id = + Freshening.Project_var.apply_closure_id + value_set_of_closures.freshening closure_id + in + try + ignore (Flambda_utils.find_declaration closure_id + value_set_of_closures.function_decls); + closure_id + with Not_found -> + Misc.fatal_error (Format.asprintf + "Function %a not found in the set of closures@ %a@.%a@." + Closure_id.print closure_id + print_value_set_of_closures value_set_of_closures + Flambda.print_function_declarations value_set_of_closures.function_decls) + +type checked_approx_for_set_of_closures = + | Wrong + | Unresolved of Symbol.t + | Unknown + | Unknown_because_of_unresolved_symbol of Symbol.t + | 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_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 + to the set now out of scope. *) + Ok (t.var, value_set_of_closures) + | Value_closure _ | Value_block _ | Value_int _ | Value_char _ + | Value_constptr _ | Value_float _ | Value_boxed_int _ | Value_unknown _ + | Value_bottom | Value_extern _ | Value_string _ | Value_float_array _ + | Value_symbol _ -> + Wrong + +type strict_checked_approx_for_set_of_closures = + | Wrong + | Ok of Variable.t option * value_set_of_closures + +let strict_check_approx_for_set_of_closures t + : strict_checked_approx_for_set_of_closures = + 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 + +type checked_approx_for_closure_allowing_unresolved = + | Wrong + | Unresolved of Symbol.t + | Unknown + | Unknown_because_of_unresolved_symbol of Symbol.t + | Ok of value_closure * Variable.t option + * Symbol.t option * value_set_of_closures + +let check_approx_for_closure_allowing_unresolved t + : checked_approx_for_closure_allowing_unresolved = + match t.descr with + | Value_closure value_closure -> + begin match value_closure.set_of_closures.descr with + | Value_set_of_closures value_set_of_closures -> + let symbol = match value_closure.set_of_closures.symbol with + | Some (symbol, None) -> Some symbol + | None | Some (_, Some _) -> None + in + Ok (value_closure, value_closure.set_of_closures.var, + symbol, value_set_of_closures) + | Value_unresolved _ + | Value_closure _ | Value_block _ | Value_int _ | Value_char _ + | Value_constptr _ | Value_float _ | Value_boxed_int _ | Value_unknown _ + | Value_bottom | Value_extern _ | Value_string _ | Value_float_array _ + | Value_symbol _ -> + Wrong + end + | Value_unknown (Unresolved_symbol symbol) -> + Unknown_because_of_unresolved_symbol symbol + | Value_unresolved symbol -> Unresolved symbol + | Value_set_of_closures _ | Value_block _ | Value_int _ | Value_char _ + | Value_constptr _ | Value_float _ | Value_boxed_int _ + | Value_bottom | Value_extern _ | Value_string _ | Value_float_array _ + | Value_symbol _ -> + Wrong + (* CR-soon mshinwell: This should be unwound once the reason for a value + being unknown can be correctly propagated through the export info. *) + | Value_unknown Other -> Unknown + +type checked_approx_for_closure = + | Wrong + | Ok of value_closure * Variable.t option + * Symbol.t option * value_set_of_closures + +let check_approx_for_closure t : checked_approx_for_closure = + match check_approx_for_closure_allowing_unresolved t with + | Ok (value_closure, set_of_closures_var, set_of_closures_symbol, + 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 + +let approx_for_bound_var value_set_of_closures var = + try + Var_within_closure.Map.find var value_set_of_closures.bound_vars + with + | Not_found -> + Misc.fatal_errorf "The set-of-closures approximation %a@ does not \ + bind the variable %a@.%s@." + print_value_set_of_closures value_set_of_closures + Var_within_closure.print var + (Printexc.raw_backtrace_to_string (Printexc.get_callstack max_int)) + +let check_approx_for_float t : float option = + match t.descr with + | Value_float f -> Some f + | Value_unresolved _ + | Value_unknown _ | Value_string _ | Value_float_array _ + | Value_bottom | Value_block _ | Value_int _ | Value_char _ + | Value_constptr _ | Value_set_of_closures _ | Value_closure _ + | Value_extern _ | Value_boxed_int _ | Value_symbol _ -> + None diff --git a/middle_end/simple_value_approx.mli b/middle_end/simple_value_approx.mli new file mode 100644 index 00000000..bc1ce121 --- /dev/null +++ b/middle_end/simple_value_approx.mli @@ -0,0 +1,401 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Simple approximations to the runtime results of computations. + This pass is designed for speed rather than accuracy; the performance + is important since it is used heavily during inlining. *) + +type 'a boxed_int = + | Int32 : int32 boxed_int + | Int64 : int64 boxed_int + | Nativeint : nativeint boxed_int + +type value_string = { + contents : string option; (* [None] if unknown or mutable *) + size : int; +} + +type value_float_array_contents = + | Contents of float option array + | Unknown_or_mutable + +type value_float_array = { + contents : value_float_array_contents; + size : int; +} + +type unknown_because_of = + | Unresolved_symbol of Symbol.t + | Other + +(** A value of type [t] corresponds to an "approximation" of the result of + a computation in the program being compiled. That is to say, it + represents what knowledge we have about such a result at compile time. + The simplification pass exploits this information to partially evaluate + computations. + + At a high level, an approximation for a value [v] has three parts: + - the "description" (for example, "the constant integer 42"); + - an optional variable; + - an optional symbol or symbol field. + If the variable (resp. symbol) is present then that variable (resp. + symbol) may be used to obtain the value [v]. + + The exact semantics of the variable and symbol fields follows. + + Approximations are deduced at particular points in an expression tree, + but may subsequently be propagated to other locations. + + At the point at which an approximation is built for some value [v], we can + construct a set of variables (call the set [S]) that are known to alias the + same value [v]. Each member of [S] will have the same or a more precise + [descr] field in its approximation relative to the approximation for [v]. + (An increase in precision may currently be introduced for pattern + matches.) If [S] is non-empty then it is guaranteed that there is a + unique member of [S] that was declared in a scope further out ("earlier") + than all other members of [S]. If such a member exists then it is + recorded in the [var] field. Otherwise [var] is [None]. + + Analogous to the construction of the set [S], we can construct a set [T] + consisting of all symbols that are known to alias the value whose + approximation is being constructed. If [T] is non-empty then the + [symbol] field is set to some member of [T]; it does not matter which + one. (There is no notion of scope for symbols.) + + Note about mutable blocks: + + Mutable blocks are always represented by [Value_unknown] or + [Value_bottom]. Any other approximation could leave the door open to + a miscompilation. Such bad scenarios are most likely a user using + [Obj.magic] or [Obj.set_field] in an inappropriate situation. + Such a situation might be: + [let x = (1, 1) in + Obj.set_field (Obj.repr x) 0 (Obj.repr 2); + assert(fst x = 2)] + The user would probably expect the assertion to be true, but the + compiler could in fact propagate the value of [x] across the + [Obj.set_field]. + + Insisting that mutable blocks have [Value_unknown] or [Value_bottom] + approximations certainly won't always prevent this kind of error, but + should help catch many of them. + + It is possible that there may be some false positives, with correct + but unreachable code causing this check to fail. However the likelihood + of this seems sufficiently low, especially compared to the advantages + gained by performing the check, that we include it. + + An example of a pattern that might trigger a false positive is: + [type a = { a : int } + type b = { mutable b : int } + type _ t = + | A : a t + | B : b t + let f (type x) (v:x t) (r:x) = + match v with + | A -> r.a + | B -> r.b <- 2; 3 + + let v = + let r = + ref A in + r := A; (* Some pattern that the compiler can't understand *) + f !r { a = 1 }] + When inlining [f], the B branch is unreachable, yet the compiler + cannot prove it and must therefore keep it. +*) +type t = private { + descr : descr; + var : Variable.t option; + symbol : (Symbol.t * int option) option; +} + +and descr = private + | Value_block of Tag.t * t array + | Value_int of int + | Value_char of char + | Value_constptr of int + | Value_float of float + | Value_boxed_int : 'a boxed_int * 'a -> descr + | Value_set_of_closures of value_set_of_closures + | Value_closure of value_closure + | Value_string of value_string + | Value_float_array of value_float_array + | Value_unknown of unknown_because_of + | 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 *) + +and value_closure = { + set_of_closures : t; + closure_id : Closure_id.t; +} + +(* CR-soon mshinwell: add support for the approximations of the results, so we + can do all of the tricky higher-order cases. *) +and value_set_of_closures = private { + function_decls : Flambda.function_declarations; + bound_vars : t Var_within_closure.Map.t; + invariant_params : Variable.Set.t Variable.Map.t lazy_t; + size : int option Variable.Map.t lazy_t; + (** For functions that are very likely to be inlined, the size of the + function's body. *) + specialised_args : Flambda.specialised_to Variable.Map.t; + (* Any freshening that has been applied to [function_decls]. *) + freshening : Freshening.Project_var.t; + direct_call_surrogates : Closure_id.t Closure_id.Map.t; +} + +(** Extraction of the description of approximation(s). *) +val descr : t -> descr +val descrs : t list -> descr list + +(** Pretty-printing of approximations to a formatter. *) +val print : Format.formatter -> t -> unit +val print_descr : Format.formatter -> descr -> unit +val print_value_set_of_closures + : Format.formatter + -> value_set_of_closures + -> unit + +val create_value_set_of_closures + : function_decls:Flambda.function_declarations + -> bound_vars:t Var_within_closure.Map.t + -> invariant_params:Variable.Set.t Variable.Map.t lazy_t + -> specialised_args:Flambda.specialised_to Variable.Map.t + -> freshening:Freshening.Project_var.t + -> direct_call_surrogates:Closure_id.t Closure_id.Map.t + -> value_set_of_closures + +val update_freshening_of_value_set_of_closures + : value_set_of_closures + -> freshening:Freshening.Project_var.t + -> value_set_of_closures + +(** Basic construction of approximations. *) +val value_unknown : unknown_because_of -> t +val value_int : int -> t +val value_char : char -> t +val value_float : float -> t +val value_mutable_float_array : size:int -> t +val value_immutable_float_array : float option array -> t +val value_string : int -> string option -> t +val value_boxed_int : 'i boxed_int -> 'i -> t +val value_constptr : int -> t +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 + +(** Construct a closure approximation given the approximation of the + corresponding set of closures and the closure ID of the closure to + be projected from such set. [closure_var] and/or [set_of_closures_var] + may be specified to augment the approximation with variables that may + be used to access the closure value itself, so long as they are in + scope at the proposed point of use. *) +val value_closure + : ?closure_var:Variable.t + -> ?set_of_closures_var:Variable.t + -> ?set_of_closures_symbol:Symbol.t + -> value_set_of_closures + -> Closure_id.t + -> t + +(** Construct a set of closures approximation. [set_of_closures_var] is as for + the parameter of the same name in [value_closure], above. *) +val value_set_of_closures + : ?set_of_closures_var:Variable.t + -> value_set_of_closures + -> t + +(** Take the given constant and produce an appropriate approximation for it + together with an Flambda expression representing it. *) +val make_const_int : int -> Flambda.t * t +val make_const_char : char -> Flambda.t * t +val make_const_ptr : int -> Flambda.t * t +val make_const_bool : bool -> Flambda.t * t +val make_const_float : float -> Flambda.t * t +val make_const_boxed_int : 'i boxed_int -> 'i -> Flambda.t * t + +val make_const_int_named : int -> Flambda.named * t +val make_const_char_named : char -> Flambda.named * t +val make_const_ptr_named : int -> Flambda.named * t +val make_const_bool_named : bool -> Flambda.named * t +val make_const_float_named : float -> Flambda.named * t +val make_const_boxed_int_named : 'i boxed_int -> 'i -> Flambda.named * t + +(** Augment an approximation with a given variable (see comment above). + If the approximation was already augmented with a variable, the one + passed to this function replaces it within the approximation. *) +val augment_with_variable : t -> Variable.t -> t + +(** Like [augment_with_variable], but for symbol information. *) +val augment_with_symbol : t -> Symbol.t -> t + +(** Like [augment_with_symbol], but for symbol field information. *) +val augment_with_symbol_field : t -> Symbol.t -> int -> t + +(** Replace the description within an approximation. *) +val replace_description : t -> descr -> t + +val equal_boxed_int : 'a boxed_int -> 'a -> 'b boxed_int -> 'b -> bool + +(* CR-soon mshinwell for pchambart: Add comment describing semantics. (Maybe + we should move the comment from the .ml file into here.) *) +val meet : t -> t -> t + +(** An approximation is "known" iff it is not [Value_unknown]. *) +val known : t -> bool + +(** An approximation is "useful" iff it is neither unknown nor bottom. *) +val useful : t -> bool + +(** Whether all approximations in the given list do *not* satisfy [useful]. *) +val all_not_useful : t list -> bool + +(** A value is certainly immutable if its approximation is known and not bottom. + It must have been resolved (it cannot be [Value_extern] or + [Value_symbol]). (See comment above for further explanation.) *) +val is_definitely_immutable : t -> bool + +type simplification_summary = + | Nothing_done + | Replaced_term + +type simplification_result = Flambda.t * simplification_summary * t +type simplification_result_named = Flambda.named * simplification_summary * t + +(** Given an expression and its approximation, attempt to simplify the + expression to a constant (with associated approximation), taking into + account whether the expression has any side effects. *) +val simplify : t -> Flambda.t -> simplification_result + +(** As for [simplify], but also enables us to simplify based on equalities + between variables. The caller must provide a function that tells us + whether, if we simplify to a given variable, the value of that variable + will be accessible in the current environment. *) +val simplify_using_env + : t + -> is_present_in_env:(Variable.t -> bool) + -> Flambda.t + -> simplification_result + +val simplify_named : t -> Flambda.named -> simplification_result_named + +val simplify_named_using_env + : t + -> is_present_in_env:(Variable.t -> bool) + -> Flambda.named + -> simplification_result_named + +(** If the given approximation identifies another variable and + [is_present_in_env] deems it to be in scope, return that variable (wrapped + in a [Some]), otherwise return [None]. *) +val simplify_var_to_var_using_env + : t + -> is_present_in_env:(Variable.t -> bool) + -> Variable.t option + +val simplify_var : t -> (Flambda.named * t) option + +type get_field_result = + | Ok of t + | Unreachable + +(** Given the approximation [t] of a value, expected to correspond to a block + (in the [Pmakeblock] sense of the word), and a field index then return + an appropriate approximation for that field of the block (or + [Unreachable] if the code with the approximation [t] is unreachable). + N.B. Not all cases of unreachable code are returned as [Unreachable]. +*) +val get_field : t -> field_index:int -> get_field_result + +type checked_approx_for_block = + | Wrong + | Ok of Tag.t * t array + +(** Try to prove that a value with the given approximation may be used + as a block. *) +val check_approx_for_block : t -> checked_approx_for_block + +(** Find the approximation for a bound variable in a set-of-closures + approximation. A fatal error is produced if the variable is not bound in + the given approximation. *) +val approx_for_bound_var : value_set_of_closures -> Var_within_closure.t -> t + +(** Given a set-of-closures approximation and a closure ID, apply any + freshening specified by the approximation to the closure ID, and return + the resulting ID. Causes a fatal error if the resulting closure ID does + not correspond to any function declaration in the approximation. *) +val freshen_and_check_closure_id + : value_set_of_closures + -> Closure_id.t + -> Closure_id.t + +type strict_checked_approx_for_set_of_closures = + | Wrong + | Ok of Variable.t option * value_set_of_closures + +val strict_check_approx_for_set_of_closures + : t + -> strict_checked_approx_for_set_of_closures + +type checked_approx_for_set_of_closures = + | Wrong + | Unresolved of Symbol.t + | Unknown + | Unknown_because_of_unresolved_symbol of Symbol.t + (* 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 + +(** Try to prove that a value with the given approximation may be used as a + set of closures. Values coming from external compilation units with + unresolved approximations are permitted. *) +val check_approx_for_set_of_closures : t -> checked_approx_for_set_of_closures + +type checked_approx_for_closure = + | Wrong + | Ok of value_closure * Variable.t option + * Symbol.t option * value_set_of_closures + +(** Try to prove that a value with the given approximation may be used as a + closure. Values coming from external compilation units with unresolved + approximations are not permitted. *) +(* CR-someday mshinwell: naming is inconsistent: this is as "strict" + as "strict_check_approx_for_set_of_closures" *) +val check_approx_for_closure : t -> checked_approx_for_closure + +type checked_approx_for_closure_allowing_unresolved = + | Wrong + | Unresolved of Symbol.t + | Unknown + | Unknown_because_of_unresolved_symbol of Symbol.t + | Ok of value_closure * Variable.t option + * Symbol.t option * value_set_of_closures + +(** As for [check_approx_for_closure], but values coming from external + compilation units with unresolved approximations are permitted. *) +val check_approx_for_closure_allowing_unresolved + : t + -> checked_approx_for_closure_allowing_unresolved + +(** Returns the value if it can be proved to be a constant float *) +val check_approx_for_float : t -> float option diff --git a/middle_end/simplify_boxed_integer_ops.ml b/middle_end/simplify_boxed_integer_ops.ml new file mode 100644 index 00000000..336cc16b --- /dev/null +++ b/middle_end/simplify_boxed_integer_ops.ml @@ -0,0 +1,110 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module S = Simplify_common + +(* Simplification of operations on boxed integers (nativeint, Int32, Int64). *) +module Simplify_boxed_integer_operator (I : sig + type t + val kind : Lambda.boxed_integer + val zero : 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 logand : t -> t -> t + val logor : t -> t -> t + val logxor : t -> t -> t + val shift_left : t -> int -> t + val shift_right : t -> int -> t + val shift_right_logical : t -> int -> t + val to_int : t -> int + val to_int32 : t -> Int32.t + val to_int64 : t -> Int64.t + val neg : t -> t + val swap : t -> t + val compare : t -> t -> int +end) : Simplify_boxed_integer_ops_intf.S with type t := I.t = struct + module A = Simple_value_approx + module C = Inlining_cost + + let simplify_unop (p : Lambda.primitive) (kind : I.t A.boxed_int) + expr (n : I.t) = + let eval op = S.const_boxed_int_expr expr kind (op n) in + let eval_conv kind op = S.const_boxed_int_expr expr kind (op n) in + let eval_unboxed op = S.const_int_expr expr (op n) in + match p with + | Pintofbint kind when kind = I.kind -> eval_unboxed I.to_int + | Pcvtbint (kind, Pint32) when kind = I.kind -> + eval_conv A.Int32 I.to_int32 + | Pcvtbint (kind, Pint64) when kind = I.kind -> + eval_conv A.Int64 I.to_int64 + | Pnegbint kind when kind = I.kind -> eval I.neg + | Pbbswap kind when kind = I.kind -> eval I.swap + | _ -> expr, A.value_unknown Other, C.Benefit.zero + + let simplify_binop (p : Lambda.primitive) (kind : I.t A.boxed_int) + expr (n1 : I.t) (n2 : I.t) = + let eval op = S.const_boxed_int_expr expr kind (op n1 n2) in + let non_zero n = (I.compare I.zero n) <> 0 in + match p with + | Paddbint kind when kind = I.kind -> eval I.add + | Psubbint kind when kind = I.kind -> eval I.sub + | Pmulbint kind when kind = I.kind -> eval I.mul + | Pdivbint kind when kind = I.kind && non_zero n2 -> eval I.div + | Pmodbint kind when kind = I.kind && non_zero n2 -> eval I.rem + | Pandbint kind when kind = I.kind -> eval I.logand + | Porbint kind when kind = I.kind -> eval I.logor + | Pxorbint kind when kind = I.kind -> eval I.logxor + | Pbintcomp (kind, c) when kind = I.kind -> + S.const_comparison_expr expr c n1 n2 + | _ -> expr, A.value_unknown Other, C.Benefit.zero + + let simplify_binop_int (p : Lambda.primitive) (kind : I.t A.boxed_int) + expr (n1 : I.t) (n2 : int) ~size_int = + let eval op = S.const_boxed_int_expr expr kind (op n1 n2) in + let precond = 0 <= n2 && n2 < 8 * size_int in + match p with + | Plslbint kind when kind = I.kind && precond -> eval I.shift_left + | Plsrbint kind when kind = I.kind && precond -> eval I.shift_right_logical + | Pasrbint kind when kind = I.kind && precond -> eval I.shift_right + | _ -> expr, A.value_unknown Other, C.Benefit.zero +end + +module Simplify_boxed_nativeint = Simplify_boxed_integer_operator (struct + include Nativeint + let to_int64 = Int64.of_nativeint + let swap = S.swapnative + let kind = Lambda.Pnativeint +end) + +module Simplify_boxed_int32 = Simplify_boxed_integer_operator (struct + include Int32 + let to_int32 i = i + let to_int64 = Int64.of_int32 + let swap = S.swap32 + let kind = Lambda.Pint32 +end) + +module Simplify_boxed_int64 = Simplify_boxed_integer_operator (struct + include Int64 + let to_int64 i = i + let swap = S.swap64 + let kind = Lambda.Pint64 +end) diff --git a/middle_end/simplify_boxed_integer_ops.mli b/middle_end/simplify_boxed_integer_ops.mli new file mode 100644 index 00000000..f3461043 --- /dev/null +++ b/middle_end/simplify_boxed_integer_ops.mli @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(* Simplification of operations on boxed integers (nativeint, Int32, Int64). *) + +module Simplify_boxed_nativeint : Simplify_boxed_integer_ops_intf.S + with type t := Nativeint.t + +module Simplify_boxed_int32 : Simplify_boxed_integer_ops_intf.S + with type t := Int32.t + +module Simplify_boxed_int64 : Simplify_boxed_integer_ops_intf.S + with type t := Int64.t diff --git a/middle_end/simplify_boxed_integer_ops_intf.mli b/middle_end/simplify_boxed_integer_ops_intf.mli new file mode 100644 index 00000000..ee621002 --- /dev/null +++ b/middle_end/simplify_boxed_integer_ops_intf.mli @@ -0,0 +1,45 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module type S = sig + type t + + val simplify_unop + : Lambda.primitive + -> t Simple_value_approx.boxed_int + -> Flambda.named + -> t + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + + val simplify_binop + : Lambda.primitive + -> t Simple_value_approx.boxed_int + -> Flambda.named + -> t + -> t + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + + val simplify_binop_int + : Lambda.primitive + -> t Simple_value_approx.boxed_int + -> Flambda.named + -> t + -> int + -> size_int:int + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t +end diff --git a/middle_end/simplify_common.ml b/middle_end/simplify_common.ml new file mode 100644 index 00000000..8044621b --- /dev/null +++ b/middle_end/simplify_common.ml @@ -0,0 +1,66 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module C = Inlining_cost + +external swap16 : int -> int = "%bswap16" +external swap32 : int32 -> int32 = "%bswap_int32" +external swap64 : int64 -> int64 = "%bswap_int64" +external swapnative : nativeint -> nativeint = "%bswap_native" + +let const_int_expr expr n = + if Effect_analysis.no_effects_named expr then + let (new_expr, approx) = A.make_const_int_named n in + new_expr, approx, C.Benefit.remove_code_named expr C.Benefit.zero + else expr, A.value_int n, C.Benefit.zero +let const_char_expr expr c = + if Effect_analysis.no_effects_named expr then + let (new_expr, approx) = A.make_const_char_named c in + new_expr, approx, C.Benefit.remove_code_named expr C.Benefit.zero + else expr, A.value_char c, C.Benefit.zero +let const_ptr_expr expr n = + if Effect_analysis.no_effects_named expr then + let (new_expr, approx) = A.make_const_ptr_named n in + new_expr, approx, C.Benefit.remove_code_named expr C.Benefit.zero + else expr, A.value_constptr n, C.Benefit.zero +let const_bool_expr expr b = + const_int_expr expr (if b then 1 else 0) +let const_float_expr expr f = + if Effect_analysis.no_effects_named expr then + let (new_expr, approx) = A.make_const_float_named f in + new_expr, approx, C.Benefit.remove_code_named expr C.Benefit.zero + else expr, A.value_float f, C.Benefit.zero +let const_boxed_int_expr expr t i = + if Effect_analysis.no_effects_named expr then + let (new_expr, approx) = A.make_const_boxed_int_named t i in + new_expr, approx, C.Benefit.remove_code_named expr C.Benefit.zero + else expr, A.value_boxed_int t i, C.Benefit.zero + +let const_comparison_expr expr (cmp : Lambda.comparison) x y = + (* Using the [Pervasives] comparison functions here in the compiler + coincides with the definitions of such functions in the code + compiled by the user, and is thus correct. *) + const_bool_expr expr + (match cmp with + | Ceq -> x = y + | Cneq -> x <> y + | Clt -> x < y + | Cgt -> x > y + | Cle -> x <= y + | Cge -> x >= y) diff --git a/middle_end/simplify_common.mli b/middle_end/simplify_common.mli new file mode 100644 index 00000000..1ab90cce --- /dev/null +++ b/middle_end/simplify_common.mli @@ -0,0 +1,73 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** [const_*_expr expr v annot], where the expression [expr] is known to + evaluate to the value [v], attempt to produce a more simple expression + together with its approximation and the benefit gained by replacing [expr] + with this new expression. This simplification is only performed if [expr] + is known to have no side effects. Otherwise, [expr] itself is returned, + with an appropriate approximation but zero benefit. + + [const_boxed_int_expr] takes an additional argument specifying the kind of + boxed integer to which the given expression evaluates. +*) + +val const_int_expr + : Flambda.named + -> int + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +val const_char_expr + : Flambda.named + -> char + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +val const_bool_expr + : Flambda.named + -> bool + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +val const_ptr_expr + : Flambda.named + -> int + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +val const_float_expr + : Flambda.named + -> float + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +val const_boxed_int_expr + : Flambda.named + -> 'a Simple_value_approx.boxed_int + -> 'a + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +val const_comparison_expr + : Flambda.named + -> Lambda.comparison + -> 'a + -> 'a + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t + +(** Functions for transposing the order of bytes within words of various + sizes. *) +val swap16 : int -> int +val swap32 : int32 -> int32 +val swap64 : int64 -> int64 +val swapnative : nativeint -> nativeint diff --git a/middle_end/simplify_primitives.ml b/middle_end/simplify_primitives.ml new file mode 100644 index 00000000..c6ec4ad0 --- /dev/null +++ b/middle_end/simplify_primitives.ml @@ -0,0 +1,217 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module A = Simple_value_approx +module C = Inlining_cost +module I = Simplify_boxed_integer_ops +module S = Simplify_common + +let phys_equal (approxs:A.t list) = + match approxs with + | [] | [_] | _ :: _ :: _ :: _ -> + Misc.fatal_error "wrong number of arguments for equality" + | [a1; a2] -> + (* N.B. The following would be incorrect if the variables are not + bound in the environment: + match a1.var, a2.var with + | Some v1, Some v2 when Variable.equal v1 v2 -> true + | _ -> ... + *) + match a1.symbol, a2.symbol with + | Some (s1, None), Some (s2, None) -> Symbol.equal s1 s2 + | Some (s1, Some f1), Some (s2, Some f2) -> Symbol.equal s1 s2 && f1 = f2 + | _ -> false + +let primitive (p : Lambda.primitive) (args, approxs) expr dbg ~size_int + ~big_endian : Flambda.named * A.t * Inlining_cost.Benefit.t = + let fpc = !Clflags.float_const_prop in + match p with + | Pmakeblock(tag, Asttypes.Immutable) -> + let tag = Tag.create_exn tag in + expr, A.value_block tag (Array.of_list approxs), C.Benefit.zero + | Praise _ -> + expr, A.value_bottom, C.Benefit.zero + | Pignore -> begin + match args, A.descrs approxs with + | [arg], [(Value_int 0 | Value_constptr 0)] -> + S.const_ptr_expr (Flambda.Expr (Var arg)) 0 + | _ -> S.const_ptr_expr expr 0 + end + | Pmakearray (Pfloatarray, Mutable) -> + let approx = + A.value_mutable_float_array ~size:(List.length args) + in + expr, approx, C.Benefit.zero + | Pmakearray (Pfloatarray, Immutable) -> + let approx = + A.value_immutable_float_array + (Array.of_list (List.map A.check_approx_for_float approxs)) + in + expr, approx, C.Benefit.zero + | Pintcomp Ceq when phys_equal approxs -> + S.const_bool_expr expr true + (* N.B. Having [not (phys_equal approxs)] would not on its own tell us + anything about whether the two values concerned are unequal. To judge + that, it would be necessary to prove that the approximations are + different, which would in turn entail them being completely known. + + It may seem that in the case where we have two approximations each + annotated with a symbol that we should be able to judge inequality + even if part of the approximation description(s) are unknown. This is + unfortunately not the case. Here is an example: + + let a = f 1 + let b = f 1 + let c = a, a + let d = a, a + + If [Share_constants] is run before [f] is completely inlined (assuming + [f] always generates the same result; effects of [f] aren't in fact + relevant) then [c] and [d] will not be shared. However if [f] is + inlined later, [a] and [b] could be shared and thus [c] and [d] could + be too. As such, any intermediate non-aliasing judgement would be + invalid. *) + | _ -> + match A.descrs approxs with + | [Value_int x] -> + begin match p with + | Pidentity -> S.const_int_expr expr x + | Pnot -> S.const_bool_expr expr (x = 0) + | Pnegint -> S.const_int_expr expr (-x) + | Pbswap16 -> S.const_int_expr expr (S.swap16 x) + | Poffsetint y -> S.const_int_expr expr (x + y) + | Pfloatofint when fpc -> S.const_float_expr expr (float_of_int x) + | Pbintofint Pnativeint -> + S.const_boxed_int_expr expr Nativeint (Nativeint.of_int x) + | Pbintofint Pint32 -> S.const_boxed_int_expr expr Int32 (Int32.of_int x) + | Pbintofint Pint64 -> S.const_boxed_int_expr expr Int64 (Int64.of_int x) + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | [(Value_int x | Value_constptr x); (Value_int y | Value_constptr y)] -> + let shift_precond = 0 <= y && y < 8 * size_int in + begin match p with + | Paddint -> S.const_int_expr expr (x + y) + | Psubint -> S.const_int_expr expr (x - y) + | Pmulint -> S.const_int_expr expr (x * y) + | Pdivint when y <> 0 -> S.const_int_expr expr (x / y) + | Pmodint when y <> 0 -> S.const_int_expr expr (x mod y) + | Pandint -> S.const_int_expr expr (x land y) + | Porint -> S.const_int_expr expr (x lor y) + | Pxorint -> S.const_int_expr expr (x lxor y) + | Plslint when shift_precond -> S.const_int_expr expr (x lsl y) + | Plsrint when shift_precond -> S.const_int_expr expr (x lsr y) + | Pasrint when shift_precond -> S.const_int_expr expr (x asr y) + | Pintcomp cmp -> S.const_comparison_expr expr cmp x y + | Pisout -> S.const_bool_expr expr (y > x || y < 0) + (* [Psequand] and [Psequor] have special simplification rules, above. *) + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | [Value_constptr x] -> + begin match p with + (* [Pidentity] should probably never appear, but is here for + completeness. *) + | Pidentity -> S.const_ptr_expr expr x + | Pnot -> S.const_bool_expr expr (x = 0) + | Pisint -> S.const_bool_expr expr true + | Poffsetint y -> S.const_ptr_expr expr (x + y) + | Pctconst c -> + begin match c with + | Big_endian -> S.const_bool_expr expr big_endian + | Word_size -> S.const_int_expr expr (8*size_int) + | Int_size -> S.const_int_expr expr (8*size_int - 1) + | Max_wosize -> + (* CR-someday mshinwell: this function should maybe not live here. *) + S.const_int_expr expr ((1 lsl ((8*size_int) - 10)) - 1) + | Ostype_unix -> S.const_bool_expr expr (Sys.os_type = "Unix") + | Ostype_win32 -> S.const_bool_expr expr (Sys.os_type = "Win32") + | Ostype_cygwin -> S.const_bool_expr expr (Sys.os_type = "Cygwin") + end + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | [Value_float x] when fpc -> + begin match p with + | Pintoffloat -> S.const_int_expr expr (int_of_float x) + | Pnegfloat -> S.const_float_expr expr (-. x) + | Pabsfloat -> S.const_float_expr expr (abs_float x) + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | [Value_float n1; Value_float n2] when fpc -> + begin match p with + | Paddfloat -> S.const_float_expr expr (n1 +. n2) + | Psubfloat -> S.const_float_expr expr (n1 -. n2) + | Pmulfloat -> S.const_float_expr expr (n1 *. n2) + | Pdivfloat -> S.const_float_expr expr (n1 /. n2) + | Pfloatcomp c -> S.const_comparison_expr expr c n1 n2 + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | [A.Value_boxed_int(A.Nativeint, n)] -> + I.Simplify_boxed_nativeint.simplify_unop p Nativeint expr n + | [A.Value_boxed_int(A.Int32, n)] -> + I.Simplify_boxed_int32.simplify_unop p Int32 expr n + | [A.Value_boxed_int(A.Int64, n)] -> + I.Simplify_boxed_int64.simplify_unop p Int64 expr n + | [A.Value_boxed_int(A.Nativeint, n1); + A.Value_boxed_int(A.Nativeint, n2)] -> + I.Simplify_boxed_nativeint.simplify_binop p Nativeint expr n1 n2 + | [A.Value_boxed_int(A.Int32, n1); A.Value_boxed_int(A.Int32, n2)] -> + I.Simplify_boxed_int32.simplify_binop p Int32 expr n1 n2 + | [A.Value_boxed_int(A.Int64, n1); A.Value_boxed_int(A.Int64, n2)] -> + I.Simplify_boxed_int64.simplify_binop p Int64 expr n1 n2 + | [A.Value_boxed_int(A.Nativeint, n1); Value_int n2] -> + I.Simplify_boxed_nativeint.simplify_binop_int p Nativeint expr n1 n2 + ~size_int + | [A.Value_boxed_int(A.Int32, n1); Value_int n2] -> + I.Simplify_boxed_int32.simplify_binop_int p Int32 expr n1 n2 + ~size_int + | [A.Value_boxed_int(A.Int64, n1); Value_int n2] -> + I.Simplify_boxed_int64.simplify_binop_int p Int64 expr n1 n2 + ~size_int + | [Value_block _] when p = Lambda.Pisint -> + S.const_bool_expr expr false + | [Value_string { size }] when p = Lambda.Pstringlength -> + S.const_int_expr expr size + | [Value_string { size; contents = Some s }; + (Value_int x | Value_constptr x)] when x >= 0 && x < size -> + begin match p with + | Pstringrefu + | Pstringrefs -> S.const_char_expr expr s.[x] + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | [Value_string { size; contents = None }; + (Value_int x | Value_constptr x)] + when x >= 0 && x < size && p = Lambda.Pstringrefs -> + Flambda.Prim (Pstringrefu, args, dbg), + A.value_unknown Other, + (* we improved it, but there is no way to account for that: *) + C.Benefit.zero + | [Value_float_array { size; contents }] -> + begin match p with + | Parraylength _ -> S.const_int_expr expr size + | Pfloatfield i -> + begin match contents with + | A.Contents a when i >= 0 && i < size -> + begin match a.(i) with + | None -> expr, A.value_unknown Other, C.Benefit.zero + | Some v -> S.const_float_expr expr v + end + | Contents _ | Unknown_or_mutable -> + expr, A.value_unknown Other, C.Benefit.zero + end + | _ -> expr, A.value_unknown Other, C.Benefit.zero + end + | _ -> expr, A.value_unknown Other, C.Benefit.zero diff --git a/middle_end/simplify_primitives.mli b/middle_end/simplify_primitives.mli new file mode 100644 index 00000000..7f1f149b --- /dev/null +++ b/middle_end/simplify_primitives.mli @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Simplifies an application of a primitive based on approximation + information. *) +val primitive + : Lambda.primitive + -> (Variable.t list * (Simple_value_approx.t list)) + -> Flambda.named + -> Debuginfo.t + -> size_int:int + -> big_endian:bool + -> Flambda.named * Simple_value_approx.t * Inlining_cost.Benefit.t diff --git a/middle_end/unbox_closures.ml b/middle_end/unbox_closures.ml new file mode 100644 index 00000000..43c22abe --- /dev/null +++ b/middle_end/unbox_closures.ml @@ -0,0 +1,87 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module ASA = Augment_specialised_args +module W = ASA.What_to_specialise +module E = Inline_and_simplify_aux.Env + +module Transform = struct + let pass_name = "unbox-closures" + let variable_suffix = "" + + let precondition ~env ~(set_of_closures : Flambda.set_of_closures) = + !Clflags.unbox_closures + && not (E.at_toplevel env) + && not (Variable.Map.is_empty set_of_closures.free_vars) + + let what_to_specialise ~env ~(set_of_closures : Flambda.set_of_closures) = + let what_to_specialise = W.create ~set_of_closures in + if not (precondition ~env ~set_of_closures) then + what_to_specialise + else begin + let round = E.round env in + let num_closure_vars = Variable.Map.cardinal set_of_closures.free_vars in + let module B = Inlining_cost.Benefit in + let saved_by_not_building_closure = + (* For the moment assume that we're going to cause all functions in the + set to become closed. *) + B.remove_prims (B.remove_call B.zero) num_closure_vars + in + Flambda_iterators.fold_function_decls_ignoring_stubs set_of_closures + ~init:what_to_specialise + ~f:(fun ~fun_var ~(function_decl : Flambda.function_declaration) + what_to_specialise -> + let body_size = Inlining_cost.lambda_size function_decl.body in + (* If the function is small enough, make a direct call surrogate + for it, so that indirect calls are not penalised by having to + bounce through the stub. (Making such a surrogate involves + duplicating the function.) *) + let small_enough_to_duplicate = + let module W = Inlining_cost.Whether_sufficient_benefit in + let wsb = + W.create_estimate ~original_size:0 + ~toplevel:false + ~branch_depth:0 + ~new_size:((body_size / !Clflags.unbox_closures_factor) + 1) + ~benefit:saved_by_not_building_closure + ~lifting:false + ~round + in + W.evaluate wsb + in + let what_to_specialise = + if small_enough_to_duplicate then + W.make_direct_call_surrogate_for what_to_specialise ~fun_var + else + what_to_specialise + in + let bound_by_the_closure = + Flambda_utils.variables_bound_by_the_closure + (Closure_id.wrap fun_var) + set_of_closures.function_decls + in + Variable.Set.fold (fun inner_free_var what_to_specialise -> + W.new_specialised_arg what_to_specialise + ~fun_var ~group:inner_free_var + ~definition:(Existing_inner_free_var inner_free_var)) + bound_by_the_closure + what_to_specialise) + end +end + +include ASA.Make (Transform) diff --git a/middle_end/unbox_closures.mli b/middle_end/unbox_closures.mli new file mode 100644 index 00000000..6fa07a1b --- /dev/null +++ b/middle_end/unbox_closures.mli @@ -0,0 +1,32 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +(** Turn free variables of closures into specialised arguments. + The aim is to cause the closure to become closed. *) + +val rewrite_set_of_closures + : env:Inline_and_simplify_aux.Env.t + (* CR-soon mshinwell: eliminate superfluous parameter *) + -> duplicate_function:( + env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> fun_var:Variable.t + -> Flambda.function_declaration + * Flambda.specialised_to Variable.Map.t) + -> set_of_closures:Flambda.set_of_closures + -> (Flambda.expr * Inlining_cost.Benefit.t) option diff --git a/middle_end/unbox_free_vars_of_closures.ml b/middle_end/unbox_free_vars_of_closures.ml new file mode 100644 index 00000000..41c3c4ff --- /dev/null +++ b/middle_end/unbox_free_vars_of_closures.ml @@ -0,0 +1,175 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module B = Inlining_cost.Benefit + +let pass_name = "unbox-free-vars-of-closures" +let () = Pass_wrapper.register ~pass_name +let variable_suffix = "" + +(* CR-someday mshinwell: Nearly but not quite the same as something that + Augment_specialised_args uses. *) +let add_lifted_projections_around_set_of_closures + ~set_of_closures ~existing_inner_to_outer_vars ~benefit + ~definitions_indexed_by_new_inner_vars = + let body = + Flambda_utils.name_expr (Set_of_closures set_of_closures) + ~name:pass_name + in + Variable.Map.fold (fun new_inner_var (projection : Projection.t) + (expr, benefit) -> + let find_outer_var inner_var = + match + Variable.Map.find inner_var existing_inner_to_outer_vars + with + | (outer_var : Flambda.specialised_to) -> outer_var.var + | exception Not_found -> + Misc.fatal_errorf "(UFV) find_outer_var: expected %a \ + to be in [existing_inner_to_outer_vars], but it is \ + not. (The projection was: %a)" + Variable.print inner_var + Projection.print projection + in + let benefit = B.add_projection projection benefit in + let named : Flambda.named = + (* The lifted projection must be in terms of outer variables, + not inner variables. *) + let projection = + Projection.map_projecting_from projection ~f:find_outer_var + in + Flambda_utils.projection_to_named projection + in + let expr = + Flambda.create_let (find_outer_var new_inner_var) named expr + in + (expr, benefit)) + definitions_indexed_by_new_inner_vars + (body, benefit) + +let run ~env ~(set_of_closures : Flambda.set_of_closures) = + if not !Clflags.unbox_free_vars_of_closures then + None + else + let definitions_indexed_by_new_inner_vars, _, free_vars, done_something = + let all_existing_definitions = + Variable.Map.fold (fun _inner_var (outer_var : Flambda.specialised_to) + all_existing_definitions -> + match outer_var.projection with + | None -> all_existing_definitions + | Some projection -> + Projection.Set.add projection all_existing_definitions) + set_of_closures.free_vars + Projection.Set.empty + in + Flambda_iterators.fold_function_decls_ignoring_stubs set_of_closures + ~init:(Variable.Map.empty, all_existing_definitions, + set_of_closures.free_vars, false) + ~f:(fun ~fun_var:_ ~function_decl result -> + let extracted = + Extract_projections.from_function_decl ~env ~function_decl + ~which_variables:set_of_closures.free_vars + in + Projection.Set.fold (fun projection + ((definitions_indexed_by_new_inner_vars, + all_existing_definitions_including_added_ones, + additional_free_vars, _done_something) as result) -> + (* Don't add a new free variable if there already exists a + free variable with the desired projection. We need to + dedup not only across the existing free variables but + also across newly-added ones (unlike in + [Augment_specialised_args]), since free variables are + not local to a function declaration but rather to a + set of closures. *) + if Projection.Set.mem projection + all_existing_definitions_including_added_ones + then begin + result + end else begin + (* Add a new free variable. This needs both a fresh + "new inner" and a fresh "new outer" var, since we know + the definition is not a duplicate. *) + let projecting_from = Projection.projecting_from projection in + let new_inner_var = + Variable.rename projecting_from + ~append:variable_suffix + in + let new_outer_var = + Variable.rename projecting_from + ~append:variable_suffix + in + let definitions_indexed_by_new_inner_vars = + Variable.Map.add new_inner_var projection + definitions_indexed_by_new_inner_vars + in + let all_existing_definitions_including_added_ones = + Projection.Set.add projection + all_existing_definitions_including_added_ones + in + let new_outer_var : Flambda.specialised_to = + { var = new_outer_var; + projection = Some projection; + } + in + let additional_free_vars = + Variable.Map.add new_inner_var new_outer_var + additional_free_vars + in + definitions_indexed_by_new_inner_vars, + all_existing_definitions_including_added_ones, + additional_free_vars, + true + end) + extracted + result) + in + if not done_something then + None + else + (* CR-someday mshinwell: could consider doing the grouping thing + similar to Augment_specialised_args *) + let num_free_vars_before = + Variable.Map.cardinal set_of_closures.free_vars + in + let num_free_vars_after = + Variable.Map.cardinal free_vars + in + assert (num_free_vars_after > num_free_vars_before); + (* Don't let the closure grow too large. *) + if num_free_vars_after > 2 * num_free_vars_before then + None + else + let set_of_closures = + Flambda.create_set_of_closures + ~function_decls:set_of_closures.function_decls + ~free_vars + ~specialised_args:set_of_closures.specialised_args + ~direct_call_surrogates:set_of_closures.direct_call_surrogates + in + let expr, benefit = + add_lifted_projections_around_set_of_closures ~set_of_closures + ~benefit:B.zero + ~existing_inner_to_outer_vars:set_of_closures.free_vars + ~definitions_indexed_by_new_inner_vars + in + Some (expr, benefit) + +let run ~env ~set_of_closures = + Pass_wrapper.with_dump ~pass_name ~input:set_of_closures + ~print_input:Flambda.print_set_of_closures + ~print_output:(fun ppf (expr, _) -> Flambda.print ppf expr) + ~f:(fun () -> run ~env ~set_of_closures) diff --git a/middle_end/unbox_free_vars_of_closures.mli b/middle_end/unbox_free_vars_of_closures.mli new file mode 100644 index 00000000..3ee181ee --- /dev/null +++ b/middle_end/unbox_free_vars_of_closures.mli @@ -0,0 +1,26 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +(** When approximations of free variables of closures indicate that they + are closures or blocks, rewrite projections from such blocks to new + variables (which become free in the closures), with the defining + expressions of the projections lifted out of the corresponding sets + of closures. *) + +val run + : env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> (Flambda.expr * Inlining_cost.Benefit.t) option diff --git a/middle_end/unbox_specialised_args.ml b/middle_end/unbox_specialised_args.ml new file mode 100644 index 00000000..ced1636c --- /dev/null +++ b/middle_end/unbox_specialised_args.ml @@ -0,0 +1,103 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +[@@@ocaml.warning "+a-4-9-30-40-41-42"] + +module ASA = Augment_specialised_args +module W = ASA.What_to_specialise + +module Transform = struct + let pass_name = "unbox-specialised-args" + let variable_suffix = "" + + let precondition ~env:_ ~(set_of_closures : Flambda.set_of_closures) = + !Clflags.unbox_specialised_args + && not (Variable.Map.is_empty set_of_closures.specialised_args) + + let what_to_specialise ~env ~(set_of_closures : Flambda.set_of_closures) = + let what_to_specialise = W.create ~set_of_closures in + if not (precondition ~env ~set_of_closures) then + what_to_specialise + else + let projections_by_function = + Variable.Map.filter_map set_of_closures.function_decls.funs + ~f:(fun _fun_var (function_decl : Flambda.function_declaration) -> + if function_decl.stub then None + else + Some (Extract_projections.from_function_decl ~env + ~function_decl + ~which_variables:set_of_closures.specialised_args)) + in + (* CR-soon mshinwell: consider caching the Invariant_params *relation* + as well as the "_in_recursion" map *) + let invariant_params_flow = + Invariant_params.invariant_param_sources set_of_closures.function_decls + ~backend:(Inline_and_simplify_aux.Env.backend env) + in + Variable.Map.fold (fun fun_var extractions what_to_specialise -> + Projection.Set.fold (fun (projection : Projection.t) + what_to_specialise -> + let group = Projection.projecting_from projection in + assert (Variable.Map.mem group set_of_closures.specialised_args); + let what_to_specialise = + W.new_specialised_arg what_to_specialise ~fun_var ~group + ~definition:(Projection_from_existing_specialised_arg + projection) + in + match Variable.Map.find group invariant_params_flow with + | exception Not_found -> what_to_specialise + | flow -> + (* If for function [f] we would extract a projection expression + [e] from some specialised argument [x] of [f], and we know + from [Invariant_params] that a specialised argument [y] of + another function [g] flows to [x], we will add add [e] with + [y] substituted for [x] throughout as a newly-specialised + argument for [g]. This should help reduce the number of + simplification rounds required for mutually-recursive + functions. *) + Variable.Pair.Set.fold (fun (target_fun_var, target_spec_arg) + what_to_specialise -> + if Variable.equal fun_var target_fun_var + || not (Variable.Map.mem target_spec_arg + set_of_closures.specialised_args) + then begin + what_to_specialise + end else begin + (* Rewrite the projection (that was in terms of an inner + specialised arg of [fun_var]) to be in terms of the + corresponding inner specialised arg of + [target_fun_var]. (The outer vars referenced in the + projection remain unchanged.) *) + let projection = + Projection.map_projecting_from projection + ~f:(fun var -> + assert (Variable.equal var group); + target_spec_arg) + in + W.new_specialised_arg what_to_specialise + ~fun_var:target_fun_var ~group + ~definition: + (Projection_from_existing_specialised_arg projection) + end) + flow + what_to_specialise) + extractions + what_to_specialise) + projections_by_function + what_to_specialise +end + +include ASA.Make (Transform) diff --git a/middle_end/unbox_specialised_args.mli b/middle_end/unbox_specialised_args.mli new file mode 100644 index 00000000..1e079591 --- /dev/null +++ b/middle_end/unbox_specialised_args.mli @@ -0,0 +1,49 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* Mark Shinwell and Leo White, Jane Street Europe *) +(* *) +(* Copyright 2013--2016 OCamlPro SAS *) +(* Copyright 2014--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. *) +(* *) +(**************************************************************************) + +(** When approximations of specialised arguments indicate that they are + closures or blocks, add more specialised arguments corresponding to + the projections from such blocks (with definitions of such projections + lifted out), such that the original specialised arguments may later be + eliminated. + + This in particular enables elimination of closure allocations in + examples such as: + + let rec map f = function + | [] -> [] + | a::l -> let r = f a in r :: map f l + + let g x = + map (fun y -> x + y) [1; 2; 3; 4] + + Here, the specialised version of [map] initially has a specialised + argument [f]; and upon inlining there will be a projection of [x] from + the closure of [f]. This pass adds a new specialised argument to carry + that projection, at which point the closure of [f] is redundant. +*) + +val rewrite_set_of_closures + : env:Inline_and_simplify_aux.Env.t + (* CR-soon mshinwell: eliminate superfluous parameter *) + -> duplicate_function:( + env:Inline_and_simplify_aux.Env.t + -> set_of_closures:Flambda.set_of_closures + -> fun_var:Variable.t + -> Flambda.function_declaration + * Flambda.specialised_to Variable.Map.t) + -> set_of_closures:Flambda.set_of_closures + -> (Flambda.expr * Inlining_cost.Benefit.t) option diff --git a/ocamlbuild/.depend b/ocamlbuild/.depend deleted file mode 100644 index 3b67d873..00000000 --- a/ocamlbuild/.depend +++ /dev/null @@ -1,207 +0,0 @@ -bool.cmi : -command.cmi : tags.cmi signatures.cmi -configuration.cmi : tags.cmi pathname.cmi loc.cmi -digest_cache.cmi : -discard_printf.cmi : -display.cmi : tags.cmi -exit_codes.cmi : -fda.cmi : slurp.cmi -findlib.cmi : signatures.cmi command.cmi -flags.cmi : tags.cmi command.cmi -glob.cmi : signatures.cmi glob_ast.cmi bool.cmi -glob_ast.cmi : bool.cmi -glob_lexer.cmi : glob_ast.cmi -hooks.cmi : -hygiene.cmi : slurp.cmi -lexers.cmi : loc.cmi glob.cmi -loc.cmi : -log.cmi : tags.cmi signatures.cmi -main.cmi : -my_std.cmi : signatures.cmi -my_unix.cmi : -ocaml_arch.cmi : signatures.cmi command.cmi -ocaml_compiler.cmi : tags.cmi rule.cmi pathname.cmi command.cmi -ocaml_dependencies.cmi : pathname.cmi -ocaml_specific.cmi : -ocaml_tools.cmi : tags.cmi rule.cmi pathname.cmi command.cmi -ocaml_utils.cmi : tags.cmi pathname.cmi command.cmi -ocamlbuild.cmi : -ocamlbuild_executor.cmi : -ocamlbuild_plugin.cmi : -ocamlbuild_unix_plugin.cmi : -ocamlbuild_where.cmi : -ocamlbuildlight.cmi : -options.cmi : slurp.cmi signatures.cmi command.cmi -param_tags.cmi : tags.cmi loc.cmi -pathname.cmi : signatures.cmi -plugin.cmi : -ppcache.cmi : -report.cmi : solver.cmi -resource.cmi : slurp.cmi pathname.cmi my_std.cmi command.cmi -rule.cmi : tags.cmi resource.cmi pathname.cmi my_std.cmi command.cmi -shell.cmi : -signatures.cmi : -slurp.cmi : my_unix.cmi -solver.cmi : pathname.cmi -tags.cmi : signatures.cmi -tools.cmi : tags.cmi pathname.cmi -bool.cmo : bool.cmi -bool.cmx : bool.cmi -command.cmo : tags.cmi shell.cmi param_tags.cmi my_unix.cmi my_std.cmi \ - log.cmi lexers.cmi const.cmo command.cmi -command.cmx : tags.cmx shell.cmx param_tags.cmx my_unix.cmx my_std.cmx \ - log.cmx lexers.cmx const.cmx command.cmi -configuration.cmo : tags.cmi param_tags.cmi my_std.cmi log.cmi loc.cmi \ - lexers.cmi glob.cmi const.cmo configuration.cmi -configuration.cmx : tags.cmx param_tags.cmx my_std.cmx log.cmx loc.cmx \ - lexers.cmx glob.cmx const.cmx configuration.cmi -const.cmo : -const.cmx : -digest_cache.cmo : shell.cmi pathname.cmi options.cmi my_unix.cmi my_std.cmi \ - digest_cache.cmi -digest_cache.cmx : shell.cmx pathname.cmx options.cmx my_unix.cmx my_std.cmx \ - digest_cache.cmi -discard_printf.cmo : discard_printf.cmi -discard_printf.cmx : discard_printf.cmi -display.cmo : tags.cmi my_unix.cmi my_std.cmi discard_printf.cmi display.cmi -display.cmx : tags.cmx my_unix.cmx my_std.cmx discard_printf.cmx display.cmi -exit_codes.cmo : exit_codes.cmi -exit_codes.cmx : exit_codes.cmi -fda.cmo : pathname.cmi options.cmi log.cmi hygiene.cmi fda.cmi -fda.cmx : pathname.cmx options.cmx log.cmx hygiene.cmx fda.cmi -findlib.cmo : my_unix.cmi my_std.cmi lexers.cmi const.cmo command.cmi \ - findlib.cmi -findlib.cmx : my_unix.cmx my_std.cmx lexers.cmx const.cmx command.cmx \ - findlib.cmi -flags.cmo : tags.cmi param_tags.cmi log.cmi command.cmi bool.cmi flags.cmi -flags.cmx : tags.cmx param_tags.cmx log.cmx command.cmx bool.cmx flags.cmi -glob.cmo : my_std.cmi glob_lexer.cmi glob_ast.cmi bool.cmi glob.cmi -glob.cmx : my_std.cmx glob_lexer.cmx glob_ast.cmx bool.cmx glob.cmi -glob_ast.cmo : bool.cmi glob_ast.cmi -glob_ast.cmx : bool.cmx glob_ast.cmi -glob_lexer.cmo : glob_ast.cmi bool.cmi glob_lexer.cmi -glob_lexer.cmx : glob_ast.cmx bool.cmx glob_lexer.cmi -hooks.cmo : hooks.cmi -hooks.cmx : hooks.cmi -hygiene.cmo : slurp.cmi shell.cmi pathname.cmi options.cmi my_std.cmi \ - log.cmi hygiene.cmi -hygiene.cmx : slurp.cmx shell.cmx pathname.cmx options.cmx my_std.cmx \ - log.cmx hygiene.cmi -lexers.cmo : my_std.cmi loc.cmi glob_ast.cmi glob.cmi bool.cmi lexers.cmi -lexers.cmx : my_std.cmx loc.cmx glob_ast.cmx glob.cmx bool.cmx lexers.cmi -loc.cmo : loc.cmi -loc.cmx : loc.cmi -log.cmo : my_unix.cmi my_std.cmi display.cmi log.cmi -log.cmx : my_unix.cmx my_std.cmx display.cmx log.cmi -main.cmo : tools.cmi tags.cmi solver.cmi slurp.cmi shell.cmi rule.cmi \ - resource.cmi report.cmi plugin.cmi pathname.cmi param_tags.cmi \ - options.cmi ocaml_utils.cmi ocaml_specific.cmi ocaml_dependencies.cmi \ - my_unix.cmi my_std.cmi log.cmi loc.cmi lexers.cmi hooks.cmi flags.cmi \ - fda.cmi exit_codes.cmi digest_cache.cmi const.cmo configuration.cmi \ - command.cmi main.cmi -main.cmx : tools.cmx tags.cmx solver.cmx slurp.cmx shell.cmx rule.cmx \ - resource.cmx report.cmx plugin.cmx pathname.cmx param_tags.cmx \ - options.cmx ocaml_utils.cmx ocaml_specific.cmx ocaml_dependencies.cmx \ - my_unix.cmx my_std.cmx log.cmx loc.cmx lexers.cmx hooks.cmx flags.cmx \ - fda.cmx exit_codes.cmx digest_cache.cmx const.cmx configuration.cmx \ - command.cmx main.cmi -my_std.cmo : my_std.cmi -my_std.cmx : my_std.cmi -my_unix.cmo : my_std.cmi my_unix.cmi -my_unix.cmx : my_std.cmx my_unix.cmi -ocaml_arch.cmo : pathname.cmi my_std.cmi command.cmi ocaml_arch.cmi -ocaml_arch.cmx : pathname.cmx my_std.cmx command.cmx ocaml_arch.cmi -ocaml_compiler.cmo : tools.cmi tags.cmi rule.cmi resource.cmi pathname.cmi \ - options.cmi ocaml_utils.cmi ocaml_dependencies.cmi ocaml_arch.cmi \ - my_std.cmi log.cmi command.cmi ocaml_compiler.cmi -ocaml_compiler.cmx : tools.cmx tags.cmx rule.cmx resource.cmx pathname.cmx \ - options.cmx ocaml_utils.cmx ocaml_dependencies.cmx ocaml_arch.cmx \ - my_std.cmx log.cmx command.cmx ocaml_compiler.cmi -ocaml_dependencies.cmo : tools.cmi resource.cmi pathname.cmi ocaml_utils.cmi \ - my_std.cmi log.cmi ocaml_dependencies.cmi -ocaml_dependencies.cmx : tools.cmx resource.cmx pathname.cmx ocaml_utils.cmx \ - my_std.cmx log.cmx ocaml_dependencies.cmi -ocaml_specific.cmo : tools.cmi tags.cmi rule.cmi pathname.cmi options.cmi \ - ocamlbuild_config.cmo ocaml_utils.cmi ocaml_tools.cmi ocaml_compiler.cmi \ - my_std.cmi log.cmi flags.cmi findlib.cmi configuration.cmi command.cmi \ - ocaml_specific.cmi -ocaml_specific.cmx : tools.cmx tags.cmx rule.cmx pathname.cmx options.cmx \ - ocamlbuild_config.cmx ocaml_utils.cmx ocaml_tools.cmx ocaml_compiler.cmx \ - my_std.cmx log.cmx flags.cmx findlib.cmx configuration.cmx command.cmx \ - ocaml_specific.cmi -ocaml_tools.cmo : tools.cmi tags.cmi rule.cmi pathname.cmi options.cmi \ - ocaml_utils.cmi ocaml_compiler.cmi my_std.cmi flags.cmi command.cmi \ - ocaml_tools.cmi -ocaml_tools.cmx : tools.cmx tags.cmx rule.cmx pathname.cmx options.cmx \ - ocaml_utils.cmx ocaml_compiler.cmx my_std.cmx flags.cmx command.cmx \ - ocaml_tools.cmi -ocaml_utils.cmo : tools.cmi tags.cmi pathname.cmi param_tags.cmi options.cmi \ - my_std.cmi log.cmi lexers.cmi flags.cmi const.cmo command.cmi \ - ocaml_utils.cmi -ocaml_utils.cmx : tools.cmx tags.cmx pathname.cmx param_tags.cmx options.cmx \ - my_std.cmx log.cmx lexers.cmx flags.cmx const.cmx command.cmx \ - ocaml_utils.cmi -ocamlbuild.cmo : ocamlbuild_unix_plugin.cmi ocamlbuild.cmi -ocamlbuild.cmx : ocamlbuild_unix_plugin.cmx ocamlbuild.cmi -ocamlbuild_config.cmo : -ocamlbuild_config.cmx : -ocamlbuild_executor.cmo : ocamlbuild_executor.cmi -ocamlbuild_executor.cmx : ocamlbuild_executor.cmi -ocamlbuild_plugin.cmo : ocamlbuild_plugin.cmi -ocamlbuild_plugin.cmx : ocamlbuild_plugin.cmi -ocamlbuild_unix_plugin.cmo : ocamlbuild_executor.cmi my_unix.cmi my_std.cmi \ - exit_codes.cmi ocamlbuild_unix_plugin.cmi -ocamlbuild_unix_plugin.cmx : ocamlbuild_executor.cmx my_unix.cmx my_std.cmx \ - exit_codes.cmx ocamlbuild_unix_plugin.cmi -ocamlbuild_where.cmo : ocamlbuild_config.cmo ocamlbuild_where.cmi -ocamlbuild_where.cmx : ocamlbuild_config.cmx ocamlbuild_where.cmi -ocamlbuildlight.cmo : ocamlbuildlight.cmi -ocamlbuildlight.cmx : ocamlbuildlight.cmi -options.cmo : shell.cmi ocamlbuild_where.cmi ocamlbuild_config.cmo \ - my_std.cmi log.cmi lexers.cmi const.cmo command.cmi options.cmi -options.cmx : shell.cmx ocamlbuild_where.cmx ocamlbuild_config.cmx \ - my_std.cmx log.cmx lexers.cmx const.cmx command.cmx options.cmi -param_tags.cmo : tags.cmi my_std.cmi log.cmi loc.cmi lexers.cmi \ - param_tags.cmi -param_tags.cmx : tags.cmx my_std.cmx log.cmx loc.cmx lexers.cmx \ - param_tags.cmi -pathname.cmo : shell.cmi options.cmi my_unix.cmi my_std.cmi log.cmi glob.cmi \ - pathname.cmi -pathname.cmx : shell.cmx options.cmx my_unix.cmx my_std.cmx log.cmx glob.cmx \ - pathname.cmi -plugin.cmo : tools.cmi tags.cmi shell.cmi rule.cmi pathname.cmi \ - param_tags.cmi options.cmi ocamlbuild_where.cmi my_unix.cmi my_std.cmi \ - log.cmi const.cmo command.cmi plugin.cmi -plugin.cmx : tools.cmx tags.cmx shell.cmx rule.cmx pathname.cmx \ - param_tags.cmx options.cmx ocamlbuild_where.cmx my_unix.cmx my_std.cmx \ - log.cmx const.cmx command.cmx plugin.cmi -ppcache.cmo : shell.cmi pathname.cmi my_std.cmi log.cmi command.cmi \ - ppcache.cmi -ppcache.cmx : shell.cmx pathname.cmx my_std.cmx log.cmx command.cmx \ - ppcache.cmi -report.cmo : solver.cmi resource.cmi my_std.cmi log.cmi glob.cmi report.cmi -report.cmx : solver.cmx resource.cmx my_std.cmx log.cmx glob.cmx report.cmi -resource.cmo : slurp.cmi shell.cmi pathname.cmi options.cmi my_unix.cmi \ - my_std.cmi log.cmi lexers.cmi glob_ast.cmi glob.cmi digest_cache.cmi \ - const.cmo command.cmi resource.cmi -resource.cmx : slurp.cmx shell.cmx pathname.cmx options.cmx my_unix.cmx \ - my_std.cmx log.cmx lexers.cmx glob_ast.cmx glob.cmx digest_cache.cmx \ - const.cmx command.cmx resource.cmi -rule.cmo : shell.cmi resource.cmi pathname.cmi options.cmi my_std.cmi \ - log.cmi digest_cache.cmi command.cmi rule.cmi -rule.cmx : shell.cmx resource.cmx pathname.cmx options.cmx my_std.cmx \ - log.cmx digest_cache.cmx command.cmx rule.cmi -shell.cmo : tags.cmi my_unix.cmi my_std.cmi log.cmi shell.cmi -shell.cmx : tags.cmx my_unix.cmx my_std.cmx log.cmx shell.cmi -slurp.cmo : my_unix.cmi my_std.cmi slurp.cmi -slurp.cmx : my_unix.cmx my_std.cmx slurp.cmi -solver.cmo : rule.cmi resource.cmi pathname.cmi my_std.cmi log.cmi \ - command.cmi solver.cmi -solver.cmx : rule.cmx resource.cmx pathname.cmx my_std.cmx log.cmx \ - command.cmx solver.cmi -tags.cmo : tags.cmi -tags.cmx : tags.cmi -tools.cmo : tags.cmi rule.cmi pathname.cmi my_std.cmi log.cmi \ - configuration.cmi tools.cmi -tools.cmx : tags.cmx rule.cmx pathname.cmx my_std.cmx log.cmx \ - configuration.cmx tools.cmi diff --git a/ocamlbuild/AUTHORS b/ocamlbuild/AUTHORS deleted file mode 100644 index 0b27a5b1..00000000 --- a/ocamlbuild/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -Nicolas Pouillard -Berke Durak diff --git a/ocamlbuild/ChangeLog b/ocamlbuild/ChangeLog deleted file mode 100644 index 183be582..00000000 --- a/ocamlbuild/ChangeLog +++ /dev/null @@ -1,3621 +0,0 @@ -2007-03-22 Nicolas Pouillard - - Allow to receive the build function in {custom,file}_rule. - - * rule.ml, - * rule.mli, - * signatures.mli: Ditto. - * ocaml_specific.ml: Update. - - * command.ml, - * command.mli: Add a function to get string and tags. - - * ocamldep.ml, - * ocamldep.mli: Make tag based dependencies. - - * ocaml_compiler.ml: Do the pack as one command to be sure running the - remove. - - * test/test8/myocamlbuild.ml, - * test/good-output: Update. - -2007-03-21 Nicolas Pouillard - - Fix the previous fix. - - * ocaml_compiler.ml: Remove the empty file. - * test/good-output: Update. - -2007-03-21 Nicolas Pouillard - - [native pack] use touch instead of mv and cmp. - - * ocaml_compiler.ml: This version is will force ocamlopt to do the - right thing. - * test/good-output: Update. - -2007-03-20 Nicolas Pouillard - - Two bugs, two fixes. - - * ocaml_tools.ml: Add pp flags to interface inference. - * ocaml_specific.ml: Add a rule for packing with a cmi that already - exists. - * test/good-output: Update. - * Makefile: Change the default location. - -2007-03-13 Nicolas Pouillard - - Fix a bug in expand_module. - - * ocaml_utils.ml: Handle correctly pathnames instead of just basenames. - -2007-03-13 Nicolas Pouillard - - Use sys_file_exists instead of Sys.file_exists. - - * my_unix.ml: Since Sys.file_exists don't treat well captial letters. - * my_std.ml: Fix a bug. - * pathname.ml: Here is a an exception to the previous rule so, put a - comment. - -2007-03-11 Nicolas Pouillard - - Fix the List.union order. - - * my_std.ml: Fix and improve List.union. - * pathname.ml: Use it and fix merge_include_dirs. - * test/good-output: Update since the union order was wrong. - -2007-03-11 Nicolas Pouillard - - Re fix menhir and include dirs. - - * ocaml_tools.ml: Specifiy ocamlc and -I with --ocamlc. - -2007-03-11 Nicolas Pouillard - - Fix a bug: Add include directories to menhir. - - * ocaml_tools.ml: Ditto. - * my_std.ml, - * signatures.mli: Specification typo. - -2007-03-07 Nicolas Pouillard - - Handle specially archives files during an import. - - * shell.ml: Ditto. - -2007-03-07 Nicolas Pouillard - - Use cp -p in copy_rule, and fix some typos in the manual. - - * manual/manual.tex: Typos. - * rule.ml, - * rule.mli: Add cp_p and use it for copy_rule. - -2007-03-05 Nicolas Pouillard - - Relaxe executor on exception condition. - - Patch from Berke. - * executor.ml: Ignore Not_found and exceptional conditions. - * TODO: Add an entry (needs to better understand POSIX). - -2007-03-04 Nicolas Pouillard - - Split where in bindir and libdir. - - * ocamlbuild_where.mli: Ditto. - * ocaml_specific.ml: Update. - * options.ml: Use bindir. - * plugin.ml: Update. - * start.sh: Update. - -2007-03-04 Nicolas Pouillard - - Virtual solvers for ocaml tools. - - * options.ml: Setup virtual command solver for commands like ocamlc, - ocamlopt... This allow to have full pathname but let also failback to - classic search path. - * ocaml_compiler.ml: Add a tag to differentiate dependencies at link - time. - * ocamlbuild-presentation.rslide: Add an item as suggested by a friend. - -2007-03-02 Nicolas Pouillard - - Same thing for the second link function. - - * ocaml_compiler.ml: Ignore stdlib. - -2007-03-02 Nicolas Pouillard - - Move the stdlib hack. - - * ocaml_compiler.ml: Should works better. - -2007-03-02 Nicolas Pouillard - - Little fix about library linking. - - * ocaml_utils.ml: Avoid linking twice in some cases. - * ocaml_compiler.ml: Handle specially the OCaml stdlib. - -2007-03-01 Nicolas Pouillard - - Remove a rec. - - * glob.ml: Parse is not rec. - -2007-03-01 Nicolas Pouillard - - true: traverse and FAQ. - - * main.ml: Move the inital config upper to be loaded before the others - and hygiene. - * FAQ: New. - -2007-02-28 Nicolas Pouillard - - Improve the glob dir handling. - - * glob.ml: Extend the ast instead of parsing an extended string. - -2007-02-28 Nicolas Pouillard - - Ensure that the whole boolean expression is only valid in the directory. - - * glob.ml: Ditto. - -2007-02-28 Nicolas Pouillard - - Put -g on link only for programs. - - * ocaml_specific.ml: Ditto. - -2007-02-26 Berke Durak - - Added disclaimer to default rules table. - - * manual/manual.tex: . - -2007-02-26 Nicolas Pouillard - - Add the -documentation option. - - * main.ml: Implement it. - * flags.ml, - * flags.mli: Add get_flags. - * man/ocamlbuild.1: Update. - * signatures.mli, - * options.ml: Add show_documention. - * rule.ml, - * rule.mli: Add pretty_print. - -2007-02-26 Nicolas Pouillard - - Add the -dont-catch-errors option. - - * main.ml: Implement it. - * options.ml: Parse it. - * signatures.mli: Declare it. - * _tags: Use debug. - -2007-02-26 Nicolas Pouillard - - Deal with the camlp4 library name. - - * ocaml_specific.ml: Introduce use_old_camlp4 for the old one. - -2007-02-26 Nicolas Pouillard - - Minor `ocaml_lib' improvments. - - * signatures.mli: Declare and doc it. - * ocamlbuild_plugin.ml: Export it. - * ocaml_specific.ml, - * ocaml_specific.mli: Add some dirs to std libs. - Move the ocaml_lib implem to ... - * ocaml_utils.mli, - * ocaml_utils.ml: ... here. Improve it by adding the ~tag_name option. - * ocaml_compiler.ml: The hash now contains the tag. - * _tags: *.top use unix too. - -2007-02-22 Berke Durak - - Should use Log.eprintf for show_tags. - - * main.ml: . - -2007-02-22 Nicolas Pouillard - - ( & ), sanitize.sh, and the manual... - - * signatures.mli: Add ( & ). - - * hygiene.ml: Also clean the sanitize.sh script itself. - * my_std.ml: Add ( & ). - * manual/manual.tex: Some fixes and a section that I wrote but that's - needs reflexion about what solution we want to support. - -2007-02-22 Berke Durak - - Implemented fixes suggested by Commissar Leroy. - - * fda.ml: . - * hygiene.ml: . - * hygiene.mli: . - * man/ocamlbuild.1: . - * manual/manual.tex: . - * ocaml_specific.ml: . - * options.ml: . - * signatures.mli: . - -2007-02-20 Nicolas Pouillard - - Add -show-tags. - - * hygiene.ml: Rewrap the error message. - * main.ml: Do the show_tags job. Move one hook. - * ocaml_specific.ml: Add -g also in native code. - * options.ml, - * signatures.mli: Add the -show-tags option. - * tags.ml: Fix print. - * TODO: Add a done entry. - -2007-02-16 Nicolas Pouillard - - Relaxing plural options to spaces. - - * lexers.mli, - * lexers.mll: Add comma_or_blank_sep_strings. - * options.ml: Use it. - -2007-02-16 Nicolas Pouillard - - Add a plugin example. - - * manual/myocamlbuild.ml: New. - -2007-02-16 Nicolas Pouillard - - Typos. - - * ocamlbuild-presentation.rslide: . - * manual/trace.out: . - -2007-02-16 Berke Durak - - Fixed a few typos and sentences. - - * ocamlbuild-presentation.rslide: . - -2007-02-15 Nicolas Pouillard - - Little changes... - - * ocamlbuild-presentation.rslide: . - -2007-02-15 Nicolas Pouillard - - Slides almost done... - - * manual/trace.out: New. Of course you needed it. - * ocamlbuild-presentation.rslide: Ditto. - -2007-02-15 Berke Durak - - Improving slides. - - * ocamlbuild-presentation.rslide: . - -2007-02-15 Nicolas Pouillard - - Slides... - - * ocamlbuild-presentation.rslide: . - -2007-02-15 Nicolas Pouillard - - Working on slides... - - * ocamlbuild-presentation.rslide: . - -2007-02-15 Nicolas Pouillard - - More slides... - - * ocamlbuild-presentation.rslide: . - -2007-02-12 Nicolas Pouillard - - Keep include dirs uniq. - - * ocaml_compiler.ml: Ditto. - -2007-02-12 Nicolas Pouillard - - Keep include dirs uniq. - - * ocaml_compiler.ml: Ditto. - -2007-02-12 Nicolas Pouillard - - Add ocamlmktop support. - - * ocamlbuild.mltop: New. - * main.ml: Handle .top as binaries. - * ocaml_compiler.ml, - * ocaml_specific.ml, - * ocaml_compiler.mli: Add mktop functions and rules. - * options.ml, - * signatures.mli: Add an ocamlmktop option. - -2007-02-09 Berke Durak - - Was attempting to link with threads.cmxa in byte mode. - - * ocaml_specific.ml: . - -2007-02-09 Berke Durak - - Talking of sterilize.sh. - - * manual/manual.tex: . - -2007-02-09 Berke Durak - - Rewrote some parts, filled the abstract, moved rantings to the appendix. - - * manual/manual.tex: . - * .vcs: . - -2007-02-08 Nicolas Pouillard - - Add manual/manual.hva. - - * manual/manual.hva: New. - -2007-02-08 Nicolas Pouillard - - Changes done with Luc. - - * manual/manual.tex: . - * manual/Makefile: . - -2007-02-08 Nicolas Pouillard - - Fix a bug found by Luc in hevea. - - * ocaml_utils.ml, - * ocaml_utils.mli: Change keep_this_module into module_importance to - have a finer grain. - * ocaml_compiler.ml: Update to importance. - * ocamldep.ml, - * ocamldep.mli: We now try to also build stdlib modules but don't fail - if they don't exists. - * test/test5/stack.ml: New. - * test/test5/a.ml: A test case (from hevea). - * test/good-output: Update. - -2007-02-08 Nicolas Pouillard - - Ocamldoc, extension:* tag ... - - * ocaml_tools.mli, - * ocaml_tools.ml: The ocamldoc support now takes into account two modes - *d and -o. - * ocaml_specific.ml: Two more rules and many flags for some of the - standard behaviors. - * signatures.mli: Some comments. - * tools.ml: Add the extension:* tag. - * TODO: Update. - -2007-02-08 Berke Durak - - Hygiene generates sterilize.sh. - - * fda.ml: . - * fda.mli: . - * hygiene.ml: . - * hygiene.mli: . - * main.ml: . - * options.ml: . - * signatures.mli: . - -2007-02-07 Berke Durak - - Updated section on ocamldoc. - - * manual/manual.tex: . - -2007-02-07 Nicolas Pouillard - - Some minor manual and slides changes. - - * ocamlbuild-presentation.rslide, - * manual/manual.tex: Ditto. - -2007-02-07 Nicolas Pouillard - - Make links for the documentation. - - * main.ml: Handle doc. - * test/good-output: Update. - -2007-02-07 Berke Durak - - Added manual section for ocamldoc. - - * manual/manual.tex: . - * manual/Makefile: . - -2007-02-07 Berke Durak - - Fixed truncated display problem. - - * executor.ml: . - * .vcs: . - -2007-02-07 Nicolas Pouillard - - Fix the bootstrap. - - * start.sh: Swap lines. - * Makefile: -verbose. - -2007-02-07 Berke Durak - - TODO + Executor. - - * manual/manual.tex: . - * TODO: . - -2007-02-06 Nicolas Pouillard - - Make -a more static, to avoid some complications. - - * ocaml_utils.ml, - * ocaml_compiler.ml, - * ocaml_compiler.ml, - * ocaml_specific.ml: Ditto. - -2007-02-06 Nicolas Pouillard - - A fix. - - * ocaml_compiler.ml: Don't use these refs too early. - * ocamlbuild-presentation.rslide: . - -2007-02-05 Nicolas Pouillard - - Plugin signature. - - Somewhat a big patch, but that's just moving things around. - - * signatures.mli: Add TAGS, OUTCOME, MISC, OPTIONS, ARCH and PLUGIN. - * ocamlbuild_plugin.mli: New. - * ocamlbuild_plugin.ml: Conform to the sig. - - * command.ml, - * command.mli: Add a tags type. - * main.ml: Quit early if no targets. - * my_std.ml, - * my_std.mli: More things are in signatures. - * resource.ml, - * resource.mli: Remove the type t that was an Pathname.t alias. - * options.ml, - * options.mli: Add ext_lib, ext_obj, ext_dll. - * ocaml_compiler.ml: Update. - * ocaml_tools.ml: Update to Outcome. - * ocaml_specific.ml: Update. - * ocaml_utils.mli: Remove *ext_*. - * ocaml_arch.mli: Now in signatures. - * pathname.ml: Add readdir. - * slurp.ml: open Outcome. - * rule.ml, - * rule.mli, - * solver.ml, - * solver.mli: Update to Resource.t and Outcome.t. - * tags.mli: Now in Signatures. - * test/good-output: Update. - * test/test8/test.sh, - * test/test3/test.sh, - * test/test4/test.sh, - * test/test5/test.sh, - * test/test6/test.sh, - * test/test7/test.sh, - * test/test2/test.sh: Update to -verbose 0. - -2007-02-05 Berke Durak - - Continuing doc. - - * manual/manual.tex: . - * .: . - -2007-02-05 Berke Durak - - Described display line. - - * manual/manual.tex: . - -2007-02-05 Berke Durak - - Renamed -debug as -verbose. Authorized spaces etc. in flags. Continuing documentation. - - * lexers.mll: . - * manual/manual.tex: . - * options.ml: . - -2007-02-05 Berke Durak - - Added man page. - - * main.ml: . - * man: New. - * man/ocamlbuild.1: New. - * manual/manual.tex: . - * TODO: . - -2007-02-05 Nicolas Pouillard - - Update start.sh. - - * start.sh: Update. - -2007-02-05 Nicolas Pouillard - - Typo s/Orignal/Original/g. - -2007-02-05 Nicolas Pouillard - - Make signatures and std_signatures mliS. - - * signatures.ml: Remove. - * std_signatures.ml: Remove. - * signatures.mli: New. - * std_signatures.mli: New. - * Makefile: Update. - * lexers.mll: Allow any prefix: for tags. - -2007-02-04 Nicolas Pouillard - - The beginning of a presentation. - - * ocamlbuild-presentation.rslide: New. - -2007-02-04 Nicolas Pouillard - - Also add who is the original author of the file. - - * ocamlbuild.ml, - * ocamlbuild_plugin.ml, - * ocamlbuildlight.ml, - * ocamlbuild_where.mli, - * ocamlbuild.mli, - * ocamlbuildlight.mli, - * bool.ml, - * bool.mli, - * configuration.ml, - * configuration.mli, - * command.ml, - * command.mli, - * display.ml, - * discard_printf.ml, - * display.mli, - * discard_printf.mli, - * executor.ml, - * executor.mli, - * flags.ml, - * fda.ml, - * flags.mli, - * fda.mli, - * glob.ml, - * glob_ast.ml, - * glob_ast.mli, - * glob.mli, - * glob_lexer.mli, - * glob_lexer.mll, - * hygiene.ml, - * hooks.ml, - * hygiene.mli, - * hooks.mli, - * log.ml, - * lexers.mli, - * log.mli, - * lexers.mll, - * my_unix_with_unix.ml, - * main.ml, - * my_unix.ml, - * my_std.ml, - * my_unix_with_unix.mli, - * my_std.mli, - * my_unix.mli, - * main.mli, - * ocaml_utils.ml, - * ocaml_tools.ml, - * ocaml_arch.ml, - * ocaml_specific.ml, - * ocaml_compiler.ml, - * ocaml_dependencies.ml, - * ocaml_utils.mli, - * ocaml_specific.mli, - * ocaml_dependencies.mli, - * ocaml_tools.mli, - * ocaml_arch.mli, - * ocaml_compiler.mli, - * options.ml, - * options.mli, - * ocamldep.ml, - * ocamldep.mli, - * plugin.ml, - * ppcache.ml, - * pathname.ml, - * ppcache.mli, - * plugin.mli, - * pathname.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * report.ml, - * report.mli, - * signatures.ml, - * slurp.ml, - * std_signatures.ml, - * solver.ml, - * shell.ml, - * shell.mli, - * slurp.mli, - * solver.mli, - * tags.ml, - * tools.ml, - * tags.mli, - * tools.mli: Ditto. - -2007-02-04 Nicolas Pouillard - - Add the header license. - - * ocamlbuildlight.ml, - * ocamlbuild.ml, - * ocamlbuild_plugin.ml, - * ocamlbuild_where.mli, - * ocamlbuild.mli, - * ocamlbuildlight.mli, - * bool.ml, - * bool.mli, - * configuration.ml, - * configuration.mli, - * command.ml, - * command.mli, - * discard_printf.ml, - * display.ml, - * display.mli, - * discard_printf.mli, - * executor.ml, - * executor.mli, - * fda.ml, - * flags.ml, - * flags.mli, - * fda.mli, - * glob.ml, - * glob_ast.ml, - * glob.mli, - * glob_ast.mli, - * glob_lexer.mli, - * glob_lexer.mll, - * hygiene.ml, - * hooks.ml, - * hygiene.mli, - * hooks.mli, - * log.ml, - * lexers.mli, - * log.mli, - * lexers.mll, - * my_unix.ml, - * main.ml, - * my_std.ml, - * my_unix_with_unix.ml, - * misc/opentracer.ml, - * my_std.mli, - * main.mli, - * my_unix.mli, - * my_unix_with_unix.mli, - * ocaml_arch.ml, - * ocaml_compiler.ml, - * ocaml_specific.ml, - * ocaml_tools.ml, - * ocaml_utils.ml, - * ocaml_dependencies.ml, - * ocaml_utils.mli, - * ocaml_tools.mli, - * ocaml_dependencies.mli, - * ocaml_compiler.mli, - * ocaml_specific.mli, - * ocaml_arch.mli, - * options.ml, - * options.mli, - * ocamldep.ml, - * ocamldep.mli, - * plugin.ml, - * pathname.ml, - * ppcache.ml, - * plugin.mli, - * ppcache.mli, - * pathname.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * report.ml, - * report.mli, - * slurp.ml, - * std_signatures.ml, - * signatures.ml, - * solver.ml, - * shell.ml, - * shell.mli, - * slurp.mli, - * solver.mli, - * tools.ml, - * tags.ml, - * tags.mli, - * tools.mli: Ditto. - -2007-02-03 Nicolas Pouillard - - Fix a bug in copy_file. - - * my_std.ml: Also use the binary mode for the output channel. - -2007-02-03 Nicolas Pouillard - - Add nopervasives, and nolabels. - - * ocaml_specific.ml: Ditto. - -2007-02-03 Nicolas Pouillard - - Windows cannot use executor. - - * shell.ml: As in command.ml use executor only in non-windows and - non-degraded mode. - * rule.ml: Update two error messages. - -2007-02-02 Nicolas Pouillard - - Some minor things for the ocaml myocamlbuild for instance. - - * configuration.ml, - * configuration.mli: Add has_tag. - * my_std.ml, - * my_std.mli: Add getenv and copy_chan. - * ocaml_utils.ml, - * ocaml_utils.mli: Move some commands to rule. - * ocaml_specific.ml: Improve the menhir switching. - * options.ml, - * options.mli: Add -use-menhir and -menhir options. - * rule.ml, - * rule.mli: Add copy_rule and move some commands from ocaml_utils. - * signatures.ml: . - -2007-02-01 Nicolas Pouillard - - Move main sigs in signatures.ml and std_signatures.ml. - - * ocamlbuild_pack.mlpack: . - * ocamlbuildlib.mllib: . - * ocamlbuildlightlib.mllib: . - * ocamlbuild.odocl: . - * command.mli: . - * glob.mli: . - * log.mli: . - * my_unix_with_unix.ml: . - * my_std.ml: . - * my_std.mli: . - * ocaml_specific.ml: . - * pathname.mli: . - * std_signatures.ml: New. - * signatures.ml: New. - * start.sh: . - * tags.ml: . - * tags.mli: . - * test/test5/_tags: . - * Makefile: . - * _tags: . - -2007-02-01 Berke Durak - - Shell.run doesn't use execute_many in degraded mode. - - * shell.ml: . - -2007-02-01 Berke Durak - - cp, rm -rf and mv-like commands use Executor to better play with display. - - * display.ml: . - * my_unix.ml: . - * main.ml: . - * my_std.ml: . - * my_unix.mli: . - * shell.ml: . - * shell.mli: . - * start.sh: . - * _tags: . - -2007-02-01 Berke Durak - - Systematizing exit codes. - - * executor.ml: . - * main.ml: . - -2007-02-01 Berke Durak - - Added automatic file: tag, changed flag syntax. - - * lexers.mli: . - * lexers.mll: . - * main.ml: . - * ocamldep.ml: . - * ocamldep.mli: . - * tools.ml: . - -2007-01-31 Berke Durak - - Cleans up links to the _build directory. - - * main.ml: . - * options.ml: . - * options.mli: . - * pathname.ml: . - * pathname.mli: . - -2007-01-31 Nicolas Pouillard - - Restore the link to binary targets functionality. - - * main.ml: Make it separate from target running. - -2007-01-31 Nicolas Pouillard - - Add an hygiene hook pair. - - * ocamlbuild_plugin.ml, - * hooks.ml, - * hooks.mli, - * main.ml: Ditto. - -2007-01-31 Nicolas Pouillard - - The Killer feature about a fine grained dependency injection control. - - * rule.ml, - * rule.mli: Add build_deps_of_tags and call it automatically before - * ocaml_compiler.ml, - * ocaml_compiler.mli: Rework tags, to have them when callinng - build_deps_of_tags. - executing a command. - * ocaml_specific.ml, - * ocaml_specific.mli: Move the exception Exit_build_error to main and - remove the old dep function. - * ocamlbuild_plugin.ml: Export some new functions. - * test/test7/myocamlbuild.ml: Add a dep declaration. - * test/test7/cool_plugin.ml: New. - * test/test7/_tags: New. - * test/good-output: Update. - * flags.ml, - * command.ml, - * command.mli: Rename flags_of_tags as tag_handler. - * main.ml: Update error handling. - * TODO: Done. - -2007-01-30 Nicolas Pouillard - - Fix and improve the new link/deps system. - - * ocaml_dependencies.ml, - * ocaml_dependencies.mli: Some fixes and improvements. - * pathname.ml, - * pathname.mli: Add check_extension. - * ocaml_compiler.ml, - * ocaml_compiler.mli: Add support for hidden_packages and update. - -2007-01-30 Nicolas Pouillard - - Reverse the last 2 patches, since there is fact no name clash. - -2007-01-30 Nicolas Pouillard - - Shell -> Oshell second part. - - * ocamlbuild.odocl: Ditto. - * test/good-output: Update. - -2007-01-30 Nicolas Pouillard - - Rename the Shell module as Oshell to avoid a name clash with labltk. - - * shell.ml: Remove. - * shell.mli: Remove. - * oshell.ml: New. - * oshell.mli: New. - * ocamlbuild_pack.mlpack, - * command.ml, - * display.ml, - * main.ml, - * options.ml, - * ppcache.ml, - * pathname.ml, - * plugin.ml, - * resource.ml, - * start.sh: Update. - -2007-01-30 Nicolas Pouillard - - Fix 2 bugs. - - * test/test9/testglob.ml: More tests. - * glob_lexer.mll: Fix "/**". - * _tags: Restore my warnings. - * executor.ml: Use the unused variable. - -2007-01-30 Nicolas Pouillard - - Improve dprintf and update. - - * log.ml, log.mli: dprintf now wraps the message between "@[<2>" and "@]@.". - * command.ml, - * display.ml, - * fda.ml, - * main.ml, - * ocaml_dependencies.ml, - * ocaml_compiler.ml, - * ocaml_utils.ml, - * ocamldep.ml, - * pathname.ml, - * resource.ml, - * rule.ml, - * solver.ml: Update the dprintf usage. - -2007-01-30 Nicolas Pouillard - - Add the new dependency linking system (plz test it !). - - * ocamlbuild_pack.mlpack: Add a brand new module. - * ocaml_dependencies.ml: New. - * ocaml_dependencies.mli: New. - * ocaml_compiler.ml, - * ocaml_compiler.mli: Use this new module. - * resource.ml, - * resource.mli: Export a folding function on dependencies. - * TODO: Add something to do. - * start.sh: . - * main.ml: Update. - -2007-01-29 Nicolas Pouillard - - Executor exit codes. - - * executor.ml: Use the standard exit. - * main.ml: Some exit codes are reserved for Executor. - -2007-01-29 Berke Durak - - Executor returns finer-grained results. - - * executor.ml: . - * manual/manual.tex: . - -2007-01-29 Nicolas Pouillard - - Toward a working command execute feature :). - - * executor.ml, - * executor.mli: FIXME. - * command.ml, - * command.mli: Update to the new signature and merge the degraded mode - to avoid duplication. - * my_unix.ml, - * my_unix.mli, - * ocaml_utils.ml, - * ocamldep.ml, - * plugin.ml, - * resource.ml, - * rule.ml, - * solver.ml, - * test/good-output: Update. - -2007-01-29 Nicolas Pouillard - - Revert almost all of the 2 last patches. - - * command.ml: . - * command.mli: . - * executor.ml: . - * executor.mli: . - * my_unix.ml: . - * my_unix.mli: . - * ocaml_utils.ml: . - * ocaml_specific.ml: . - * ocamldep.ml: . - * plugin.ml: . - * resource.ml: . - * rule.ml: . - * solver.ml: . - -2007-01-29 Berke Durak - - Fixing before/after thunks. - - * command.ml: . - * command.mli: . - * ocaml_utils.ml: . - * ocamldep.ml: . - * plugin.ml: . - * resource.ml: . - * rule.ml: . - * solver.ml: . - * TODO: . - -2007-01-29 Berke Durak - - Adding before and after handlers to Executor. - - * command.ml: . - * executor.ml: . - * executor.mli: . - * my_unix.ml: . - * my_unix.mli: . - * manual/manual.tex: . - -2007-01-29 Berke Durak - - Fixed multi-dir globbing. - - * glob_lexer.mll: . - * manual/manual.tex: . - -2007-01-29 Nicolas Pouillard - - Add Rule.custom_rule and cleanup the ocamldep meta rule. - - * ocamldep.ml, - * ocamldep.mli: Make it a meta rule (or a rule generator). - * rule.ml, - * rule.mli: Add custom_rule. - * ocaml_specific.ml: Update to Ocamldep. - * test/good-output: Minor update. - -2007-01-29 Nicolas Pouillard - - MakefileS... - - * manual/Makefile: More things to remove (sometimes). - * Makefile: Use $(BUILDDIR) instead of _build. - -2007-01-26 Berke Durak - - Documenting glob expressions. - - * glob_lexer.mll: Added negative character classes. - * manual/manual.tex: . - -2007-01-26 Berke Durak - - Started documenting glob syntax. - - * manual/manual.tex: . - -2007-01-25 Nicolas Pouillard - - One other include dir fix. - - * main.ml: Ditto. - * test/test9/testglob.ml: Add a failing test (request for feature). - * test/good-output: Update. - -2007-01-25 Nicolas Pouillard - - Include dirs and Backtrace. - - * main.ml: Fix -I, and restore the backtrace. - * report.ml, - * report.mli: Fix the backtrace and rename analyze to - print_backtrace_analyze. - -2007-01-25 Berke Durak - - Added cross-directory globbing. - - * glob_ast.ml: . - * glob.ml: . - * glob_ast.mli: . - * glob_lexer.mll: . - * test/test9/testglob.ml: . - -2007-01-25 Nicolas Pouillard - - Inlcude dirs trought tags. - - * main.ml: Ditto. - * my_unix_with_unix.ml: Imrpove stat errors. - * my_std.ml, - * my_std.mli: . - * pathname.ml: bmla. - * slurp.ml, - * slurp.mli: Add force, fix bugs. - -2007-01-25 Berke Durak - - Fixed double display of error status. - - * command.ml: . - * display.ml: . - * display.mli: . - * log.ml: . - * log.mli: . - * main.ml: . - * my_std.ml: . - * my_std.mli: . - * plugin.ml: . - -2007-01-25 Berke Durak - - Stupid bug. - - * log.ml: . - * main.ml: . - * options.ml: . - -2007-01-25 Berke Durak - - Fixed interface, handling of -- with no argument. - - * ocamlbuild_plugin.mli: Remove. - * manual/manual.tex: . - * options.ml: . - -2007-01-25 Berke Durak - - Updated start.sh. - - * start.sh: . - -2007-01-25 Berke Durak - - Added .mlis. - - * ocamlbuild_plugin.mli: New. - * fda.mli: New. - * main.ml: . - * ocaml_specific.ml: . - * plugin.ml: . - * plugin.mli: New. - -2007-01-25 Nicolas Pouillard - - Cut down ocaml_specific in pieces. - - * ocaml_specific.ml, - * ocaml_specific.mli: Split. - * ocamlbuild_plugin.ml: Update. - * ocamlbuild_pack.mlpack: Add new modules. - * my_std.ml, - * my_std.mli: Add good_outcome. - * ocaml_utils.ml: New. - * ocaml_tools.ml: New. - * ocaml_compiler.ml: New. - * ocaml_utils.mli: New. - * ocaml_compiler.mli: New. - * ocaml_tools.mli: New. - * ocamldep.ml: New. - * ocamldep.mli: New. - * start.sh: Update. - * TODO: Move things done. - -2007-01-25 Berke Durak - - Fixer return codes and error message flushing issues. - - * display.ml: . - * log.ml: . - * log.mli: . - * main.ml: . - * report.ml: . - * report.mli: . - -2007-01-25 Nicolas Pouillard - - Add a warning. - - * ocaml_specific.ml: In -debug 1 mode there is a now a warning when - ocamlbuild skip a seliently a module, supposing that's an error of - ocamldep. - -2007-01-24 Nicolas Pouillard - - More hooks. - - * ocamlbuild_plugin.ml, - * hooks.ml, - * hooks.mli, - * main.ml: Add {Before,After}_rules. - -2007-01-24 Nicolas Pouillard - - Call these hooks. - - * main.ml: Call these hooks. - -2007-01-24 Nicolas Pouillard - - Add a first version of dispatch. - - * ocamlbuild_plugin.ml: Export dispatch and the hooks type. - * ocamlbuild_pack.mlpack: Add Hooks. - * hooks.ml: New. - * hooks.mli: New. - * ocaml_specific.mli: New line. - -2007-01-24 Berke Durak - - Mini slurp bug. - - * slurp.ml: . - * TODO: . - -2007-01-24 Nicolas Pouillard - - Fix few more things. - - * ocamlbuildlight.ml: . - * ocamlbuild_version.ml: Remove. - * ocamlbuild.ml: . - * ocamlbuild_pack.mlpack: . - * main.ml: . - * ocaml_specific.ml: . - * ocaml_specific.mli: . - * start.sh: . - * test/test2/toto.ml: . - * test/good-output: . - -2007-01-24 Berke Durak - - Read directories before files in Slurp. - - * slurp.ml: . - * TODO: . - -2007-01-24 Nicolas Pouillard - - Fix some bugs. - - * ocamlbuild_version.ml: Remove. - * ocamlbuild.ml, - * ocamlbuildlight.ml: Main is now in the pack. - * ocamlbuild_pack.mlpack: more things. - * ocaml_specific.ml: One fix and one comment. - * start.sh: Update. - -2007-01-24 Berke Durak - - Splitting ocaml_specific into multiple files. - - * ocamlbuildlight.ml: . - * ocamlbuild.ml: . - * ocamlbuild_version.ml: New. - * ocamlbuild.mli: . - * ocamlbuildlight.mli: . - * ocamlbuild_pack.mlpack: . - * command.ml: . - * fda.ml: New. - * hygiene.ml: . - * main.ml: New. - * my_std.ml: . - * my_std.mli: . - * main.mli: New. - * manual/manual.tex: . - * ocaml_specific.ml: . - * ocaml_specific.mli: . - * options.ml: . - * options.mli: . - * plugin.ml: New. - * rule.ml: . - * report.ml: . - * tools.ml: New. - * tools.mli: New. - * TODO: . - * _tags: . - -2007-01-24 Nicolas Pouillard - - Minor changes. - - * manual/manual.tex: Typo s/the the/the/g. - * ocaml_specific.ml, - * ocaml_specific.mli: Add some function to deal with linking of a - module list. Add a better lib declaration function. - * TODO: Update. - -2007-01-17 Nicolas Pouillard - - A new pathname operator and a bug fix. - - * pathname.ml, - * pathname.mli: add the ( -.- ) operator to add an extension to a - pathname. - * ocaml_specific.ml: Use that new operator. - * resource.ml: Fix a bug. - -2007-01-17 Berke Durak - - More examples. - - * examples/example3/epoch.ml: . - * examples/example3/make.sh: New. - * manual/manual.tex: . - * TODO: . - -2007-01-17 Nicolas Pouillard - - Infered mli's, and bug fixes. - - * my_unix.ml: Fix a bug. - * my_std.mli: Doc. - * manual/manual.tex: Use \verb. - * ocaml_arch.ml: Don't always overide the forpack_flags_of_pathname - function reference. - * ocaml_arch.mli: Remove the reference. - * ocaml_specific.ml: Update for forpack and add infered mli's. - * pathname.ml, - * pathname.mli: Add is_directory. - -2007-01-17 Berke Durak - - More examples. - - * examples/example3/epoch.ml: New. - * examples/example2/hello.ml: . - * examples/example2/greet.ml: New. - * examples/example3: New. - * examples/example2: New. - * manual/manual.tex: . - * TODO: . - -2007-01-17 Berke Durak - - Started examples. - - * examples/example1/hello.ml: New. - * examples/example1: New. - * examples: New. - * manual/manual.tex: . - * .vcs: . - * TODO: . - -2007-01-17 Berke Durak - - Wrote limitations and features. - - * manual/manual.tex: . - -2007-01-17 Berke Durak - - Wrote motivations. - - * manual/manual.tex: . - * _tags: . - -2007-01-17 Berke Durak - - Started manual. - - * manual/Makefile: New. - * manual/manual.tex: New. - * manual: New. - -2007-01-17 Nicolas Pouillard - - Bugs, menhir, path variables. - - * display.ml: Fix a bug. - * glob.mli: Fix a typo. - * lexers.mli, - * lexers.mll: Extend ocamldep_output lexer and meta_path lexer. - * my_std.ml, - * my_std.mli: Add memo and String.rev. - * ocaml_specific.ml, - * ocaml_specific.mli: Better rules for C lib linking and menhir rules. - * resource.ml, - * resource.mli: Handle naively some multiple variables. - * rule.ml, - * rule.mli: Update. - * start.sh: Update. - -2007-01-11 Nicolas Pouillard - - Integrate dprintf to the display. - - * display.ml, - * display.mli: Add dprintf and log_level. - * log.ml, - * log.mli: Add dprintf and level. - * debug.ml: Remove. - * debug.mli: Remove. - * options.ml: Update. - * command.ml, ocaml_specific.ml, my_std.ml, - * pathname.ml, ppcache.ml, resource.ml, - * rule.ml, report.ml, slurp.ml, solver.ml, - * configuration.ml, tags.ml: Update to Log. - * ocamlbuild.odocl: Add Log, remove Debug. - * ocamlbuild_pack.mlpack: Remove Debug. - * bool.ml: Remove the debug dependency. - -2007-01-10 Nicolas Pouillard - - Execute and windows... - - * command.ml: Test windows here. - * my_unix_with_unix.ml: Revert a little. - -2007-01-10 Nicolas Pouillard - - Don't use executor on windows. - - * my_unix_with_unix.ml: Since at least set_nonblock does not works on - windows. - -2007-01-10 Nicolas Pouillard - - Add the -no-log option and fix a log bug. - - * log.mli, - * log.ml: Log is now a lazy to have the good setup order. - * options.ml: Add the -no-log option. - -2007-01-10 Nicolas Pouillard - - Fix a bug with quoting of the nil string. - - * shell.ml: Quote the nil string. - -2007-01-09 Berke Durak - - Documented the interface of the glob module. - - * glob.mli: . - -2007-01-09 Berke Durak - - Continuing to document interfaces. - - * bool.mli: . - * debug.mli: . - * discard_printf.mli: . - * executor.mli: . - * hygiene.mli: . - * my_std.mli: . - * slurp.mli: . - * Makefile: . - -2007-01-09 Nicolas Pouillard - - Fix a bug with directory links to build dir. - - * ocaml_specific.ml, - * options.ml, - * options.mli: Keep the Slurp.entry instead of a set. - * pathname.ml: Clean the entry instead of the set, that more precise. - * Makefile: Add doc phonny rules. - -2007-01-09 Berke Durak - - Doc for Configuration. - - * ocamlbuild_plugin.ml: . - * bool.mli: . - * configuration.ml: . - * configuration.mli: . - * command.mli: . - * doc: New. - * glob.ml: . - * ocaml_specific.ml: . - * Makefile: . - -2007-01-09 Berke Durak - - Started documentation. - - * bool.mli: . - * command.ml: . - * command.mli: . - -2007-01-09 Nicolas Pouillard - - Export the doc. - - * Makefile: Use a link. - * _tags: Don't spend times in that dir. - -2007-01-09 Nicolas Pouillard - - Put the log file in the source dir and not when building plugin. - - * log.ml, - * log.mli: Use an optional. - * options.ml: Update. - * pathname.mli: Export in_source_dir. - * .vcs: Add _log. - -2007-01-09 Berke Durak - - Added doc target. - - * report.ml: . - * Makefile: . - * TODO: . - -2007-01-09 Berke Durak - - Writes tags to log file. - - * display.ml: . - -2007-01-09 Nicolas Pouillard - - Add the Log module. - - * ocamlbuild_pack.mlpack: Add Log. - * command.ml, - * command.mli: Use Log. - * log.ml: New. - * log.mli: New. - * options.ml: Use Log. - * start.sh: Update. - -2007-01-09 Berke Durak - - Added -log option. - - * command.ml: . - * command.mli: . - * display.ml: . - * display.mli: . - * executor.mli: . - * options.ml: . - * _tags: . - -2007-01-09 Nicolas Pouillard - - Make usable the ocamldoc support. - - * ocaml_specific.ml: Add rules for ocamldoc. - * ocamlbuild.odocl: New. - * test/test3/proj.odocl: New. - * test/good-output: Update. - * test/test3/test.sh: Add a odoc test. - -2007-01-09 Nicolas Pouillard - - Some cleanups. - - * ocamlbuild_plugin.ml: Add tag_file that simule one simple line in the - _tags file. - * ocaml_specific.ml, - * ocaml_specific.mli: Add ln_s, touch, chmod. - * pathname.ml, - * pathname.mli: Remove map_extension*, split_extension* and compiled - files hack skipping. - * rule.ml: Improve logging. - * solver.ml: Use another level. - -2007-01-07 Nicolas Pouillard - - Fix a bug with debug rules. - - * ocaml_specific.ml: Move %.cmi from prods to deps. - * test/good-output: Update. - -2007-01-07 Nicolas Pouillard - - Add debugging rules. - To get a ocamlbuild with debugging info you can - call `make debug' that will produce ocamlbuild.d.byte - and x.d.cmo files. - - * ocaml_specific.ml, - * ocaml_specific.mli: Add debugging rules, reorder warnings flag to - have 'A' and 'a' before others. - * Makefile: Add the debug target. - * _tags: Cleanup (remove the debug tag that was set by default). - -2007-01-07 Nicolas Pouillard - - Add profiling support directly in rules. - This means that you can now request for building a target such as - my_main.p.native or my_lib.p.cmxa, that will create %.p.cmx - intermediate files that do not interfer with non-profiling ones. - - * ocaml_specific.ml, - * ocaml_specific.mli: Add rules and functions for native link and - comilation in profiling mode. - * Makefile: Add a profile target (require a fixed ocamlopt w.r.t pack). - * _tags: Take care also of .p.cmx files. - * glob.ml: IS.print is equivalent to print_is. - * my_std.ml: Fix a bug. - -2007-01-07 Nicolas Pouillard - - Add some functions... - - * glob.ml: Extract is_suffix and is_prefix. - * my_std.ml, - * my_std.mli: Add String.{is_suffix,is_prefix,first_chars,last_chars} - and List.union. - * pathname.ml, - * pathname.mli: Add get_extensions, remove_extensions, - update_extensions, map_extensions that treat all extensions instead of - just the last. - * tags.ml, - * tags.mli: Add +++ and --- that treat optional tags. - -2007-01-06 Nicolas Pouillard - - Change the default display in degraded mode. - - * command.ml: Ditto. - -2007-01-06 Nicolas Pouillard - - Cleanup Makefile options. - - * Makefile: Ditto. - -2007-01-06 Nicolas Pouillard - - Add a simple opened files tracer. - - * misc/opentracer.ml: New. - Just support ktrace for now. A strace one will be appreciated the - interface to follow is quite simple anyway. - * misc: New. - -2007-01-06 Nicolas Pouillard - - Handle better commands without Px atom. - - * command.ml: Display the whole command if no Px is found. - * display.mli: No longer export these strings. - -2007-01-06 Nicolas Pouillard - - Handle myocamlbuild_config.mli. - - * ocaml_specific.ml: Add support for an interface to the config. - -2007-01-06 Berke Durak - - Improved language of explanations in Report. - - * report.ml: . - -2007-01-06 Nicolas Pouillard - - Factor and fix the plugin building. - - * ocamlbuildlight.mli: New. - * executor.ml: Call cleanup, add a fixme. - * ocaml_specific.ml: Factor and fix plugin stuffs. - * start.sh: Update. - * Makefile: Update. - * TODO: Update. - * _tags: No longer do favors to some modules. - -2007-01-05 Nicolas Pouillard - - Fix plugins. - - * ocamlbuildlib.mllib: Add missing modules. - * ocamlbuildlightlib.mllib: New. - * Makefile: Update. - -2007-01-05 Nicolas Pouillard - - Change the my_unix system. - - * ocamlbuildlight.ml: Just call the main. - * ocamlbuild.ml: Setup my_unix_with_unix. - * ocamlbuildlib.mllib: Remove executor and exit_codes for the lib. - * ocamlbuild_pack.mlpack: Remove my_std and my_unix. - * exit_codes.ml: Remove. Put them directly in executor. - * executor.ml: Add exitcodes. - * my_unix.ml: New. Default implem. - * my_unix_with_unix.ml: Extend the default implem. - * my_unix_without_unix.ml: Remove. - * my_unix.mli: Add the implem type and val. - * my_unix_with_unix.mli: New. - * ocaml_specific.ml, - * pathname.ml, - * slurp.ml, - * Makefile, - * command.ml, - * _tags: Update. - -2007-01-05 Nicolas Pouillard - - Don't use executor for the myocamlbuild call. - - * ocaml_specific.ml: Use sys_command directly. - -2007-01-05 Nicolas Pouillard - - Fix a stupid bug. - - * command.ml: That cause to have reversed sequences. - -2007-01-05 Nicolas Pouillard - - Some libs and ocamldoc changes. - - * ocaml_specific.ml, - * ocaml_specific.mli: Improve ocaml_lib_flag, add fews libs. - Fix ocamldoc support update tags, and use Px only once. - -2007-01-05 Berke Durak - - Started ocamldoc support. - - * ocaml_specific.ml: . - * options.ml: . - * options.mli: . - -2007-01-05 Berke Durak - - Pretend option didn't work. - - * command.ml: . - -2007-01-05 Berke Durak - - TODO + typo. - - * options.ml: . - * TODO: . - -2007-01-05 Nicolas Pouillard - - Really call executor all time. - - * command.ml, - * command.mli: Remove normalization. - And execute_many, it's now execute that do all the job. - In degraded mode it's execute_degraded. - * my_unix_without_unix.ml: Update. - * ocaml_specific.ml, - * resource.ml, - * rule.ml, - * solver.ml: Update to Command.execute type. - -2007-01-05 Berke Durak - - Isatty detection logic. - - * command.ml: . - * executor.ml: . - * my_unix_with_unix.ml: . - * my_unix_without_unix.ml: . - * my_unix.mli: . - -2007-01-05 Nicolas Pouillard - - Always call executor. - - * command.ml: Unless in degraded mode. - -2007-01-05 Berke Durak - - Removed debugging output, added period argument for ticker. - - * display.ml: . - * executor.ml: . - * executor.mli: . - * my_unix.mli: . - -2007-01-05 Berke Durak - - Somewhat slow but executor seems to work. - - * executor.ml: . - -2007-01-05 Berke Durak - - Added an Exit_codes module. Fixing Executor... - - * ocamlbuild.ml: . - * ocamlbuildlib.mllib: . - * executor.ml: . - * exit_codes.ml: New. - * solver.ml: . - -2007-01-05 Nicolas Pouillard - - Fix the max_jobs argument passing. - - * command.ml: Use an optional argument. - -2007-01-05 Nicolas Pouillard - - Subway changes... - - * my_unix_without_unix.ml, - * my_unix_with_unix.ml, - * my_unix.mli, - * command.ml: Call the new execute_many. - * executor.ml, - * executor.mli: Handle command sequences. - -2007-01-04 Berke Durak - - Added Display.update. - - * display.ml: . - * display.mli: . - * executor.ml: . - -2007-01-04 Berke Durak - - Added display function, indentation, language. - - * display.ml: . - * display.mli: . - * hygiene.ml: . - -2007-01-04 Berke Durak - - Fixing interface of Executor. - - * executor.ml: . - * executor.mli: . - * my_unix_with_unix.ml: . - -2007-01-04 Nicolas Pouillard - - Add attributes to entries. Add the -byte-plugin option. - - * slurp.ml, - * slurp.mli: Add an attribute field, add map, rename fold_pathnames to - fold and filter_on_names to filter. - * hygiene.ml, - * hygiene.mli: Perform hygiene only on entries with a true attribute. - * options.ml, - * options.mli: Add the native_plugin reference and the -byte-plugin - option. - * ocaml_specific.ml, - * ocaml_specific.mli: Exclude files tagged not_hygienic or precious - from hygiene. - -2007-01-04 Berke Durak - - Fixed pack issues. - - * ocamlbuild.ml: . - * executor.ml: . - * executor.mli: New. - * _tags: . - -2007-01-04 Berke Durak - - Started executor module. - - * executor.ml: New. - * hygiene.ml: . - * my_unix_with_unix.ml: . - -2007-01-04 Nicolas Pouillard - - Add virtual commands. - - * command.ml, - * command.mli: Add the V constructor for virtual commands that - will query a virtual command solver to use the best implementation - of that virtual command. - -2007-01-04 Nicolas Pouillard - - Mainly, prepare for parallel display. - - * ocamlbuild_plugin.ml: Export file_rule. - * command.ml, - * command.mli: Some cleanup and preparation. - * lexers.mll: Remove the dirty hack. - * my_std.ml, - * my_std.mli: Move search_in_path to Command and add ( @:= ). - * my_unix_with_unix.ml, - * my_unix_without_unix.ml, - * my_unix.mli: Change the execute_many_using_fork type. - * ocaml_specific.ml: Use the nopervasives tag for - pervasives dependencies. - * start.sh: Update. - * test/test8/myocamlbuild.ml: Update. - * test/good-output: Update. - * Makefile: Update. - -2007-01-03 Nicolas Pouillard - - I don't like microbes. - - * hygiene.ml: Reverse the bool. - -2007-01-03 Nicolas Pouillard - - Fix the stat problem. - - * ocaml_specific.ml: Use the filtered entry for source_dir_path_set. - -2007-01-03 Berke Durak - - Hygiene filters cleaned out microbes. - - * hygiene.ml: . - * hygiene.mli: . - * ocaml_specific.ml: . - * ocaml_specific.mli: . - * slurp.ml: . - * slurp.mli: . - -2007-01-03 Nicolas Pouillard - - Filename concat cleanup. - - * my_std.ml, - * my_std.mli: Add filename_concat. - * glob.ml, - * hygiene.ml, - * lexers.mll, - * pathname.ml, - * resource.ml, - * report.ml, - * solver.ml, - * slurp.ml, - * solver.mli: - Use filename_concat. - * flags.ml: FIXME. - -2007-01-03 Berke Durak - - Revert to old. - - * slurp.ml: . - -2007-01-03 Berke Durak - - Debugging tags for myocamlbuild.ml. - - * ocaml_specific.ml: . - * slurp.ml: . - -2007-01-02 Nicolas Pouillard - - Another atempt to fix the slurp bug and lazy. - - * slurp.ml: Ditto. - -2007-01-02 Nicolas Pouillard - - Fix slurp w.r.t lazyness: keep the cwd. - - * slurp.ml: Ditto. - -2007-01-02 Nicolas Pouillard - - My_unix, slurp in degraded mode, _tags in subdirs, fix the bug with -j... - - * ocamlbuild_version.mli: Remove. - * ocamlbuild_where.mli: New. - * display.mli: New. - * shell.ml: New. - * shell.mli: New. - * glob.ml, - * glob.mli, - * configuration.ml, - * lexers.mli, - * lexers.mll, - * configuration.mli: Honor _tags files in subdirs. - * my_unix_with_unix.ml, - * command.ml, - * command.mli, - * resource.ml, - * resource.mli, - * solver.ml: Fix the bug with the -j option. - * slurp.ml, - * slurp.mli: New degraded mode using the find command. - Use lazy values to avoid computing useless directories. - * options.ml, - * options.mli: Update -version and -where. - * pathname.ml, - * pathname.mli: Remove the init section. - * rule.ml, - * rule.mli: Add file_rule useful for rules that don't run a command but - just write a file. - * ocaml_specific.ml: Fix some plugin bugs. Remove -I to ocamldep. - Handle msvc .obj,.lib instead of .o,.a. - * my_unix_without_unix.ml: Make works link stuffs running the readlink - command. - * display.ml, - * hygiene.ml, - * my_std.ml, - * my_unix.mli, - * my_std.mli, - * start.sh, - * test/test5/test.sh, - * test/good-output, - * test/test6/test.sh, - * test/test7/test.sh, - * test/test4/test.sh, - * test/test8/test.sh, - * test/test3/test.sh, - * test/test2/test.sh, - * Makefile, - * _tags, - * ocamlbuild_pack.mlpack: Update. - -2007-01-02 Berke Durak - - Fixed ticker. - - * display.ml: . - -2006-12-21 Berke Durak - - Cosmetic. - - * command.ml: . - * display.ml: . - -2006-12-21 Berke Durak - - Computing display length. - - * display.ml: . - -2006-12-21 Nicolas Pouillard - - Add -classic-display. - - * command.ml, - * command.mli: Provide a way to use the classic display. - * options.ml: Add the -classic-display option. - * Makefile: Remove ppcache form the default. - -2006-12-21 Berke Durak - - Finish display only once ; display number of jobs cached. - - * command.ml: . - * display.ml: . - -2006-12-21 Nicolas Pouillard - - Oops fix a bug. - - * command.ml: Add begin .. end. - -2006-12-21 Nicolas Pouillard - - Some display fixes. - - * command.ml: Select the display mode and remove the assert false. - * display.ml: Change the print function to have a more compact one. - * start.sh: Update. - -2006-12-21 Berke Durak - - Error support in Display.finish. - - * display.ml: . - -2006-12-21 Berke Durak - - Support for cache. - - * display.ml: . - -2006-12-21 Nicolas Pouillard - - Integrate display mode. - - * ocamlbuild_pack.mlpack: Add display. - * command.mli: Add Px to indicate to highligth this pathname. - * command.ml: Support Px and call Display. - * display.ml: Fix minor bugs. - * ocaml_specific.ml: Declare some Px, and quiet ocamlyacc, ocamllex. - * options.ml: Add quiet to default tags. - * ppcache.ml: Detect more accuratly ocamlrun. - * pathname.ml: Improve concat. - * _tags: No profile. - -2006-12-21 Berke Durak - - Added pretend. - - * display.ml: . - -2006-12-21 Berke Durak - - Added ticker. - - * display.ml: . - -2006-12-21 Berke Durak - - Display module. - - * display.ml: . - * my_unix_with_unix.ml: . - * my_unix_without_unix.ml: . - * my_unix.mli: . - * test/test10/test.sh: New. - * test/test10: New. - * test/test10/dbdi: New. - -2006-12-21 Nicolas Pouillard - - Use a better init order, and fix a Filename.concat usage. - - * ocaml_specific.ml: The plugin should act before any initialization. - * ocaml_arch.ml: Use Pathname.(/). - -2006-12-21 Berke Durak - - Started user-friendly display module. - - * display.ml: New. - -2006-12-21 Nicolas Pouillard - - Fix init order. - - * ocaml_specific.ml: Config must be available for plugin building. - -2006-12-21 Nicolas Pouillard - - Some fixes. - - * command.ml: Quote if needed. - * my_std.mli: Comment String.contains_string. - * resource.ml: Remove a useless separator. - * test/good-output: Update. - -2006-12-21 Nicolas Pouillard - - Plugin config file and profile mode. - - * ocaml_specific.ml: Fix a bug due to the lazyness of &&. - * ocaml_specific.mli: Move some functions. - -2006-12-21 Berke Durak - - Now compiles patterns for fast matching. Removed regexp support. - - * glob_ast.ml: . - * glob.ml: . - * glob_lexer.mli: . - * glob_ast.mli: . - * glob_lexer.mll: . - * test/test9/testglob.ml: . - * test/test9/dbgl: New. - -2006-12-20 Berke Durak - - Pattern matching seems to start to work. - - * glob.ml: . - -2006-12-20 Berke Durak - - Started faster pattern matching code. - - * ocaml_specific.ml: . - * _tags: . - -2006-12-20 Berke Durak - - myocamlbuild is rebuilt only as needed. - - * hygiene.ml: . - * ocaml_specific.ml: . - * pathname.ml: . - * pathname.mli: . - * resource.ml: . - -2006-12-20 Nicolas Pouillard - - Some changes mainly for windows support. - - * command.ml, - * command.mli: Add the Quote constructor to help quoting building in - commands. - * my_unix_with_unix.ml, - * my_unix_without_unix.ml, - * glob.ml: Commented reslash mode. - * my_std.ml, - * my_std.mli: Some new functions. - * my_unix.mli: Export sys_command. - * ocaml_specific.ml, - * ocaml_specific.mli: Update and windows support. - * options.ml, - * options.mli: Remove the ocamlmklib option. - * ppcache.ml: Fix a bug. - * pathname.ml: Add more dirseps. Use a custom Filename.concat (for now). - * resource.ml, - * rule.ml, - * Makefile, - * _tags: Update. - -2006-12-15 Nicolas Pouillard - - Update start order. - - * start.sh: Ditto. - -2006-12-11 Berke Durak - - Added -custom, fixed paths for installation. - - * ocaml_specific.ml: . - * Makefile: . - -2006-12-11 Berke Durak - - Typo. - - * report.ml: . - -2006-12-08 Nicolas Pouillard - - Add a basic ocamlmklib support. - - * ocaml_specific.ml, - * ocaml_specific.mli: Use ocamlmklib to make libraries if enabled. - * options.ml, - * options.mli: Add -ocamlmklib and -use-ocamlmklib. - -2006-12-08 Nicolas Pouillard - - Export more references of options. - - * command.ml, - * command.mli: Add ?quiet to execute. - * ocaml_specific.ml, - * ocaml_specific.mli: Update to options. - * options.ml, - * options.mli: Move ocamlc, ocamlopt... to references on command specs. - * solver.ml: Update. - * Makefile: Use _ocamldistr to avoid hygiene. - * .vcs: Use _ocamldistr. - -2006-12-08 Nicolas Pouillard - - OCaml distrib stuffs. - - * command.ml, - * command.mli: Add a normalization callback. - * ocaml_specific.ml, - * ocaml_specific.mli: Add a more complete interface. - * options.ml, - * options.mli: Add nostdlib. - * pathname.ml: Add mkdir -p to import in build. - * rule.ml, - * rule.mli: Call normalization of commands for digest. - * report.ml: Add ignore. - * start.sh: Add report.ml*. - * Makefile: Add distrib exportation (make a link). - * .vcs: Unmask ocamldistrib link. - -2006-12-07 Berke Durak - - Added TODO item. - - * .vcs: . - * TODO: . - -2006-12-07 Berke Durak - - Added TODO file. - - * TODO: New. - -2006-12-07 Berke Durak - - Very rudimentary report analysis. - - * report.ml: . - * _tags: . - -2006-12-07 Nicolas Pouillard - - Update tests to run ocamlbuild correctly. - - * test/test2/test.sh, - * test/test3/test.sh, - * test/test4/test.sh, - * test/test5/test.sh, - * test/test6/test.sh, - * test/test7/test.sh, - * test/test8/test.sh, - * test/test9/test.sh: Ditto. - * test/good-output: Update. - -2006-12-07 Nicolas Pouillard - - Make test9 independant. - - * test/test9/test.sh: Ditto. - -2006-12-07 Berke Durak - - Rewrote globbing engine, adding {,} ; moved reporting functions to Report. - - * ocamlbuild_pack.mlpack: . - * command.ml: . - * glob_ast.ml: . - * glob.ml: . - * glob_ast.mli: . - * glob_lexer.mll: . - * ocaml_specific.ml: . - * report.ml: New. - * report.mli: New. - * solver.ml: . - * solver.mli: . - * start.sh: . - * test/test9/testglob.ml: . - * test/test9/test.sh: . - * test/test3/test.sh: . - * _tags: . - -2006-12-07 Nicolas Pouillard - - Degraded mode... - - * ocamlbuildlight.ml: New. - * ocamlbuild_pack.mlpack: Include new modules. - * bool.ml: Fake dependency. - * configuration.ml: Adapt to the glob parser. - * command.ml: Export the fork usage. - * glob.ml: Use Str through My_unix. - * glob_lexer.mli: New. - * glob_lexer.mll: Add slashs to valid character patterns. - * lexers.mli, - * lexers.mll: Use the glob parser. - * my_std.ml: Use My_unix. - * my_unix_with_unix.ml: New. - * my_unix_without_unix.ml: New. - * my_unix.mli: New. - * my_std.mli: Add search_in_path and change lazy force to ( !* ). - * ocaml_specific.ml: Some updates. - * options.ml, - * options.mli: Add -ocamlrun. - * pathname.ml: Adapt to an optional slurp. - * ppcache.ml: Use search_in_path of my_std. - * resource.ml: Update to ( !* ). - * solver.ml: Export Unix errors reporting. - * slurp.ml, - * slurp.mli: Use My_unix. - * start.sh: Update. - * test/test9/testglob.ml: Test a constant. - * test/test5/_tags, - * test/test3/_tags, - * test/test4/_tags: Don't use regexp. - * test/good-output: Add test9. - * test/test9/test.sh: Remove the parent usage. - * Makefile: Add the light mode. - * .vcs: Update. - * _tags: Update. - -2006-12-06 Berke Durak - - Extra tests for globbing. - - * test/test9/testglob.ml: . - -2006-12-06 Berke Durak - - First draft of pattern matching. - - * glob_ast.ml: . - * glob.ml: . - * glob_ast.mli: . - * glob_lexer.mll: . - -2006-12-06 Berke Durak - - More hard-wired but common cases for globbing. - - * glob.ml: . - * test/test9/testglob.ml: . - -2006-12-06 Berke Durak - - Hidden interface in globber. - - * glob.mli: . - * test/test9/testglob.ml: . - -2006-12-06 Berke Durak - - Basic globbing works. - - * glob.ml: . - * glob.mli: . - * test/test9/testglob.ml: . - -2006-12-06 Berke Durak - - Improved interface. - - * glob.ml: . - * glob_ast.ml: New. - * glob_ast.mli: New. - * glob.mli: New. - * glob_lexer.mll: . - * test/test9/testglob.ml: . - * _tags: . - -2006-12-06 Berke Durak - - Added test9. - - * test/test9/testglob.ml: New. - * test/test9/parent: New. - * test/runtest.sh: . - * test/test9: New. - * test/test9/test.sh: New. - -2006-12-06 Berke Durak - - Parser seems to work. - - * glob.ml: . - * glob_lexer.mll: . - -2006-12-06 Berke Durak - - Removed eof_char. - - * glob.ml: . - * glob_lexer.mll: . - -2006-12-06 Berke Durak - - Interface seems to be OK. - - * glob.ml: . - * glob_lexer.mll: . - -2006-12-06 Berke Durak - - Adding files for the globbing module. - - * bool.ml: New. - * bool.mli: New. - * glob.ml: New. - * glob_lexer.mll: New. - * _tags: . - -2006-12-06 Berke Durak - - Replaced numeric escapes. - - * lexers.mll: . - -2006-12-05 Nicolas Pouillard - - Remove most of the Str usage by using ocamllex. - - * ocamlbuild_pack.mlpack: Remove Re, add Lexers. - * configuration.ml: Use Lexers. - * command.ml: Don't use Re. - * lexers.mli: New. - * lexers.mll: New. - * my_std.ml, - * my_std.mli: Add String.before and String.after. - * ocaml_specific.ml, - * ocaml_specific.mli: Use Lexers but also provide tags for warnings. - * resource.ml, - * rule.ml, - * options.ml, - * ppcache.ml, - * pathname.ml: Use Lexers. - * re.ml: Remove. - * re.mli: Remove. - * start.sh: Update. - * Makefile: Igonre _build... and gives -ml to ocamllex. - * _tags: Warnings for lexers. - -2006-12-05 Nicolas Pouillard - - Use Sys instead of Unix for readdir. - - * my_std.ml, - * my_std.mli: Supress a Unix usage. - -2006-12-05 Nicolas Pouillard - - Add an option to disable the link creation. - - * ocaml_specific.ml: Honor this option. - * options.ml: Declare it. - * options.mli: Define it. - -2006-12-05 Nicolas Pouillard - - Don't import compiled files... - - * pathname.ml: For the OCaml compilation itself I need to exclude some - dirs that contains compiled files but I want to use some of them with - ocamlbuild. - -2006-12-05 Nicolas Pouillard - - Support flags for ocamlyacc and ocamllex. - - * ocaml_specific.ml, - * options.ml, - * options.mli: Add these options. - -2006-12-04 Nicolas Pouillard - - Two fixes (hygiene and libraries)... - - * hygiene.ml: Exit 0 if sterilize removes some files (since source - files are cached in a rather persistent data structure I prefer let the - user start on a fresh setup). - * ocaml_specific.ml: Use the dirname if there is no directory named by - removing the extension. - -2006-12-04 Berke Durak - - Small bug in hygiene. - - * hygiene.ml: . - -2006-12-04 Nicolas Pouillard - - Add postition specifications to rules. - - * rule.ml, - * rule.mli: Add a way to specifie where to put a new rule - (top,bottom,before another,after another). - * flags.ml: Reorder. - * my_std.ml, - * my_std.mli: Add mv, fix an error handling. - * ocaml_specific.ml: Better error message for circular dependencies. - * ppcache.ml: Handle errors better. - -2006-11-29 Nicolas Pouillard - - Add a working multiple job support. - - * command.ml, - * command.mli: Add different versions of execute_many including a - version that use forks. - * options.ml, - * options.mli: Restore the -j option. - * solver.ml: Call Command.execute_many. - * test/runtest.sh: Pass $@ to sub tests. - * test/good-output: Update. - -2006-11-28 Nicolas Pouillard - - Fix the link order. - - * start.sh: Fix the link order. - -2006-11-28 Nicolas Pouillard - - One step toward multiple jobs: Add the support for suspended building. - - * resource.ml, - * resource.mli: Add the notion of suspended building. - This represent a resource that is fully ready for evaluation, it's just - a command and a function to apply after. - * rule.ml: Do not really execute rules that can be safely suspended. - * solver.ml: Play with suspended rules to collect as many as possible - to get closer to a pararllel execution. - -2006-11-27 Nicolas Pouillard - - Fix the makefile. - - * Makefile: Fix deps. - -2006-11-27 Nicolas Pouillard - - Activates more warnings, and prepare the -j feature. - - * hygiene.ml: Consolidates fragile patterns. - * my_std.ml: Likewise. - * ocaml_specific.ml: Mainly update to the new builder prototype. - * pathname.ml, - * pathname.mli: Kick a useless parameter. - * resource.ml: Remove dead code and update. - * rule.ml, - * rule.mli: The bulider now takes a list of resource lists, it will - try to make in parallel the first level of commands. - * solver.ml: Update to builder without parallelism. - * test/good-output: Update. - * Makefile: Warnings are now set to -w A -warn-error A. - -2006-11-26 Nicolas Pouillard - - Fix packages... again. - - * ocaml_specific.ml: Ditto. - -2006-11-26 Nicolas Pouillard - - Fix packages. - - * ocaml_specific.ml: Try to handle better packages during link. - * Makefile: Add the try_bootstrap rule. - -2006-11-26 Nicolas Pouillard - - Add -tag, -tags to options. - - * ocaml_specific.ml: Append default tags from options. - * options.ml, - * options.mli: Add -tag and -tags. - * tags.mli: Indent. - -2006-11-26 Nicolas Pouillard - - Fix a bug and update tests. - - * resource.ml: Use Hashtbl.replace of course instead of Hashtbl.add to - avoid a nasty bug. - * test/test7/test.sh, - * test/test8/test.sh, - * test/test2/test.sh, - * test/test6/test.sh, - * test/test4/test.sh, - * test/test5/test.sh, - * test/test3/test.sh: Extract program options to be sure that - the -nothing-should-be-rebuilt option is before the -- one. - * test/good-output: Update. - -2006-11-26 Nicolas Pouillard - - Use a hashtbl for digests. - - * resource.ml: Ditto. - * ocaml_specific.ml: Remove dead code. - -2006-11-26 Nicolas Pouillard - - Use lists instead of sets for rule deps & prods. - - * ocaml_specific.ml: Move the mli dep first. - * resource.ml, - * resource.mli: No more provide digest_resources but digest_resource. - * rule.ml, - * rule.mli: Use list instead of sets for deps and prods, since they are - not heavily updated and the order matter. - * solver.ml: Adapt. - * test/good-output: Yeah! - -2006-11-26 Nicolas Pouillard - - One more fix for libraries. - - * ocaml_specific.ml: Improve the link_exception handling. - * test/good-output: Update. - -2006-11-25 Nicolas Pouillard - - Fix the library linking. - - * ocaml_specific.ml: The test7 is specially made to check that feature. - -2006-11-25 Nicolas Pouillard - - Remove list_set. - - * ocamlbuild_pack.mlpack: Remove list_set - * list_set.ml: Remove. - * list_set.mli: Remove. - * start.sh: Remove list_set. - * test/good-output: Regen. - -2006-11-25 Nicolas Pouillard - - Fix the C rule when dirname = '.'. - - * ocaml_specific.ml: Don't move the output when it's useless. - -2006-11-25 Nicolas Pouillard - - Ignore ocamlbuild_version.ml. - -2006-11-25 Nicolas Pouillard - - New transitive closure. - - * ocamlbuild_version.ml: Remove. - * my_std.ml, - * my_std.mli: Add a debug mode for digests and run_and_read. - * ocaml_specific.ml: New transitive closure. - * pathname.ml, - * pathname.mli: Export also parent_dir_name and fix same_contents. - * resource.ml, - * resource.mli: Add dependencies. - * rule.ml: Adapt. - * test/good-output: Regen. - * Makefile: Improve install. - * .vcs: Ignore other _build dirs. - -2006-11-20 Nicolas Pouillard - - Rule definition shortcut and C files. - - * rule.ml, - * rule.mli: Allow to pass ~prod and ~dep when there is just one file. - * ocaml_specific.ml: Add a rule for C files and use the previous - shortcut. - -2006-11-18 Nicolas Pouillard - - No more extend Format. - - * command.ml, - * my_std.ml, - * my_std.mli: Put directly ksbprintf and sbprintf in My_std. - -2006-11-18 Nicolas Pouillard - - Clean up and consistent use of Pathname instead of Filename. - - * command.ml, - * my_std.ml, - * my_std.mli, - * ocaml_specific.ml, - * pathname.ml, - * ppcache.ml, - * pathname.mli, - * resource.ml: That's it. - -2006-11-18 Nicolas Pouillard - - Restore List_set. - - * ocamlbuild_pack.mlpack, - * list_set.ml, - * list_set.mli, - * resource.ml, - * start.sh: Ditto. - -2006-11-18 Nicolas Pouillard - - Remove List_set and List_map. - - * ocamlbuild_pack.mlpack: No more in the pack. - * list_set.ml: Remove. - * list_map.ml: Remove. - * list_map.mli: Remove. - * list_set.mli: Remove. - * resource.ml: Use a Set. - * start.sh: Adapt. - -2006-11-18 Nicolas Pouillard - - Huge speed up, worth updating. - - * resource.ml, - * resource.mli: Use a hash instead of map, remove the percent type. - * rule.ml, - * rule.mli: Remove the function for rule names. Use an exception to - choose matching rules. - -2006-11-18 Nicolas Pouillard - - Speedup rule calling. - - * rule.ml, - * rule.mli: No more call the code rule twice to compute the digest. - * ocaml_specific.ml, - * ocaml_specific.mli: Adapt to Rule. - * test/test8/myocamlbuild.ml: Use the exception. - * test/good-output: Update. - * boot: Update svn:ignore. - -2006-11-16 Nicolas Pouillard - - Remove phony resources and include dependencies. - - * ocaml_specific.ml, - * options.ml, - * options.mli, - * pathname.ml, - * pathname.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * solver.ml, - * test/test8/myocamlbuild.ml: Simplify a lot the code. - -2006-11-16 Nicolas Pouillard - - Some improvements... - - * ocamlbuild.ml: . - * ocamlbuild_version.ml: New. - * ocamlbuild_plugin.ml: New. - * ocamlbuild_version.mli: New. - * ocamlbuildlib.mllib: . - * ocamlbuild.sh: Remove. - * ocamlbuild_pack.mlpack: New. - * boot: . - * ocaml_specific.ml: . - * ocaml_specific.mli: . - * options.ml: . - * options.mli: . - * rule.ml: . - * rule.mli: . - * start.sh: . - * test/test8/a.ml: New. - * test/test7/a2.ml: . - * test/test7/a3.ml: New. - * test/test8/myocamlbuild.ml: New. - * test/test7/myocamlbuild.ml: New. - * test/test8: New. - * test/test8/test.sh: New. - * test/runtest.sh: . - * test/test7/test.sh: . - * test/good-output: . - * Makefile: . - * _tags: . - -2006-11-15 Nicolas Pouillard - - Add support for libraries. - - * ocamlbuildlib.ml: Remove. - * ocamlbuildlib.mllib: New. - * ocaml_specific.ml: Rules and actions for libraries. - * rule.ml: Improve explanations. - * start.sh: Don't make ocamlbuildlib. - * test/test7/a.mli: New. - * test/runtest.sh: Add test7. - * test/test7/test.sh: Add reverts for a.ml. - * test/good-output: Update. - * Makefile: Remove junk lines. - -2006-11-14 Nicolas Pouillard - - Add a tests for libraries. - - * test/test7/e.ml: New. - * test/test7/d.ml: New. - * test/test7/a.ml: New. - * test/test7/b.ml: New. - * test/test7/a2.ml: New. - * test/test7/c.ml: New. - * test/test7/test.sh: New. - * test/test7/ablib.mllib: New. - * test/test7: New. - -2006-11-14 Nicolas Pouillard - - Simplify dependency rules. - - * ocaml_specific.ml: No more use bytelinkdeps... - * rule.ml, - * rule.mli: Add a dyndeps set. - * ocamlbuild.sh, - * pathname.ml, - * Makefile: Update. - -2006-11-14 Nicolas Pouillard - - Update tests... - - * test/test2/vivi3.ml: . - * test/good-output: . - -2006-11-10 Berke Durak - - Added -sterilize option. - - * hygiene.ml: ditto - * hygiene.mli: ditto - * ocaml_specific.ml: ditto - * options.ml: ditto - * options.mli: ditto - -2006-11-10 Nicolas Pouillard - - View the context dir in first. - - * pathname.ml: Ditto. - -2006-11-10 Berke Durak - - Added thread and profile tags. - - * ocaml_specific.ml: ditto. - -2006-11-10 Berke Durak - - Added law for leftover dependency files. - - * ocaml_specific.ml: ditto. - -2006-11-10 Nicolas Pouillard - - Reverse the ignore_auto default value. - - * options.ml: Add -no-skip, remove -ignore-auto, add -Is and -Xs. - * test/test2/test.sh, - * test/test5/test.sh, - * test/test6/test.sh, - * test/test4/test.sh, - * test/test3/test.sh, - * Makefile: Revert flags. - -2006-11-10 Berke Durak - - Added install target to Makefile. - - * Makefile: . - -2006-11-10 Nicolas Pouillard - - Deal with for-pack flags... - - * ocaml_arch.ml: Define a hook. - * ocaml_arch.mli: Declare it. - * ocaml_specific.ml: Use it. - * test/test6: Ignore main.byte. - -2006-11-09 Nicolas Pouillard - - Fix start.sh and remove dead code. - - * ocaml_specific.ml: Remove dead code about ignore_auto. - * start.sh: Swap two modules. - * test/test6/main.byte: Remove. - -2006-11-09 Nicolas Pouillard - - Pack now works great... - - * ocamlbuild.sh: Use ocamlopt. - * command.ml: Reset filesys cache. - * my_std.ml, - * my_std.mli: Add a filesys cache for - case sensitive file_exists and digest over files. - * ocaml_specific.ml: Work on link and packs. - * ppcache.ml: Exit 2 is for unix. - * pathname.ml, - * resource.ml, - * rule.ml, - * rule.mli, - * slurp.ml, - * solver.ml, - * solver.mli, - * test/test5: Update. - -2006-11-07 Nicolas Pouillard - - Too lazy to fill this up :). - - * ocamlbuild.sh, - * configuration.ml, - * command.ml, - * debug.ml, - * debug.mli, - * my_std.ml, - * my_std.mli, - * ocaml_specific.ml, - * ocaml_specific.mli, - * options.ml, - * options.mli, - * pathname.ml, - * ppcache.ml,ew. - * ppcache.mli,ew. - * pathname.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * slurp.ml, - * solver.ml, - * solver.mli, - * slurp.mli, - * start.sh, - * tags.ml, - * test/test5/test.sh, - * test/test4/test.sh, - * test/test3/test.sh, - * test/good-output, - * test/test2/test.sh, - * test/test6/test.sh, - * Makefile, - * _tags: This too. - -2006-11-04 Nicolas Pouillard - - Some pack,dirs stuffs. - - * ocamlbuild.ml, - * ocamlbuildlib.ml,ew. - * ocamlbuild.sh,ew. - * configuration.ml, - * my_std.ml, - * my_std.mli, - * ocaml_arch.ml,ew. - * ocaml_specific.ml, - * ocaml_specific.mli, - * ocaml_arch.mli,ew. - * options.ml, - * options.mli, - * pathname.ml, - * pathname.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * solver.ml, - * test/good-output, - * Makefile, - * _tags: That's it. - -2006-10-31 Nicolas Pouillard - - Remove the dirty thing about cmi's. - - * ocaml_specific.ml, - * ocaml_specific.mli: Moves of files are no more needed. - * test/good-output: Update. - -2006-10-31 Nicolas Pouillard - - Some renaming and cleanup... - - * ocamlbuild.ml, - * configuration.ml, - * configuration.mli, - * list_set.ml, - * ocaml_specific.ml, - * resource.ml, - * test/good-output, - * test/test6/test.sh: Do that. - -2006-10-31 Nicolas Pouillard - - Use the nothing-should-be-rebuilt for tests and update the output. - - * test/test2, - * test/test2/test.sh, - * test/test3/test.sh, - * test/test4/test.sh, - * test/test5/test.sh, - * test/test6/test.sh, - * test/good-output: Do that. - -2006-10-31 Nicolas Pouillard - - Add a mode usefull for tests. - - * options.ml, options.mli, rule.ml: - This new mode fails when something needs to be rebuilt. - -2006-10-31 Nicolas Pouillard - - Improve the ocaml rule set. - - * ocaml_specific.ml: Yipee! - -2006-10-31 Nicolas Pouillard - - Add scripts to run tests. - - * test/test2/vivi1.ml: New. - * test/test2/vivi2.ml: New. - * test/test2/vivi3.ml: New. - * test/test2/vivi.ml: . - * test/test4/test.sh: New. - * test/test5/test.sh: New. - * test/test2/test.sh: New. - * test/test6/test.sh: . - * test/good-output: New. - * test/test3/test.sh: New. - * test/runtest.sh: New. - -2006-10-31 Nicolas Pouillard - - Restore some recursivity for includes. - - * resource.ml, - * resource.mli: Remove the digest field. - * rule.ml: . - * test/test6/test.sh: . - -2006-10-30 Nicolas Pouillard - - Remove the arbitrary deep dependencies. - - * ocaml_specific.ml, - * ocaml_specific.mli: No more implicit transitives deps. - * resource.ml, - * resource.mli: Remove as many things as possible. - * rule.ml, - * rule.mli, - * solver.ml: Simplify. - * command.ml: Fix newlines and flush. - -2006-10-30 Nicolas Pouillard - - Separated preprocessing, total order over rules... - - * ocamlbuild.ml, - * my_std.ml, - * my_std.mli, - * ocaml_specific.ml, - * ocaml_specific.mli, - * options.ml, - * options.mli, - * pathname.ml, - * pathname.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * solver.ml, - * test/test2/tutu.ml, - * tags.ml, - * test/test2/tyty.mli,ew. - * test/test6/test.sh, - * test/test6, - * test/test5/_tags, - * test/test5: Update. - -2006-10-27 Nicolas Pouillard - - Add options: -ocamlc,-ocamlopt,-ocamldep,-ocamlyacc,-ocamllex. - - * options.ml, - * options.mli: Declare them. - * ocaml_specific.ml: Use them. - -2006-10-27 Nicolas Pouillard - - Fix start.sh. - - * start.sh: Fix the output. - -2006-10-27 Nicolas Pouillard - - Regen start.sh. - - * start.sh: Regen. - -2006-10-27 Nicolas Pouillard - - Use the list based implems and fix many bugs. - - * ocamlbuild.ml: Rename some dependency files. - * boot: Ignore boot/ocamlbuild.byte.save.* files. - * command.ml: Fix command printing. - * my_std.ml, - * my_std.mli: Add List.equal, use the cp command in Shell.cp. - * ocaml_specific.ml, - * ocaml_specific.mli: Many things. - * pathname.ml, pathname.mli: Make compare obselete prefer equal. - * resource.ml, resource.mli: Add print_cache and use list based - sets and maps. - * Makefile: Add the bootstrap rule. - -2006-10-27 Nicolas Pouillard - - Add a test for fine-grained dependencies. - - * test/test6/main.ml: New. - * test/test6/d.ml: New. - * test/test6/b.ml: New. - * test/test6/a.ml: New. - * test/test6/main.mli: New. - * test/test6/a.mli: New. - * test/test6/d.mli: New. - * test/test6/b.mli: New. - * test/test6/b.mli.v2: New. - * test/test6/main.byte: New. - * test/test6/d.mli.v1: New. - * test/test6/test.sh: New. - * test/test6/d.mli.v2: New. - * test/test6/b.mli.v1: New. - * test/test6: New. - -2006-10-26 Nicolas Pouillard - - Dummy implementations for set and map using lists. - The main advantage is to only rely on the equal function that is simpler - to maintain correct in an imperative setting. - - * list_map.ml: New. - * list_set.ml: New. - * list_map.mli: New. - * list_set.mli: New. - -2006-10-24 Nicolas Pouillard - - Fixes and improvment. - - * ocamlbuild.ml, - * my_std.ml, - * my_std.mli, - * ocaml_specific.ml, - * ocaml_specific.mli, - * pathname.ml, - * resource.ml, - * rule.ml, - * rule.mli, - * solver.ml, - * solver.mli: The previous version was somwhat unstable. - -2006-10-24 Nicolas Pouillard - - Many things... - - * ocamlbuild.ml, - * command.ml, - * command.mli, - * ocaml_specific.ml, - * ocaml_specific.mli, - * options.ml, - * options.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * solver.ml, - * solver.mli: - Simplify the whole solver by removing the value type. - Rule code now returns a resource set, that is injected as dependencies. - So rule code always returns unit. But can raise exceptions. - Add -ignore, and -ignore-auto options to workaround ocamldep - approximations without igonring errors. - * Makefile: Add backup and restore targets. - -2006-10-23 Nicolas Pouillard - - Compute digests of dependencies recursively. - - * ocamlbuild.ml, - * ocaml_specific.ml, - * options.ml, - * options.mli, - * resource.ml, - * resource.mli, - * rule.ml: Ditto. - -2006-10-23 Nicolas Pouillard - - One step toward a parallelisable system. - - * boot, - * command.ml, - * ocaml_specific.ml, - * ocaml_specific.mli, - * options.ml, - * options.mli, - * rule.ml, - * rule.mli, - * solver.ml: Update. - * value.ml: Remove. - * value.mli: Remove. - -2006-10-20 Nicolas Pouillard - - Add vcs config file to setup a good default setup. - - * .vcs: New. - -2006-10-20 Nicolas Pouillard - - Simplify the bootstrap by introducing a shell script. - - * boot/ocamlbuild.byte: Remove. Useless in distribution mode - but will be created, the first time. So the devel is not - disturbed. - * start.sh: New. - * Makefile: Remove the old one to use start.sh. - -2006-10-20 Nicolas Pouillard - - Take command line in account for the digest computation. - - * command.ml, - * command.mli, - * debug.ml, - * ocaml_specific.ml, - * ocaml_specific.mli, - * resource.ml, - * resource.mli, - * rule.ml, - * rule.mli, - * solver.ml, - * value.ml, - * value.mli: Update. - -2006-10-19 Nicolas Pouillard - - New pathname representation. - - * pathname.ml, pathname.mli: This new representation should - avoids "fix" problems. - -2006-10-17 Nicolas Pouillard - - Change the cache implem -> now really fast at link time. - - * ocamlbuild.ml, - * boot/ocamlbuild.byte, - * my_std.ml, - * ocaml_specific.ml, - * pathname.ml, - * resource.ml, - * resource.mli, - * solver.ml: By replacing various sets by a map of records and - remember that something has not changed, or cannot be built; - there is a real speedup. In particular to detect that the link is - not necessary to do. - -2006-10-17 Nicolas Pouillard - - Add a basic support for a digest based cache verification. - - * resource.ml, resource.mli: Add have_digest and store_digest. - * rule.ml: Use these digests but don't include the command for - now. - * test/test2/vivi.ml, test/test2/tata.mli: Dummy updates. - -2006-10-16 Nicolas Pouillard - - Split in many files. - - * ocamlbuild.ml: Splitted. - * boot/ocamlbuild.byte: Updated. - * configuration.ml: New. - * configuration.mli: New. - * command.ml: New. - * command.mli: New. - * debug.ml: New. - * debug.mli: New. - * flags.ml: New. - * flags.mli: New. - * my_std.ml: New. - * my_std.mli: New. - * ocaml_specific.ml: New. - * ocaml_specific.mli: New. - * options.ml: New. - * options.mli: New. - * pathname.ml: New. - * pathname.mli: New. - * re.ml: New. - * re.mli: New. - * resource.ml: New. - * resource.mli: New. - * rule.ml: New. - * rule.mli: New. - * solver.ml: New. - * solver.mli: New. - * test/test5/d.ml: New. - * tags.ml: New. - * test/test5/b.ml: New. - * test/test5/a.ml: New. - * tags.mli: New. - * test/test5/a.mli: New. - * test/test5/c.mlpack: New. - * test/test5/_tags: New. - * test/test5: New. - * value.ml: New. - * value.mli: New. - * Makefile: . - -2006-10-16 Berke Durak - - Various useful changes. - - * ocamlbuild.ml: Hygiene to true. - * slurp.ml: Remove debugging - * Makefile: Clean annot and object files. - -2006-10-15 Nicolas Pouillard - - Bootstrap it ;). - - * ocamlbuild.ml: Add support for -g, -dtypes, and -rectypes in - four lines. - * _tags: New. Specify how to build ocamlbuild itself. - * boot: New. - * boot/ocamlbuild.byte: New. A bytecode version needed to - bootstrap - * Makefile: By default make it a wrapper over ocamlbuild in boot. - -2006-10-15 Nicolas Pouillard - - Little fix... - - * ocamlbuild.ml: Don't assoc over pathnames since the default - compare is wrong and slow use the string repr. - -2006-10-15 Nicolas Pouillard - - Allow to control flags, and libraries by tags. - - * ocamlbuild.ml: In the _tags file you can add or remove flags - using a colon flag_name:flag_value. - * test/test2/vivi.ml, - * test/test3/f.ml, - * test/test4/b/bb.ml: Dummy updates. - * test/test3/_tags: New. - * test/test4/_tags: New. - -2006-10-15 Nicolas Pouillard - - Add a tag based flag system. - - * test/test2/vivi.ml: An example. - * test/test2/_tags: New. - * ocamlbuild.ml: Now a command can request for flags by giving a - set of tags these tags include file specific tags this allow to - tweak flags by just providing a _tags file. - -2006-10-15 Nicolas Pouillard - - Add -lib,-libs options remove -P. - - * ocamlbuild.ml: -P Is useless due to the fact that we now - have the same directory structure in the _build directory. - Add -lib,-libs that allows one to specify -lib unix without - its extension in order to request for native and byte - compilations. - -2006-10-15 Nicolas Pouillard - - Multi directories now works ;). - - * ocamlbuild.ml: Solve the whole problem by improving the - Pathname module. Pathnames are now symbolic values that - can include variable names. These variable names represent - still ambiguous pathnames /a/b/(c|d as x1)/e.ml but variables - can be shared, so discovering that /a/b/(c|d as x1)/e.ml is in - fact /a/b/c/e.ml will make /a/b/(c|d as x1)/e.cmo automatically - take this value /a/b/c/e.cmo cause it shares the x1 variable. - -2006-10-13 Nicolas Pouillard - - I prefer capitalized names. - - * AUTHORS - -2006-10-13 Berke Durak - - Added an AUTHORS file. - - * AUTHORS: New. - -2006-10-13 Nicolas Pouillard - - Add the vcs dir. - - * vcs: New. - * vcs/ocamlbuild.rb: New. - -2006-10-13 Nicolas Pouillard - - * ocamlbuild.ml: Restore dependencies. - -2006-10-13 Nicolas Pouillard - - Fix the makefile. - - * Makefile, discard_printf.ml: Ditto. - -2006-10-13 Nicolas Pouillard - - Improve the directory handling. - - * ocamlbuild.ml: Ditto, but there is still a problem with native. - * Makefile: Update. - -2006-10-11 Nicolas Pouillard - - Fix native dependencies. - - * ocamlbuild.ml: By default due to inlining the cmx dependencies - are needed to build a cmx. - * Makefile: Add native support. - -2006-10-11 Nicolas Pouillard - - Use phony for linkdeps. - - * ocamlbuild.ml: Ditto. - -2006-10-11 Nicolas Pouillard - - Fix exit on multiple targets. - - * ocamlbuild.ml: Ditto. - -2006-10-11 Nicolas Pouillard - - More flags -lflags,-lflag... - - * ocamlbuild.ml: Add plrual form options for those that use - comma separated lists. - -2006-10-11 Nicolas Pouillard - - Use phony resources for .cmo.linkdeps. - - * ocamlbuild.ml: Also restore the command running if "--" - is specified - -2006-10-11 Nicolas Pouillard - - Remove Include_string_list resources, add Phony resources. - - * ocamlbuild.ml: Also fix some rules. - -2006-10-11 Nicolas Pouillard - - Shift debug levels. - - * ocamlbuild.ml: Add -quiet. - -2006-10-11 Nicolas Pouillard - - Use str more intensively. - - * ocamlbuild.ml: Also clean up useless functions. - -2006-10-11 Nicolas Pouillard - - Fix link dependencies. - - * ocamlbuild.ml: Force to consider recursivly Include_ tagged - resources for their full contents. Alas it takes more time to - know if we need to recompute the link. - * test/test2/vivi.ml: Update. - -2006-10-10 Nicolas Pouillard - - Support multiple directories, it can compile the OCaml compiler :). - - * ocamlbuild.ml: Add directory handling but also start - the tags config files handling. - * Makefile: Use str.cma. - -2006-10-08 Nicolas Pouillard - - Add library support. - - * ocamlbuild.ml: Deduce basic set of tags form the target - extension. - -2006-10-08 Nicolas Pouillard - - More customisable flags, and cycle detection. - - * ocamlbuild.ml: Add some flags -lflag, -ppflag, -cflag, --. - Also add a detection mechanism for dependencies. - * discard_printf.ml, Makefile: Update. diff --git a/ocamlbuild/FAQ b/ocamlbuild/FAQ deleted file mode 100644 index b71516b9..00000000 --- a/ocamlbuild/FAQ +++ /dev/null @@ -1,35 +0,0 @@ -Q: I've a directory with examples and I want build all of them easily? - -R: - - You can use an .itarget file listing all products that you want. - - $ cat examples.itarget - examples/a.byte - examples/b.byte - - $ ocamlbuild examples.otarget - - You can also have a dynamic rule that read the examples directory: - - $ cat myocamlbuild.ml - open Ocamlbuild_plugin;; - - dispatch begin function - | After_rules -> - let examples = - Array.fold_right begin fun f acc -> - if Pathname.get_extension f = "ml" then - ("examples" / Pathname.update_extension "byte" f) :: acc - else - acc - end (Pathname.readdir "examples") [] - in - rule "All examples" - ~prod:"examples.otarget" - ~deps:examples - (fun _ _ -> Command.Nop) - | _ -> () - end - - $ ocamlbuild examples.otarget diff --git a/ocamlbuild/Makefile b/ocamlbuild/Makefile deleted file mode 100644 index d302d206..00000000 --- a/ocamlbuild/Makefile +++ /dev/null @@ -1,213 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2007 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. # -# # -######################################################################### - -include ../config/Makefile -CAMLRUN ?= ../boot/ocamlrun -CAMLYACC ?= ../boot/ocamlyacc - -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 -CP = cp -COMPFLAGS= -warn-error A -w L -w R -w Z -I ../otherlibs/$(UNIXLIB) -safe-string -LINKFLAGS= -I ../otherlibs/$(UNIXLIB) - -PACK_CMO=\ - const.cmo \ - loc.cmo \ - discard_printf.cmo \ - signatures.cmi \ - my_std.cmo \ - my_unix.cmo \ - tags.cmo \ - display.cmo \ - log.cmo \ - shell.cmo \ - bool.cmo \ - glob_ast.cmo \ - glob_lexer.cmo \ - glob.cmo \ - lexers.cmo \ - param_tags.cmo \ - command.cmo \ - ocamlbuild_config.cmo \ - ocamlbuild_where.cmo \ - slurp.cmo \ - options.cmo \ - pathname.cmo \ - configuration.cmo \ - flags.cmo \ - hygiene.cmo \ - digest_cache.cmo \ - resource.cmo \ - rule.cmo \ - solver.cmo \ - report.cmo \ - tools.cmo \ - fda.cmo \ - findlib.cmo \ - ocaml_arch.cmo \ - ocaml_utils.cmo \ - ocaml_dependencies.cmo \ - ocaml_compiler.cmo \ - ocaml_tools.cmo \ - ocaml_specific.cmo \ - plugin.cmo \ - exit_codes.cmo \ - hooks.cmo \ - main.cmo - -EXTRA_CMO=\ - ocamlbuild_plugin.cmo \ - ocamlbuild_executor.cmo \ - ocamlbuild_unix_plugin.cmo - -PACK_CMX=$(PACK_CMO:.cmo=.cmx) -EXTRA_CMX=$(EXTRA_CMO:.cmo=.cmx) -EXTRA_CMI=$(EXTRA_CMO:.cmo=.cmi) - -INSTALL_LIB=\ - ocamlbuildlib.cma \ - ocamlbuild.cmo \ - ocamlbuild_pack.cmi \ - $(EXTRA_CMO:.cmo=.cmi) - -INSTALL_LIB_OPT=\ - ocamlbuildlib.cmxa ocamlbuildlib.$(A) \ - ocamlbuild.cmx ocamlbuild.$(O) \ - ocamlbuild_pack.cmx \ - $(EXTRA_CMO:.cmo=.cmx) $(EXTRA_CMO:.cmo=.$(O)) - -INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR)/ocamlbuild -INSTALL_BINDIR=$(DESTDIR)$(BINDIR) - -all: ocamlbuild.byte ocamlbuildlib.cma - # ocamlbuildlight.byte ocamlbuildlightlib.cma -allopt: ocamlbuild.native ocamlbuildlib.cmxa - -# The executables - -ocamlbuild.byte: ocamlbuild_pack.cmo $(EXTRA_CMO) ocamlbuild.cmo - $(OCAMLC) $(LINKFLAGS) -o ocamlbuild.byte \ - unix.cma ocamlbuild_pack.cmo $(EXTRA_CMO) ocamlbuild.cmo - -ocamlbuildlight.byte: ocamlbuild_pack.cmo ocamlbuildlight.cmo - $(OCAMLC) $(LINKFLAGS) -o ocamlbuildlight.byte \ - ocamlbuild_pack.cmo ocamlbuildlight.cmo - -ocamlbuild.native: ocamlbuild_pack.cmx $(EXTRA_CMX) ocamlbuild.cmx - $(OCAMLOPT) $(LINKFLAGS) -o ocamlbuild.native \ - unix.cmxa ocamlbuild_pack.cmx $(EXTRA_CMX) ocamlbuild.cmx - -# The libraries - -ocamlbuildlib.cma: ocamlbuild_pack.cmo $(EXTRA_CMO) - $(OCAMLC) -a -o ocamlbuildlib.cma \ - ocamlbuild_pack.cmo $(EXTRA_CMO) - -ocamlbuildlightlib.cma: ocamlbuild_pack.cmo ocamlbuildlight.cmo - $(OCAMLC) -a -o ocamlbuildlightlib.cma \ - ocamlbuild_pack.cmo ocamlbuildlight.cmo - -ocamlbuildlib.cmxa: ocamlbuild_pack.cmx $(EXTRA_CMX) - $(OCAMLOPT) -a -o ocamlbuildlib.cmxa \ - ocamlbuild_pack.cmx $(EXTRA_CMX) - -# The packs - -ocamlbuild_pack.cmo: $(PACK_CMO) - $(OCAMLC) -pack $(PACK_CMO) -o ocamlbuild_pack.cmo - -ocamlbuild_pack.cmi: ocamlbuild_pack.cmo - -ocamlbuild_pack.cmx: $(PACK_CMX) - $(OCAMLOPT) -pack $(PACK_CMX) -o ocamlbuild_pack.cmx - -# The config file - -ocamlbuild_config.ml: ../config/Makefile - (echo 'let bindir = "$(BINDIR)"'; \ - echo 'let libdir = "$(LIBDIR)"'; \ - echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\ - echo 'let a = "$(A)"'; \ - echo 'let o = "$(O)"'; \ - echo 'let so = "$(SO)"'; \ - echo 'let ext_dll = "$(EXT_DLL)"'; \ - echo 'let exe = "$(EXE)"'; \ - ) > ocamlbuild_config.ml -clean:: - rm -f ocamlbuild_config.ml -beforedepend:: ocamlbuild_config.ml - -# The lexers - -lexers.ml: lexers.mll - $(OCAMLLEX) lexers.mll -clean:: - rm -f lexers.ml -beforedepend:: lexers.ml - -glob_lexer.ml: glob_lexer.mll - $(OCAMLLEX) glob_lexer.mll -clean:: - rm -f glob_lexer.ml -beforedepend:: glob_lexer.ml - -# Installation - -install: - $(CP) ocamlbuild.byte $(INSTALL_BINDIR)/ocamlbuild$(EXE) - $(CP) ocamlbuild.byte $(INSTALL_BINDIR)/ocamlbuild.byte$(EXE) - mkdir -p $(INSTALL_LIBDIR) - $(CP) $(INSTALL_LIB) $(INSTALL_LIBDIR)/ - -installopt: - if test -f ocamlbuild.native; then $(MAKE) installopt_really; fi - -installopt_really: - $(CP) ocamlbuild.native $(INSTALL_BINDIR)/ocamlbuild$(EXE) - $(CP) ocamlbuild.native $(INSTALL_BINDIR)/ocamlbuild.native$(EXE) - mkdir -p $(INSTALL_LIBDIR) - $(CP) $(INSTALL_LIB_OPT) $(INSTALL_LIBDIR)/ - -# The generic rules - -.SUFFIXES: .ml .mli .cmo .cmi .cmx - -.ml.cmo: - $(OCAMLC) $(COMPFLAGS) -c $< - -.mli.cmi: - $(OCAMLC) $(COMPFLAGS) -c $< - -.ml.cmx: - $(OCAMLOPT) -for-pack Ocamlbuild_pack $(COMPFLAGS) -c $< - -clean:: - rm -f *.cm? *.$(O) *.cmxa *.$(A) - rm -f *.byte *.native - -# The dependencies - -depend: beforedepend - $(OCAMLDEP) *.mli *.ml > .depend - -$(EXTRA_CMI): ocamlbuild_pack.cmi -$(EXTRA_CMO): ocamlbuild_pack.cmo ocamlbuild_pack.cmi -$(EXTRA_CMX): ocamlbuild_pack.cmx ocamlbuild_pack.cmi - -include .depend - -.PHONY: all allopt clean beforedepend -.PHONY: install installopt installopt_really depend diff --git a/ocamlbuild/TODO b/ocamlbuild/TODO deleted file mode 100644 index fd7ef2c9..00000000 --- a/ocamlbuild/TODO +++ /dev/null @@ -1,38 +0,0 @@ -To do: -* Add rules for producing .recdepends from .ml, .mli, .mllib, .mlpack -* Produce a dependency subgraph when failing on circular deps (e.g. "A: B C\nB: D") -* Executor: exceptional conditions and Not_found -* Fix report -* Design a nice, friendly, future-proof plugin (myocamlbuild) API -* Ocamlbuild should keep track of files removed from the source directory, e.g., -removing a .mli should be mirrored in the _build directory. - -Being done: -* Write doc - -Almost done: -* Fine control for hygiene using a glob pattern (command line option + tag) - => the command line option is todo. - -tag " or ..." "tag1, -tag2, ..." - -Won't fix: -* Config file for options => no since myocamlbuild is sufficent -* Optimize MD5 (Daemon ? Dnotify ?) : too much hassle for little gain - -Done: -* Fix uncaught exception handler to play well with the Display module -* Finish display before executing target -* Slurp: in a directory read files, before subdirs (to have _tags before foo/_tags) -* Add a -clean option -* Add ocamldoc rules (use .odoc extension) -* Add .inferred.mli target rules -* -- with no args does not call the executable -* Complain when used with -- and no target -* dep ["ocaml"; "link"; "use_foo"] ["foo/foo.o"] tags for adding targets -* Ensure that _build and _log are not created if not needed (with -help for - instance) -* Display: should display nothing (even when finish is called) when no real - event as occured. -* Have some option to draw tags/rules that applies on a target (it's -show-tags). -* rm sanitize.sh during -clean -* rm sanitize.sh when running ocamlbuild diff --git a/ocamlbuild/_tags b/ocamlbuild/_tags deleted file mode 100644 index cf63d892..00000000 --- a/ocamlbuild/_tags +++ /dev/null @@ -1,22 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2007 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. # -# # -######################################################################### - -# OCamlbuild tags file -true: debug -<*.ml> or <*.mli>: warn_L, warn_R, warn_Z, annot -"discard_printf.ml": rectypes -"ocamlbuildlib.cma" or "ocamlbuildlightlib.cma": linkall -<*.byte> or <*.native> or <*.top>: use_unix -"ocamlbuildlight.byte": -use_unix, nopervasives -<*.cmx>: for-pack(Ocamlbuild_pack) -<{ocamlbuild_{pack,unix_plugin,plugin,executor},ppcache}{,.p}.cmx>: -for-pack(Ocamlbuild_pack) -"doc": not_hygienic diff --git a/ocamlbuild/bool.ml b/ocamlbuild/bool.ml deleted file mode 100644 index 56dec3b0..00000000 --- a/ocamlbuild/bool.ml +++ /dev/null @@ -1,39 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Bool *) - -type 'a boolean = And of 'a boolean list | Or of 'a boolean list | Not of 'a boolean | Atom of 'a | True | False;; - -let rec eval f = function - | And l -> List.for_all (eval f) l - | Or l -> List.exists (eval f) l - | Not x -> not (eval f x) - | Atom a -> f a - | True -> true - | False -> false -;; -let rec iter f = function - | (And l|Or l) -> List.iter (iter f) l - | Not x -> iter f x - | Atom a -> f a - | True|False -> () -;; -let rec map f = function - | And l -> And(List.map (map f) l) - | Or l -> Or(List.map (map f) l) - | Not x -> Not(map f x) - | Atom a -> Atom(f a) - | (True|False) as b -> b -;; diff --git a/ocamlbuild/bool.mli b/ocamlbuild/bool.mli deleted file mode 100644 index 8ebbd440..00000000 --- a/ocamlbuild/bool.mli +++ /dev/null @@ -1,35 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Bool *) - -(** Provides a datatype for representing boolean formulas and evaluation, - iteration and map functions. *) - -(** Public type for generic boolean formulas. An empty conjunction [And[]] is true and - an empty disjunction [Or[]] is false. *) -type 'a boolean = - And of 'a boolean list - | Or of 'a boolean list - | Not of 'a boolean - | Atom of 'a - | True - | False - -val eval : ('a -> bool) -> 'a boolean -> bool -(** [eval g f] evaluates the boolean formula [f] using the values returned by [g] for the atoms. *) -val iter : ('a -> unit) -> 'a boolean -> unit -(** [iter g f] calls [g] over every atom of [f]. *) -val map : ('a -> 'b) -> 'a boolean -> 'b boolean -(** [map g f] replaces every atom of [f] by its image by [g]. *) diff --git a/ocamlbuild/command.ml b/ocamlbuild/command.ml deleted file mode 100644 index 79e2a1dc..00000000 --- a/ocamlbuild/command.ml +++ /dev/null @@ -1,422 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Command *) - -open My_std -open Log - -type tags = Tags.t -type pathname = string - -let jobs = ref 1 - -type t = -| Seq of t list -| Cmd of spec -| Echo of string list * pathname -| Nop -and spec = -| N (* nop or nil *) -| S of spec list -| A of string -| P of pathname -| Px of pathname -| Sh of string -| T of Tags.t -| V of string -| Quote of spec - -(*type v = [ `Seq of v list | `Cmd of vspec | `Nop ] -and vspec = - [ `N - | `S of vspec list - | `A of string - | `P of pathname - | `Px of pathname - | `Sh of string - | `Quote of vspec ] - -let rec spec_of_vspec = - function - | `N -> N - | `S vspecs -> S (List.map spec_of_vspec vspecs) - | `A s -> A s - | `P s -> P s - | `Px s -> Px s - | `Sh s -> Sh s - | `Quote vspec -> Quote (spec_of_vspec vspec) - -let rec vspec_of_spec = - function - | N -> `N - | S specs -> `S (List.map vspec_of_spec specs) - | A s -> `A s - | P s -> `P s - | Px s -> `Px s - | Sh s -> `Sh s - | T _ -> invalid_arg "vspec_of_spec: T not supported" - | Quote spec -> `Quote (vspec_of_spec spec) - -let rec t_of_v = - function - | `Nop -> Nop - | `Cmd vspec -> Cmd (spec_of_vspec vspec) - | `Seq cmds -> Seq (List.map t_of_v cmds) - -let rec v_of_t = - function - | Nop -> `Nop - | Cmd spec -> `Cmd (vspec_of_spec spec) - | Seq cmds -> `Seq (List.map v_of_t cmds)*) - -let no_tag_handler _ = failwith "no_tag_handler" - -let tag_handler = ref no_tag_handler - -(*** atomize *) -let atomize l = S(List.map (fun x -> A x) l) -let atomize_paths l = S(List.map (fun x -> P x) l) -(* ***) - -let env_path = lazy begin - let path_var = Sys.getenv "PATH" in - let parse_path = - if Sys.os_type = "Win32" then - Lexers.parse_environment_path_w - else - Lexers.parse_environment_path - in - let paths = - parse_path Const.Source.path (Lexing.from_string path_var) in - let norm_current_dir_name path = - if path = "" then Filename.current_dir_name else path - in - List.map norm_current_dir_name paths -end - -let virtual_solvers = Hashtbl.create 32 -let setup_virtual_command_solver virtual_command solver = - Hashtbl.replace virtual_solvers virtual_command solver -let virtual_solver virtual_command = - let solver = - try - Hashtbl.find virtual_solvers virtual_command - with Not_found -> - failwith (sbprintf "no solver for the virtual command %S \ - (setup one with Command.setup_virtual_command_solver)" - virtual_command) - in - try solver () - with Not_found -> - failwith (Printf.sprintf "the solver for the virtual command %S \ - has failed finding a valid command" virtual_command) - -(* On Windows, we need to also check for the ".exe" version of the file. *) -let file_or_exe_exists file = - sys_file_exists file || ((Sys.win32 || Sys.cygwin) && sys_file_exists (file ^ ".exe")) - -let search_in_path cmd = - (* Try to find [cmd] in path [path]. *) - let try_path path = - (* Don't know why we're trying to be subtle here... *) - if path = Filename.current_dir_name then file_or_exe_exists cmd - else file_or_exe_exists (filename_concat path cmd) - in - if Filename.is_implicit cmd then - let path = List.find try_path !*env_path in - (* We're not trying to append ".exe" here because all windows shells are - * capable of understanding the command without the ".exe" suffix. *) - filename_concat path cmd - else - cmd - -(*** string_of_command_spec{,_with_calls *) -let rec string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals spec = - let self = string_of_command_spec_with_calls call_with_tags call_with_target resolve_virtuals in - let b = Buffer.create 256 in - (* The best way to prevent bash from switching to its windows-style - * quote-handling is to prepend an empty string before the command name. *) - if Sys.os_type = "Win32" then - Buffer.add_string b "''"; - let first = ref true in - let put_space () = - if !first then - first := false - else - Buffer.add_char b ' ' - in - let put_filename p = - Buffer.add_string b (Shell.quote_filename_if_needed p) - in - let rec do_spec = function - | N -> () - | A u -> put_space (); put_filename u - | Sh u -> put_space (); Buffer.add_string b u - | P p -> put_space (); put_filename p - | Px u -> put_space (); put_filename u; call_with_target u - | V v -> if resolve_virtuals then do_spec (virtual_solver v) - else (put_space (); Printf.bprintf b "" (Shell.quote_filename_if_needed v)) - | S l -> List.iter do_spec l - | T tags -> call_with_tags tags; do_spec (!tag_handler tags) - | Quote s -> put_space (); put_filename (self s) - in - do_spec spec; - Buffer.contents b - -let string_of_command_spec x = string_of_command_spec_with_calls ignore ignore false x - -let string_target_and_tags_of_command_spec spec = - let rtags = ref Tags.empty in - let rtarget = ref "" in - let union_rtags tags = rtags := Tags.union !rtags tags in - let s = string_of_command_spec_with_calls union_rtags ((:=) rtarget) true spec in - let target = if !rtarget = "" then s else !rtarget in - s, target, !rtags - -let string_print_of_command_spec spec quiet pretend = - let s, target, tags = string_target_and_tags_of_command_spec spec in - fun () -> if not quiet then Log.event ~pretend s target tags; s -(* ***) - -let print_escaped_string f = Format.fprintf f "%S" - -let rec print f = - function - | Cmd spec -> Format.pp_print_string f (string_of_command_spec spec) - | Seq seq -> List.print print f seq - | Nop -> Format.pp_print_string f "nop" - | Echo(texts, dest_path) -> - Format.fprintf f "@[<2>Echo(%a,@ %a)@]" - (List.print print_escaped_string) texts print_escaped_string dest_path - -let to_string x = sbprintf "%a" print x - -let add_parallel_stat, dump_parallel_stats = - let xmin = ref max_int in - let xmax = ref 0 in - let xsum = ref 0 in - let xsumall = ref 0 in - let xcount = ref 0 in - let xcountall = ref 0 in - let add_parallel_stat x = - if x > 0 then begin - incr xcountall; - xsumall := x + !xsumall; - end; - if x > 1 then begin - incr xcount; - xsum := x + !xsum; - xmax := max !xmax x; - xmin := min !xmin x; - end - in - let dump_parallel_stats () = - if !jobs <> 1 then - if !xcount = 0 then - dprintf 1 "# No parallelism done" - else - let xaverage = float_of_int !xsumall /. float_of_int !xcountall in - let xaveragepara = float_of_int !xsum /. float_of_int !xcount in - dprintf 1 "# Parallel statistics: { count(total): %d(%d), max: %d, min: %d, average(total): %.3f(%.3f) }" - !xcount !xcountall !xmax !xmin xaveragepara xaverage - in - add_parallel_stat, dump_parallel_stats - -module Primitives = struct - let do_echo texts dest_path = - with_output_file dest_path begin fun oc -> - List.iter (output_string oc) texts - end - let echo x y () = (* no print here yet *) do_echo x y; "" -end - -let rec list_rev_iter f = - function - | [] -> () - | x :: xs -> list_rev_iter f xs; f x - -let flatten_commands quiet pretend cmd = - let rec loop acc = - function - | [] -> acc - | Nop :: xs -> loop acc xs - | Cmd spec :: xs -> loop (string_print_of_command_spec spec quiet pretend :: acc) xs - | Echo(texts, dest_path) :: xs -> loop (Primitives.echo texts dest_path :: acc) xs - | Seq l :: xs -> loop (loop acc l) xs - in List.rev (loop [] [cmd]) - -let execute_many ?(quiet=false) ?(pretend=false) cmds = - add_parallel_stat (List.length cmds); - let degraded = !*My_unix.is_degraded || Sys.os_type = "Win32" in - let jobs = !jobs in - if jobs < 0 then invalid_arg "jobs < 0"; - let max_jobs = if jobs = 0 then None else Some jobs in - - let ticker = Log.update in - let display = Log.display in - - if cmds = [] then - None - else - begin - let konts = List.map (flatten_commands quiet pretend) cmds in - if pretend then - begin - List.iter (List.iter (fun f -> ignore (f ()))) konts; - None - end - else - begin - reset_filesys_cache (); - if degraded then - let res, opt_exn = - List.fold_left begin fun (acc_res, acc_exn) cmds -> - match acc_exn with - | None -> - begin try - List.iter begin fun action -> - let cmd = action () in - let rc = sys_command cmd in - if rc <> 0 then begin - if not quiet then - eprintf "Exit code %d while executing this \ - command:@\n%s" rc cmd; - raise (Exit_with_code rc) - end - end cmds; - true :: acc_res, None - with e -> false :: acc_res, Some e - end - | Some _ -> false :: acc_res, acc_exn - end ([], None) konts - in match opt_exn with - | Some(exn) -> Some(List.rev res, exn) - | None -> None - else - My_unix.execute_many ~ticker ?max_jobs ~display konts - end - end -;; - -let execute ?quiet ?pretend cmd = - match execute_many ?quiet ?pretend [cmd] with - | Some(_, exn) -> raise exn - | _ -> () - -let iter_tags f x = - let rec spec x = - match x with - | N | A _ | Sh _ | P _ | Px _ | V _ | Quote _ -> () - | S l -> List.iter spec l - | T tags -> f tags - in - let rec cmd x = - match x with - | Nop | Echo _ -> () - | Cmd(s) -> spec s - | Seq(s) -> List.iter cmd s in - cmd x - -let fold_pathnames f x = - let rec spec = function - | N | A _ | Sh _ | V _ | Quote _ | T _ -> fun acc -> acc - | P p | Px p -> f p - | S l -> List.fold_right spec l - in - let rec cmd = function - | Nop -> fun acc -> acc - | Echo(_, p) -> f p - | Cmd(s) -> spec s - | Seq(s) -> List.fold_right cmd s in - cmd x - -let rec reduce x = - let rec self x acc = - match x with - | N -> acc - | A _ | Sh _ | P _ | Px _ | V _ -> x :: acc - | S l -> List.fold_right self l acc - | T tags -> self (!tag_handler tags) acc - | Quote s -> Quote (reduce s) :: acc in - match self x [] with - | [] -> N - | [x] -> x - | xs -> S xs - -let digest = - let list = List.fold_right in - let text x acc = Digest.string x :: acc in - let rec cmd = - function - | Cmd spec -> fun acc -> string_of_command_spec spec :: acc - | Seq seq -> list cmd seq - | Nop -> fun acc -> acc - | Echo(texts, dest_path) -> list text (dest_path :: texts) - in - fun x -> - match cmd x [] with - | [x] -> x - | xs -> Digest.string ("["^String.concat ";" xs^"]") - -let all_deps_of_tags = ref [] - -let cons deps acc = - List.rev& - List.fold_left begin fun acc dep -> - if List.mem dep acc then acc else dep :: acc - end acc deps - -let deps_of_tags tags = - List.fold_left begin fun acc (xtags, xdeps) -> - if Tags.does_match tags xtags then cons xdeps acc - else acc - end [] !all_deps_of_tags - -let set_deps_of_tags tags deps = - all_deps_of_tags := (tags, deps) :: !all_deps_of_tags - -let dep tags deps = set_deps_of_tags (Tags.of_list tags) deps - -let pdep tags ptag deps = - Param_tags.declare ptag - (fun param -> dep (Param_tags.make ptag param :: tags) (deps param)) - -let list_all_deps () = - !all_deps_of_tags - -(* -let to_string_for_digest x = - let rec cmd_of_spec = - function - | [] -> None - | N :: xs -> cmd_of_spec xs - | (A x | P x | P x) :: _ -> Some x - | Sh x :: _ -> - if Shell.is_simple_filename x then Some x - else None (* Sh"ocamlfind ocamlc" for example will not be digested. *) - | S specs1 :: specs2 -> cmd_of_spec (specs1 @ specs2) - | (T _ | Quote _) :: _ -> assert false in - let rec cmd_of_cmds = - function - | Nop | Seq [] -> None - | Cmd spec -> cmd_of_spec [spec] - | Seq (cmd :: _) -> cmd_of_cmds cmd in - let s = to_string x in - match cmd_of_cmds x with - | Some x -> - if sys_file_exists x then sprintf "(%S,%S)" s (Digest.file x) - else s - | None -> s -*) diff --git a/ocamlbuild/command.mli b/ocamlbuild/command.mli deleted file mode 100644 index a28c7519..00000000 --- a/ocamlbuild/command.mli +++ /dev/null @@ -1,51 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Command *) - -(** Provides an abstract type for easily building complex shell commands without making - quotation mistakes. *) -include Signatures.COMMAND with type tags = Tags.t and type pathname = string - -(** {6 For system use only, not for the casual user} *) - -val string_target_and_tags_of_command_spec : spec -> string * string * Tags.t - -val iter_tags : (Tags.t -> unit) -> t -> unit - -val fold_pathnames : (pathname -> 'a -> 'a) -> t -> 'a -> 'a - -(** Digest the given command. *) -val digest : t -> Digest.t - -(** Maximum number of parallel jobs. *) -val jobs : int ref - -(** Hook here the function that maps a set of tags to appropriate command - options. It also build the dependencies that matches the tags. *) -val tag_handler : (Tags.t -> spec) ref - -(** For system use only *) -val dump_parallel_stats : unit -> unit - -val deps_of_tags : Tags.t -> pathname list - -(** [dep tags deps] Will build [deps] when [tags] will be activated. *) -val dep : Tags.elt list -> pathname list -> unit - -val pdep : Tags.elt list -> Tags.elt -> (string -> pathname list) -> unit - -val list_all_deps : unit -> (Tags.t * pathname list) list - -val file_or_exe_exists: string -> bool diff --git a/ocamlbuild/configuration.ml b/ocamlbuild/configuration.ml deleted file mode 100644 index bc50a010..00000000 --- a/ocamlbuild/configuration.ml +++ /dev/null @@ -1,95 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Log -open Lexers - -type t = Lexers.conf - -let acknowledge_config source config = - let ack (tag, loc) = Param_tags.acknowledge source (Some loc) tag in - List.iter (fun (_, config) -> List.iter ack config.plus_tags) config - -let cache = Hashtbl.create 107 -let (configs, add_config) = - let configs = ref [] in - (fun () -> !configs), - (fun source config -> - acknowledge_config source config; - configs := config :: !configs; - Hashtbl.clear cache) - -let parse_lexbuf ?dir source lexbuf = - let conf = Lexers.conf_lines dir source lexbuf in - add_config source conf - -let parse_string ?source s = - let source = match source with - | Some source -> source - | None -> Const.Source.configuration - in - parse_lexbuf source (lexbuf_of_string s) - -let parse_file ?dir file = - with_input_file file begin fun ic -> - let lexbuf = Lexing.from_channel ic in - set_lexbuf_fname file lexbuf; - parse_lexbuf ?dir Const.Source.file lexbuf - end - -let key_match = Glob.eval - -let apply_config s (config : t) init = - let add (tag, _loc) = Tags.add tag in - let remove (tag, _loc) = Tags.remove tag in - List.fold_left begin fun tags (key, v) -> - if key_match key s then - List.fold_right add v.plus_tags (List.fold_right remove v.minus_tags tags) - else tags - end init config - -let apply_configs s = List.fold_right (apply_config s) (configs ()) Tags.empty - -let tags_of_filename s = - try Hashtbl.find cache s - with Not_found -> - let res = apply_configs s in - let () = Hashtbl.replace cache s res in - res - -let global_tags () = tags_of_filename "" -let has_tag tag = Tags.mem tag (global_tags ()) - -let tag_file file tags = - if tags <> [] then parse_string (Printf.sprintf "%S: %s" file (String.concat ", " tags));; - -let tag_any tags = - if tags <> [] then parse_string (Printf.sprintf "true: %s" (String.concat ", " tags));; - -let check_tags_usage useful_tags = - let check_tag (tag, loc) = - if not (Tags.mem tag useful_tags) then - - Log.eprintf "%aWarning: the tag %S is not used in any flag or dependency \ - declaration, so it will have no effect; it may be a typo. \ - Otherwise you can use `mark_tag_used` in your myocamlbuild.ml \ - to disable this warning." - Loc.print_loc loc tag - in - let check_conf (_, values) = - List.iter check_tag values.plus_tags; - List.iter check_tag values.minus_tags; - in - List.iter (List.iter check_conf) (configs ()) diff --git a/ocamlbuild/configuration.mli b/ocamlbuild/configuration.mli deleted file mode 100644 index 2bfd6bb8..00000000 --- a/ocamlbuild/configuration.mli +++ /dev/null @@ -1,44 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Configuration *) - -(** Handles the "_tags" file mechanism. *) - -(** Incorporate a newline-separated configuration string into the current configuration. - Will usually raising an [Invalid_arg] with an appropriately explicit message in case of error. *) -val parse_string : ?source:Loc.source -> string -> unit - -(** [parse_file ?dir fn] incorporates the configuration file named [fn], prefixing its glob patterns - with [dir] if given. *) -val parse_file : ?dir:string -> string -> unit - -(** Return the set of tags that apply to a given filename under the current configuration. *) -val tags_of_filename : string -> Tags.t - -val has_tag : string -> bool - -(** [tag_file filename tag_list] Tag the given filename with all given tags. *) -val tag_file : Pathname.t -> Tags.elt list -> unit - -(** [tag_any tag_list] Tag anything with all given tags. *) -val tag_any : Tags.elt list -> unit - -(** the tags that apply to any file *) -val global_tags : unit -> Tags.t - -(** Given the list of all tags that are really used by an existing - flagset, traverse existing configuration files and warns on tags - that will never get used. *) -val check_tags_usage : Tags.t -> unit diff --git a/ocamlbuild/const.ml b/ocamlbuild/const.ml deleted file mode 100644 index dac87789..00000000 --- a/ocamlbuild/const.ml +++ /dev/null @@ -1,11 +0,0 @@ -module Source = struct - let file = "file" - let command_line = "command-line" - let path = "path" - let ocamlfind_query = "ocamlfind query" - let ocamldep = "ocamldep" - let target_pattern = "target pattern" - let builtin = "builtin configuration" - let configuration = "configuration" - let plugin_tag = "plugin tag" -end diff --git a/ocamlbuild/digest_cache.ml b/ocamlbuild/digest_cache.ml deleted file mode 100644 index 319e7d06..00000000 --- a/ocamlbuild/digest_cache.ml +++ /dev/null @@ -1,42 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -(* Original author: Nicolas Pouillard *) - -open My_std -open Pathname.Operators - -let digests = Hashtbl.create 103 - -let get = Hashtbl.find digests - -let put = Hashtbl.replace digests - -let _digests = lazy (!Options.build_dir / (Pathname.mk "_digests")) - -let finalize () = - with_output_file !*_digests begin fun oc -> - Hashtbl.iter begin fun name digest -> - Printf.fprintf oc "%S: %S\n" name digest - end digests - end - -let init () = - Shell.chdir !Options.build_dir; - if Pathname.exists !*_digests then - with_input_file !*_digests begin fun ic -> - try while true do - let l = input_line ic in - Scanf.sscanf l "%S: %S" put - done with End_of_file -> () - end; - My_unix.at_exit_once finalize diff --git a/ocamlbuild/digest_cache.mli b/ocamlbuild/digest_cache.mli deleted file mode 100644 index d10627a2..00000000 --- a/ocamlbuild/digest_cache.mli +++ /dev/null @@ -1,18 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -(* Original author: Nicolas Pouillard *) - -val init : unit -> unit - -val get : string -> string -val put : string -> string -> unit diff --git a/ocamlbuild/discard_printf.ml b/ocamlbuild/discard_printf.ml deleted file mode 100644 index 8adc83e8..00000000 --- a/ocamlbuild/discard_printf.ml +++ /dev/null @@ -1,16 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -let discard_printf fmt = Format.ifprintf Format.std_formatter fmt;; diff --git a/ocamlbuild/discard_printf.mli b/ocamlbuild/discard_printf.mli deleted file mode 100644 index a3d2a012..00000000 --- a/ocamlbuild/discard_printf.mli +++ /dev/null @@ -1,20 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Discard_printf *) - -(** This module compiled with [-rectypes] allows one to write functions - taking formatters as arguments. *) -open Format -val discard_printf: ('a, formatter, unit) format -> 'a diff --git a/ocamlbuild/display.ml b/ocamlbuild/display.ml deleted file mode 100644 index 2e0b1e39..00000000 --- a/ocamlbuild/display.ml +++ /dev/null @@ -1,393 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Display *) -open My_std;; - -open My_unix;; - -let fp = Printf.fprintf;; - -(*** ANSI *) -module ANSI = - struct - let up oc n = fp oc "\027[%dA" n;; - let clear_to_eol oc () = fp oc "\027[K";; - let bol oc () = fp oc "\r";; - let get_columns () = - if Sys.os_type = "Unix" then - try - int_of_string (String.chomp (My_unix.run_and_read "tput cols")) - with - | Failure _ -> 80 - else 80 - end -;; -(* ***) -(*** tagline_description *) -type tagline_description = (string * char) list;; -(* ***) -(*** sophisticated_display *) -type sophisticated_display = { - ds_channel : out_channel; (** Channel for writing *) - ds_start_time : float; (** When was compilation started *) - mutable ds_last_update : float; (** When was the display last updated *) - mutable ds_last_target : string; (** Last target built *) - mutable ds_last_cached : bool; (** Was the last target cached or really built ? *) - mutable ds_last_tags : Tags.t; (** Tags of the last command *) - mutable ds_changed : bool; (** Does the tag line need recomputing ? *) - ds_update_interval : float; (** Minimum interval between updates *) - ds_columns : int; (** Number of columns in dssplay *) - mutable ds_jobs : int; (** Number of jobs launched or cached *) - mutable ds_jobs_cached : int; (** Number of jobs cached *) - ds_tagline : bytes; (** Current tagline *) - mutable ds_seen_tags : Tags.t; (** Tags that we have encountered *) - ds_pathname_length : int; (** How much space for displaying pathnames ? *) - ds_tld : tagline_description; (** Description for the tagline *) -};; -(* ***) -(*** display_line, display *) -type display_line = -| Classic -| Sophisticated of sophisticated_display - -type display = { - di_log_level : int; - mutable di_log_channel : (Format.formatter * out_channel) option; - di_channel : out_channel; - di_formatter : Format.formatter; - di_display_line : display_line; - mutable di_finished : bool; -} -;; -(* ***) -(*** various defaults *) -let default_update_interval = 0.05;; -let default_tagline_description = [ - "ocaml", 'O'; - "native", 'N'; - "byte", 'B'; - "program", 'P'; - "pp", 'R'; - "debug", 'D'; - "interf", 'I'; - "link", 'L'; -];; - -(* NOT including spaces *) -let countdown_chars = 8;; -let jobs_chars = 3;; -let jobs_cached_chars = 5;; -let dots = "...";; -let start_target = "STARTING";; -let finish_target = "FINISHED";; -let ticker_chars = 3;; -let ticker_period = 0.25;; -let ticker_animation = [| - "\\"; - "|"; - "/"; - "-"; -|];; -let cached = "*";; -let uncached = " ";; -let cache_chars = 1;; -(* ***) -(*** create_tagline *) -let create_tagline description = Bytes.make (List.length description) '-';; -(* ***) -(*** create *) -let create - ?(channel=stdout) - ?(mode:[`Classic|`Sophisticated] = `Sophisticated) - ?columns:(_columns=75) - ?(description = default_tagline_description) - ?log_file - ?(log_level=1) - () - = - let log_channel = - match log_file with - | None -> None - | Some fn -> - let oc = open_out_gen [Open_text; Open_wronly; Open_creat; Open_trunc] 0o666 fn in - let f = Format.formatter_of_out_channel oc in - Format.fprintf f "### Starting build.\n"; - Some (f, oc) - in - - let display_line = - match mode with - | `Classic -> Classic - | `Sophisticated -> - (* We assume Unix is not degraded. *) - let n = ANSI.get_columns () in - let tag_chars = List.length description in - Sophisticated - { ds_channel = stdout; - ds_start_time = gettimeofday (); - ds_last_update = 0.0; - ds_last_target = start_target; - ds_last_tags = Tags.empty; - ds_last_cached = false; - ds_changed = false; - ds_update_interval = default_update_interval; - ds_columns = n; - ds_jobs = 0; - ds_jobs_cached = 0; - ds_tagline = create_tagline description; - ds_seen_tags = Tags.empty; - ds_pathname_length = n - - (countdown_chars + 1 + jobs_chars + 1 + jobs_cached_chars + 1 + - cache_chars + 1 + tag_chars + 1 + ticker_chars + 2); - ds_tld = description } - in - { di_log_level = log_level; - di_log_channel = log_channel; - di_channel = channel; - di_formatter = Format.formatter_of_out_channel channel; - di_display_line = display_line; - di_finished = false } -;; -(* ***) -(*** print_time *) -let print_time oc t = - let t = int_of_float t in - let s = t mod 60 in - let m = (t / 60) mod 60 in - let h = t / 3600 in - fp oc "%02d:%02d:%02d" h m s -;; -(* ***) -(*** print_shortened_pathname *) -let print_shortened_pathname length oc u = - assert(length >= 3); - let m = String.length u in - if m <= length then - begin - output_string oc u; - fp oc "%*s" (length - m) "" - end - else - begin - let n = String.length dots in - let k = length - n in - output_string oc dots; - output_substring oc u (m - k) k; - end -(* ***) -(*** Layout - -00000000001111111111222222222233333333334444444444555555555566666666667777777777 -01234567890123456789012345678901234567890123456789012345678901234567890123456789 -HH MM SS XXXX PATHNAME -00:12:31 32 ( 26) ...lp4Filters/Camlp4LocationStripper.cmo * OBn------------- -| | | | | \ tags -| | | \ last target built \ cached ? -| | | -| | \ number of jobs cached -| \ number of jobs -\ elapsed time -cmo mllib -***) -(*** redraw_sophisticated *) -let redraw_sophisticated ds = - let t = gettimeofday () in - let oc = ds.ds_channel in - let dt = t -. ds.ds_start_time in - ds.ds_last_update <- t; - fp oc "%a" ANSI.bol (); - let ticker_phase = (abs (int_of_float (ceil (dt /. ticker_period)))) mod (Array.length ticker_animation) in - let ticker = ticker_animation.(ticker_phase) in - fp oc "%a %-4d (%-4d) %a %s %s %s" - print_time dt - ds.ds_jobs - ds.ds_jobs_cached - (print_shortened_pathname ds.ds_pathname_length) ds.ds_last_target - (if ds.ds_last_cached then cached else uncached) - (Bytes.to_string ds.ds_tagline) - ticker; - fp oc "%a%!" ANSI.clear_to_eol () -;; -(* ***) -(*** redraw *) -let redraw = function - | Classic -> () - | Sophisticated ds -> redraw_sophisticated ds -;; -(* ***) -(*** finish_sophisticated *) -let finish_sophisticated ?(how=`Success) ds = - let t = gettimeofday () in - let oc = ds.ds_channel in - let dt = t -. ds.ds_start_time in - match how with - | `Success|`Error -> - fp oc "%a" ANSI.bol (); - fp oc "%s %d target%s (%d cached) in %a." - (if how = `Error then - "Compilation unsuccessful after building" - else - "Finished,") - ds.ds_jobs - (if ds.ds_jobs = 1 then "" else "s") - ds.ds_jobs_cached - print_time dt; - fp oc "%a\n%!" ANSI.clear_to_eol () - | `Quiet -> - fp oc "%a%a%!" ANSI.bol () ANSI.clear_to_eol (); -;; -(* ***) -(*** sophisticated_display *) -let sophisticated_display ds f = - fp ds.ds_channel "%a%a%!" ANSI.bol () ANSI.clear_to_eol (); - f ds.ds_channel -;; -(* ***) -(*** call_if *) -let call_if log_channel f = - match log_channel with - | None -> () - | Some x -> f x -;; -(* ***) -(*** display *) -let display di f = - call_if di.di_log_channel (fun (_, oc) -> f oc); - match di.di_display_line with - | Classic -> f di.di_channel - | Sophisticated ds -> sophisticated_display ds f -;; -(* ***) -(*** finish *) -let finish ?(how=`Success) di = - if not di.di_finished then begin - di.di_finished <- true; - call_if di.di_log_channel - begin fun (fmt, oc) -> - Format.fprintf fmt "# Compilation %ssuccessful.@." (if how = `Error then "un" else ""); - close_out oc; - di.di_log_channel <- None - end; - match di.di_display_line with - | Classic -> () - | Sophisticated ds -> finish_sophisticated ~how ds - end -;; -(* ***) -(*** update_tagline_from_tags *) -let update_tagline_from_tags ds = - let tagline = ds.ds_tagline in - let tags = ds.ds_last_tags in - let rec loop i = function - | [] -> - for j = i to Bytes.length tagline - 1 do - Bytes.set tagline j '-' - done - | (tag, c) :: rest -> - if Tags.mem tag tags then - Bytes.set tagline i (Char.uppercase c) - else - if Tags.mem tag ds.ds_seen_tags then - Bytes.set tagline i (Char.lowercase c) - else - Bytes.set tagline i '-'; - loop (i + 1) rest - in - loop 0 ds.ds_tld; -;; -(* ***) -(*** update_sophisticated *) -let update_sophisticated ds = - let t = gettimeofday () in - let dt = t -. ds.ds_last_update in - if dt > ds.ds_update_interval then - begin - if ds.ds_changed then - begin - update_tagline_from_tags ds; - ds.ds_changed <- false - end; - redraw_sophisticated ds - end - else - () -;; -(* ***) -(*** set_target_sophisticated *) -let set_target_sophisticated ds target tags cached = - ds.ds_changed <- true; - ds.ds_last_target <- target; - ds.ds_last_tags <- tags; - ds.ds_jobs <- 1 + ds.ds_jobs; - if cached then ds.ds_jobs_cached <- 1 + ds.ds_jobs_cached; - ds.ds_last_cached <- cached; - ds.ds_seen_tags <- Tags.union ds.ds_seen_tags ds.ds_last_tags; - update_sophisticated ds -;; - -let print_tags f tags = - let first = ref true in - Tags.iter begin fun tag -> - if !first then begin - first := false; - Format.fprintf f "%s" tag - end else Format.fprintf f ", %s" tag - end tags -;; -(* ***) -(*** update *) -let update di = - match di.di_display_line with - | Classic -> () - | Sophisticated ds -> update_sophisticated ds -;; -(* ***) -(*** event *) -let event di ?(pretend=false) command target tags = - call_if di.di_log_channel - (fun (fmt, _) -> - Format.fprintf fmt "# Target: %s, tags: { %a }\n" target print_tags tags; - Format.fprintf fmt "%s%s@." command (if pretend then " # cached" else "")); - match di.di_display_line with - | Classic -> - if pretend then - begin - (* This should work, even on Windows *) - let command = Filename.basename command in - if di.di_log_level >= 2 then Format.fprintf di.di_formatter "[cache hit] %s\n%!" command - end - else - (if di.di_log_level >= 1 then Format.fprintf di.di_formatter "%s\n%!" command) - | Sophisticated ds -> - set_target_sophisticated ds target tags pretend; - update_sophisticated ds -;; -(* ***) -(*** dprintf *) -let dprintf ?(log_level=1) di fmt = - if log_level > di.di_log_level then Discard_printf.discard_printf fmt else - match di.di_display_line with - | Classic -> Format.fprintf di.di_formatter fmt - | Sophisticated _ -> - if log_level < 0 then - begin - display di ignore; - Format.fprintf di.di_formatter fmt - end - else - match di.di_log_channel with - | Some (f, _) -> Format.fprintf f fmt - | None -> Discard_printf.discard_printf fmt -(* ***) diff --git a/ocamlbuild/display.mli b/ocamlbuild/display.mli deleted file mode 100644 index 4dc399b1..00000000 --- a/ocamlbuild/display.mli +++ /dev/null @@ -1,34 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Display *) - -type display -type tagline_description = (string * char) list - -val create : - ?channel:out_channel -> - ?mode:[ `Classic | `Sophisticated ] -> - ?columns:int -> - ?description:tagline_description -> - ?log_file:string -> - ?log_level:int -> - unit -> - display - -val finish : ?how:[`Success|`Error|`Quiet] -> display -> unit -val event : display -> ?pretend:bool -> string -> string -> Tags.t -> unit -val display : display -> (out_channel -> unit) -> unit -val update : display -> unit -val dprintf : ?log_level:int -> display -> ('a, Format.formatter, unit) format -> 'a diff --git a/ocamlbuild/examples/example1/hello.ml b/ocamlbuild/examples/example1/hello.ml deleted file mode 100644 index f21b6ae1..00000000 --- a/ocamlbuild/examples/example1/hello.ml +++ /dev/null @@ -1,17 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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 _ = - Printf.printf "Hello, %s ! My name is %s\n" - (if Array.length Sys.argv > 1 then Sys.argv.(1) else "stranger") - Sys.argv.(0) -;; diff --git a/ocamlbuild/examples/example2/greet.ml b/ocamlbuild/examples/example2/greet.ml deleted file mode 100644 index 84f1e28f..00000000 --- a/ocamlbuild/examples/example2/greet.ml +++ /dev/null @@ -1,18 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -type how = Nicely | Badly;; - -let greet how who = - match how with Nicely -> Printf.printf "Hello, %s !\n" who - | Badly -> Printf.printf "Oh, here is that %s again.\n" who -;; diff --git a/ocamlbuild/examples/example2/hello.ml b/ocamlbuild/examples/example2/hello.ml deleted file mode 100644 index 4dee0a70..00000000 --- a/ocamlbuild/examples/example2/hello.ml +++ /dev/null @@ -1,26 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -open Greet - -let _ = - let name = - if Array.length Sys.argv > 1 then - Sys.argv.(1) - else - "stranger" - in - greet - (if name = "Caesar" then Nicely else Badly) - name; - Printf.printf "My name is %s\n" Sys.argv.(0) -;; diff --git a/ocamlbuild/examples/example3/epoch.ml b/ocamlbuild/examples/example3/epoch.ml deleted file mode 100644 index 0d235d16..00000000 --- a/ocamlbuild/examples/example3/epoch.ml +++ /dev/null @@ -1,18 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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 _ = - let s = Num.num_of_string (Printf.sprintf "%.0f" (Unix.gettimeofday ())) in - let ps = Num.mult_num (Num.num_of_string "1000000000000") s in - Printf.printf "%s picoseconds have passed since January 1st, 1970.\n" - (Num.string_of_num ps) -;; diff --git a/ocamlbuild/examples/example3/make.sh b/ocamlbuild/examples/example3/make.sh deleted file mode 100755 index e64152e1..00000000 --- a/ocamlbuild/examples/example3/make.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -######################################################################### -# # -# OCaml # -# # -# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2007 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. # -# # -######################################################################### - -set -e - -TARGET=epoch -FLAGS="-libs unix,nums" -OCAMLBUILD=ocamlbuild - -ocb() -{ - $OCAMLBUILD $FLAGS $* -} - -rule() { - case $1 in - clean) ocb -clean;; - native) ocb $TARGET.native;; - byte) ocb $TARGET.byte;; - all) ocb $TARGET.native $TARGET.byte;; - depend) echo "Not needed.";; - *) echo "Unknown action $1";; - esac; -} - -if [ $# -eq 0 ]; then - rule all -else - while [ $# -gt 0 ]; do - rule $1; - shift - done -fi diff --git a/ocamlbuild/exit_codes.ml b/ocamlbuild/exit_codes.ml deleted file mode 100644 index 10a3ac99..00000000 --- a/ocamlbuild/exit_codes.ml +++ /dev/null @@ -1,27 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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 rc_ok = 0 -let rc_usage = 1 -let rc_failure = 2 -let rc_invalid_argument = 3 -let rc_system_error = 4 -let rc_hygiene = 1 -let rc_circularity = 5 -let rc_solver_failed = 6 -let rc_ocamldep_error = 7 -let rc_lexing_error = 8 -let rc_build_error = 9 -let rc_executor_subcommand_failed = 10 -let rc_executor_subcommand_got_signal = 11 -let rc_executor_io_error = 12 -let rc_executor_excetptional_condition = 13 diff --git a/ocamlbuild/exit_codes.mli b/ocamlbuild/exit_codes.mli deleted file mode 100644 index cfbc3e25..00000000 --- a/ocamlbuild/exit_codes.mli +++ /dev/null @@ -1,27 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -val rc_ok : int -val rc_usage : int -val rc_failure : int -val rc_invalid_argument : int -val rc_system_error : int -val rc_hygiene : int -val rc_circularity : int -val rc_solver_failed : int -val rc_ocamldep_error : int -val rc_lexing_error : int -val rc_build_error : int -val rc_executor_subcommand_failed : int -val rc_executor_subcommand_got_signal : int -val rc_executor_io_error : int -val rc_executor_excetptional_condition : int diff --git a/ocamlbuild/fda.ml b/ocamlbuild/fda.ml deleted file mode 100644 index 8877e0c6..00000000 --- a/ocamlbuild/fda.ml +++ /dev/null @@ -1,82 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* FDA *) - -open Log -open Hygiene -;; - -exception Exit_hygiene_failed -;; - -let laws = - [ - { law_name = "Leftover OCaml compilation files"; - law_rules = [Not ".cmo"; Not ".cmi"; Not ".cmx"; Not ".cma"; Not ".cmxa"]; - law_penalty = Fail }; - { law_name = "Leftover OCaml type annotation files"; - law_rules = [Not ".annot"]; - law_penalty = Warn }; - { law_name = "Leftover object files"; - law_rules = [Not ".o"; Not ".a"; Not ".so"; Not ".obj"; Not ".lib"; Not ".dll"]; - law_penalty = Fail }; - { law_name = "Leftover ocamlyacc-generated files"; - law_rules = [Implies_not(".mly",".ml"); Implies_not(".mly",".mli")]; - law_penalty = Fail }; - { law_name = "Leftover ocamllex-generated files"; - law_rules = [Implies_not(".mll",".ml")]; - law_penalty = Fail }; - { law_name = "Leftover dependency files"; - law_rules = [Not ".ml.depends"; Not ".mli.depends"]; - law_penalty = Fail } - ] - -let inspect entry = - dprintf 5 "Doing sanity checks"; - let evil = ref false in - match Hygiene.check - ?sanitize: - begin - if !Options.sanitize then - Some(Pathname.concat !Options.build_dir !Options.sanitization_script) - else - None - end - laws entry - with - | [] -> () - | stuff -> - List.iter - begin fun (law, msgs) -> - Printf.printf "%s: %s:\n" - (match law.law_penalty with - | Warn -> "Warning" - | Fail -> - if not !evil then - begin - Printf.printf "IMPORTANT: I cannot work with leftover compiled files.\n%!"; - evil := true - end; - "ERROR") - law.law_name; - List.iter - begin fun msg -> - Printf.printf " %s\n" msg - end - msgs - end - stuff; - if !evil then raise Exit_hygiene_failed; -;; diff --git a/ocamlbuild/fda.mli b/ocamlbuild/fda.mli deleted file mode 100644 index 40103f99..00000000 --- a/ocamlbuild/fda.mli +++ /dev/null @@ -1,19 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Fda *) - -exception Exit_hygiene_failed - -val inspect : bool Slurp.entry -> unit diff --git a/ocamlbuild/findlib.ml b/ocamlbuild/findlib.ml deleted file mode 100644 index 18f4d2c9..00000000 --- a/ocamlbuild/findlib.ml +++ /dev/null @@ -1,198 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Romain Bardou *) - -open My_std -open My_unix -open Command - -type command_spec = Command.spec - -type error = - | Cannot_run_ocamlfind - | Dependency_not_found of string * string (* package, dependency *) - | Package_not_found of string - | Cannot_parse_query of string * string (* package, explaination *) - -exception Findlib_error of error - -let error x = raise (Findlib_error x) - -let string_of_error = function - | Cannot_run_ocamlfind -> - "Cannot run Ocamlfind." - | Dependency_not_found(p, d) -> - Printf.sprintf - "Ocamlfind returned \"%s\" as a dependency for package \"%s\" but does \ -not know this dependency." d p - | Package_not_found p -> - Printf.sprintf "Findlib package not found: \"%s\"." p - | Cannot_parse_query(p, e) -> - Printf.sprintf "Cannot parse Ocamlfind query for package \"%s\": %s" p e - -let report_error e = - prerr_endline (string_of_error e); - exit 2 - -let ocamlfind = "ocamlfind" - -type package = { - name: string; - description: string; - version: string; - archives_byte: string; - archives_native: string; - link_options: string; - location: string; - dependencies: package list; -} - -let packages = Hashtbl.create 42 - -let run_and_parse lexer command = - Printf.ksprintf - (fun command -> lexer & Lexing.from_string & run_and_read command) - command - -let run_and_read command = - Printf.ksprintf run_and_read command - -let rec query name = - try - Hashtbl.find packages name - with Not_found -> - try - let n, d, v, a_byte, lo, l = - run_and_parse - (Lexers.ocamlfind_query Const.Source.ocamlfind_query) - "%s query -l -predicates byte %s" ocamlfind name - in - let a_native = - run_and_parse - (Lexers.trim_blanks Const.Source.ocamlfind_query) - "%s query -a-format -predicates native %s" ocamlfind name - in - let deps = - run_and_parse - (Lexers.blank_sep_strings Const.Source.ocamlfind_query) - "%s query -r -p-format %s" ocamlfind name - in - let deps = List.filter ((<>) n) deps in - let deps = - try - List.map query deps - with Findlib_error (Package_not_found dep_name) -> - (* Ocamlfind cannot find a package which it returned as a dependency. - This should not happen. *) - error (Dependency_not_found (name, dep_name)) - in - let package = { - name = n; - description = d; - version = v; - archives_byte = a_byte; - archives_native = a_native; - link_options = lo; - location = l; - dependencies = deps; - } in - Hashtbl.add packages n package; - package - with - | Failure _ -> - (* TODO: Improve to differenciate whether ocamlfind cannot be - run or is not installed *) - error Cannot_run_ocamlfind - | Lexers.Error (s,_) -> - error (Cannot_parse_query (name, s)) - -let split_nl s = - let x = ref [] in - let rec go s = - let pos = String.index s '\n' in - x := (String.before s pos)::!x; - go (String.after s (pos + 1)) - in - try - go s - with Not_found -> !x - -let before_space s = - try - String.before s (String.index s ' ') - with Not_found -> s - -let list () = - List.map before_space (split_nl & run_and_read "%s list" ocamlfind) - -(* The closure algorithm is easy because the dependencies are already closed -and sorted for each package. We only have to make the union. We could also -make another ocamlfind query such as: - ocamlfind query -p-format -r package1 package2 ... *) -let topological_closure l = - let add l x = if List.mem x l then l else x :: l in - let l = List.fold_left begin fun acc p -> - add (List.fold_left add acc p.dependencies) p - end [] l in - List.rev l - -module SSet = Set.Make(String) - -let add_atom a l = match a, l with - | A "", _ -> l - | _ -> a :: l - -let compile_flags l = - let pkgs = topological_closure l in - let locations = List.fold_left begin fun acc p -> - SSet.add p.location acc - end SSet.empty pkgs in - let flags = [] in - (* includes *) - let flags = - List.fold_left begin fun acc l -> - add_atom (P l) (add_atom (A "-I") acc) - end flags (SSet.elements locations) - in - S (List.rev flags) -let compile_flags_byte = compile_flags -let compile_flags_native = compile_flags - -let link_flags f l = - let pkgs = topological_closure l in - let locations = List.fold_left begin fun acc p -> - SSet.add p.location acc - end SSet.empty pkgs in - let flags = [] in - (* includes *) - let flags = - List.fold_left begin fun acc l -> - add_atom (P l) (add_atom (A "-I") acc) - end flags (SSet.elements locations) - in - (* special link options *) - let flags = - List.fold_left begin fun acc x -> - add_atom (A x.link_options) acc - end flags pkgs - in - (* archives *) - let flags = - List.fold_left begin fun acc x -> - add_atom (A (f x)) acc - end flags pkgs - in - S (List.rev flags) -let link_flags_byte = link_flags (fun x -> x.archives_byte) -let link_flags_native = link_flags (fun x -> x.archives_native) diff --git a/ocamlbuild/findlib.mli b/ocamlbuild/findlib.mli deleted file mode 100644 index 8bb29a80..00000000 --- a/ocamlbuild/findlib.mli +++ /dev/null @@ -1,16 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Romain Bardou *) - -include Signatures.FINDLIB with type command_spec = Command.spec diff --git a/ocamlbuild/flags.ml b/ocamlbuild/flags.ml deleted file mode 100644 index c776953b..00000000 --- a/ocamlbuild/flags.ml +++ /dev/null @@ -1,78 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open Command -open Bool (* FIXME remove me *) -open Tags.Operators - -type decl = { - tags: Tags.t; - flags: Command.spec; - deprecated: bool; -} -let flags_of_decl { flags; _ } = flags -let tags_of_decl { tags; _ } = tags - -let all_decls = ref [] - -let of_tags matched_tags = - S begin - List.fold_left begin fun acc { tags; flags; _ } -> - if Tags.does_match matched_tags tags then flags :: acc - else acc - end [] !all_decls - end - -let () = Command.tag_handler := of_tags - -let of_tag_list x = of_tags (Tags.of_list x) - -let add_decl decl = - all_decls := decl :: !all_decls - -let flag ?(deprecated=false) tags flags = - let tags = Tags.of_list tags in - add_decl { tags; flags; deprecated } - -let pflag tags ptag flags = - Param_tags.declare ptag - (fun param -> flag (Param_tags.make ptag param :: tags) (flags param)) - -let add x xs = x :: xs -let remove me = List.filter (fun x -> me <> x) - -let pretty_print { tags; flags; deprecated } = - let sflag = Command.string_of_command_spec flags in - let header = if deprecated then "deprecated flag" else "flag" in - let pp fmt = Log.raw_dprintf (-1) fmt in - pp "@[<2>%s@ {. %a .}@ %S@]@\n@\n" header Tags.print tags sflag - -let show_documentation () = - List.iter - (fun decl -> if not decl.deprecated then pretty_print decl) - !all_decls; - List.iter - (fun decl -> if decl.deprecated then pretty_print decl) - !all_decls; - let pp fmt = Log.raw_dprintf (-1) fmt in - pp "@." - -let used_tags = ref Tags.empty - -let mark_tag_used tag = - used_tags := Tags.add tag !used_tags - -let get_used_tags () = - List.fold_left (fun acc decl -> Tags.union acc decl.tags) - !used_tags !all_decls diff --git a/ocamlbuild/flags.mli b/ocamlbuild/flags.mli deleted file mode 100644 index b32de2bc..00000000 --- a/ocamlbuild/flags.mli +++ /dev/null @@ -1,40 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -val of_tags : Tags.t -> Command.spec -val of_tag_list : Tags.elt list -> Command.spec - -(* The ?deprecated parameter marks the flag declaration as deprecated, - because it is superseded by a different, better way to express the - same thing (eg. a parametrized tag). So far, it is only used when - showing documentation. - - This flag is not exported in OCamlbuild_plugin interface for now. It - would make sense to let plugin authors deprecate their own flags, - but it has to be balanced again the simplicity of the plugin - interface exposed. If you're reading this as a plugin author that - has a real need for deprecation, drop us a note on the bugtracker. *) -val flag : ?deprecated:bool -> Tags.elt list -> Command.spec -> unit - -val pflag : Tags.elt list -> string -> (string -> Command.spec) -> unit -val add : 'a -> 'a list -> 'a list -val remove : 'a -> 'a list -> 'a list - -val show_documentation : unit -> unit - -(** "useful" tags: they are used by a tag declaration, or have been - explicitly added with [mark_as_used] *) -val get_used_tags : unit -> Tags.t - -val mark_tag_used : Tags.elt -> unit diff --git a/ocamlbuild/glob.ml b/ocamlbuild/glob.ml deleted file mode 100644 index 0bfa61f6..00000000 --- a/ocamlbuild/glob.ml +++ /dev/null @@ -1,413 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Glob *) -open My_std;; -open Bool;; -include Glob_ast;; -open Glob_lexer;; - -let sf = Printf.sprintf;; - -let brute_limit = 10;; - -(*** string_of_token *) -let string_of_token = function -| ATOM _ -> "ATOM" -| AND -> "AND" -| OR -> "OR" -| NOT -> "NOT" -| LPAR -> "LPAR" -| RPAR -> "RPAR" -| TRUE -> "TRUE" -| FALSE -> "FALSE" -| EOF -> "EOF" -;; -(* ***) -(*** match_character_class *) -let match_character_class cl c = - Bool.eval - begin function (c1,c2) -> - c1 <= c && c <= c2 - end - cl -;; -(* ***) -(*** NFA *) -module NFA = - struct - type transition = - | QCLASS of character_class - | QEPSILON - ;; - - module IS = Set.Make(struct type t = int let compare (x:t) y = compare x y let print = Format.pp_print_int end);; - module ISM = Map.Make(struct type t = IS.t let compare = IS.compare let print = IS.print end);; - - type machine = { - mc_qi : IS.t; - mc_table : (character_class * IS.t) list array; - mc_qf : int; - mc_power_table : (char, IS.t ISM.t) Hashtbl.t - } - - (*** build' *) - let build' p = - let count = ref 0 in - let transitions = ref [] in - let epsilons : (int * int) list ref = ref [] in - let state () = let id = !count in incr count; id in - let ( --> ) q1 t q2 = - match t with - | QEPSILON -> epsilons := (q1,q2) :: !epsilons; q1 - | QCLASS cl -> transitions := (q1,cl,q2) :: !transitions; q1 - in - (* Construit les transitions correspondant au motif donne et arrivant - * sur l'etat qf. Retourne l'etat d'origine. *) - let rec loop qf = function - | Epsilon -> qf - | Word u -> - let m = String.length u in - let q0 = state () in - let rec loop q i = - if i = m then - q0 - else - begin - let q' = - if i = m - 1 then - qf - else - state () - in - let _ = (q --> QCLASS(Atom(u.[i], u.[i]))) q' in - loop q' (i + 1) - end - in - loop q0 0 - | Class cl -> - let q1 = state () in - (q1 --> QCLASS cl) qf - | Star p -> - (* The fucking Kleene star *) - let q2 = state () in - let q1 = loop q2 p in (* q1 -{p}-> q2 *) - let _ = (q1 --> QEPSILON) qf in - let _ = (q2 --> QEPSILON) q1 in - let _ = (q2 --> QEPSILON) q1 in - q1 - | Concat(p1,p2) -> - let q12 = state () in - let q1 = loop q12 p1 in (* q1 -{p1}-> q12 *) - let q2 = loop qf p2 in (* q2 -{p2}-> qf *) - let _ = (q12 --> QEPSILON) q2 in - q1 - | Union pl -> - let qi = state () in - List.iter - begin fun p -> - let q = loop qf p in (* q -{p2}-> qf *) - let _ = (qi --> QEPSILON) q in (* qi -{}---> q *) - () - end - pl; - qi - in - let qf = state () in - let qi = loop qf p in - let m = !count in - - (* Compute epsilon closure *) - let graph = Array.make m IS.empty in - List.iter - begin fun (q,q') -> - graph.(q) <- IS.add q' graph.(q) - end - !epsilons; - - let closure = Array.make m IS.empty in - let rec transitive past = function - | [] -> past - | q :: future -> - let past' = IS.add q past in - let future' = - IS.fold - begin fun q' future' -> - (* q -{}--> q' *) - if IS.mem q' past' then - future' - else - q' :: future' - end - graph.(q) - future - in - transitive past' future' - in - for i = 0 to m - 1 do - closure.(i) <- transitive IS.empty [i] (* O(n^2), I know *) - done; - - (* Finally, build the table *) - let table = Array.make m [] in - List.iter - begin fun (q,t,q') -> - table.(q) <- (t, closure.(q')) :: table.(q) - end - !transitions; - - (graph, closure, - { mc_qi = closure.(qi); - mc_table = table; - mc_qf = qf; - mc_power_table = Hashtbl.create 37 }) - ;; - let build x = let (_,_, machine) = build' x in machine;; - (* ***) - (*** run *) - let run ?(trace=false) machine u = - let m = String.length u in - let apply qs c = - try - let t = Hashtbl.find machine.mc_power_table c in - ISM.find qs t - with - | Not_found -> - let qs' = - IS.fold - begin fun q qs' -> - List.fold_left - begin fun qs' (cl,qs'') -> - if match_character_class cl c then - IS.union qs' qs'' - else - qs' - end - qs' - machine.mc_table.(q) - end - qs - IS.empty - in - let t = - try - Hashtbl.find machine.mc_power_table c - with - | Not_found -> ISM.empty - in - Hashtbl.replace machine.mc_power_table c (ISM.add qs qs' t); - qs' - in - let rec loop qs i = - if IS.is_empty qs then - false - else - begin - if i = m then - IS.mem machine.mc_qf qs - else - begin - let c = u.[i] in - if trace then - begin - Printf.printf "%d %C {" i c; - IS.iter (fun q -> Printf.printf " %d" q) qs; - Printf.printf " }\n%!" - end; - let qs' = apply qs c in - loop qs' (i + 1) - end - end - in - loop machine.mc_qi 0 - ;; - (* ***) - end -;; -(* ***) -(*** Brute *) -module Brute = - struct - exception Succeed;; - exception Fail;; - exception Too_hard;; - - (*** match_pattern *) - let match_pattern counter p u = - let m = String.length u in - (** [loop i n p] returns [true] iff the word [u.(i .. i + n - 1)] is in the - ** language generated by the pattern [p]. - ** We must have 0 <= i and i + n <= m *) - let rec loop (i,n,p) = - assert (0 <= i && 0 <= n && i + n <= m); - incr counter; - if !counter >= brute_limit then raise Too_hard; - match p with - | Word v -> - String.length v = n && - begin - let rec check j = j = n || (v.[j] = u.[i + j] && check (j + 1)) - in - check 0 - end - | Epsilon -> n = 0 - | Star(Class True) -> true - | Star(Class cl) -> - let rec check k = - if k = n then - true - else - (match_character_class cl u.[i + k]) && check (k + 1) - in - check 0 - | Star _ -> raise Too_hard - | Class cl -> n = 1 && match_character_class cl u.[i] - | Concat(p1,p2) -> - let rec scan j = - j <= n && ((loop (i,j,p1) && loop (i+j, n - j,p2)) || scan (j + 1)) - in - scan 0 - | Union pl -> List.exists (fun p' -> loop (i,n,p')) pl - in - loop (0,m,p) - ;; - (* ***) -end -;; -(* ***) -(*** fast_pattern_contents, fast_pattern, globber *) -type fast_pattern_contents = -| Brute of int ref * pattern -| Machine of NFA.machine -;; -type fast_pattern = fast_pattern_contents ref;; -type globber = fast_pattern atom Bool.boolean;; -(* ***) -(*** fast_pattern_of_pattern *) -let fast_pattern_of_pattern p = ref (Brute(ref 0, p));; -(* ***) -(*** add_dir *) -let add_dir dir x = - match dir with - | None -> x - | Some(dir) -> - match x with - | Constant(s) -> - Constant(My_std.filename_concat dir s) - | Pattern(p) -> - Pattern(Concat(Word(My_std.filename_concat dir ""), p)) -;; -(* ***) -(*** add_ast_dir *) -let add_ast_dir dir x = - match dir with - | None -> x - | Some dir -> - let slash = Class(Atom('/','/')) in - let any = Class True in - let q = Union[Epsilon; Concat(slash, Star any)] in (* ( /** )? *) - And[Atom(Pattern(ref (Brute(ref 0, Concat(Word dir, q))))); x] -;; -(* ***) -(*** parse *) -let parse ?dir u = - let l = Lexing.from_string u in - let tok = ref None in - let f = - fun () -> - match !tok with - | None -> token l - | Some x -> - tok := None; - x - in - let g t = - match !tok with - | None -> tok := Some t - | Some t' -> - raise (Parse_error(sf "Trying to unput token %s while %s is active" (string_of_token t) (string_of_token t'))) - in - let read x = - let y = f () in - if x = y then - () - else - raise (Parse_error(sf "Unexpected token, expecting %s, got %s" (string_of_token x) (string_of_token y))) - in - let rec atomizer continuation = match f () with - | NOT -> atomizer (fun x -> continuation (Not x)) - | ATOM x -> - begin - let a = - match add_dir dir x with - | Constant u -> Constant u - | Pattern p -> Pattern(fast_pattern_of_pattern p) - in - continuation (Atom a) - end - | TRUE -> continuation True - | FALSE -> continuation False - | LPAR -> - let y = parse_s () in - read RPAR; - continuation y - | t -> raise (Parse_error(sf "Unexpected token %s in atomizer" (string_of_token t))) - and parse_s1 x = match f () with - | OR -> let y = parse_s () in Or[x; y] - | AND -> parse_t x - | t -> g t; x - and parse_t1 x y = match f () with - | OR -> let z = parse_s () in Or[And[x;y]; z] - | AND -> parse_t (And[x;y]) - | t -> g t; And[x;y] - and parse_s () = atomizer parse_s1 - and parse_t x = atomizer (parse_t1 x) - in - let x = parse_s () in - read EOF; - add_ast_dir dir x -;; -(* ***) -(*** eval *) -let eval g u = - Bool.eval - begin function - | Constant v -> u = v - | Pattern kind -> - match !kind with - | Brute(count, p) -> - begin - let do_nfa () = - let m = NFA.build p in - kind := Machine m; - NFA.run m u - in - if !count >= brute_limit then - do_nfa () - else - try - Brute.match_pattern count p u - with - | Brute.Too_hard -> do_nfa () - end - | Machine m -> NFA.run m u - end - g -(* ***) -(*** Debug *) -(*let (Atom(Pattern x)) = parse "<{a,b}>";; -#install_printer IS.print;; -#install_printer ISM.print;; -let (graph, closure, machine) = build' x;;*) -(* ***) diff --git a/ocamlbuild/glob.mli b/ocamlbuild/glob.mli deleted file mode 100644 index b13a6fc2..00000000 --- a/ocamlbuild/glob.mli +++ /dev/null @@ -1,24 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Glob *) - -(** The type representing fast patterns. Do not attempt to compare them, as they get on-the-fly optimizations. *) -type fast_pattern - -(** A self-contained module implementing extended shell glob patterns who have an expressive power - equal to boolean combinations of regular expressions. *) -include Signatures.GLOB with type globber = fast_pattern Glob_ast.atom Bool.boolean - -val fast_pattern_of_pattern : Glob_ast.pattern -> fast_pattern diff --git a/ocamlbuild/glob_ast.ml b/ocamlbuild/glob_ast.ml deleted file mode 100644 index 435033ad..00000000 --- a/ocamlbuild/glob_ast.ml +++ /dev/null @@ -1,32 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Glob_ast *) - -exception Parse_error of string;; - -type pattern = -| Epsilon -| Star of pattern (* The fucking Kleene star *) -| Class of character_class -| Concat of pattern * pattern -| Union of pattern list -| Word of string -and character_class = (char * char) Bool.boolean -;; - -type 'pattern atom = -| Constant of string -| Pattern of 'pattern -;; diff --git a/ocamlbuild/glob_ast.mli b/ocamlbuild/glob_ast.mli deleted file mode 100644 index b6f7b282..00000000 --- a/ocamlbuild/glob_ast.mli +++ /dev/null @@ -1,26 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Glob_ast *) - -exception Parse_error of string -type pattern = -| Epsilon -| Star of pattern -| Class of character_class -| Concat of pattern * pattern -| Union of pattern list -| Word of string -and character_class = (char * char) Bool.boolean -type 'pattern atom = Constant of string | Pattern of 'pattern diff --git a/ocamlbuild/glob_lexer.mli b/ocamlbuild/glob_lexer.mli deleted file mode 100644 index 724c237c..00000000 --- a/ocamlbuild/glob_lexer.mli +++ /dev/null @@ -1,28 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -open Glob_ast - -type token = -| ATOM of pattern atom -| AND -| OR -| NOT -| LPAR -| RPAR -| TRUE -| FALSE -| EOF - -val token : Lexing.lexbuf -> token diff --git a/ocamlbuild/glob_lexer.mll b/ocamlbuild/glob_lexer.mll deleted file mode 100644 index 5bc35c18..00000000 --- a/ocamlbuild/glob_lexer.mll +++ /dev/null @@ -1,117 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Glob *) -{ -open Bool;; -open Glob_ast;; - -type token = -| ATOM of pattern atom -| AND -| OR -| NOT -| LPAR -| RPAR -| TRUE -| FALSE -| EOF -;; - -let sf = Printf.sprintf;; - -let concat_patterns p1 p2 = - match (p1,p2) with - | (Epsilon,_) -> p2 - | (_,Epsilon) -> p1 - | (_,_) -> Concat(p1,p2) -;; - -let slash = Class(Atom('/','/'));; -let not_slash = Class(Not(Atom('/','/')));; -let any = Class True;; -} - -let pattern_chars = ['a'-'z']|['A'-'Z']|'_'|'-'|['0'-'9']|'.' -let space_chars = [' ' '\t' '\n' '\r' '\012'] - -rule token = parse -| '<' { ATOM(Pattern(let (p,_) = parse_pattern ['>'] Epsilon lexbuf in p)) } -| '"' { ATOM(Constant(parse_string (Buffer.create 32) lexbuf)) } -| "and"|"AND"|"&" { AND } -| "or"|"OR"|"|" { OR } -| "not"|"NOT"|"~" { NOT } -| "true"|"1" { TRUE } -| "false"|"0" { FALSE } -| "(" { LPAR } -| ")" { RPAR } -| space_chars+ { token lexbuf } -| eof { EOF } - -and parse_pattern eof_chars p = parse -| (pattern_chars+ as u) { parse_pattern eof_chars (concat_patterns p (Word u)) lexbuf } -| '{' - { - let rec loop pl = - let (p',c) = parse_pattern ['}';','] Epsilon lexbuf in - let pl = p' :: pl in - if c = ',' then - loop pl - else - parse_pattern eof_chars (concat_patterns p (Union pl)) lexbuf - in - loop [] - } -| "[^" - { - let cl = Not(Or(parse_class [] lexbuf)) in - parse_pattern eof_chars (concat_patterns p (Class cl)) lexbuf - } -| '[' - { - let cl = Or(parse_class [] lexbuf) in - parse_pattern eof_chars (concat_patterns p (Class cl)) lexbuf - } -(* Random thought... **/* seems to be equal to True *) -| "/**/" (* / | /\Sigma^*/ *) - { let q = Union[slash; Concat(slash, Concat(Star any, slash)) ] in - parse_pattern eof_chars (concat_patterns p q) lexbuf } -| "/**" (* \varepsilon | /\Sigma^* *) - { let q = Union[Epsilon; Concat(slash, Star any)] in - parse_pattern eof_chars (concat_patterns p q) lexbuf } -| "**/" (* \varepsilon | \Sigma^*/ *) - { let q = Union[Epsilon; Concat(Star any, slash)] in - parse_pattern eof_chars (concat_patterns p q) lexbuf } -| "**" { raise (Parse_error("Ambiguous ** pattern not allowed unless surrounded by one or more slashes")) } -| '*' { parse_pattern eof_chars (concat_patterns p (Star not_slash)) lexbuf } -| '/' { parse_pattern eof_chars (concat_patterns p slash) lexbuf } -| '?' { parse_pattern eof_chars (concat_patterns p not_slash) lexbuf } -| _ as c - { if List.mem c eof_chars then - (p,c) - else - raise (Parse_error(sf "Unexpected character %C in glob pattern" c)) - } - -and parse_string b = parse -| "\"" { Buffer.contents b } -| "\\\"" { Buffer.add_char b '"'; parse_string b lexbuf } -| [^'"' '\\']+ as u { Buffer.add_string b u; parse_string b lexbuf } -| _ as c { raise (Parse_error(sf "Unexpected character %C in string" c)) } - -and parse_class cl = parse -| ']' { cl } -| "-]" { ((Atom('-','-'))::cl) } -| (_ as c1) '-' (_ as c2) { parse_class ((Atom(c1,c2))::cl) lexbuf } -| _ as c { parse_class ((Atom(c,c))::cl) lexbuf } diff --git a/ocamlbuild/hooks.ml b/ocamlbuild/hooks.ml deleted file mode 100644 index 4dfcf292..00000000 --- a/ocamlbuild/hooks.ml +++ /dev/null @@ -1,27 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -type message = - | Before_hygiene - | After_hygiene - | Before_options - | After_options - | Before_rules - | After_rules - -let hooks = ref ignore - -let setup_hooks f = hooks := f - -let call_hook m = !hooks m diff --git a/ocamlbuild/hooks.mli b/ocamlbuild/hooks.mli deleted file mode 100644 index 92f9a0e7..00000000 --- a/ocamlbuild/hooks.mli +++ /dev/null @@ -1,24 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -type message = - | Before_hygiene - | After_hygiene - | Before_options - | After_options - | Before_rules - | After_rules - -val setup_hooks : (message -> unit) -> unit -val call_hook : message -> unit diff --git a/ocamlbuild/hygiene.ml b/ocamlbuild/hygiene.ml deleted file mode 100644 index 9a52cd94..00000000 --- a/ocamlbuild/hygiene.ml +++ /dev/null @@ -1,176 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Hygiene *) -open My_std -open Slurp - -exception Exit_hygiene_violations - -type rule = -| Implies_not of pattern * pattern -| Not of pattern -and pattern = suffix -and suffix = string - -type penalty = Warn | Fail - -type law = { - law_name : string; - law_rules : rule list; - law_penalty : penalty -} - -let list_collect f l = - let rec loop result = function - | [] -> List.rev result - | x :: rest -> - match f x with - | None -> loop result rest - | Some y -> loop (y :: result) rest - in - loop [] l - -let list_none_for_all f l = - let rec loop = function - | [] -> None - | x :: rest -> - match f x with - | None -> loop rest - | y -> y - in - loop l - -let sf = Printf.sprintf - -module SS = Set.Make(String);; - -let check ?sanitize laws entry = - let penalties = ref [] in - let microbes = ref SS.empty in - let () = - match sanitize with - | Some fn -> if sys_file_exists fn then sys_remove fn - | None -> () - in - let remove path name = - if sanitize <> None then - microbes := SS.add (filename_concat path name) !microbes - in - let check_rule = fun entries -> function - | Not suffix -> - list_collect - begin function - | File(path, name, _, true) -> - if Filename.check_suffix name suffix - && not ( Pathname.link_to_dir (filename_concat path name) !Options.build_dir ) then - begin - remove path name; - Some(sf "File %s in %s has suffix %s" name path suffix) - end - else - None - | File _ | Dir _| Error _ | Nothing -> None - end - entries - | Implies_not(suffix1, suffix2) -> - list_collect - begin function - | File(path, name, _, true) -> - if Filename.check_suffix name suffix1 then - begin - let base = Filename.chop_suffix name suffix1 in - let name' = base ^ suffix2 in - if List.exists - begin function - | File(_, name'', _, true) -> name' = name'' - | File _ | Dir _ | Error _ | Nothing -> false - end - entries - then - begin - remove path name'; - Some(sf "Files %s and %s should not be together in %s" name name' path) - end - else - None - end - else - None - | File _ | Dir _ | Error _ | Nothing -> None - end - entries - in - let rec check_entry = function - | Dir(_,_,_,true,entries) -> - List.iter - begin fun law -> - match List.concat (List.map (check_rule !*entries) law.law_rules) with - | [] -> () - | explanations -> - penalties := (law, explanations) :: !penalties - end - laws; - List.iter check_entry !*entries - | Dir _ | File _ | Error _ | Nothing -> () - in - check_entry entry; - begin - let microbes = !microbes in - if not (SS.is_empty microbes) then - begin - match sanitize with - | None -> - Log.eprintf "sanitize: the following are files that should probably not be in your\n\ - source tree:\n"; - SS.iter - begin fun fn -> - Log.eprintf " %s" fn - end - microbes; - Log.eprintf "Remove them manually, don't use the -no-sanitize option, use -no-hygiene, or\n\ - define hygiene exceptions using the tags or plugin mechanism.\n"; - raise Exit_hygiene_violations - | Some fn -> - let m = SS.cardinal microbes in - Log.eprintf - "@[SANITIZE:@ a@ total@ of@ %d@ file%s@ that@ should@ probably\ - @ not@ be@ in@ your@ source@ tree@ has@ been@ found.\ - @ A@ script@ shell@ file@ %S@ is@ being@ created.\ - @ Check@ this@ script@ and@ run@ it@ to@ remove@ unwanted@ files\ - @ or@ use@ other@ options@ (such@ as@ defining@ hygiene@ exceptions\ - @ or@ using@ the@ -no-hygiene@ option).@]" - m (if m = 1 then "" else "s") fn; - let oc = open_out_gen [Open_wronly; Open_creat; Open_trunc; Open_binary] 0o777 fn in - (* See PR #5338: under mingw, one produces a shell script, which must follow - Unix eol convention; hence Open_binary. *) - let fp = Printf.fprintf in - fp oc "#!/bin/sh\n\ - # File generated by ocamlbuild\n\ - \n\ - cd %s\n\ - \n" (Shell.quote_filename_if_needed Pathname.pwd); - SS.iter - begin fun fn -> - fp oc "rm -f %s\n" (Shell.quote_filename_if_needed fn) - end - microbes; - (* Also clean itself *) - fp oc "# Also clean the script itself\n"; - fp oc "rm -f %s\n" (Shell.quote_filename_if_needed fn); - close_out oc - end; - !penalties - end -;; diff --git a/ocamlbuild/hygiene.mli b/ocamlbuild/hygiene.mli deleted file mode 100644 index 1dd55f8a..00000000 --- a/ocamlbuild/hygiene.mli +++ /dev/null @@ -1,47 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Hygiene *) - -(** Module for checking that the source tree is not polluted by object files. *) - -(** Sanity rules to abide. Not to be confused with compilation rules. *) -type rule = - Implies_not of pattern * pattern (** The rule [Implies_not(".mll",".ml")] is broken if there is a file [foo.mll] - together with a file [foo.ml] int the same directory. The second file can - get sanitized. *) -| Not of pattern (* No files with suffix [pattern] will be tolerated. *) - -(** Suffix matching is enough for the purpose of this module. *) -and pattern = suffix - -(** And a suffix is a string. *) -and suffix = string - -(** A warning is simply displayed. A failures stops the compilation. *) -type penalty = Warn | Fail - -(** This type is used to encode laws that will be checked by this module. *) -type law = { - law_name : string; (** The name of the law that will be printed when it is violated. *) - law_rules : rule list; (** Breaking any of these rules is breaking this law. *) - law_penalty : penalty; (** Breaking the law gives you either a warning or a failure. *) -} - -(** [check ~sanitize laws entry] will scan the directory tree [entry] for violation to the given [laws]. - Any warnings or errors will be printed on the [stdout]. If [sanitize] is [Some fn], a shell script will be written - into the file [fn] with commands to delete the offending files. The command will return a pair [(fatal, penalties)] - where [fatal] is [true] when serious hygiene violations have been spotted, and [penalties] is a list of laws and - messages describing the offenses. *) -val check : ?sanitize:string -> law list -> bool Slurp.entry -> (law * string list) list diff --git a/ocamlbuild/lexers.mli b/ocamlbuild/lexers.mli deleted file mode 100644 index 5b14f04c..00000000 --- a/ocamlbuild/lexers.mli +++ /dev/null @@ -1,48 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -exception Error of (string * Loc.location) - -type conf_values = - { plus_tags : (string * Loc.location) list; - minus_tags : (string * Loc.location) list } - -type conf = (Glob.globber * conf_values) list - -val ocamldep_output : Loc.source -> Lexing.lexbuf -> (string * string list) list -val space_sep_strings : Loc.source -> Lexing.lexbuf -> string list -val blank_sep_strings : Loc.source -> Lexing.lexbuf -> string list -val comma_sep_strings : Loc.source -> Lexing.lexbuf -> string list -val comma_or_blank_sep_strings : Loc.source -> Lexing.lexbuf -> string list -val trim_blanks : Loc.source -> Lexing.lexbuf -> string - -(* Parse an environment path (i.e. $PATH). - This is a colon separated string. - Note: successive colons means an empty string. - Example: - ":aaa:bbb:::ccc:" -> [""; "aaa"; "bbb"; ""; ""; "ccc"; ""] *) -val parse_environment_path : Loc.source -> Lexing.lexbuf -> string list -(* Same one, for Windows (PATH is ;-separated) *) -val parse_environment_path_w : Loc.source -> Lexing.lexbuf -> string list - -val conf_lines : string option -> Loc.source -> Lexing.lexbuf -> conf -val path_scheme : bool -> Loc.source -> Lexing.lexbuf -> - [ `Word of string - | `Var of (string * Glob.globber) - ] list - -val ocamlfind_query : Loc.source -> Lexing.lexbuf -> - string * string * string * string * string * string - -val tag_gen : Loc.source -> Lexing.lexbuf -> string * string option diff --git a/ocamlbuild/lexers.mll b/ocamlbuild/lexers.mll deleted file mode 100644 index d0b8cfdb..00000000 --- a/ocamlbuild/lexers.mll +++ /dev/null @@ -1,191 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -{ -exception Error of (string * Loc.location) - -let error source lexbuf fmt = - Printf.ksprintf (fun s -> - raise (Error (s, Loc.of_lexbuf source lexbuf)) - ) fmt - -open Glob_ast - -type conf_values = - { plus_tags : (string * Loc.location) list; - minus_tags : (string * Loc.location) list } - -type conf = (Glob.globber * conf_values) list - -let empty = { plus_tags = []; minus_tags = [] } - -let locate source lexbuf txt = - (txt, Loc.of_lexbuf source lexbuf) - -let sublex lexer s = lexer (Lexing.from_string s) -} - -let newline = ('\n' | '\r' | "\r\n") -let space = [' ' '\t' '\012'] -let space_or_esc_nl = (space | '\\' newline) -let sp = space_or_esc_nl -let blank = newline | space -let not_blank = [^' ' '\t' '\012' '\n' '\r'] -let not_space_nor_comma = [^' ' '\t' '\012' ','] -let not_newline = [^ '\n' '\r' ] -let not_newline_nor_colon = [^ '\n' '\r' ':' ] -let normal_flag_value = [^ '(' ')' '\n' '\r'] -let normal = [^ ':' ',' '(' ')' ''' ' ' '\n' '\r'] -let tag = normal+ | ( normal+ ':' normal+ ) | normal+ '(' [^ ')' ]* ')' -let variable = [ 'a'-'z' 'A'-'Z' '_' '-' '0'-'9' ]* -let pattern = ([^ '(' ')' '\\' ] | '\\' [ '(' ')' ])* - -rule ocamldep_output source = parse - | ([^ ':' '\n' '\r' ]+ as k) ':' { let x = (k, space_sep_strings_nl source lexbuf) in x :: ocamldep_output source lexbuf } - | eof { [] } - | _ { error source lexbuf "Expecting colon followed by space-separated module name list" } - -and space_sep_strings_nl source = parse - | space* (not_blank+ as word) { word :: space_sep_strings_nl source lexbuf } - | space* newline { Lexing.new_line lexbuf; [] } - | _ { error source lexbuf "Expecting space-separated strings terminated with newline" } - -and space_sep_strings source = parse - | space* (not_blank+ as word) { word :: space_sep_strings source lexbuf } - | space* newline? eof { [] } - | _ { error source lexbuf "Expecting space-separated strings" } - -and blank_sep_strings source = parse - | blank* '#' not_newline* newline { blank_sep_strings source lexbuf } - | blank* '#' not_newline* eof { [] } - | blank* (not_blank+ as word) { word :: blank_sep_strings source lexbuf } - | blank* eof { [] } - | _ { error source lexbuf "Expecting blank-separated strings" } - -and comma_sep_strings source = parse - | space* (not_space_nor_comma+ as word) space* eof { [word] } - | space* (not_space_nor_comma+ as word) { word :: comma_sep_strings_aux source lexbuf } - | space* eof { [] } - | _ { error source lexbuf "Expecting comma-separated strings (1)" } -and comma_sep_strings_aux source = parse - | space* ',' space* (not_space_nor_comma+ as word) { word :: comma_sep_strings_aux source lexbuf } - | space* eof { [] } - | _ { error source lexbuf "Expecting comma-separated strings (2)" } - -and comma_or_blank_sep_strings source = parse - | space* (not_space_nor_comma+ as word) space* eof { [word] } - | space* (not_space_nor_comma+ as word) { word :: comma_or_blank_sep_strings_aux source lexbuf } - | space* eof { [] } - | _ { error source lexbuf "Expecting (comma|blank)-separated strings (1)" } -and comma_or_blank_sep_strings_aux source = parse - | space* ',' space* (not_space_nor_comma+ as word) { word :: comma_or_blank_sep_strings_aux source lexbuf } - | space* (not_space_nor_comma+ as word) { word :: comma_or_blank_sep_strings_aux source lexbuf } - | space* eof { [] } - | _ { error source lexbuf "Expecting (comma|blank)-separated strings (2)" } - -and parse_environment_path_w source = parse - | ([^ ';']* as word) { word :: parse_environment_path_aux_w source lexbuf } - | ';' ([^ ';']* as word) { "" :: word :: parse_environment_path_aux_w source lexbuf } - | eof { [] } -and parse_environment_path_aux_w source = parse - | ';' ([^ ';']* as word) { word :: parse_environment_path_aux_w source lexbuf } - | eof { [] } - | _ { error source lexbuf "Impossible: expecting colon-separated strings" } - -and parse_environment_path source = parse - | ([^ ':']* as word) { word :: parse_environment_path_aux source lexbuf } - | ':' ([^ ':']* as word) { "" :: word :: parse_environment_path_aux source lexbuf } - | eof { [] } -and parse_environment_path_aux source = parse - | ':' ([^ ':']* as word) { word :: parse_environment_path_aux source lexbuf } - | eof { [] } - | _ { error source lexbuf "Impossible: expecting colon-separated strings" } - -and conf_lines dir source = parse - | space* '#' not_newline* newline { Lexing.new_line lexbuf; conf_lines dir source lexbuf } - | space* '#' not_newline* eof { [] } - | space* newline { Lexing.new_line lexbuf; conf_lines dir source lexbuf } - | space* eof { [] } - | space* (not_newline_nor_colon+ as k) (sp* as s1) ':' (sp* as s2) - { - let bexpr = - try Glob.parse ?dir k - with exn -> error source lexbuf "Invalid globbing pattern %S" k (Printexc.to_string exn) - in - sublex (count_lines lexbuf) s1; sublex (count_lines lexbuf) s2; - let v1 = conf_value empty source lexbuf in - let v2 = conf_values v1 source lexbuf in - let rest = conf_lines dir source lexbuf in (bexpr,v2) :: rest - } - | _ { error source lexbuf "Invalid line syntax" } - -and conf_value x source = parse - | '-' (tag as tag) { { (x) with minus_tags = locate source lexbuf tag :: x.minus_tags } } - | '+'? (tag as tag) { { (x) with plus_tags = locate source lexbuf tag :: x.plus_tags } } - | (_ | eof) { error source lexbuf "Invalid tag modifier only '+ or '-' are allowed as prefix for tag" } - -and conf_values x source = parse - | (sp* as s1) ',' (sp* as s2) { - sublex (count_lines lexbuf) s1; sublex (count_lines lexbuf) s2; - conf_values (conf_value x source lexbuf) source lexbuf - } - | newline { Lexing.new_line lexbuf; x } - | eof { x } - | _ { error source lexbuf "Only ',' separated tags are alllowed" } - -and path_scheme patt_allowed source = parse - | ([^ '%' ]+ as prefix) - { `Word prefix :: path_scheme patt_allowed source lexbuf } - | "%(" (variable as var) ')' - { `Var (var, Bool.True) :: path_scheme patt_allowed source lexbuf } - | "%(" (variable as var) ':' (pattern as patt) ')' - { if patt_allowed then - let patt = My_std.String.implode (unescape (Lexing.from_string patt)) in - `Var (var, Glob.parse patt) :: path_scheme patt_allowed source lexbuf - else - error source lexbuf "Patterns are not allowed in this pathname (%%(%s:%s) only in ~prod)" var patt } - | '%' - { `Var ("", Bool.True) :: path_scheme patt_allowed source lexbuf } - | eof - { [] } - | _ { error source lexbuf "Bad pathanme scheme" } - -and unescape = parse - | '\\' (['(' ')'] as c) { c :: unescape lexbuf } - | _ as c { c :: unescape lexbuf } - | eof { [] } - -and ocamlfind_query source = parse - | newline* - "package:" space* (not_newline* as n) newline+ - "description:" space* (not_newline* as d) newline+ - "version:" space* (not_newline* as v) newline+ - "archive(s):" space* (not_newline* as a) newline+ - "linkopts:" space* (not_newline* as lo) newline+ - "location:" space* (not_newline* as l) newline+ - { n, d, v, a, lo, l } - | _ { error source lexbuf "Bad ocamlfind query" } - -and trim_blanks source = parse - | blank* (not_blank* as word) blank* { word } - | _ { error source lexbuf "Bad input for trim_blanks" } - -and tag_gen source = parse - | (normal+ as name) ('(' ([^')']* as param) ')')? { name, param } - | _ { error source lexbuf "Not a valid parametrized tag" } - -and count_lines lb = parse - | space* { count_lines lb lexbuf } - | '\\' newline { Lexing.new_line lb; count_lines lb lexbuf } - | eof { () } diff --git a/ocamlbuild/loc.ml b/ocamlbuild/loc.ml deleted file mode 100644 index 7a324c16..00000000 --- a/ocamlbuild/loc.ml +++ /dev/null @@ -1,35 +0,0 @@ -(* it's not worth adding a dependency on parsing/location.ml(i) or - compilerlibs just to support location printing, so we re-implement - that here *) - -open Lexing - -(* We use a loosely structural type so that this bit of code can be - easily reused by project that would wish it, without introducing - any type-compatibility burden. *) -type source = string (* "file", "environment variable", "command-line option" ... *) -type location = source * position * position - -let file loc = loc.pos_fname -let line loc = loc.pos_lnum -let char loc = loc.pos_cnum - loc.pos_bol - -let print_loc ppf (source, start, end_) = - let open Format in - let print one_or_two ppf (start_num, end_num) = - if one_or_two then fprintf ppf " %d" start_num - else fprintf ppf "s %d-%d" start_num end_num in - fprintf ppf "%s %S, line%a, character%a:@." - (String.capitalize source) - (file start) - (print (line start = line end_)) - (line start, line end_) - (print (line start = line end_ && char start = char end_)) - (char start, char end_) - -let of_lexbuf source lexbuf = - (source, lexbuf.lex_start_p, lexbuf.lex_curr_p) - -let print_loc_option ppf = function - | None -> () - | Some loc -> print_loc ppf loc diff --git a/ocamlbuild/loc.mli b/ocamlbuild/loc.mli deleted file mode 100644 index c5768bc1..00000000 --- a/ocamlbuild/loc.mli +++ /dev/null @@ -1,7 +0,0 @@ -type source = string -type location = source * Lexing.position * Lexing.position - -val print_loc : Format.formatter -> location -> unit -val print_loc_option : Format.formatter -> location option -> unit - -val of_lexbuf : source -> Lexing.lexbuf -> location diff --git a/ocamlbuild/log.ml b/ocamlbuild/log.ml deleted file mode 100644 index d50969e3..00000000 --- a/ocamlbuild/log.ml +++ /dev/null @@ -1,80 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std - -module Debug = struct -let mode _ = true -end -include Debug - -let level = ref 1 - -let classic_display = ref false -let internal_display = ref None -let failsafe_display = lazy (Display.create ~mode:`Classic ~log_level:!level ()) - -let ( !- ) r = - match !r with - | None -> !*failsafe_display - | Some x -> x - -let init log_file = - let mode = - if !classic_display || !*My_unix.is_degraded || !level <= 0 || not (My_unix.stdout_isatty ()) then - `Classic - else - `Sophisticated - in - internal_display := Some (Display.create ~mode ?log_file ~log_level:!level ()) - -let raw_dprintf log_level = Display.dprintf ~log_level !-internal_display - -let dprintf log_level fmt = raw_dprintf log_level ("@[<2>"^^fmt^^"@]@.") -let eprintf fmt = dprintf (-1) fmt - -let update () = Display.update !-internal_display -let event ?pretend x = Display.event !-internal_display ?pretend x -let display x = Display.display !-internal_display x - -let do_at_end = Queue.create () -let already_asked = Hashtbl.create 10 - -let at_end_always ~name thunk = - if not (Hashtbl.mem already_asked name) then begin - Hashtbl.add already_asked name (); - Queue.add thunk do_at_end; - end - -let at_end ~name thunk = at_end_always ~name (function - | `Quiet -> () - | `Success | `Error -> thunk `Error) -let at_failure ~name thunk = at_end_always ~name (function - | `Success | `Quiet -> () - | `Error -> thunk `Error) - -let finish ?how () = - while not (Queue.is_empty do_at_end) do - let actions = Queue.copy do_at_end in - Queue.clear do_at_end; - (* calling a thunk may add new actions again, hence the loop *) - Queue.iter (fun thunk -> - thunk (match how with None -> `Quiet | Some how -> how) - ) actions; - done; - match !internal_display with - | None -> () - | Some d -> Display.finish ?how d - -(*let () = My_unix.at_exit_once finish*) diff --git a/ocamlbuild/log.mli b/ocamlbuild/log.mli deleted file mode 100644 index 413a476d..00000000 --- a/ocamlbuild/log.mli +++ /dev/null @@ -1,44 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Log *) - -(** Module for modulating the logging output with the logging level. *) -include Signatures.LOG - -(** Turn it to true to have a classic display of commands. *) -val classic_display : bool ref - -(** See {Display.event}. *) -val event : ?pretend:bool -> string -> string -> Tags.t -> unit - -(**/**) - -(** Initialize the Log module given a log file name. *) -val init : string option -> unit - -val finish : ?how:[`Success|`Error|`Quiet] -> unit -> unit -val display : (out_channel -> unit) -> unit -val update : unit -> unit -val mode : string -> bool - -(** Wrap logging event so that only fire at the end of the compilation - process, possibly depending on the termination status. - - The name is used to avoid printing the same hint/warning twice, - even if [at_end] is called several times. Use different names for - distinct events. -*) -val at_end : name:string -> ([> `Error | `Quiet ] -> unit) -> unit -val at_failure : name:string -> ([> `Error ] -> unit) -> unit diff --git a/ocamlbuild/main.ml b/ocamlbuild/main.ml deleted file mode 100644 index d59a450b..00000000 --- a/ocamlbuild/main.ml +++ /dev/null @@ -1,356 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -open My_std -open Log -open Pathname.Operators -open Command -open Tools -open Ocaml_specific -open Format -;; - -exception Exit_build_error of string -exception Exit_silently - -let clean () = - Shell.rm_rf !Options.build_dir; - if !Options.make_links then begin - let entry = - Slurp.map (fun _ _ _ -> true) - (Slurp.slurp Filename.current_dir_name) - in - Slurp.force (Resource.clean_up_links entry) - end; - Log.finish (); - raise Exit_silently -;; - -let show_tags () = - if List.length !Options.show_tags > 0 then - Log.eprintf "Warning: the following tags do not include \ - dynamically-generated tags, such as link, compile, pack, byte, native, c, \ - pdf... (this list is by no means exhaustive).\n"; - List.iter begin fun path -> - Log.eprintf "@[<2>Tags for %S:@ {. %a .}@]" path Tags.print (tags_of_pathname path) - end !Options.show_tags -;; - -let show_documentation () = - Rule.show_documentation (); - Flags.show_documentation (); -;; - -(* these tags are used in an ad-hoc way by the ocamlbuild implementation; - this means that even if they were not part of any flag declaration, - they should be marked as useful, to avoid the "unused tag" warning. *) -let builtin_useful_tags = - Tags.of_list [ - "include"; "traverse"; "not_hygienic"; "precious"; - "pack"; "ocamlmklib"; "native"; "thread"; - "nopervasives"; "use_menhir"; "ocamldep"; - "thread"; - ] -;; - -let proceed () = - Hooks.call_hook Hooks.Before_options; - Options.init (); - Options.include_dirs := List.map Pathname.normalize !Options.include_dirs; - Options.exclude_dirs := List.map Pathname.normalize !Options.exclude_dirs; - if !Options.must_clean then clean (); - Hooks.call_hook Hooks.After_options; - let options_wd = Sys.getcwd () in - let first_run_for_plugin = - (* If we are in the first run before launching the plugin, we - should skip the user-visible operations (hygiene) that may need - information from the plugin to run as the user expects it. - - Note that we don't need to disable the [Hooks] call as they are - no-ops anyway, before any plugin has registered hooks. *) - Plugin.we_need_a_plugin () && not !Options.just_plugin in - - let target_dirs = List.union [] (List.map Pathname.dirname !Options.targets) in - - Configuration.parse_string ~source:Const.Source.builtin - "<**/*.ml> or <**/*.mli> or <**/*.mlpack> or <**/*.ml.depends>: ocaml\n\ - <**/*.byte>: ocaml, byte, program\n\ - <**/*.odoc>: ocaml, doc\n\ - <**/*.native>: ocaml, native, program\n\ - <**/*.cma>: ocaml, byte, library\n\ - <**/*.cmxa>: ocaml, native, library\n\ - <**/*.cmo>: ocaml, byte\n\ - <**/*.cmi>: ocaml, byte, native\n\ - <**/*.cmx>: ocaml, native\n\ - <**/*.mly>: infer\n\ - <**/.svn>|\".bzr\"|\".hg\"|\".git\"|\"_darcs\": -traverse\n\ - "; - - List.iter - (Configuration.parse_string ~source:Const.Source.command_line) - !Options.tag_lines; - - Configuration.tag_any !Options.tags; - if !Options.recursive || Options.ocamlbuild_project_heuristic () - then Configuration.tag_any ["traverse"]; - - (* options related to findlib *) - if !Options.use_ocamlfind then - List.iter - (fun pkg -> - let tag = Param_tags.make "package" pkg in - Configuration.tag_any [tag]) - !Options.ocaml_pkgs; - - begin match !Options.ocaml_syntax with - | Some syntax -> Configuration.tag_any [Param_tags.make "syntax" syntax] - | None -> () end; - - let newpwd = Sys.getcwd () in - Sys.chdir Pathname.pwd; - let entry_include_dirs = ref [] in - let entry = - Slurp.filter - begin fun path name () -> - let dir = - if path = Filename.current_dir_name then - None - else - Some path - in - let path_name = path/name in - - if name = "_tags" then begin - let tags_path = - (* PR#6482: remember that this code is run lazily by the Slurp command, - and may run only after the working directory has been changed. - - On the other hand, always using the absolute path makes - error messages longer and more frigthening in case of - syntax error in the _tags file. So we use the absolute - path only when necessary -- the working directory has - changed. *) - if Sys.getcwd () = Pathname.pwd then path_name - else Pathname.pwd / path_name in - ignore (Configuration.parse_file ?dir tags_path); - end; - - (List.mem name ["_oasis"] || (String.length name > 0 && name.[0] <> '_')) - && (name <> !Options.build_dir && not (List.mem name !Options.exclude_dirs)) - && begin - not (path_name <> Filename.current_dir_name && Pathname.is_directory path_name) - || begin - let tags = tags_of_pathname path_name in - (if Tags.mem "include" tags - || List.mem path_name !Options.include_dirs then - (entry_include_dirs := path_name :: !entry_include_dirs; true) - else - Tags.mem "traverse" tags - || List.exists (Pathname.is_prefix path_name) !Options.include_dirs - || List.exists (Pathname.is_prefix path_name) target_dirs) - && ((* beware: !Options.build_dir is an absolute directory *) - Pathname.normalize !Options.build_dir - <> Pathname.normalize (Pathname.pwd/path_name)) - end - end - end - (Slurp.slurp Filename.current_dir_name) - in - Hooks.call_hook Hooks.Before_hygiene; - let hygiene_entry = - Slurp.map begin fun path name () -> - let tags = tags_of_pathname (path/name) in - not (Tags.mem "not_hygienic" tags) && not (Tags.mem "precious" tags) - end entry in - Slurp.force hygiene_entry; - if !Options.hygiene && not first_run_for_plugin then - Fda.inspect hygiene_entry; - let entry = hygiene_entry in - Hooks.call_hook Hooks.After_hygiene; - Options.include_dirs := Pathname.current_dir_name :: List.rev !entry_include_dirs; - dprintf 3 "include directories are:@ %a" print_string_list !Options.include_dirs; - Options.entry := Some entry; - - Hooks.call_hook Hooks.Before_rules; - Ocaml_specific.init (); - Hooks.call_hook Hooks.After_rules; - - Sys.chdir options_wd; - Plugin.execute_plugin_if_needed (); - - (* [Param_tags.init ()] is called *after* the plugin is executed, as - some of the parametrized tags present in the _tags files parsed - will be declared by the plugin, and would therefore result in - "tag X does not expect a parameter" warnings if initialized - before. Note that [Plugin.rebuild_plugin_if_needed] is careful to - partially initialize the tags that it uses for plugin compilation. *) - Param_tags.init (); - - Sys.chdir newpwd; - (*let () = dprintf 0 "source_dir_path_set:@ %a" StringSet.print source_dir_path_set*) - - if !Options.show_documentation then begin - show_documentation (); - raise Exit_silently - end; - - let all_tags = - let builtin = builtin_useful_tags in - let used_in_flags = Flags.get_used_tags () in - let used_in_deps = - List.fold_left (fun acc (tags, _deps) -> Tags.union acc tags) - Tags.empty (Command.list_all_deps ()) - in - Tags.union builtin (Tags.union used_in_flags used_in_deps) in - Configuration.check_tags_usage all_tags; - - Digest_cache.init (); - - Sys.catch_break true; - - show_tags (); - - let targets = - List.map begin fun starget -> - let starget = Resource.import starget in - let target = path_and_context_of_string starget in - let ext = Pathname.get_extension starget in - (target, starget, ext) - end !Options.targets in - - try - let targets = - List.map begin fun (target, starget, ext) -> - Shell.mkdir_p (Pathname.dirname starget); - let target = Solver.solve_target starget target in - (target, ext) - end targets in - - Command.dump_parallel_stats (); - - Log.finish (); - - Shell.chdir Pathname.pwd; - - let call spec = sys_command (Command.string_of_command_spec spec) in - - let cmds = - List.fold_right begin fun (target, ext) acc -> - let cmd = !Options.build_dir/target in - let link x = - if !Options.make_links then ignore (call (S [A"ln"; A"-sf"; P x; A Pathname.current_dir_name])) in - match ext with - | "byte" | "native" | "top" -> - link cmd; cmd :: acc - | "html" -> - link (Pathname.dirname cmd); acc - | _ -> - if !Options.program_to_execute then - eprintf "Warning: Won't execute %s whose extension is neither .byte nor .native" cmd; - acc - end targets [] in - - if !Options.program_to_execute then - begin - match List.rev cmds with - | [] -> raise (Exit_usage "Using -- requires one target"); - | cmd :: rest -> - if rest <> [] then dprintf 0 "Warning: Using -- only run the last target"; - let cmd_spec = S [P cmd; atomize !Options.program_args] in - dprintf 3 "Running the user command:@ %a" Pathname.print cmd; - raise (Exit_with_code (call cmd_spec)) (* Exit with the exit code of the called command *) - end - else - () - with - | Ocaml_dependencies.Circular_dependencies(cycle, p) -> - raise - (Exit_build_error - (sbprintf "@[<2>Circular dependencies: %S already seen in@ %a@]@." p pp_l cycle)) -;; - -open Exit_codes;; - -let main () = - let exit rc = - Log.finish ~how:(if rc <> 0 then `Error else `Success) (); - Pervasives.exit rc - in - try - proceed () - with e -> - if !Options.catch_errors then - try raise e with - | Exit_OK -> exit rc_ok - | Fda.Exit_hygiene_failed -> - Log.eprintf "Exiting due to hygiene violations."; - exit rc_hygiene - | Exit_usage u -> - Log.eprintf "Usage:@ %s." u; - exit rc_usage - | Exit_system_error msg -> - Log.eprintf "System error:@ %s." msg; - exit rc_system_error - | Exit_with_code rc -> - exit rc - | Exit_silently -> - Log.finish ~how:`Quiet (); - Pervasives.exit rc_ok - | Exit_silently_with_code rc -> - Log.finish ~how:`Quiet (); - Pervasives.exit rc - | Solver.Failed backtrace -> - Log.raw_dprintf (-1) "@[@[<2>Solver failed:@ %a@]@." - Report.print_backtrace_analyze backtrace; - Log.raw_dprintf 1 "@[Backtrace:%a@]@]@." - Report.print_backtrace backtrace; - exit rc_solver_failed - | Failure s -> - Log.eprintf "Failure:@ %s." s; - exit rc_failure - | Solver.Circular(r, rs) -> - Log.eprintf "Circular build detected@ (%a already seen in %a)" - Resource.print r (List.print Resource.print) rs; - exit rc_circularity - | Invalid_argument s -> - Log.eprintf - "INTERNAL ERROR: Invalid argument %s\n\ - This is likely to be a bug, please report this to the ocamlbuild\n\ - developers." s; - exit rc_invalid_argument - | Ocaml_utils.Ocamldep_error msg -> - Log.eprintf "Ocamldep error: %s" msg; - exit rc_ocamldep_error - | Lexers.Error (msg,loc) -> - Log.eprintf "%aLexing error: %s." Loc.print_loc loc msg; - exit rc_lexing_error - | Arg.Bad msg -> - Log.eprintf "%s" msg; - exit rc_usage - | Exit_build_error msg -> - Log.eprintf "%s" msg; - exit rc_build_error - | Arg.Help msg -> - Log.eprintf "%s" msg; - exit rc_ok - | e -> - try - Log.eprintf "%a" My_unix.report_error e; - exit 100 - with - | e -> - Log.eprintf "Exception@ %s." (Printexc.to_string e); - exit 100 - else raise e -;; diff --git a/ocamlbuild/main.mli b/ocamlbuild/main.mli deleted file mode 100644 index d9e781f8..00000000 --- a/ocamlbuild/main.mli +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -val main : unit -> unit diff --git a/ocamlbuild/man/ocamlbuild.1 b/ocamlbuild/man/ocamlbuild.1 deleted file mode 100644 index b02d340b..00000000 --- a/ocamlbuild/man/ocamlbuild.1 +++ /dev/null @@ -1,268 +0,0 @@ -.\"***********************************************************************) -.\"* *) -.\"* ocamlbuild *) -.\"* *) -.\"* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -.\"* *) -.\"* Copyright 2007 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. *) -.\"* *) -.\"***********************************************************************) -.\" -.TH OCAMLBUILD 1 - -.SH NAME -ocamlbuild \- The OCaml project compilation tool - - -.SH SYNOPSIS -.B ocamlbuild -[ -.B \-Is \ dir1,... -] -[ -.BI \-libs \ lib1,... -] -[ -.BI \-lflags \ flag1,... -] -[ -.BI \-pp \ flags -] -[ -.BI \-tags \ tag1,... -] -[ -.B \-j \ parallel-jobs -] -.I target.native -[ -.B \-\- arg1 arg2 ... -] - -.I (same options) - -.SH DESCRIPTION - -.BR ocamlbuild (1) -orchestrates the compilation process of your OCaml project. It is similar -in function to -.BR make (1) -except that it is tailor-made to automatically compile most OCaml projects -with very little user input. - -.BR ocamlbuild -should be invoked in the root of a clean project tree (e.g., with no leftover -compilation files). Given one or more targets to compile, it scans the required -subdirectories to gather information about the various files present, running -tools such as -.BR ocamldep (1) -to extract dependency information, and gathering optional files that fine-tune -its behaviour. -Target names are very significant. - -.SH TARGET NAMES -.BR ocamlbuild -uses a set of target naming conventions to select the kind of objects to -produce. Target names are of the form -.BR base.extension -where -.BR base -is usually the name of the underlying OCaml module and -.BR extension -denotes the kind of object to produce from that file -- a byte code executable, -a native executable, documentation... -Of course extensions such as -.BR .cmo, -.BR .cma, -.BR .cmi... -map to their usual counterparts. Here is a list of the most important -.BR ocamlbuild \&-specific -extensions: - -.TP 2i -.B .native -Native code executable - -.TP 2i -.B .byte -Byte code executable - -.TP 2i -.B .inferred.mli -Interface inferred with -.BR ocamlc -i - -.TP 2i -.B .docdir/index.html -HTML documentation generated with -.BR ocamldoc - -.PP - -.SH OPTIONS - -The following command-line options are recognized by -.BR ocamlbuild (1). - -.TP -\fB\-version\fR -Display the version -.TP -\fB\-quiet\fR -Make as quiet as possible -.TP -\fB\-verbose\fR -Set the verbose level -.TP -\fB\-documentation\fR -Show rules and flags -.TP -\fB\-log\fR -Set log file -.TP -\fB\-no\-log\fR -No log file -.TP -\fB\-clean\fR -Remove build directory and other files, then exit -.TP -\fB\-I\fR -Add to include directories -.TP -\fB\-Is\fR -(same as above, but accepts a comma\-separated list) -.TP -\fB\-X\fR -Directory to ignore -.TP -\fB\-Xs\fR -(idem) -.TP -\fB\-lib\fR -Link to this ocaml library -.TP -\fB\-libs\fR -(idem) -.TP -\fB\-lflag\fR -Add to ocamlc link flags -.TP -\fB\-lflags\fR -(idem) -.TP -\fB\-cflag\fR -Add to ocamlc compile flags -.TP -\fB\-cflags\fR -(idem) -.TP -\fB\-yaccflag\fR -Add to ocamlyacc flags -.TP -\fB\-yaccflags\fR -(idem) -.TP -\fB\-lexflag\fR -Add to ocamllex flags -.TP -\fB\-lexflags\fR -(idem) -.TP -\fB\-ppflag\fR -Add to ocaml preprocessing flags -.TP -\fB\-pp\fR -(idem) -.TP -\fB\-tag\fR -Add to default tags -.TP -\fB\-tags\fR -(idem) -.TP -\fB\-ignore\fR -Don't try to build these modules -.TP -\fB\-no\-links\fR -Don't make links of produced final targets -.TP -\fB\-no\-skip\fR -Don't skip modules that are requested by ocamldep but cannot be built -.TP -\fB\-no\-hygiene\fR -Don't apply sanity\-check rules -.TP -\fB\-no\-plugin\fR -Don't build myocamlbuild.ml -.TP -\fB\-no\-stdlib\fR -Don't ignore stdlib modules -.TP -\fB\-just\-plugin\fR -Just build myocamlbuild.ml -.TP -\fB\-byte\-plugin\fR -Don't use a native plugin but bytecode -.TP -\fB\-no-sanitize\fR -Do not enforce sanity\-check rules -.TP -\fB\-nothing\-should\-be\-rebuilt\fR -Fail if something needs to be rebuilt -.TP -\fB\-classic\-display\fR -Display executed commands the old\-fashioned way -.TP -\fB\-j\fR -Allow N jobs at once (0 for unlimited) -.TP -\fB\-build\-dir\fR -Set build directory -.TP -\fB\-install\-dir\fR -Set the install directory -.TP -\fB\-where\fR -Display the install directory -.TP -\fB\-ocamlc\fR -Set the OCaml bytecode compiler -.TP -\fB\-ocamlopt\fR -Set the OCaml native compiler -.TP -\fB\-ocamldep\fR -Set the OCaml dependency tool -.TP -\fB\-ocamldoc\fR -Set the OCaml documentation generator -.TP -\fB\-ocamlyacc\fR -Set the ocamlyacc tool -.TP -\fB\-ocamllex\fR -Set the ocamllex tool -.TP -\fB\-ocamlrun\fR -Set the ocamlrun tool -.TP -\fB\-\-\fR -Stop argument processing, remaining arguments are given to the user program -.TP -\fB\-help\fR -Display the list of options -.TP -\fB\-\-help\fR -Display the list of options -.PP - -.SH SEE ALSO -The -.BR ocamlbuild -manual, -.BR ocaml (1), -.BR make (1). -.br -.I The OCaml user's manual, chapter "Batch compilation". diff --git a/ocamlbuild/misc/opentracer.ml b/ocamlbuild/misc/opentracer.ml deleted file mode 100644 index f6dcc1f3..00000000 --- a/ocamlbuild/misc/opentracer.ml +++ /dev/null @@ -1,102 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -open My_std - -module type TRACER = sig - (** Call the given command using the tracer, it returns the exit status. *) - val call : string -> string list -> StringSet.t * Unix.process_status -end - -module Ktrace = struct - let process_line line (wait_a_string, set) = - let strings = Lexers.space_sep_strings (Lexing.from_string line) in - if wait_a_string then - match strings with - | [_; _; "NAMI"; file] -> false, StringSet.add file set - | _ -> failwith (Printf.sprintf "unexpected ktrace output line (%S)" line) - else - match strings with - | [_; _; "CALL"; fct] -> - (String.length fct > 5 && String.sub fct 0 5 = "open("), set - | _ -> false, set - - let call cmd args = - let tmp = Filename.temp_file "ktrace" "out" in - match Unix.fork () with - | 0 -> Unix.execvp "ktrace" (Array.of_list("-d"::"-i"::"-t"::"nc"::"-f"::tmp::cmd::args)) - | pid -> - let _, st = Unix.waitpid [] pid in - let ic = Unix.open_process_in (Printf.sprintf "kdump -f %s" (Filename.quote tmp)) in - let close () = ignore (Unix.close_process_in ic); Sys.remove tmp in - let set = - try - let rec loop acc = - match try Some (input_line ic) with End_of_file -> None with - | Some line -> loop (process_line line acc) - | None -> acc in - let _, set = loop (false, StringSet.empty) in - close (); - set - with e -> (close (); raise e) - in set, st - -end - -module Driver (T : TRACER) = struct - let usage () = - Printf.eprintf "Usage: %s [-a ]* *\n%!" Sys.argv.(0); - exit 2 - - let main () = - let log = "opentracer.log" in - let oc = - if sys_file_exists log then - open_out_gen [Open_wronly;Open_append;Open_text] 0 log - else - let oc = open_out log in - let () = output_string oc "---\n" in - oc in - let rec loop acc = - function - | "-a" :: file :: rest -> loop (StringSet.add file acc) rest - | "-a" :: _ -> usage () - | "--" :: cmd :: args -> acc, cmd, args - | cmd :: args -> acc, cmd, args - | [] -> usage () in - let authorized_files, cmd, args = - loop StringSet.empty (List.tl (Array.to_list Sys.argv)) in - let opened_files, st = T.call cmd args in - let forbidden_files = StringSet.diff opened_files authorized_files in - - if not (StringSet.is_empty forbidden_files) then begin - Printf.fprintf oc "- cmd: %s\n args:\n%!" cmd; - let pp = Printf.fprintf oc " - %s\n%!" in - List.iter pp args; - Printf.fprintf oc " forbidden_files:\n%!"; - StringSet.iter pp forbidden_files; - end; - close_out oc; - match st with - | Unix.WEXITED st -> exit st - | Unix.WSIGNALED s | Unix.WSTOPPED s -> Unix.kill (Unix.getpid ()) s -end - -let main = - (* match os with *) - (* | "macos" -> *) - let module M = Driver(Ktrace) in M.main - (* | "linux" -> *) - (* let module M = Driver(Strace) in M.main *) - -let () = main () diff --git a/ocamlbuild/my_std.ml b/ocamlbuild/my_std.ml deleted file mode 100644 index 4dce7a0c..00000000 --- a/ocamlbuild/my_std.ml +++ /dev/null @@ -1,431 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open Format - -exception Exit_OK -exception Exit_usage of string -exception Exit_system_error of string -exception Exit_with_code of int -exception Exit_silently_with_code of int - -module Outcome = struct - type ('a,'b) t = - | Good of 'a - | Bad of 'b - - let ignore_good = - function - | Good _ -> () - | Bad e -> raise e - - let good = - function - | Good x -> x - | Bad exn -> raise exn - - let wrap f x = - try Good (f x) with e -> Bad e - -end - -let opt_print elt ppf = - function - | Some x -> fprintf ppf "@[<2>Some@ %a@]" elt x - | None -> pp_print_string ppf "None" - -open Format -let ksbprintf g fmt = - let buff = Buffer.create 42 in - let f = formatter_of_buffer buff in - kfprintf (fun f -> (pp_print_flush f (); g (Buffer.contents buff))) f fmt -let sbprintf fmt = ksbprintf (fun x -> x) fmt - -(** Some extensions of the standard library *) -module Set = struct - - module type OrderedTypePrintable = sig - include Set.OrderedType - val print : formatter -> t -> unit - end - - module type S = sig - include Set.S - val find_elt : (elt -> bool) -> t -> elt - val map : (elt -> elt) -> t -> t - val of_list : elt list -> t - val print : formatter -> t -> unit - end - - module Make (M : OrderedTypePrintable) : S with type elt = M.t = struct - include Set.Make(M) - exception Found of elt - let find_elt p set = - try - iter begin fun elt -> - if p elt then raise (Found elt) - end set; raise Not_found - with Found elt -> elt - let map f set = fold (fun x -> add (f x)) set empty - let of_list l = List.fold_right add l empty - let print f s = - let () = fprintf f "@[@[{.@ " in - let _ = - fold begin fun elt first -> - if not first then fprintf f ",@ "; - M.print f elt; - false - end s true in - fprintf f "@]@ .}@]" - end -end - -module List = struct - include List - let print pp_elt f ls = - fprintf f "@[<2>[@ "; - let _ = - fold_left begin fun first elt -> - if not first then fprintf f ";@ "; - pp_elt f elt; - false - end true ls in - fprintf f "@ ]@]" - - let filter_opt f xs = - List.fold_right begin fun x acc -> - match f x with - | Some x -> x :: acc - | None -> acc - end xs [] - - let rec rev_append_uniq acc = - function - | [] -> acc - | x :: xs -> - if mem x acc then rev_append_uniq acc xs - else rev_append_uniq (x :: acc) xs - - let union a b = - rev (rev_append_uniq (rev_append_uniq [] a) b) - - let ordered_unique (type el) (lst : el list) = - let module Set = Set.Make(struct - type t = el - let compare = Pervasives.compare - let print _ _ = () - end) - in - let _, lst = - List.fold_left (fun (set,acc) el -> - if Set.mem el set - then set, acc - else Set.add el set, el :: acc) (Set.empty,[]) lst - in - List.rev lst - -end - -module String = struct - include String - - let print f s = fprintf f "%S" s - - let chomp s = - let is_nl_char = function '\n' | '\r' -> true | _ -> false in - let rec cut n = - if n = 0 then 0 else if is_nl_char s.[n-1] then cut (n-1) else n - in - let ls = length s in - let n = cut ls in - if n = ls then s else sub s 0 n - - let before s pos = sub s 0 pos - let after s pos = sub s pos (length s - pos) - let first_chars s n = sub s 0 n - let last_chars s n = sub s (length s - n) n - - let rec eq_sub_strings s1 p1 s2 p2 len = - if len > 0 then s1.[p1] = s2.[p2] && eq_sub_strings s1 (p1+1) s2 (p2+1) (len-1) - else true - - let rec contains_string s1 p1 s2 = - let ls1 = length s1 in - let ls2 = length s2 in - try let pos = index_from s1 p1 s2.[0] in - if ls1 - pos < ls2 then None - else if eq_sub_strings s1 pos s2 0 ls2 then - Some pos else contains_string s1 (pos + 1) s2 - with Not_found -> None - - let subst patt repl s = - let lpatt = length patt in - let lrepl = length repl in - let rec loop s from = - match contains_string s from patt with - | Some pos -> - loop (before s pos ^ repl ^ after s (pos + lpatt)) (pos + lrepl) - | None -> s - in loop s 0 - - let tr patt subst text = - String.map (fun c -> if c = patt then subst else c) text - - (*** is_prefix : is u a prefix of v ? *) - let is_prefix u v = - let m = String.length u - and n = String.length v - in - m <= n && - let rec loop i = i = m || u.[i] = v.[i] && loop (i + 1) in - loop 0 - (* ***) - - (*** is_suffix : is v a suffix of u ? *) - let is_suffix u v = - let m = String.length u - and n = String.length v - in - n <= m && - let rec loop i = i = n || u.[m - 1 - i] = v.[n - 1 - i] && loop (i + 1) in - loop 0 - (* ***) - - let rev s = - let sl = String.length s in - let s' = Bytes.create sl in - for i = 0 to sl - 1 do - Bytes.set s' i s.[sl - i - 1] - done; - Bytes.to_string s';; - - let implode l = - match l with - | [] -> "" - | cs -> - let r = Bytes.create (List.length cs) in - let pos = ref 0 in - List.iter begin fun c -> - Bytes.unsafe_set r !pos c; - incr pos - end cs; - Bytes.to_string r - - let explode s = - let sl = String.length s in - let rec go pos = - if pos >= sl then [] else unsafe_get s pos :: go (pos + 1) - in go 0 -end - -module StringSet = Set.Make(String) - -let sys_readdir, reset_readdir_cache, reset_readdir_cache_for = - let cache = Hashtbl.create 103 in - let sys_readdir dir = - try Hashtbl.find cache dir with Not_found -> - let res = Outcome.wrap Sys.readdir dir in - (Hashtbl.add cache dir res; res) - and reset_readdir_cache () = - Hashtbl.clear cache - and reset_readdir_cache_for dir = - Hashtbl.remove cache dir in - (sys_readdir, reset_readdir_cache, reset_readdir_cache_for) - -let sys_file_exists x = - let dirname = Filename.dirname x in - let basename = Filename.basename x in - match sys_readdir dirname with - | Outcome.Bad _ -> false - | Outcome.Good a -> - if basename = Filename.current_dir_name then true else - try Array.iter (fun x -> if x = basename then raise Exit) a; false - with Exit -> true - -let sys_command = - match Sys.os_type with - | "Win32" -> fun cmd -> - if cmd = "" then 0 else - let cmd = "bash --norc -c "^Filename.quote cmd in - Sys.command cmd - | _ -> fun cmd -> if cmd = "" then 0 else Sys.command cmd - -(* FIXME warning fix and use Filename.concat *) -let filename_concat x y = - if x = Filename.current_dir_name || x = "" then y else - if Sys.os_type = "Win32" && (x.[String.length x - 1] = '\\') || x.[String.length x - 1] = '/' then - if y = "" then x - else x ^ y - else - x ^ "/" ^ y - -(* let reslash = - match Sys.os_type with - | "Win32" -> tr '\\' '/' - | _ -> (fun x -> x) *) - -open Format - -let invalid_arg' fmt = ksbprintf invalid_arg fmt - -let the = function Some x -> x | None -> invalid_arg "the: expect Some not None" - -let getenv ?default var = - try Sys.getenv var - with Not_found -> - match default with - | Some x -> x - | None -> failwith (sprintf "This command must have %S in his environment" var);; - -let with_input_file ?(bin=false) x f = - let ic = (if bin then open_in_bin else open_in) x in - try let res = f ic in close_in ic; res with e -> (close_in ic; raise e) - -let with_output_file ?(bin=false) x f = - reset_readdir_cache_for (Filename.dirname x); - let oc = (if bin then open_out_bin else open_out) x in - try let res = f oc in close_out oc; res with e -> (close_out oc; raise e) - -let read_file x = - with_input_file ~bin:true x begin fun ic -> - let len = in_channel_length ic in - really_input_string ic len - end - -let copy_chan ic oc = - let m = in_channel_length ic in - let m = (m lsr 12) lsl 12 in - let m = max 16384 (min Sys.max_string_length m) in - let buf = Bytes.create m in - let rec loop () = - let len = input ic buf 0 m in - if len > 0 then begin - output oc buf 0 len; - loop () - end - in loop () - -let copy_file src dest = - reset_readdir_cache_for (Filename.dirname dest); - with_input_file ~bin:true src begin fun ic -> - with_output_file ~bin:true dest begin fun oc -> - copy_chan ic oc - end - end - -let ( !* ) = Lazy.force - -let ( @:= ) ref list = ref := !ref @ list - -let ( & ) f x = f x - -let ( |> ) x f = f x - -let print_string_list = List.print String.print - -module Digest = struct - include Digest -(* USEFUL FOR DIGEST DEBUGING - let digest_log_hash = Hashtbl.create 103;; - let digest_log = "digest.log";; - let digest_log_oc = open_out_gen [Open_append;Open_wronly;Open_text;Open_creat] 0o666 digest_log;; - let my_to_hex x = to_hex x ^ ";";; - if sys_file_exists digest_log then - with_input_file digest_log begin fun ic -> - try while true do - let l = input_line ic in - Scanf.sscanf l "%S: %S" (Hashtbl.replace digest_log_hash) - done with End_of_file -> () - end;; - let string s = - let res = my_to_hex (string s) in - if try let x = Hashtbl.find digest_log_hash res in s <> x with Not_found -> true then begin - Hashtbl.replace digest_log_hash res s; - Printf.fprintf digest_log_oc "%S: %S\n%!" res s - end; - res - let file f = my_to_hex (file f) - let to_hex x = x -*) - - let digest_cache = Hashtbl.create 103 - let reset_digest_cache () = Hashtbl.clear digest_cache - let reset_digest_cache_for file = Hashtbl.remove digest_cache file - let file f = - try Hashtbl.find digest_cache f - with Not_found -> - let res = file f in - (Hashtbl.add digest_cache f res; res) -end - -let reset_filesys_cache () = - Digest.reset_digest_cache (); - reset_readdir_cache () - -let reset_filesys_cache_for_file file = - Digest.reset_digest_cache_for file; - reset_readdir_cache_for (Filename.dirname file) - -let sys_remove x = - reset_filesys_cache_for_file x; - Sys.remove x - -let with_temp_file pre suf fct = - let tmp = Filename.temp_file pre suf in - (* Sys.remove is used instead of sys_remove since we know that the tempfile is not that important *) - try let res = fct tmp in Sys.remove tmp; res - with e -> (Sys.remove tmp; raise e) - -let memo f = - let cache = Hashtbl.create 103 in - fun x -> - try Hashtbl.find cache x - with Not_found -> - let res = f x in - (Hashtbl.add cache x res; res) - -let memo2 f = - let cache = Hashtbl.create 103 in - fun x y -> - try Hashtbl.find cache (x,y) - with Not_found -> - let res = f x y in - (Hashtbl.add cache (x,y) res; res) - -let memo3 f = - let cache = Hashtbl.create 103 in - fun x y z -> - try Hashtbl.find cache (x,y,z) - with Not_found -> - let res = f x y z in - (Hashtbl.add cache (x,y,z) res; res) - -let set_lexbuf_fname fname lexbuf = - let open Lexing in - lexbuf.lex_start_p <- { lexbuf.lex_start_p with pos_fname = fname }; - lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = fname }; - () - -let lexbuf_of_string ?name content = - let lexbuf = Lexing.from_string content in - let fname = match name with - | Some name -> name - | None -> - (* 40: hope the location will fit one line of 80 chars *) - if String.length content < 40 && not (String.contains content '\n') then - String.escaped content - else "" - in - set_lexbuf_fname fname lexbuf; - lexbuf diff --git a/ocamlbuild/my_std.mli b/ocamlbuild/my_std.mli deleted file mode 100644 index d7e14637..00000000 --- a/ocamlbuild/my_std.mli +++ /dev/null @@ -1,67 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* My_std *) - -(** Generic utility functions, and system-independent glue. *) - -exception Exit_OK -exception Exit_usage of string -exception Exit_system_error of string -exception Exit_with_code of int -exception Exit_silently_with_code of int - -module Outcome : Signatures.OUTCOME - -val ksbprintf : (string -> 'a) -> ('b, Format.formatter, unit, 'a) format4 -> 'b -val sbprintf : ('a, Format.formatter, unit, string) format4 -> 'a - -module Set : sig - module type OrderedTypePrintable = Signatures.OrderedTypePrintable - module type S = Signatures.SET - module Make (M : OrderedTypePrintable) : S with type elt = M.t -end - -module List : Signatures.LIST - -module String : Signatures.STRING - -module Digest : sig - type t = string - val string : string -> t - val substring : string -> int -> int -> t - external channel : in_channel -> int -> t = "caml_md5_chan" - val file : string -> t - val output : out_channel -> t -> unit - val input : in_channel -> t - val to_hex : t -> string -end - -module StringSet : Set.S with type elt = String.t - -val sys_readdir : string -> (string array, exn) Outcome.t -val sys_remove : string -> unit -val reset_readdir_cache : unit -> unit -val reset_filesys_cache : unit -> unit -val reset_filesys_cache_for_file : string -> unit -val sys_file_exists : string -> bool -val sys_command : string -> int -val filename_concat : string -> string -> string - -val invalid_arg' : ('a, Format.formatter, unit, 'b) format4 -> 'a - -include Signatures.MISC - -val set_lexbuf_fname : string -> Lexing.lexbuf -> unit -val lexbuf_of_string : ?name:string -> string -> Lexing.lexbuf diff --git a/ocamlbuild/my_unix.ml b/ocamlbuild/my_unix.ml deleted file mode 100644 index 5bfbee01..00000000 --- a/ocamlbuild/my_unix.ml +++ /dev/null @@ -1,146 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std - -type file_kind = -| FK_dir -| FK_file -| FK_link -| FK_other - -type stats = - { - stat_file_kind : file_kind; - stat_key : string - } - -type implem = - { - mutable is_degraded : bool; - mutable is_link : string -> bool; - mutable run_and_open : 'a . string -> (in_channel -> 'a) -> 'a; - mutable readlink : string -> string; - mutable execute_many : ?max_jobs:int -> - ?ticker:(unit -> unit) -> - ?period:float -> - ?display:((out_channel -> unit) -> unit) -> - ((unit -> string) list list) -> - (bool list * exn) option; - mutable report_error : Format.formatter -> exn -> unit; - mutable at_exit_once : (unit -> unit) -> unit; - mutable gettimeofday : unit -> float; - mutable stdout_isatty : unit -> bool; - mutable stat : string -> stats; - mutable lstat : string -> stats; - } - -let is_degraded = true - -let stat f = - { stat_key = f; - stat_file_kind = - if sys_file_exists f then - if Sys.is_directory f then - FK_dir - else - FK_file - else let _ = with_input_file f input_char in assert false } - -let run_and_open s kont = - with_temp_file "ocamlbuild" "out" begin fun tmp -> - let s = Printf.sprintf "%s > '%s'" s tmp in - let st = sys_command s in - if st <> 0 then failwith (Printf.sprintf "Error while running: %s" s); - with_input_file tmp kont - end - -exception Not_a_link -exception No_such_file -exception Link_to_directories_not_supported - -let readlinkcmd = - let cache = Hashtbl.create 32 in - fun x -> - try Hashtbl.find cache x - with Not_found -> - run_and_open (Printf.sprintf "readlink %s" (Filename.quote x)) begin fun ic -> - let y = String.chomp (input_line ic) in - Hashtbl.replace cache x y; y - end - -let rec readlink x = - if sys_file_exists x then - try - let y = readlinkcmd x in - let y = - if Filename.is_relative y then - Filename.concat (Filename.dirname x) y - else - y - in - if (lstat y).stat_file_kind = FK_dir then raise Link_to_directories_not_supported else y - with Failure(_) -> raise Not_a_link - else raise No_such_file - -and is_link x = - try ignore(readlink x); true with - | No_such_file | Not_a_link -> false - -and lstat x = - if is_link x then { stat_key = x; stat_file_kind = FK_link } else stat x - -let implem = - { - is_degraded = true; - - stat = stat; - lstat = lstat; - readlink = readlink; - is_link = is_link; - run_and_open = run_and_open; - - (* at_exit_once is at_exit in the degraded mode since fork is not accessible in this mode *) - at_exit_once = at_exit; - report_error = (fun _ -> raise); - gettimeofday = (fun () -> assert false); - stdout_isatty = (fun () -> false); - execute_many = (fun ?max_jobs:(_) ?ticker:(_) ?period:(_) ?display:(_) _ -> assert false) - } - -let is_degraded = lazy implem.is_degraded -let stat x = implem.stat x -let lstat x = implem.lstat x -let readlink x = implem.readlink x -let is_link x = implem.is_link x -let run_and_open x = implem.run_and_open x -let at_exit_once x = implem.at_exit_once x -let report_error x = implem.report_error x -let gettimeofday x = implem.gettimeofday x -let stdout_isatty x = implem.stdout_isatty x -let execute_many ?max_jobs = implem.execute_many ?max_jobs - -let run_and_read cmd = - let bufsiz = 2048 in - let buf = Bytes.create bufsiz in - let totalbuf = Buffer.create 4096 in - implem.run_and_open cmd begin fun ic -> - let rec loop pos = - let len = input ic buf 0 bufsiz in - if len > 0 then begin - Buffer.add_subbytes totalbuf buf 0 len; - loop (pos + len) - end - in loop 0; Buffer.contents totalbuf - end diff --git a/ocamlbuild/my_unix.mli b/ocamlbuild/my_unix.mli deleted file mode 100644 index c7ee6e81..00000000 --- a/ocamlbuild/my_unix.mli +++ /dev/null @@ -1,74 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -type file_kind = -| FK_dir -| FK_file -| FK_link -| FK_other - -type stats = - { - stat_file_kind : file_kind; - stat_key : string - } - -val is_degraded : bool Lazy.t - -val is_link : string -> bool -val run_and_open : string -> (in_channel -> 'a) -> 'a -val readlink : string -> string -val run_and_read : string -> string - -(** See [Ocamlbuild_executor.execute] *) -val execute_many : - ?max_jobs:int -> - ?ticker:(unit -> unit) -> - ?period:float -> - ?display:((out_channel -> unit) -> unit) -> - ((unit -> string) list list) -> - (bool list * exn) option - -val report_error : Format.formatter -> exn -> unit -val at_exit_once : (unit -> unit) -> unit - -val gettimeofday : unit -> float - -val stdout_isatty : unit -> bool - -val stat : string -> stats -val lstat : string -> stats - -(** internal usage only *) -type implem = - { - mutable is_degraded : bool; - mutable is_link : string -> bool; - mutable run_and_open : 'a . string -> (in_channel -> 'a) -> 'a; - mutable readlink : string -> string; - mutable execute_many : ?max_jobs:int -> - ?ticker:(unit -> unit) -> - ?period:float -> - ?display:((out_channel -> unit) -> unit) -> - ((unit -> string) list list) -> - (bool list * exn) option; - mutable report_error : Format.formatter -> exn -> unit; - mutable at_exit_once : (unit -> unit) -> unit; - mutable gettimeofday : unit -> float; - mutable stdout_isatty : unit -> bool; - mutable stat : string -> stats; - mutable lstat : string -> stats; - } - -val implem : implem diff --git a/ocamlbuild/ocaml_arch.ml b/ocamlbuild/ocaml_arch.ml deleted file mode 100644 index cb5b7802..00000000 --- a/ocamlbuild/ocaml_arch.ml +++ /dev/null @@ -1,136 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Command -open Pathname.Operators - -type 'a arch = - | Arch_dir of string * 'a * 'a arch list - | Arch_dir_pack of string * 'a * 'a arch list - | Arch_file of string * 'a - -let dir name contents = Arch_dir(name, (), contents) -let dir_pack name contents = Arch_dir_pack(name, (), contents) -let file name = Arch_file(name, ()) - -type info = -{ - current_path : string; - include_dirs : string list; - for_pack : string; -} - -let join_pack parent base = - if parent = "" then base else parent ^ "." ^ base - -let annotate arch = - let rec self arch acc = - match arch with - | Arch_dir_pack(name, _, contents) -> - let acc = { (acc) with for_pack = join_pack acc.for_pack name } in - let (_, _, i, new_contents) = self_contents name contents acc in - ([], Arch_dir_pack(name, i, List.rev new_contents)) - | Arch_dir(name, _, contents) -> - let (current_path, include_dirs, i, new_contents) = self_contents name contents acc in - (current_path :: include_dirs, Arch_dir(name, i, List.rev new_contents)) - | Arch_file(name, _) -> - ([], Arch_file(name, acc)) - and self_contents name contents acc = - let current_path = acc.current_path/name in - let include_dirs = if current_path = "" then acc.include_dirs else current_path :: acc.include_dirs in - let i = { (acc) with current_path = current_path; include_dirs = include_dirs } in - let (include_dirs, new_contents) = - List.fold_left begin fun (include_dirs, new_contents) x -> - let j = { (i) with include_dirs = include_dirs @ i.include_dirs } in - let (include_dirs', x') = self x j in - (include_dirs @ include_dirs', x' :: new_contents) - end ([], []) contents in - (current_path, include_dirs, i, new_contents) in - let init = { current_path = ""; include_dirs = []; for_pack = "" } in - snd (self arch init) - -let rec print print_info f = - let rec print_contents f = - function - | [] -> () - | x :: xs -> Format.fprintf f "@ %a%a" (print print_info) x print_contents xs in - function - | Arch_dir(name, info, contents) -> - Format.fprintf f "@[dir %S%a%a@]" name print_info info print_contents contents - | Arch_dir_pack(name, info, contents) -> - Format.fprintf f "@[dir_pack %S%a%a@]" name print_info info print_contents contents - | Arch_file(name, info) -> - Format.fprintf f "@[<2>file %S%a@]" name print_info info - -let print_include_dirs = List.print String.print - -let print_info f i = - Format.fprintf f "@ @[{ @[<2>current_path =@ %S@];@\ - \ @[<2>include_dirs =@ %a@];@\ - \ @[<2>for_pack =@ %S@] }@]" - i.current_path print_include_dirs i.include_dirs i.for_pack - -let rec iter_info f = - function - | Arch_dir_pack(_, i, xs) | Arch_dir(_, i, xs) -> - f i; List.iter (iter_info f) xs - | Arch_file(_, i) -> f i - -let rec fold_info f arch acc = - match arch with - | Arch_dir_pack(_, i, xs) | Arch_dir(_, i, xs) -> - List.fold_right (fold_info f) xs (f i acc) - | Arch_file(_, i) -> f i acc - -module SS = Set.Make(String) - -let iter_include_dirs arch = - let set = fold_info (fun i -> List.fold_right SS.add i.include_dirs) arch SS.empty in - fun f -> SS.iter f set - -let forpack_flags_of_pathname = ref (fun _ -> N) - -let print_table print_value f table = - Format.fprintf f "@[{:@["; - Hashtbl.iter begin fun k v -> - if k <> "" then - Format.fprintf f "@ @[<2>%S =>@ %a@];" k print_value v; - end table; - Format.fprintf f "@]@ :}@]" - -let print_tables f (include_dirs_table, for_pack_table) = - Format.fprintf f "@[<2>@[<2>include_dirs_table:@ %a@];@ @[<2>for_pack_table: %a@]@]" - (print_table (List.print String.print)) include_dirs_table - (print_table String.print) for_pack_table - -let mk_tables arch = - let include_dirs_table = Hashtbl.create 17 - and for_pack_table = Hashtbl.create 17 in - iter_info begin fun i -> - Hashtbl.replace include_dirs_table i.current_path i.include_dirs; - Hashtbl.replace for_pack_table i.current_path i.for_pack - end arch; - let previous_forpack_flags_of_pathname = !forpack_flags_of_pathname in - forpack_flags_of_pathname := begin fun m -> - let m' = Pathname.dirname m in - try - let for_pack = Hashtbl.find for_pack_table m' in - if for_pack = "" then N else S[A"-for-pack"; A for_pack] - with Not_found -> previous_forpack_flags_of_pathname m - end; - (* Format.eprintf "@[<2>%a@]@." print_tables (include_dirs_table, for_pack_table); *) - (include_dirs_table, for_pack_table) - -let forpack_flags_of_pathname m = !forpack_flags_of_pathname m diff --git a/ocamlbuild/ocaml_arch.mli b/ocamlbuild/ocaml_arch.mli deleted file mode 100644 index 6739e8ff..00000000 --- a/ocamlbuild/ocaml_arch.mli +++ /dev/null @@ -1,17 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -include Signatures.ARCH -val forpack_flags_of_pathname : string -> Command.spec diff --git a/ocamlbuild/ocaml_compiler.ml b/ocamlbuild/ocaml_compiler.ml deleted file mode 100644 index 7526598f..00000000 --- a/ocamlbuild/ocaml_compiler.ml +++ /dev/null @@ -1,432 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log -open Pathname.Operators -open Tools -open Command -open Rule -open Tags.Operators -open Ocaml_utils -open Rule.Common_commands -open Outcome - -let forpack_flags arg tags = - if Tags.mem "pack" tags then - Ocaml_arch.forpack_flags_of_pathname arg - else N - -let ocamlc_c tags arg out = - let tags = tags++"ocaml"++"byte" in - Cmd (S [!Options.ocamlc; A"-c"; T(tags++"compile"); - ocaml_ppflags tags; ocaml_include_flags arg; A"-o"; Px out; P arg]) - -let ocamlc_link flag tags deps out = - Cmd (S [!Options.ocamlc; flag; T tags; - atomize_paths deps; A"-o"; Px out]) - -let ocamlc_link_lib = ocamlc_link (A"-a") -let ocamlc_link_prog = ocamlc_link N - -let ocamlmklib tags deps out = - Cmd (S [!Options.ocamlmklib; T tags; - atomize_paths deps; A"-o"; Px (Pathname.remove_extensions out)]) - -let ocamlmktop tags deps out = - Cmd( S [!Options.ocamlmktop; T (tags++"mktop"); - atomize_paths deps; A"-o"; Px out]) - -let byte_lib_linker tags = - if Tags.mem "ocamlmklib" tags then - ocamlmklib tags - else - ocamlc_link_lib tags - -let byte_lib_linker_tags tags = tags++"ocaml"++"link"++"byte"++"library" - -let ocamlc_p tags deps out = - Cmd (S [!Options.ocamlc; A"-pack"; T tags; - atomize_paths deps; A"-o"; Px out]) - -let ocamlopt_c tags arg out = - let tags = tags++"ocaml"++"native" in - Cmd (S [!Options.ocamlopt; A"-c"; Ocaml_arch.forpack_flags_of_pathname arg; - T(tags++"compile"); ocaml_ppflags tags; ocaml_include_flags arg; - A"-o"; Px out (* FIXME ocamlopt bug -o cannot be after the input file *); P arg]) - -let ocamlopt_link flag tags deps out = - Cmd (S [!Options.ocamlopt; flag; forpack_flags out tags; T tags; - atomize_paths deps; A"-o"; Px out]) - -let ocamlopt_link_lib = ocamlopt_link (A"-a") -let ocamlopt_link_shared_lib = ocamlopt_link (A"-shared") -let ocamlopt_link_prog = ocamlopt_link N - -let ocamlopt_p tags deps out = - let dirnames = List.union [] (List.map Pathname.dirname deps) in - let include_flags = List.fold_right ocaml_add_include_flag dirnames [] in - let mli = Pathname.update_extensions "mli" out in - let cmd = - S [!Options.ocamlopt; A"-pack"; forpack_flags out tags; T tags; - S include_flags; atomize_paths deps; - A"-o"; Px out] in - if (*FIXME true ||*) Pathname.exists mli then Cmd cmd - else - let rm = S[A"rm"; A"-f"; P mli] in - Cmd(S[A"touch"; P mli; Sh" ; if "; cmd; Sh" ; then "; rm; Sh" ; else "; - rm; Sh" ; exit 1; fi"]) - -let native_lib_linker tags = - if Tags.mem "ocamlmklib" tags then - ocamlmklib tags - else - ocamlopt_link_lib tags - -let native_shared_lib_linker tags = -(* ocamlmklib seems to not support -shared, is this OK? - if Tags.mem "ocamlmklib" tags then - ocamlmklib tags - else -*) - ocamlopt_link_shared_lib tags - -let native_lib_linker_tags tags = tags++"ocaml"++"link"++"native"++"library" - - -let prepare_compile build ml = - let dir = Pathname.dirname ml in - let include_dirs = Pathname.include_dirs_of dir in - let modules = path_dependencies_of ml in - let results = - build (List.map (fun (_, x) -> expand_module include_dirs x ["cmi"]) modules) in - List.iter2 begin fun (mandatory, name) res -> - match mandatory, res with - | _, Good _ -> () - | `mandatory, Bad exn -> - if not !Options.ignore_auto then raise exn; - dprintf 3 - "Warning: Failed to build the module %s requested by ocamldep." - name; - if not (!Options.recursive || Options.ocamlbuild_project_heuristic ()) - then Log.at_failure ~name:"a module failed to build, - while recursive traversal was disabled by fragile heuristic; - hint that having a _tags or myocamlbuild.ml would maybe solve - the build error" - (fun `Error -> - eprintf "Hint:@ Recursive@ traversal@ of@ subdirectories@ \ - was@ not@ enabled@ for@ this@ build,@ as@ the@ working@ \ - directory does@ not@ look@ like@ an@ ocamlbuild@ project@ \ - (no@ '_tags'@ or@ 'myocamlbuild.ml'@ file).@ \ - If@ you@ have@ modules@ in@ subdirectories,@ you@ should@ add@ \ - the@ option@ \"-r\"@ or@ create@ an@ empty@ '_tags'@ file.@\n\ - @\n\ - To@ enable@ recursive@ traversal@ for@ some@ subdirectories@ \ - only,@ you@ can@ use@ the@ following@ '_tags'@ file:@\n\ - @[@,\ - true: -traverse@,\ - or : traverse@,\ - @]" - ); - | `just_try, Bad _ -> () - end modules results - -let byte_compile_ocaml_interf mli cmi env build = - let mli = env mli and cmi = env cmi in - prepare_compile build mli; - ocamlc_c (tags_of_pathname mli++"interf") mli cmi - -(* given that .cmi can be built from either ocamlc and ocamlopt, this - "agnostic" rule chooses either compilers depending on whether the - "native" tag is present. This was requested during PR#4613 as way - to enable using ocamlbuild in environments where only ocamlopt is - available, not ocamlc. *) -let compile_ocaml_interf mli cmi env build = - let mli = env mli and cmi = env cmi in - prepare_compile build mli; - let tags = tags_of_pathname mli++"interf" in - let comp_c = if Tags.mem "native" tags then ocamlopt_c else ocamlc_c in - comp_c tags mli cmi - -let byte_compile_ocaml_implem ?tag ml cmo env build = - let ml = env ml and cmo = env cmo in - prepare_compile build ml; - ocamlc_c (Tags.union (tags_of_pathname ml) (tags_of_pathname cmo)++"implem"+++tag) ml cmo - -let cache_prepare_link = Hashtbl.create 107 -let rec prepare_link tag cmx extensions build = - let key = (tag, cmx, extensions) in - let dir = Pathname.dirname cmx in - let include_dirs = Pathname.include_dirs_of dir in - let ml = Pathname.update_extensions "ml" cmx in - let mli = Pathname.update_extensions "mli" cmx in - let modules = - List.union - (if Pathname.exists (ml-.-"depends") then path_dependencies_of ml else []) - (if Pathname.exists (mli-.-"depends") then path_dependencies_of mli else []) - in - let modules = - if (modules = []) && (Pathname.exists (ml^"pack")) then - List.map (fun s -> (`mandatory, s)) (string_list_of_file (ml^"pack")) - else - modules - in - if modules <> [] && not (Hashtbl.mem cache_prepare_link key) then - let () = Hashtbl.add cache_prepare_link key true in - let modules' = List.map (fun (_, x) -> expand_module include_dirs x extensions) modules in - List.iter2 begin fun (mandatory, _) result -> - match mandatory, result with - | _, Good p -> prepare_link tag p extensions build - | `mandatory, Bad exn -> if not !Options.ignore_auto then raise exn - | `just_try, Bad _ -> () - end modules (build modules') - -let native_compile_ocaml_implem ?tag ?(cmx_ext="cmx") ml env build = - let ml = env ml in - let cmi = Pathname.update_extensions "cmi" ml in - let cmx = Pathname.update_extensions cmx_ext ml in - prepare_link cmx cmi [cmx_ext; "cmi"] build; - ocamlopt_c (Tags.union (tags_of_pathname ml) (tags_of_pathname cmx)++"implem"+++tag) ml cmx - -let libs_of_use_lib tags = - Tags.fold begin fun tag acc -> - try let libpath, extern = Hashtbl.find info_libraries tag in - if extern then acc else libpath :: acc - with Not_found -> acc - end tags [] - -let prepare_libs cma_ext a_ext out build = - let out_no_ext = Pathname.remove_extension out in - let libs1 = List.union (libraries_of out_no_ext) (libs_of_use_lib (tags_of_pathname out)) in - let () = dprintf 10 "prepare_libs: %S -> %a" out pp_l libs1 in - let libs = List.map (fun x -> x-.-cma_ext) libs1 in - let libs2 = List.map (fun lib -> [lib-.-a_ext]) libs1 in - List.iter ignore_good (build libs2); libs - -let library_index = Hashtbl.create 32 -let package_index = Hashtbl.create 32 -let hidden_packages = ref [] - -let hide_package_contents package = hidden_packages := package :: !hidden_packages - -module Ocaml_dependencies_input = struct - let fold_dependencies = Resource.Cache.fold_dependencies - let fold_libraries f = Hashtbl.fold f library_index - let fold_packages f = Hashtbl.fold f package_index -end -module Ocaml_dependencies = Ocaml_dependencies.Make(Ocaml_dependencies_input) - -let caml_transitive_closure = Ocaml_dependencies.caml_transitive_closure - -let link_one_gen linker tagger cmX out env _build = - let cmX = env cmX and out = env out in - let tags = tagger (tags_of_pathname out) in - linker tags [cmX] out - -let link_gen cmX_ext cma_ext a_ext extensions linker tagger cmX out env build = - let cmX = env cmX and out = env out in - let tags = tagger (tags_of_pathname out) in - let dyndeps = Rule.build_deps_of_tags build (tags++"link_with") in - let cmi = Pathname.update_extensions "cmi" cmX in - prepare_link cmX cmi extensions build; - let libs = prepare_libs cma_ext a_ext out build in - let hidden_packages = List.map (fun x -> x-.-cmX_ext) !hidden_packages in - let deps = - caml_transitive_closure - ~caml_obj_ext:cmX_ext ~caml_lib_ext:cma_ext - ~used_libraries:libs ~hidden_packages (cmX :: dyndeps) in - let deps = (List.filter (fun l -> not (List.mem l deps)) libs) @ deps in - - (* Hack to avoid linking twice with the standard library. *) - let stdlib = "stdlib/stdlib"-.-cma_ext in - let is_not_stdlib x = x <> stdlib in - let deps = List.filter is_not_stdlib deps in - - if deps = [] then failwith "Link list cannot be empty"; - let () = dprintf 6 "link: %a -o %a" print_string_list deps Pathname.print out in - linker (tags++"dont_link_with") deps out - -let byte_link_gen = link_gen "cmo" "cma" "cma" ["cmo"; "cmi"] - -let byte_link = byte_link_gen ocamlc_link_prog - (fun tags -> tags++"ocaml"++"link"++"byte"++"program") - -let byte_output_obj = byte_link_gen ocamlc_link_prog - (fun tags -> tags++"ocaml"++"link"++"byte"++"output_obj") - -let byte_output_shared = byte_link_gen ocamlc_link_prog - (fun tags -> tags++"ocaml"++"link"++"byte"++"output_obj"++"output_shared") - -let byte_library_link = byte_link_gen byte_lib_linker byte_lib_linker_tags - -let byte_debug_link_gen = - link_gen "d.cmo" "d.cma" "d.cma" ["d.cmo"; "cmi"] - -let byte_debug_link = byte_debug_link_gen ocamlc_link_prog - (fun tags -> tags++"ocaml"++"link"++"byte"++"debug"++"program") - -let byte_debug_library_link = byte_debug_link_gen byte_lib_linker - (fun tags -> byte_lib_linker_tags tags++"debug") - -let native_link_gen linker = - link_gen "cmx" "cmxa" !Options.ext_lib [!Options.ext_obj; "cmi"] linker - -let native_link x = native_link_gen ocamlopt_link_prog - (fun tags -> tags++"ocaml"++"link"++"native"++"program") x - -let native_output_obj x = native_link_gen ocamlopt_link_prog - (fun tags -> tags++"ocaml"++"link"++"native"++"output_obj") x - -let native_output_shared x = native_link_gen ocamlopt_link_prog - (fun tags -> tags++"ocaml"++"link"++"native"++"output_obj"++"output_shared") x - -let native_library_link x = - native_link_gen native_lib_linker native_lib_linker_tags x - -let native_profile_link_gen linker = - link_gen "p.cmx" "p.cmxa" ("p" -.- !Options.ext_lib) ["p" -.- !Options.ext_obj; "cmi"] linker - -let native_profile_link x = native_profile_link_gen ocamlopt_link_prog - (fun tags -> tags++"ocaml"++"link"++"native"++"profile"++"program") x - -let native_profile_library_link x = native_profile_link_gen native_lib_linker - (fun tags -> native_lib_linker_tags tags++"profile") x - -let link_units table extensions cmX_ext cma_ext a_ext linker tagger contents_list cmX env build = - let cmX = env cmX in - let tags = tagger (tags_of_pathname cmX) in - let _ = Rule.build_deps_of_tags build tags in - let dir = - let dir1 = Pathname.remove_extensions cmX in - if Resource.exists_in_source_dir dir1 then dir1 - else Pathname.dirname cmX in - let include_dirs = Pathname.include_dirs_of dir in - let extension_keys = List.map fst extensions in - let libs = prepare_libs cma_ext a_ext cmX build in - let results = - build begin - List.map begin fun module_name -> - expand_module include_dirs module_name extension_keys - end contents_list - end in - let module_paths = - List.map begin function - | Good p -> - let extension_values = List.assoc (Pathname.get_extensions p) extensions in - List.iter begin fun ext -> - List.iter ignore_good (build [[Pathname.update_extensions ext p]]) - end extension_values; p - | Bad exn -> raise exn - end results in - Hashtbl.replace table cmX module_paths; - let hidden_packages = List.map (fun x -> x-.-cmX_ext) !hidden_packages in - let deps = - caml_transitive_closure - ~caml_obj_ext:cmX_ext ~caml_lib_ext:cma_ext - ~hidden_packages ~pack_mode:true module_paths in - let full_contents = libs @ module_paths in - let deps = List.filter (fun x -> List.mem x full_contents) deps in - let deps = (List.filter (fun l -> not (List.mem l deps)) libs) @ deps in - - (* Hack to avoid linking twice with the standard library. *) - let stdlib = "stdlib/stdlib"-.-cma_ext in - let is_not_stdlib x = x <> stdlib in - let deps = List.filter is_not_stdlib deps in - - linker tags deps cmX - -let link_modules = link_units library_index -let pack_modules = link_units package_index - -let link_from_file link modules_file cmX env build = - let modules_file = env modules_file in - let contents_list = string_list_of_file modules_file in - link contents_list cmX env build - -let byte_library_link_modules = - link_modules [("cmo",[])] "cmo" "cma" "cma" byte_lib_linker byte_lib_linker_tags - -let byte_library_link_mllib = link_from_file byte_library_link_modules - -let byte_toplevel_link_modules = - link_modules [("cmo",[])] "cmo" "cma" "cma" ocamlmktop - (fun tags -> tags++"ocaml"++"link"++"byte"++"toplevel") - -let byte_toplevel_link_mltop = link_from_file byte_toplevel_link_modules - -let byte_debug_library_link_modules = - link_modules [("d.cmo",[])] "d.cmo" "d.cma" "d.cma" byte_lib_linker - (fun tags -> byte_lib_linker_tags tags++"debug") - -let byte_debug_library_link_mllib = link_from_file byte_debug_library_link_modules - -let byte_pack_modules = - pack_modules [("cmo",["cmi"]); ("cmi",[])] "cmo" "cma" "cma" ocamlc_p - (fun tags -> tags++"ocaml"++"pack"++"byte") - -let byte_pack_mlpack = link_from_file byte_pack_modules - -let byte_debug_pack_modules = - pack_modules [("d.cmo",["cmi"]); ("cmi",[])] "d.cmo" "d.cma" "d.cma" ocamlc_p - (fun tags -> tags++"ocaml"++"pack"++"byte"++"debug") - -let byte_debug_pack_mlpack = link_from_file byte_debug_pack_modules - -let native_pack_modules x = - pack_modules [("cmx",["cmi"; !Options.ext_obj]); ("cmi",[])] "cmx" "cmxa" !Options.ext_lib ocamlopt_p - (fun tags -> tags++"ocaml"++"pack"++"native") x - -let native_pack_mlpack = link_from_file native_pack_modules - -let native_profile_pack_modules x = - pack_modules [("p.cmx",["cmi"; "p" -.- !Options.ext_obj]); ("cmi",[])] "p.cmx" "p.cmxa" - ("p" -.- !Options.ext_lib) ocamlopt_p - (fun tags -> tags++"ocaml"++"pack"++"native"++"profile") x - -let native_profile_pack_mlpack = link_from_file native_profile_pack_modules - -let native_library_link_modules x = - link_modules [("cmx",[!Options.ext_obj])] "cmx" "cmxa" - !Options.ext_lib native_lib_linker native_lib_linker_tags x - -let native_shared_library_link_modules x = - link_modules [("cmx",[!Options.ext_obj])] "cmx" "cmxa" - !Options.ext_lib native_shared_lib_linker - (fun tags -> native_lib_linker_tags tags++"shared") x - -let native_library_link_mllib = link_from_file native_library_link_modules - -let native_shared_library_link_mldylib = link_from_file native_shared_library_link_modules - -let native_shared_library_tags tags basetags = - List.fold_left (++) (basetags++"ocaml"++"link"++"native"++"shared"++"library") tags - -let native_shared_library_link ?(tags = []) x = - link_one_gen native_shared_lib_linker - (native_shared_library_tags tags) x - -let native_profile_library_link_modules x = - link_modules [("p.cmx",["p" -.- !Options.ext_obj])] "p.cmx" "p.cmxa" - ("p" -.- !Options.ext_lib) native_lib_linker - (fun tags -> native_lib_linker_tags tags++"profile") x - -let native_profile_shared_library_link_modules x = - link_modules [("p.cmx",["p" -.- !Options.ext_obj])] "p.cmx" "p.cmxa" - ("p" -.- !Options.ext_lib) native_shared_lib_linker - (fun tags -> native_lib_linker_tags tags++"shared"++"profile") x - -let native_profile_library_link_mllib = link_from_file native_profile_library_link_modules - -let native_profile_shared_library_link_mldylib = link_from_file native_profile_shared_library_link_modules diff --git a/ocamlbuild/ocaml_compiler.mli b/ocamlbuild/ocaml_compiler.mli deleted file mode 100644 index 0c951abd..00000000 --- a/ocamlbuild/ocaml_compiler.mli +++ /dev/null @@ -1,96 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -val forpack_flags : string -> Tags.t -> Command.spec -val ocamlc_c : Tags.t -> Pathname.t -> Pathname.t -> Command.t -val ocamlc_link_lib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlc_link_prog : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlc_p : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlopt_c : Tags.t -> Pathname.t -> Pathname.t -> Command.t -val ocamlopt_link_lib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlopt_link_shared_lib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlopt_link_prog : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlopt_p : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlmklib : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val ocamlmktop : Tags.t -> Pathname.t list -> Pathname.t -> Command.t -val prepare_compile : Rule.builder -> Pathname.t -> unit -val compile_ocaml_interf : string -> string -> Rule.action -val byte_compile_ocaml_interf : string -> string -> Rule.action -val byte_compile_ocaml_implem : ?tag:string -> string -> string -> Rule.action -val prepare_link : - Pathname.t -> Pathname.t -> - string list -> Rule.builder -> unit -val native_compile_ocaml_implem : ?tag:string -> ?cmx_ext:string -> string -> Rule.action -val prepare_libs : - string -> string -> Pathname.t -> - Rule.builder -> Pathname.t list -val link_gen : - string -> string -> string -> string list -> - (Tags.t -> Pathname.t list -> Pathname.t -> Command.t) -> - (Tags.t -> Tags.t) -> - string -> string -> Rule.action -val byte_link : string -> string -> Rule.action -val byte_output_obj : string -> string -> Rule.action -val byte_output_shared : string -> string -> Rule.action -val byte_library_link : string -> string -> Rule.action -val byte_debug_link : string -> string -> Rule.action -val byte_debug_library_link : string -> string -> Rule.action -val native_link : string -> string -> Rule.action -val native_output_obj : string -> string -> Rule.action -val native_output_shared : string -> string -> Rule.action -val native_library_link : string -> string -> Rule.action -val native_shared_library_link : ?tags:(string list) -> string -> string -> Rule.action -val native_profile_link : string -> string -> Rule.action -val native_profile_library_link : string -> string -> Rule.action -val link_modules : - (Pathname.t * string list) list -> - string -> string -> - string -> (Tags.t -> Pathname.t list -> Pathname.t -> Command.t) -> - (Tags.t -> Tags.t) -> - string list -> string -> Rule.action -val pack_modules : - (Pathname.t * string list) list -> - string -> string -> - string -> (Tags.t -> Pathname.t list -> Pathname.t -> Command.t) -> - (Tags.t -> Tags.t) -> - string list -> string -> Rule.action -val byte_library_link_modules : string list -> string -> Rule.action -val byte_library_link_mllib : string -> string -> Rule.action -val byte_debug_library_link_modules : string list -> string -> Rule.action -val byte_debug_library_link_mllib : string -> string -> Rule.action -val byte_pack_modules : string list -> string -> Rule.action -val byte_pack_mlpack : string -> string -> Rule.action -val byte_debug_pack_modules : string list -> string -> Rule.action -val byte_debug_pack_mlpack : string -> string -> Rule.action -val byte_toplevel_link_modules : string list -> string -> Rule.action -val byte_toplevel_link_mltop : string -> string -> Rule.action -val native_pack_modules : string list -> string -> Rule.action -val native_pack_mlpack : string -> string -> Rule.action -val native_library_link_modules : string list -> string -> Rule.action -val native_library_link_mllib : string -> string -> Rule.action -val native_shared_library_link_modules : string list -> string -> Rule.action -val native_shared_library_link_mldylib : string -> string -> Rule.action -val native_profile_pack_modules : string list -> string -> Rule.action -val native_profile_pack_mlpack : string -> string -> Rule.action -val native_profile_library_link_modules : string list -> string -> Rule.action -val native_profile_library_link_mllib : string -> string -> Rule.action -val native_profile_shared_library_link_modules : string list -> string -> Rule.action -val native_profile_shared_library_link_mldylib : string -> string -> Rule.action - -(** [hide_package_contents pack_name] - Don't treat the given package as an open package. - So a module will not be replaced during linking by - this package even if it contains that module. *) -val hide_package_contents : string -> unit diff --git a/ocamlbuild/ocaml_dependencies.ml b/ocamlbuild/ocaml_dependencies.ml deleted file mode 100644 index f62eb7d4..00000000 --- a/ocamlbuild/ocaml_dependencies.ml +++ /dev/null @@ -1,262 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Log -open Tools -open Ocaml_utils - -let mydprintf fmt = dprintf 10 fmt - -exception Circular_dependencies of string list * string - -module type INPUT = sig - val fold_dependencies : (string -> string -> 'a -> 'a) -> 'a -> 'a - val fold_libraries : (string -> string list -> 'a -> 'a) -> 'a -> 'a - val fold_packages : (string -> string list -> 'a -> 'a) -> 'a -> 'a -end - -module Make (I : INPUT) = struct - open I - - module SMap = Map.Make(String) - - module Resources = Resource.Resources - - module Utils = struct - let add = SMap.add - - let empty = SMap.empty - - let find_all_set x acc = - try SMap.find x acc with Not_found -> Resources.empty - - let smap_add_set src dst acc = - SMap.add src (Resources.add dst (find_all_set src acc)) acc - - let print_smap pp f smap = - Format.fprintf f "@[{:@["; - SMap.iter begin fun k v -> - Format.fprintf f "@ @[<2>%S =>@ %a@];" k pp v - end smap; - Format.fprintf f "@]@,:}@]" - - let print_smap_list = print_smap pp_l - - let print_smap_set = print_smap Resources.print - - let print_lazy pp f l = pp f !*l - - let find_all_list x acc = - try SMap.find x acc with Not_found -> [] - - let find_all_rec xs map = - let visited = Hashtbl.create 32 in - let rec self x acc = - try - Hashtbl.find visited x; acc - with Not_found -> - Hashtbl.replace visited x (); - let acc = Resources.add x acc in - try Resources.fold self (SMap.find x map) acc - with Not_found -> acc - in List.fold_right self xs Resources.empty - - let mkindex fold filter = - fold begin fun name contents acc -> - if filter name then - List.fold_right begin fun elt acc -> - add elt (name :: (find_all_list elt acc)) acc - end contents acc - else - acc - end empty - - end - open Utils - - let caml_transitive_closure - ?(caml_obj_ext="cmo") - ?(caml_lib_ext="cma") - ?(pack_mode=false) - ?(used_libraries=[]) - ?(hidden_packages=[]) fns = - - let valid_link_exts = - if pack_mode then [caml_obj_ext; "cmi"] - else [caml_obj_ext; caml_lib_ext] in - - mydprintf "caml_transitive_closure@ ~caml_obj_ext:%S@ ~pack_mode:%b@ ~used_libraries:%a@ %a" - caml_obj_ext pack_mode pp_l used_libraries pp_l fns; - - let packages = fold_packages (fun name _ -> Resources.add name) Resources.empty in - mydprintf "packages:@ %a" Resources.print packages; - - let caml_obj_ext_of_cmi x = - if Filename.check_suffix x ".cmi" then - Pathname.update_extensions caml_obj_ext x - else x in - - let maybe_caml_obj_ext_of_cmi x = - if pack_mode then - if Filename.check_suffix x ".cmi" then - let caml_obj = Pathname.update_extensions caml_obj_ext x in - if Resource.exists_in_build_dir caml_obj then - caml_obj - else - x - else - x - else - if Filename.check_suffix x ".cmi" then - Pathname.update_extensions caml_obj_ext x - else x in - - let not_linkable x = - not (List.exists (Pathname.check_extension x) valid_link_exts) in - - let dependency_map = - fold_dependencies begin fun x y acc -> - let x = maybe_caml_obj_ext_of_cmi x - and y = maybe_caml_obj_ext_of_cmi y in - if x = y || not_linkable x || not_linkable y then acc - else smap_add_set x y acc - end SMap.empty in - mydprintf "dependency_map:@ %a" print_smap_set dependency_map; - - let used_files = find_all_rec fns dependency_map in - mydprintf "used_files:@ %a" Resources.print used_files; - - let open_packages = - Resources.fold begin fun file acc -> - if Resources.mem file packages && not (List.mem file hidden_packages) - then file :: acc else acc - end used_files [] in - mydprintf "open_packages:@ %a" pp_l open_packages; - - let index_filter ext list x = - Pathname.check_extension x ext && List.mem x list in - - let lib_index = - lazy (mkindex fold_libraries (index_filter caml_lib_ext used_libraries)) in - mydprintf "lib_index:@ %a" (print_lazy print_smap_list) lib_index; - - let package_index = - lazy (mkindex fold_packages (index_filter caml_obj_ext open_packages)) in - - let rec resolve_packages x = - match find_all_list x !*package_index with - | [] -> x - | [x] -> resolve_packages x - | pkgs -> - failwith (sbprintf "the file %S is included in more than one active open package (%a)" - x pp_l pkgs) in - - let libs_of x = find_all_list x !*lib_index in - - let lib_of x = - match libs_of x with - | [] -> None - | [lib] -> Some(lib) - | libs -> - failwith (sbprintf "the file %S is included in more than one active library (%a)" - x pp_l libs) in - - let convert_dependency src dst acc = - let src = resolve_packages src in - let dst = resolve_packages dst in - let add_if_diff x y = if x = y then acc else smap_add_set x y acc in - match (lib_of src, lib_of dst) with - | None, None -> add_if_diff src dst - | Some(liba), Some(libb) -> add_if_diff liba libb - | Some(lib), None -> add_if_diff lib dst - | None, Some(lib) -> add_if_diff src lib in - - let dependencies = lazy begin - SMap.fold begin fun k -> - Resources.fold (convert_dependency k) - end dependency_map empty - end in - - mydprintf "dependencies:@ %a" (print_lazy print_smap_set) dependencies; - - let dependencies_of x = - try SMap.find x !*dependencies with Not_found -> Resources.empty in - - let refine_cycle files starting_file = - (* We are looking for a cycle starting from [fn], included in - [files]; we'll simply use a DFS which builds a path until it - finds a circularity. - - Note that if there is at least one cycle going through [fn], - calling [dfs path fn] will return it no matter what [path] is - (it may just not be the shortest possible cycle). This means - that if [dfs path fn] returns [None], [fn] is a dead-end that - should never be explored again. - *) - let dead_ends = ref Resources.empty in - let rec dfs path fn = - let through_dep f = function - | Some _ as cycle -> cycle - | None -> - if List.mem f path - then (* we have found a cycle *) - Some (List.rev path) - else if not (Resources.mem f files) - then - (* the neighbor is not in the set of paths known to have a cycle *) - None - else - (* look for cycles going through this neighbor *) - dfs (f :: path) f - in - if Resources.mem fn !dead_ends then None - else match Resources.fold through_dep (dependencies_of fn) None with - | Some _ as cycle -> cycle - | None -> dead_ends := Resources.add fn !dead_ends; None - in - match dfs [] starting_file with - | None -> Resources.elements files - | Some cycle -> cycle - in - - let needed_in_order = ref [] in - let needed = ref Resources.empty in - let seen = ref Resources.empty in - let rec aux fn = - if sys_file_exists fn && not (Resources.mem fn !needed) then begin - if Resources.mem fn !seen then - raise (Circular_dependencies (refine_cycle !seen fn, fn)); - seen := Resources.add fn !seen; - Resources.iter begin fun f -> - if sys_file_exists f then - if Filename.check_suffix f ".cmi" then - let f' = caml_obj_ext_of_cmi f in - if f' <> fn then - if sys_file_exists f' then aux f' - else if pack_mode then aux f else () - else () - else aux f - end (dependencies_of fn); - needed := Resources.add fn !needed; - needed_in_order := fn :: !needed_in_order - end - in - List.iter aux fns; - mydprintf "caml_transitive_closure:@ %a ->@ %a" - pp_l fns pp_l !needed_in_order; - List.rev !needed_in_order - - -end diff --git a/ocamlbuild/ocaml_dependencies.mli b/ocamlbuild/ocaml_dependencies.mli deleted file mode 100644 index b9e7812b..00000000 --- a/ocamlbuild/ocaml_dependencies.mli +++ /dev/null @@ -1,44 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(** OCaml dependencies *) - -exception Circular_dependencies of string list * string - -(** Give to this module a way to access libraries, packages, - and dependencies between files. *) -module type INPUT = sig - val fold_dependencies : (string -> string -> 'a -> 'a) -> 'a -> 'a - val fold_libraries : (string -> string list -> 'a -> 'a) -> 'a -> 'a - val fold_packages : (string -> string list -> 'a -> 'a) -> 'a -> 'a -end - -(** Wait an [INPUT] module and gives a function to compute the - transitive closure of caml file takeing in account libraries and packages. *) -module Make (I : INPUT) : sig - - (** [caml_transitive_closure] takes a list of root ocaml compiled files and returns - the list of files that must be given to a linker. Optionally you can change the - extension of caml object/library files (cmo/cma by default); use the pack mode - (false by default) to include only root files (just sort them); and gives the - list of used libraries (empty by default). *) - val caml_transitive_closure : - ?caml_obj_ext:string -> - ?caml_lib_ext:string -> - ?pack_mode:bool -> - ?used_libraries:string list -> - ?hidden_packages:string list -> - Pathname.t list -> Pathname.t list - -end diff --git a/ocamlbuild/ocaml_specific.ml b/ocamlbuild/ocaml_specific.ml deleted file mode 100644 index 18ae0944..00000000 --- a/ocamlbuild/ocaml_specific.ml +++ /dev/null @@ -1,792 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log -open Pathname.Operators -open Tags.Operators -open Rule -open Tools -open Rule.Common_commands -open Outcome -open Command;; - -open Ocaml_utils - -module C_tools = struct - let link_C_library clib a libname env build = - let clib = env clib and a = env a and libname = env libname in - let objs = string_list_of_file clib in - let include_dirs = Pathname.include_dirs_of (Pathname.dirname a) in - let obj_of_o x = - if Filename.check_suffix x ".o" && !Options.ext_obj <> "o" then - Pathname.update_extension !Options.ext_obj x - else x in - let resluts = build (List.map (fun o -> List.map (fun dir -> dir / obj_of_o o) include_dirs) objs) in - let objs = List.map begin function - | Good o -> o - | Bad exn -> raise exn - end resluts in - Cmd(S[!Options.ocamlmklib; A"-o"; Px libname; T(tags_of_pathname a++"c"++"ocamlmklib"); atomize objs]);; -end - -open Flags -open Command -open Rule - -let init () = let module M = struct - -let ext_lib = !Options.ext_lib;; -let ext_obj = !Options.ext_obj;; -let ext_dll = !Options.ext_dll;; -let x_o = "%"-.-ext_obj;; -let x_a = "%"-.-ext_lib;; -let x_dll = "%"-.-ext_dll;; -let x_p_o = "%.p"-.-ext_obj;; -let x_p_a = "%.p"-.-ext_lib;; -let x_p_dll = "%.p"-.-ext_dll;; - -(* -output-obj targets *) -let x_byte_c = "%.byte.c";; -let x_byte_o = "%.byte"-.-ext_obj;; -let x_byte_so = "%.byte"-.-ext_dll;; -let x_native_o = "%.native"-.-ext_obj;; -let x_native_so = "%.native"-.-ext_dll;; - -rule "target files" - ~dep:"%.itarget" - ~stamp:"%.otarget" - ~doc:"If foo.itarget contains a list of ocamlbuild targets, \ - asking ocamlbuild to produce foo.otarget will \ - build each of those targets in turn." - begin fun env build -> - let itarget = env "%.itarget" in - let dir = Pathname.dirname itarget in - let targets = string_list_of_file itarget in - List.iter ignore_good (build (List.map (fun x -> [dir/x]) targets)); - if !Options.make_links then - let link x = - Cmd (S [A"ln"; A"-sf"; P (!Options.build_dir/x); A Pathname.parent_dir_name]) in - Seq (List.map (fun x -> link (dir/x)) targets) - else - Nop - end;; - -rule "ocaml: mli -> cmi" - ~prod:"%.cmi" - ~deps:["%.mli"; "%.mli.depends"] - (Ocaml_compiler.compile_ocaml_interf "%.mli" "%.cmi");; - -rule "ocaml: mlpack & d.cmo* -> d.cmo & cmi" - ~prods:["%.d.cmo"] - ~deps:["%.mlpack"; "%.cmi"] - (Ocaml_compiler.byte_debug_pack_mlpack "%.mlpack" "%.d.cmo");; - -rule "ocaml: mlpack & cmo* & cmi -> cmo" - ~prod:"%.cmo" - ~deps:["%.mli"; "%.cmi"; "%.mlpack"] - ~doc:"If foo.mlpack contains a list of capitalized module names, \ - the target foo.cmo will produce a packed module containing \ - those modules as submodules. You can also have a foo.mli file \ - to restrict the interface of the resulting module. - -\ - Warning: to produce a native foo.cmx out of a foo.mlpack, you must \ - manually tag the included compilation units with for-pack(foo). \ - See the documentation of the corresponding rules for more details. - -\ - The modules named in the .mlpack \ - will be dynamic dependencies of the compilation action. \ - You cannot give the .mlpack the same name as one of the module \ - it contains, as this would create a circular dependency." - (Ocaml_compiler.byte_pack_mlpack "%.mlpack" "%.cmo");; - -rule "ocaml: mlpack & cmo* -> cmo & cmi" - ~prods:["%.cmo"; "%.cmi"] - ~dep:"%.mlpack" - (Ocaml_compiler.byte_pack_mlpack "%.mlpack" "%.cmo");; - -rule "ocaml: ml & cmi -> d.cmo" - ~prod:"%.d.cmo" - ~deps:["%.mli"(* This one is inserted to force this rule to be skiped when - a .ml is provided without a .mli *); "%.ml"; "%.ml.depends"; "%.cmi"] - ~doc:"The foo.d.cmo target compiles foo.ml with the 'debug' tag enabled (-g).\ - See also foo.d.byte. - -\ - For technical reason, .d.cmx and .d.native are not yet supported, \ - so you should explicitly add the 'debug' tag \ - to native targets (both compilation and linking)." - (Ocaml_compiler.byte_compile_ocaml_implem ~tag:"debug" "%.ml" "%.d.cmo");; - -rule "ocaml: ml & cmi -> cmo" - ~prod:"%.cmo" - ~deps:["%.mli"(* This one is inserted to force this rule to be skiped when - a .ml is provided without a .mli *); "%.ml"; "%.ml.depends"; "%.cmi"] - (Ocaml_compiler.byte_compile_ocaml_implem "%.ml" "%.cmo");; - -rule "ocaml: mlpack & cmi & p.cmx* & p.o* -> p.cmx & p.o" - ~prods:["%.p.cmx"; x_p_o - (* no cmi here you must make the byte version to have it *)] - ~deps:["%.mlpack"; "%.cmi"] - (Ocaml_compiler.native_profile_pack_mlpack "%.mlpack" "%.p.cmx");; - -rule "ocaml: mlpack & cmi & cmx* & o* -> cmx & o" - ~prods:["%.cmx"; x_o - (* no cmi here you must make the byte version to have it *)] - ~deps:["%.mlpack"; "%.cmi"] - ~doc:"If foo.mlpack contains a list of capitalized module names, \ - the target foo.cmx will produce a packed module containing \ - those modules as submodules. - -\ - Warning: The .cmx files that will be included must be manually tagged \ - with the tag \"for-pack(foo)\". This means that you cannot include \ - the same bar.cmx in several .mlpack files, and that you should not \ - use an included .cmx as a separate module on its own. - -\ - This requirement comes from a technical limitation of \ - native module packing: ocamlopt needs the -for-pack argument to be passed \ - ahead of time, when compiling each included submodule, \ - because there is no reliable, portable way to rewrite \ - native object files afterwards." - (Ocaml_compiler.native_pack_mlpack "%.mlpack" "%.cmx");; - -rule "ocaml: ml & cmi -> p.cmx & p.o" - ~prods:["%.p.cmx"; x_p_o] - ~deps:["%.ml"; "%.ml.depends"; "%.cmi"] - ~doc:"The foo.p.cmx target compiles foo.ml with the 'profile' \ - tag enabled (-p). Note that ocamlbuild provides no support \ - for the bytecode profiler, which works completely differently." - (Ocaml_compiler.native_compile_ocaml_implem ~tag:"profile" ~cmx_ext:"p.cmx" "%.ml");; - -rule "ocaml: ml & cmi -> cmx & o" - ~prods:["%.cmx"; x_o] - ~deps:["%.ml"; "%.ml.depends"; "%.cmi"] - (Ocaml_compiler.native_compile_ocaml_implem "%.ml");; - -rule "ocaml: ml -> d.cmo & cmi" - ~prods:["%.d.cmo"] - ~deps:["%.ml"; "%.ml.depends"; "%.cmi"] - (Ocaml_compiler.byte_compile_ocaml_implem ~tag:"debug" "%.ml" "%.d.cmo");; - -rule "ocaml: ml -> cmo & cmi" - ~prods:["%.cmo"; "%.cmi"] - ~deps:["%.ml"; "%.ml.depends"] - ~doc:"This rule allows to produce a .cmi from a .ml file \ - when the corresponding .mli is missing. - -\ - Note: you are strongly encourage to have a .mli file \ - for each of your .ml module, as it is a good development \ - practice which also simplifies the way build systems work, \ - as it avoids producing .cmi files as a silent side-effect of \ - another compilation action." - (Ocaml_compiler.byte_compile_ocaml_implem "%.ml" "%.cmo");; - -rule "ocaml: d.cmo* -> d.byte" - ~prod:"%.d.byte" - ~dep:"%.d.cmo" - ~doc:"The target foo.d.byte will build a bytecode executable \ - with debug information enabled." - (Ocaml_compiler.byte_debug_link "%.d.cmo" "%.d.byte");; - -rule "ocaml: cmo* -> byte" - ~prod:"%.byte" - ~dep:"%.cmo" - (Ocaml_compiler.byte_link "%.cmo" "%.byte");; - -rule "ocaml: cmo* -> byte.(o|obj)" - ~prod:x_byte_o - ~dep:"%.cmo" - ~doc:"The foo.byte.o target, or foo.byte.obj under Windows, \ - will produce an object file by passing the -output-obj option \ - to the OCaml compiler. See also foo.byte.c, and foo.native.{o,obj}." - (Ocaml_compiler.byte_output_obj "%.cmo" x_byte_o);; - -rule "ocaml: cmo* -> byte.c" - ~prod:x_byte_c - ~dep:"%.cmo" - (Ocaml_compiler.byte_output_obj "%.cmo" x_byte_c);; - -rule "ocaml: cmo* -> byte.(so|dll|dylib)" - ~prod:x_byte_so - ~dep:"%.cmo" - ~doc:"The foo.byte.so target, or foo.byte.dll under Windows, \ - or foo.byte.dylib under Mac OS X will produce a shared library file - by passing the -output-obj and -cclib -shared options \ - to the OCaml compiler. See also foo.native.{so,dll,dylib}." - (Ocaml_compiler.byte_output_shared "%.cmo" x_byte_so);; - -rule "ocaml: p.cmx* & p.o* -> p.native" - ~prod:"%.p.native" - ~deps:["%.p.cmx"; x_p_o] - ~doc:"The foo.p.native target builds the native executable \ - with the 'profile' tag (-p) enabled throughout compilation and linking." - (Ocaml_compiler.native_profile_link "%.p.cmx" "%.p.native");; - -rule "ocaml: cmx* & o* -> native" - ~prod:"%.native" - ~deps:["%.cmx"; x_o] - ~doc:"Builds a native executable" - (Ocaml_compiler.native_link "%.cmx" "%.native");; - -rule "ocaml: cmx* & o* -> native.(o|obj)" - ~prod:x_native_o - ~deps:["%.cmx"; x_o] - (Ocaml_compiler.native_output_obj "%.cmx" x_native_o);; - -rule "ocaml: cmx* & o* -> native.(so|dll|dylib)" - ~prod:x_native_so - ~deps:["%.cmx"; x_o] - (Ocaml_compiler.native_output_shared "%.cmx" x_native_so);; - -rule "ocaml: mllib & d.cmo* -> d.cma" - ~prod:"%.d.cma" - ~dep:"%.mllib" - (Ocaml_compiler.byte_debug_library_link_mllib "%.mllib" "%.d.cma");; - -rule "ocaml: mllib & cmo* -> cma" - ~prod:"%.cma" - ~dep:"%.mllib" - ~doc:"Build a .cma archive file (bytecode library) containing \ - the list of modules given in the .mllib file of the same name. \ - Note that the .cma archive will contain exactly the modules listed, \ - so it may not be self-contained if some dependencies are missing." - (Ocaml_compiler.byte_library_link_mllib "%.mllib" "%.cma");; - -rule "ocaml: d.cmo* -> d.cma" - ~prod:"%.d.cma" - ~dep:"%.d.cmo" - (Ocaml_compiler.byte_debug_library_link "%.d.cmo" "%.d.cma");; - -rule "ocaml: cmo* -> cma" - ~prod:"%.cma" - ~dep:"%.cmo" - ~doc:"The preferred way to build a .cma archive is to create a .mllib file \ - with a list of modules to include. It is however possible to build one \ - from a .cmo of the same name; the archive will include this module and \ - the local modules it depends upon, transitively." - (Ocaml_compiler.byte_library_link "%.cmo" "%.cma");; - -rule "ocaml C stubs: clib & (o|obj)* -> (a|lib) & (so|dll)" - ~prods:(["%(path:<**/>)lib%(libname:<*> and not <*.*>)"-.-ext_lib] @ - if Ocamlbuild_config.supports_shared_libraries then - ["%(path:<**/>)dll%(libname:<*> and not <*.*>)"-.-ext_dll] - else - []) - ~dep:"%(path)lib%(libname).clib" - ?doc:None (* TODO document *) - (C_tools.link_C_library "%(path)lib%(libname).clib" ("%(path)lib%(libname)"-.-ext_lib) "%(path)%(libname)");; - -rule "ocaml: mllib & p.cmx* & p.o* -> p.cmxa & p.a" - ~prods:["%.p.cmxa"; x_p_a] - ~dep:"%.mllib" - (Ocaml_compiler.native_profile_library_link_mllib "%.mllib" "%.p.cmxa");; - -rule "ocaml: mllib & cmx* & o* -> cmxa & a" - ~prods:["%.cmxa"; x_a] - ~dep:"%.mllib" - ~doc:"Creates a native archive file .cmxa, using the .mllib file \ - as the .cma rule above. Note that whereas bytecode .cma can \ - be used both for static and dynamic linking, .cmxa only support \ - static linking. For an archive usable with Dynlink, \ - see the rule producing a .cmxs from a .mldylib." - (Ocaml_compiler.native_library_link_mllib "%.mllib" "%.cmxa");; - -rule "ocaml: p.cmx & p.o -> p.cmxa & p.a" - ~prods:["%.p.cmxa"; x_p_a] - ~deps:["%.p.cmx"; x_p_o] - (Ocaml_compiler.native_profile_library_link "%.p.cmx" "%.p.cmxa");; - -rule "ocaml: cmx & o -> cmxa & a" - ~prods:["%.cmxa"; x_a] - ~deps:["%.cmx"; x_o] - ~doc:"Just as you can build a .cma from a .cmo in absence of .mllib file, \ - you can build a .cmxa (native archive file for static linking only) \ - from a .cmx, which will include the local modules it depends upon, \ - transitivitely." - (Ocaml_compiler.native_library_link "%.cmx" "%.cmxa");; - -rule "ocaml: mldylib & p.cmx* & p.o* -> p.cmxs & p.so" - ~prods:["%.p.cmxs"; x_p_dll] - ~dep:"%.mldylib" - (Ocaml_compiler.native_profile_shared_library_link_mldylib "%.mldylib" "%.p.cmxs");; - -rule "ocaml: mldylib & cmx* & o* -> cmxs & so" - ~prods:["%.cmxs"; x_dll] - ~dep:"%.mldylib" - ~doc:"Builds a .cmxs (native archive for dynamic linking) containing exactly \ - the modules listed in the corresponding .mldylib file." - (Ocaml_compiler.native_shared_library_link_mldylib "%.mldylib" "%.cmxs");; - -rule "ocaml: p.cmx & p.o -> p.cmxs & p.so" - ~prods:["%.p.cmxs"; x_p_dll] - ~deps:["%.p.cmx"; x_p_o] - (Ocaml_compiler.native_shared_library_link ~tags:["profile"] "%.p.cmx" "%.p.cmxs");; - -rule "ocaml: p.cmxa & p.a -> p.cmxs & p.so" - ~prods:["%.p.cmxs"; x_p_dll] - ~deps:["%.p.cmxa"; x_p_a] - (Ocaml_compiler.native_shared_library_link ~tags:["profile";"linkall"] "%.p.cmxa" "%.p.cmxs");; - -rule "ocaml: cmx & o -> cmxs" - ~prods:["%.cmxs"] - ~deps:["%.cmx"; x_o] - ~doc:"If you have not created a foo.mldylib file for a compilation unit \ - foo.cmx, the target foo.cmxs will produce a .cmxs file containing \ - exactly the .cmx. - -\ - Note: this differs from the behavior of .cmxa targets \ - with no .mllib, as the dependencies of the modules will not be \ - included: generally, the modules compiled as dynamic plugins depend \ - on library modules that will be already linked in the executable, \ - and that the .cmxs should therefore not duplicate." - (Ocaml_compiler.native_shared_library_link "%.cmx" "%.cmxs");; - -rule "ocaml: cmx & o -> cmxs & so" - ~prods:["%.cmxs"; x_dll] - ~deps:["%.cmx"; x_o] - (Ocaml_compiler.native_shared_library_link "%.cmx" "%.cmxs");; - -rule "ocaml: cmxa & a -> cmxs & so" - ~prods:["%.cmxs"; x_dll] - ~deps:["%.cmxa"; x_a] - ~doc:"This rule allows to build a .cmxs from a .cmxa, to avoid having \ - to duplicate a .mllib file into a .mldylib." - (Ocaml_compiler.native_shared_library_link ~tags:["linkall"] "%.cmxa" "%.cmxs");; - -rule "ocaml dependencies ml" - ~prod:"%.ml.depends" - ~dep:"%.ml" - ~doc:"OCamlbuild will use ocamldep to approximate dependencies \ - of a source file. The ocamldep tool being purely syntactic, \ - it only computes an over-approximation of the dependencies. - -\ - If you manipulate a module Foo that is in fact a submodule Bar.Foo \ - (after 'open Bar'), ocamldep may believe that your module depends \ - on foo.ml -- when such a file also exists in your project. This can \ - lead to spurious circular dependencies. In that case, you can use \ - OCamlbuild_plugin.non_dependency in your myocamlbuild.ml \ - to manually remove the spurious dependency. See the plugins API." - (Ocaml_tools.ocamldep_command "%.ml" "%.ml.depends");; - -rule "ocaml dependencies mli" - ~prod:"%.mli.depends" - ~dep:"%.mli" - (Ocaml_tools.ocamldep_command "%.mli" "%.mli.depends");; - -rule "ocamllex" - ~prod:"%.ml" - ~dep:"%.mll" - (Ocaml_tools.ocamllex "%.mll");; - -rule "ocaml: mli -> odoc" - ~prod:"%.odoc" - ~deps:["%.mli"; "%.mli.depends"] - ~doc:".odoc are intermediate files storing the result of ocamldoc processing \ - on a source file. See the various .docdir/... targets for ocamldoc." - (Ocaml_tools.document_ocaml_interf "%.mli" "%.odoc");; - -rule "ocaml: ml -> odoc" - ~prod:"%.odoc" - ~deps:["%.ml"; "%.ml.depends"] - (Ocaml_tools.document_ocaml_implem "%.ml" "%.odoc");; - -rule "ocamldoc: document ocaml project odocl & *odoc -> docdir (html)" - ~prod:"%.docdir/index.html" - ~stamp:"%.docdir/html.stamp" - ~dep:"%.odocl" - ~doc:"If you put a list of capitalized module names in a foo.odocl file, \ - the target foo.docdir/index.html will call ocamldoc to produce \ - the html documentation for these modules. \ - See also the max|latex|doc target below." - (Ocaml_tools.document_ocaml_project - ~ocamldoc:Ocaml_tools.ocamldoc_l_dir "%.odocl" "%.docdir/index.html" "%.docdir");; - -rule "ocamldoc: document ocaml project odocl & *odoc -> docdir (man)" - ~prod:"%.docdir/man" - ~stamp:"%.docdir/man.stamp" - ~dep:"%.odocl" - ?doc:None (* TODO document *) - (Ocaml_tools.document_ocaml_project - ~ocamldoc:Ocaml_tools.ocamldoc_l_dir "%.odocl" "%.docdir/man" "%.docdir");; - -rule "ocamldoc: document ocaml project odocl & *odoc -> man|latex|dot..." - ~prod:"%(dir).docdir/%(file)" - ~dep:"%(dir).odocl" - ?doc:None (* TODO document *) - (Ocaml_tools.document_ocaml_project - ~ocamldoc:Ocaml_tools.ocamldoc_l_file "%(dir).odocl" "%(dir).docdir/%(file)" "%(dir).docdir");; - -(* To use menhir give the -use-menhir option at command line, - Or put true: use_menhir in your tag file. *) -if !Options.use_menhir || Configuration.has_tag "use_menhir" then begin - (* Automatic handling of menhir modules, given a - description file %.mlypack *) - rule "ocaml: modular menhir (mlypack)" - ~prods:["%.mli" ; "%.ml"] - ~deps:["%.mlypack"] - ~doc:"Menhir supports building a parser by composing several .mly files \ - together, containing different parts of the grammar description. \ - To use that feature with ocamlbuild, you should create a .mlypack \ - file with the same syntax as .mllib or .mlpack files: \ - a whitespace-separated list of the capitalized module names \ - of the .mly files you want to combine together." - (Ocaml_tools.menhir_modular "%" "%.mlypack" "%.mlypack.depends"); - - rule "ocaml: menhir modular dependencies" - ~prod:"%.mlypack.depends" - ~dep:"%.mlypack" - (Ocaml_tools.menhir_modular_ocamldep_command "%.mlypack" "%.mlypack.depends"); - - rule "ocaml: menhir" - ~prods:["%.ml"; "%.mli"] - ~deps:["%.mly"; "%.mly.depends"] - ~doc:"Invokes menhir to build the .ml and .mli files derived from a .mly \ - grammar. If you want to use ocamlyacc instead, you must disable the \ - -use-menhir option that was passed to ocamlbuild." - (Ocaml_tools.menhir "%.mly"); - - rule "ocaml: menhir dependencies" - ~prod:"%.mly.depends" - ~dep:"%.mly" - (Ocaml_tools.menhir_ocamldep_command "%.mly" "%.mly.depends"); - -end else - rule "ocamlyacc" - ~prods:["%.ml"; "%.mli"] - ~dep:"%.mly" - ~doc:"By default, ocamlbuild will use ocamlyacc to produce a .ml and .mly \ - from a .mly file of the same name. You can also enable the \ - -use-menhir option to use menhir instead. Menhir is a recommended \ - replacement for ocamlyacc, that supports more feature, lets you \ - write more readable grammars, and helps you understand conflicts." - (Ocaml_tools.ocamlyacc "%.mly");; - -rule "ocaml C stubs: c -> o" - ~prod:x_o - ~dep:"%.c" - ?doc:None (* TODO document *) - begin fun env _build -> - let c = env "%.c" in - let o = env x_o in - let comp = if Tags.mem "native" (tags_of_pathname c) then !Options.ocamlopt else !Options.ocamlc in - let cc = Cmd(S[comp; T(tags_of_pathname c++"c"++"compile"); A"-c"; Px c]) in - if Pathname.dirname o = Pathname.current_dir_name then cc - else Seq[cc; mv (Pathname.basename o) o] - end;; - -rule "ocaml: ml & ml.depends & *cmi -> .inferred.mli" - ~prod:"%.inferred.mli" - ~deps:["%.ml"; "%.ml.depends"] - ~doc:"The target foo.inferred.mli will produce a .mli that exposes all the \ - declarations in foo.ml, as obtained by direct invocation of `ocamlc -i`." - (Ocaml_tools.infer_interface "%.ml" "%.inferred.mli");; - -rule "ocaml: mltop -> top" - ~prod:"%.top" - ~dep:"%.mltop" - ?doc:None (* TODO document *) - (Ocaml_compiler.byte_toplevel_link_mltop "%.mltop" "%.top");; - -rule "preprocess: ml -> pp.ml" - ~dep:"%.ml" - ~prod:"%.pp.ml" - ~doc:"The target foo.pp.ml should generate a source file equivalent \ - to foo.ml after syntactic preprocessors (camlp4, etc.) have been \ - applied. - -\ - Warning: This option is currently known to malfunction \ - when used together with -use-ocamlfind (for syntax extensions \ - coming from ocamlfind packages). Direct compilation of the \ - corresponding file to produce a .cmx or .cmo will still work well." - (Ocaml_tools.camlp4 "pp.ml" "%.ml" "%.pp.ml");; - -flag ["ocaml"; "pp"] begin - S (List.fold_right (fun x acc -> Sh x :: acc) !Options.ocaml_ppflags []) -end;; - -flag ["ocaml"; "compile"] begin - atomize !Options.ocaml_cflags -end;; - -flag ["c"; "compile"] begin - atomize !Options.ocaml_cflags -end;; - -flag ["ocaml"; "link"] begin - atomize !Options.ocaml_lflags -end;; - -flag ["c"; "link"] begin - atomize !Options.ocaml_lflags -end;; - -flag ["ocaml"; "ocamlyacc"] (atomize !Options.ocaml_yaccflags);; -flag ["ocaml"; "menhir"] (atomize !Options.ocaml_yaccflags);; -flag ["ocaml"; "doc"] (atomize !Options.ocaml_docflags);; -flag ["ocaml"; "ocamllex"] (atomize !Options.ocaml_lexflags);; - -(* Tell menhir to explain conflicts *) -flag [ "ocaml" ; "menhir" ; "explain" ] (S[A "--explain"]);; -flag [ "ocaml" ; "menhir" ; "infer" ] (S[A "--infer"]);; - -(* Define two ocamlbuild flags [only_tokens] and [external_tokens(Foo)] - which correspond to menhir's [--only-tokens] and [--external-tokens Foo]. - When they are used, these flags should be passed both to [menhir] and to - [menhir --raw-depend]. *) -let () = - List.iter begin fun mode -> - flag [ mode; "only_tokens" ] (S[A "--only-tokens"]); - pflag [ mode ] "external_tokens" (fun name -> - S[A "--external-tokens"; A name]); - end [ "menhir"; "menhir_ocamldep" ];; - -(* Tell ocamllex to generate ml code *) -flag [ "ocaml" ; "ocamllex" ; "generate_ml" ] (S[A "-ml"]);; - -flag ["ocaml"; "byte"; "link"] begin - S (List.map (fun x -> A (x^".cma")) !Options.ocaml_libs) -end;; - -flag ["ocaml"; "native"; "link"] begin - S (List.map (fun x -> A (x^".cmxa")) !Options.ocaml_libs) -end;; - -flag ["ocaml"; "byte"; "link"] begin - S (List.map (fun x -> A (x^".cmo")) !Options.ocaml_mods) -end;; - -flag ["ocaml"; "native"; "link"] begin - S (List.map (fun x -> A (x^".cmx")) !Options.ocaml_mods) -end;; - -(* findlib *) -let () = - if !Options.use_ocamlfind then begin - (* Ocamlfind will link the archives for us. *) - flag ["ocaml"; "link"; "program"] & A"-linkpkg"; - flag ["ocaml"; "link"; "toplevel"] & A"-linkpkg"; - flag ["ocaml"; "link"; "output_obj"] & A"-linkpkg"; - - (* "program" will make sure that -linkpkg is passed when compiling - whole-programs (.byte and .native); but it is occasionally - useful to pass -linkpkg when building archives for example - (.cma and .cmxa); the "linkpkg" flag allows user to request it - explicitly. *) - flag ["ocaml"; "link"; "linkpkg"] & A"-linkpkg"; - pflag ["ocaml"; "link"] "dontlink" (fun pkg -> S[A"-dontlink"; A pkg]); - - let all_tags = [ - ["ocaml"; "byte"; "compile"]; - ["ocaml"; "native"; "compile"]; - ["ocaml"; "byte"; "link"]; - ["ocaml"; "native"; "link"]; - ["ocaml"; "ocamldep"]; - ["ocaml"; "doc"]; - ["ocaml"; "mktop"]; - ["ocaml"; "infer_interface"]; - ] in - - (* tags package(X), predicate(X) and syntax(X) *) - List.iter begin fun tags -> - pflag tags "package" (fun pkg -> S [A "-package"; A pkg]); - if not (List.mem "ocamldep" tags) then - (* PR#6184: 'ocamlfind ocamldep' does not support -predicate *) - pflag tags "predicate" (fun pkg -> S [A "-predicates"; A pkg]); - pflag tags "syntax" (fun pkg -> S [A "-syntax"; A pkg]) - end all_tags - end else begin - try - (* Note: if there is no -pkg option, ocamlfind won't be called *) - let pkgs = List.map Findlib.query !Options.ocaml_pkgs in - flag ["ocaml"; "byte"; "compile"] (Findlib.compile_flags_byte pkgs); - flag ["ocaml"; "native"; "compile"] (Findlib.compile_flags_native pkgs); - flag ["ocaml"; "byte"; "link"] (Findlib.link_flags_byte pkgs); - flag ["ocaml"; "native"; "link"] (Findlib.link_flags_native pkgs) - with Findlib.Findlib_error e -> - Findlib.report_error e - end - -(* parameterized tags *) -let () = - pflag ["ocaml"; "native"; "compile"] "for-pack" - (fun param -> S [A "-for-pack"; A param]); - pflag ["ocaml"; "native"; "pack"] "for-pack" - (fun param -> S [A "-for-pack"; A param]); - pflag ["ocaml"; "native"; "compile"] "inline" - (fun param -> S [A "-inline"; A param]); - List.iter (fun pp -> - pflag ["ocaml"; "compile"] pp - (fun param -> S [A ("-" ^ pp); A param]); - pflag ["ocaml"; "ocamldep"] pp - (fun param -> S [A ("-" ^ pp); A param]); - pflag ["ocaml"; "doc"] pp - (fun param -> S [A ("-" ^ pp); A param]); - pflag ["ocaml"; "infer_interface"] pp - (fun param -> S [A ("-" ^ pp); A param]) - ) ["pp"; "ppx"]; - pflag ["ocaml";"compile";] "warn" - (fun param -> S [A "-w"; A param]); - pflag ["ocaml";"compile";] "warn_error" - (fun param -> S [A "-warn-error"; A param]); - pflag ["ocaml"; "ocamldep"] "open" - (fun param -> S [A "-open"; A param]); - pflag ["ocaml"; "compile"] "open" - (fun param -> S [A "-open"; A param]); - pflag ["ocaml"; "link"] "runtime_variant" - (fun param -> S [A "-runtime-variant"; A param]); - () - -let camlp4_flags camlp4s = - List.iter begin fun camlp4 -> - flag ["ocaml"; "pp"; camlp4] (A camlp4) - end camlp4s;; - -let p4_series = ["camlp4o"; "camlp4r"; "camlp4of"; "camlp4rf"; "camlp4orf"; "camlp4oof"];; -let p4_opt_series = List.map (fun f -> f ^ ".opt") p4_series;; - -camlp4_flags p4_series;; -camlp4_flags p4_opt_series;; - -let camlp4_flags' camlp4s = - List.iter begin fun (camlp4, flags) -> - flag ["ocaml"; "pp"; camlp4] flags - end camlp4s;; - -camlp4_flags' ["camlp4orr", S[A"camlp4of"; A"-parser"; A"reloaded"]; - "camlp4rrr", S[A"camlp4rf"; A"-parser"; A"reloaded"]];; - -flag ["ocaml"; "pp"; "camlp4:no_quot"] (A"-no_quot");; - -ocaml_lib ~extern:true "dynlink";; -ocaml_lib ~extern:true "unix";; -ocaml_lib ~extern:true "str";; -ocaml_lib ~extern:true "bigarray";; -ocaml_lib ~extern:true "nums";; -ocaml_lib ~extern:true "dbm";; -ocaml_lib ~extern:true "graphics";; -ocaml_lib ~extern:true ~tag_name:"use_toplevel" "toplevellib";; -ocaml_lib ~extern:true ~dir:"+ocamldoc" "ocamldoc";; -ocaml_lib ~extern:true ~dir:"+ocamlbuild" ~tag_name:"use_ocamlbuild" "ocamlbuildlib";; - -ocaml_lib ~extern:true ~dir:"+camlp4" ~tag_name:"use_camlp4" "camlp4lib";; -ocaml_lib ~extern:true ~dir:"+camlp4" ~tag_name:"use_old_camlp4" "camlp4";; -ocaml_lib ~extern:true ~dir:"+camlp4" ~tag_name:"use_camlp4_full" "camlp4fulllib";; -flag ["ocaml"; "compile"; "use_camlp4_full"] - (S[A"-I"; A"+camlp4/Camlp4Parsers"; - A"-I"; A"+camlp4/Camlp4Printers"; - A"-I"; A"+camlp4/Camlp4Filters"]);; -flag ["ocaml"; "use_camlp4_bin"; "link"; "byte"] (A"+camlp4/Camlp4Bin.cmo");; -flag ["ocaml"; "use_camlp4_bin"; "link"; "native"] (A"+camlp4/Camlp4Bin.cmx");; - -flag ["ocaml"; "debug"; "compile"; "byte"] (A "-g");; -flag ["ocaml"; "debug"; "link"; "byte"; "program"] (A "-g");; -flag ["ocaml"; "debug"; "pack"; "byte"] (A "-g");; -flag ["ocaml"; "debug"; "compile"; "native"] (A "-g");; -flag ["ocaml"; "debug"; "link"; "native"; "program"] (A "-g");; -flag ["ocaml"; "debug"; "pack"; "native"] (A "-g");; -flag ["c"; "debug"; "compile"] (A "-g"); -flag ["c"; "debug"; "link"] (A "-g"); -flag ["ocaml"; "link"; "native"; "output_obj"] (A"-output-obj");; -flag ["ocaml"; "link"; "byte"; "output_obj"] (A"-output-obj");; -flag ["ocaml"; "link"; "output_shared"] & (S[A"-cclib"; A"-shared"]);; -flag ["ocaml"; "dtypes"; "compile"] (A "-dtypes");; -flag ["ocaml"; "annot"; "compile"] (A "-annot");; -flag ["ocaml"; "annot"; "pack"] (A "-annot");; -flag ["ocaml"; "bin_annot"; "compile"] (A "-bin-annot");; -flag ["ocaml"; "bin_annot"; "pack"] (A "-bin-annot");; -flag ["ocaml"; "safe_string"; "compile"] (A "-safe-string");; -flag ["ocaml"; "safe_string"; "infer_interface"] (A "-safe-string");; -flag ["ocaml"; "unsafe_string"; "compile"] (A "-unsafe-string");; -flag ["ocaml"; "unsafe_string"; "infer_interface"] (A "-unsafe-string");; -flag ["ocaml"; "short_paths"; "compile"] (A "-short-paths");; -flag ["ocaml"; "short_paths"; "infer_interface"] (A "-short-paths");; -flag ["ocaml"; "rectypes"; "compile"] (A "-rectypes");; -flag ["ocaml"; "rectypes"; "infer_interface"] (A "-rectypes");; -flag ["ocaml"; "rectypes"; "doc"] (A "-rectypes");; -flag ["ocaml"; "rectypes"; "pack"] (A "-rectypes");; -flag ["ocaml"; "principal"; "compile"] (A "-principal");; -flag ["ocaml"; "principal"; "infer_interface"] (A "-principal");; -flag ["ocaml"; "linkall"; "link"] (A "-linkall");; -flag ["ocaml"; "link"; "profile"; "native"] (A "-p");; -flag ["ocaml"; "link"; "program"; "custom"; "byte"] (A "-custom");; -flag ["ocaml"; "link"; "library"; "custom"; "byte"] (A "-custom");; -flag ["ocaml"; "compile"; "profile"; "native"] (A "-p");; -flag ["ocaml"; "compile"; "no_alias_deps";] (A "-no-alias-deps");; -flag ["ocaml"; "compile"; "strict_formats";] (A "-strict-formats");; -flag ["ocaml"; "native"; "compile"; "opaque";] (A "-opaque");; -flag ["ocaml"; "native"; "compile"; "no_float_const_prop";] (A "-no-float-const-prop"); -flag ["ocaml"; "compile"; "keep_docs";] (A "-keep-docs"); -flag ["ocaml"; "compile"; "keep_locs";] (A "-keep-locs"); -flag ["ocaml"; "absname"; "compile"] (A "-absname");; -flag ["ocaml"; "absname"; "infer_interface"] (A "-absname");; -flag ["ocaml"; "byte"; "compile"; "compat_32";] (A "-compat-32"); - - -(* threads, with or without findlib *) -flag ["ocaml"; "compile"; "thread"] (A "-thread");; -flag ["ocaml"; "link"; "thread"] (A "-thread");; -if not !Options.use_ocamlfind then begin - flag ["ocaml"; "doc"; "thread"] (S[A"-I"; A"+threads"]); - flag ["ocaml"; "link"; "thread"; "native"; "program"] (A "threads.cmxa"); - flag ["ocaml"; "link"; "thread"; "byte"; "program"] (A "threads.cma"); - flag ["ocaml"; "link"; "thread"; "native"; "toplevel"] (A "threads.cmxa"); - flag ["ocaml"; "link"; "thread"; "byte"; "toplevel"] (A "threads.cma"); -end;; - -flag ["ocaml"; "compile"; "nopervasives"] (A"-nopervasives");; -flag ["ocaml"; "compile"; "nolabels"] (A"-nolabels");; - -(*flag ["ocaml"; "ocamlyacc"; "quiet"] (A"-q");;*) -flag ["ocaml"; "ocamllex"; "quiet"] (A"-q");; - -let ocaml_warn_flag c = - flag ~deprecated:true - ["ocaml"; "compile"; sprintf "warn_%c" (Char.uppercase c)] - (S[A"-w"; A (sprintf "%c" (Char.uppercase c))]); - flag ~deprecated:true - ["ocaml"; "compile"; sprintf "warn_error_%c" (Char.uppercase c)] - (S[A"-warn-error"; A (sprintf "%c" (Char.uppercase c))]); - flag ~deprecated:true - ["ocaml"; "compile"; sprintf "warn_%c" (Char.lowercase c)] - (S[A"-w"; A (sprintf "%c" (Char.lowercase c))]); - flag ~deprecated:true - ["ocaml"; "compile"; sprintf "warn_error_%c" (Char.lowercase c)] - (S[A"-warn-error"; A (sprintf "%c" (Char.lowercase c))]);; - -List.iter ocaml_warn_flag ['A'; 'C'; 'D'; 'E'; 'F'; 'K'; 'L'; 'M'; 'P'; 'R'; 'S'; 'U'; 'V'; 'X'; 'Y'; 'Z'];; - -flag ~deprecated:true - ["ocaml"; "compile"; "strict-sequence"] (A "-strict-sequence");; -flag ["ocaml"; "compile"; "strict_sequence"] (A "-strict-sequence");; - -flag ["ocaml"; "doc"; "docdir"; "extension:html"] (A"-html");; -flag ["ocaml"; "doc"; "docdir"; "manpage"] (A"-man");; -flag ["ocaml"; "doc"; "docfile"; "extension:dot"] (A"-dot");; -flag ["ocaml"; "doc"; "docfile"; "extension:tex"] (A"-latex");; -flag ["ocaml"; "doc"; "docfile"; "extension:ltx"] (A"-latex");; -flag ["ocaml"; "doc"; "docfile"; "extension:texi"] (A"-texi");; - -ocaml_lib "ocamlbuildlib";; -ocaml_lib "ocamlbuildlightlib";; - -end in () diff --git a/ocamlbuild/ocaml_specific.mli b/ocamlbuild/ocaml_specific.mli deleted file mode 100644 index 54cd7fac..00000000 --- a/ocamlbuild/ocaml_specific.mli +++ /dev/null @@ -1,17 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - - -(* Original author: Nicolas Pouillard *) - -val init : unit -> unit diff --git a/ocamlbuild/ocaml_tools.ml b/ocamlbuild/ocaml_tools.ml deleted file mode 100644 index be6fed38..00000000 --- a/ocamlbuild/ocaml_tools.ml +++ /dev/null @@ -1,163 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Pathname.Operators -open Tags.Operators -open Tools -open Command -open Ocaml_utils - -let add_suffix s = List.map (fun x -> x -.- s) ;; - -let ocamldep_command' tags = - let tags' = tags++"ocaml"++"ocamldep" in - S [!Options.ocamldep; T tags'; ocaml_ppflags (tags++"pp:dep"); A "-modules"] - -let menhir_ocamldep_command' tags ~menhir_spec out = - let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in - Cmd(S[menhir; T tags; A"--raw-depend"; - A"--ocamldep"; Quote (ocamldep_command' Tags.empty); - menhir_spec ; Sh ">"; Px out]) - -let menhir_ocamldep_command arg out env _build = - let arg = env arg and out = env out in - let tags = tags_of_pathname arg++"ocaml"++"menhir_ocamldep" in - menhir_ocamldep_command' tags ~menhir_spec:(P arg) out - -let import_mlypack build mlypack = - let tags1 = tags_of_pathname mlypack in - let files = string_list_of_file mlypack in - let include_dirs = Pathname.include_dirs_of (Pathname.dirname mlypack) in - let files_alternatives = - List.map begin fun module_name -> - expand_module include_dirs module_name ["mly"] - end files - in - let files = List.map Outcome.good (build files_alternatives) in - let tags2 = - List.fold_right - (fun file -> Tags.union (tags_of_pathname file)) - files tags1 - in - (tags2, files) - -let menhir_modular_ocamldep_command mlypack out env build = - let mlypack = env mlypack and out = env out in - let (tags,files) = import_mlypack build mlypack in - let tags = tags++"ocaml"++"menhir_ocamldep" in - let menhir_base = Pathname.remove_extensions mlypack in - let menhir_spec = S[A "--base" ; P menhir_base ; atomize_paths files] in - menhir_ocamldep_command' tags ~menhir_spec out - -let menhir_modular menhir_base mlypack mlypack_depends env build = - let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in - let menhir_base = env menhir_base in - let mlypack = env mlypack in - let mlypack_depends = env mlypack_depends in - let (tags,files) = import_mlypack build mlypack in - let () = List.iter Outcome.ignore_good (build [[mlypack_depends]]) in - Ocaml_compiler.prepare_compile build mlypack; - let ocamlc_tags = tags++"ocaml"++"byte"++"compile" in - let tags = tags++"ocaml"++"parser"++"menhir" in - Cmd(S[menhir ; - A "--ocamlc"; Quote(S[!Options.ocamlc; T ocamlc_tags; ocaml_include_flags mlypack]); - T tags ; A "--base" ; Px menhir_base ; atomize_paths files]) - -let ocamldep_command arg out env _build = - let arg = env arg and out = env out in - let tags = tags_of_pathname arg in - Cmd(S[ocamldep_command' tags; P arg; Sh ">"; Px out]) - -let ocamlyacc mly env _build = - let mly = env mly in - let ocamlyacc = if !Options.ocamlyacc = N then V"OCAMLYACC" else !Options.ocamlyacc in - Cmd(S[ocamlyacc; T(tags_of_pathname mly++"ocaml"++"parser"++"ocamlyacc"); Px mly]) - -let ocamllex mll env _build = - let mll = env mll in - Cmd(S[!Options.ocamllex; T(tags_of_pathname mll++"ocaml"++"lexer"++"ocamllex"); Px mll]) - -let infer_interface ml mli env build = - let ml = env ml and mli = env mli in - let tags = tags_of_pathname ml++"ocaml" in - Ocaml_compiler.prepare_compile build ml; - Cmd(S[!Options.ocamlc; ocaml_ppflags tags; ocaml_include_flags ml; A"-i"; - (if Tags.mem "thread" tags then A"-thread" else N); - T(tags++"infer_interface"); P ml; Sh">"; Px mli]) - -let menhir mly env build = - let mly = env mly in - let ml = Pathname.update_extension "ml" mly in - let menhir = if !Options.ocamlyacc = N then V"MENHIR" else !Options.ocamlyacc in - let ocamlc_tags = tags_of_pathname ml ++"ocaml"++"byte"++"compile" in - let menhir_tags = tags_of_pathname mly ++"ocaml"++"parser"++"menhir" in - Ocaml_compiler.prepare_compile build mly; - Cmd(S[menhir; - A"--ocamlc"; Quote(S[!Options.ocamlc; T ocamlc_tags; ocaml_include_flags mly]); - T menhir_tags; Px mly]) - -let ocamldoc_c tags arg odoc = - let tags = tags++"ocaml" in - Cmd (S [!Options.ocamldoc; A"-dump"; Px odoc; T(tags++"doc"); - ocaml_ppflags (tags++"pp:doc"); - ocaml_include_flags arg; P arg]) - -let ocamldoc_l_dir tags deps _docout docdir = - Seq[Cmd (S[A"rm"; A"-rf"; Px docdir]); - Cmd (S[A"mkdir"; A"-p"; Px docdir]); - Cmd (S [!Options.ocamldoc; - S(List.map (fun a -> S[A"-load"; P a]) deps); - T(tags++"doc"++"docdir"); A"-d"; Px docdir])] - -let ocamldoc_l_file tags deps docout _docdir = - Seq[Cmd (S[A"rm"; A"-rf"; Px docout]); - Cmd (S[A"mkdir"; A"-p"; Px (Pathname.dirname docout)]); - Cmd (S [!Options.ocamldoc; - S(List.map (fun a -> S[A"-load"; P a]) deps); - T(tags++"doc"++"docfile"); A"-o"; Px docout])] - -let document_ocaml_interf mli odoc env build = - let mli = env mli and odoc = env odoc in - Ocaml_compiler.prepare_compile build mli; - ocamldoc_c (tags_of_pathname mli++"interf") mli odoc - -let document_ocaml_implem ml odoc env build = - let ml = env ml and odoc = env odoc in - Ocaml_compiler.prepare_compile build ml; - ocamldoc_c (tags_of_pathname ml++"implem") ml odoc - -let document_ocaml_project ?(ocamldoc=ocamldoc_l_file) odocl docout docdir env build = - let odocl = env odocl and docout = env docout and docdir = env docdir in - let contents = string_list_of_file odocl in - let include_dirs = Pathname.include_dirs_of (Pathname.dirname odocl) in - let to_build = - List.map begin fun module_name -> - expand_module include_dirs module_name ["odoc"] - end contents in - let module_paths = List.map Outcome.good (build to_build) in - let tags = (Tags.union (tags_of_pathname docout) (tags_of_pathname docdir))++"ocaml" in - ocamldoc tags module_paths docout docdir - -let camlp4 ?(default=A"camlp4o") tag i o env build = - let ml = env i and pp_ml = env o in - let tags = tags_of_pathname ml++"ocaml"++"pp"++tag in - let _ = Rule.build_deps_of_tags build tags in - let pp = Command.reduce (Flags.of_tags tags) in - let pp = - match pp with - | N -> default - | _ -> pp - in - Cmd(S[pp; P ml; A"-printer"; A"o"; A"-o"; Px pp_ml]) diff --git a/ocamlbuild/ocaml_tools.mli b/ocamlbuild/ocaml_tools.mli deleted file mode 100644 index 38d36e3a..00000000 --- a/ocamlbuild/ocaml_tools.mli +++ /dev/null @@ -1,34 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -val ocamldoc_c : Tags.t -> string -> string -> Command.t -val ocamldoc_l_dir : Tags.t -> string list -> string -> string -> Command.t -val ocamldoc_l_file : Tags.t -> string list -> string -> string -> Command.t - -val ocamldep_command : string -> string -> Rule.action -val menhir_ocamldep_command : string -> string -> Rule.action -val menhir_modular_ocamldep_command : string -> string -> Rule.action -val menhir_modular : string -> string -> string -> Rule.action -val ocamlyacc : string -> Rule.action -val ocamllex : string -> Rule.action -val menhir : string -> Rule.action -val infer_interface : string -> string -> Rule.action -val document_ocaml_interf : string -> string -> Rule.action -val document_ocaml_implem : string -> string -> Rule.action -val document_ocaml_project : - ?ocamldoc:(Tags.t -> string list -> string -> string -> Command.t) -> - string -> string -> string -> Rule.action - -val camlp4 : ?default:Command.spec -> Tags.elt -> Pathname.t -> Pathname.t -> Rule.action diff --git a/ocamlbuild/ocaml_utils.ml b/ocamlbuild/ocaml_utils.ml deleted file mode 100644 index 409f0a06..00000000 --- a/ocamlbuild/ocaml_utils.ml +++ /dev/null @@ -1,178 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log -open Pathname.Operators -open Tags.Operators -open Tools -open Flags -open Command;; - - -module S = Set.Make(String) - -let flag_and_dep tags cmd_spec = - flag tags cmd_spec; - let ps = Command.fold_pathnames (fun p ps -> p :: ps) (Cmd cmd_spec) [] in - dep tags ps - -let stdlib_dir = lazy begin - let ocamlc_where = !Options.build_dir / (Pathname.mk "ocamlc.where") in - let () = Command.execute ~quiet:true (Cmd(S[!Options.ocamlc; A"-where"; Sh">"; P ocamlc_where])) in - String.chomp (read_file ocamlc_where) -end - -let pflag_and_dep tags ptag cmd_spec = - Param_tags.declare ptag - (fun param -> - flag_and_dep (Param_tags.make ptag param :: tags) (cmd_spec param)) - -let module_name_of_filename f = String.capitalize (Pathname.remove_extensions f) -let module_name_of_pathname x = - module_name_of_filename (Pathname.to_string (Pathname.basename x)) - -let ignore_stdlib x = - if !Options.nostdlib then false - else - let x' = !*stdlib_dir/((String.uncapitalize x)-.-"cmi") in - Pathname.exists x' - -let non_dependencies = ref [] -let non_dependency m1 m2 = - (* non_dependency was not supposed to accept pathnames without extension. *) - if String.length (Pathname.get_extensions m1) = 0 then - invalid_arg "non_dependency: no extension"; - non_dependencies := (m1, m2) :: !non_dependencies - -let path_importance path x = - if List.mem (path, x) !non_dependencies - || (List.mem x !Options.ignore_list) then begin - let () = dprintf 3 "This module (%s) is ignored by %s" x path in - `ignored - end - else if ignore_stdlib x then `just_try else `mandatory - -let expand_module = - memo3 (fun include_dirs module_name exts -> - let dirname = Pathname.dirname module_name in - let basename = Pathname.basename module_name in - let module_name_cap = dirname/(String.capitalize basename) in - let module_name_uncap = dirname/(String.uncapitalize basename) in - List.fold_right begin fun include_dir -> - List.fold_right begin fun ext acc -> - include_dir/(module_name_uncap-.-ext) :: - include_dir/(module_name_cap-.-ext) :: acc - end exts - end include_dirs []) - -let string_list_of_file file = - with_input_file file begin fun ic -> - Lexers.blank_sep_strings - Const.Source.file (Lexing.from_channel ic) - end -let print_path_list = Pathname.print_path_list - -let ocaml_ppflags tags = - let flags = Flags.of_tags (tags++"ocaml"++"pp") in - let reduced = Command.reduce flags in - if reduced = N then N else S[A"-pp"; Quote reduced] - -let ocaml_add_include_flag x acc = - if x = Pathname.current_dir_name then acc else A"-I" :: A x :: acc - -let ocaml_include_flags path = - S (List.fold_right ocaml_add_include_flag (Pathname.include_dirs_of (Pathname.dirname path)) []) - -let info_libraries = Hashtbl.create 103 - -let libraries = Hashtbl.create 103 -let libraries_of m = - try Hashtbl.find libraries m with Not_found -> [] -let use_lib m lib = Hashtbl.replace libraries m (lib :: libraries_of m) - -let ocaml_lib ?(extern=false) ?(byte=true) ?(native=true) ?dir ?tag_name libpath = - let add_dir x = - match dir with - | Some dir -> S[A"-I"; P dir; x] - | None -> x - in - let tag_name = - match tag_name with - | Some x -> x - | None -> "use_" ^ Pathname.basename libpath - in - let flag_and_dep tags lib = - flag tags (add_dir (A lib)); - if not extern then dep tags [lib] (* cannot happen? *) - in - Hashtbl.replace info_libraries tag_name (libpath, extern); - (* adding [tag_name] to [info_libraries] will make this tag - affect include-dir lookups, so it is used even if not - mentioned explicitly in any rule. *) - Flags.mark_tag_used tag_name; - if extern then begin - if byte then - flag_and_dep ["ocaml"; tag_name; "link"; "byte"] (libpath^".cma"); - if native then - flag_and_dep ["ocaml"; tag_name; "link"; "native"] (libpath^".cmxa"); - end else begin - if not byte && not native then - invalid_arg "ocaml_lib: ~byte:false or ~native:false only works with ~extern:true"; - end; - match dir with - | None -> () - | Some dir -> - List.iter - (fun x -> flag ["ocaml"; tag_name; x] (S[A"-I"; P dir])) - ["compile"; "doc"; "infer_interface"] - -let cmi_of = Pathname.update_extensions "cmi" - -exception Ocamldep_error of string - -let read_path_dependencies = - let path_dependencies = Hashtbl.create 103 in - let read path = - let module_name = module_name_of_pathname path in - let depends = path-.-"depends" in - with_input_file depends begin fun ic -> - let ocamldep_output = - try Lexers.ocamldep_output - Const.Source.ocamldep (Lexing.from_channel ic) - with Lexers.Error (msg,_) -> raise (Ocamldep_error(Printf.sprintf "Ocamldep.ocamldep: bad output (%s)" msg)) in - let deps = - List.fold_right begin fun (path, deps) acc -> - let module_name' = module_name_of_pathname path in - if module_name' = module_name - then List.union deps acc - else raise (Ocamldep_error(Printf.sprintf "Ocamldep.ocamldep: multiple files in ocamldep output (%s not expected)" path)) - end ocamldep_output [] in - let deps = - if !Options.nostdlib && not (Tags.mem "nopervasives" (tags_of_pathname path)) then - "Pervasives" :: deps - else deps in - let deps' = List.fold_right begin fun dep acc -> - match path_importance path dep with - | `ignored -> acc - | (`just_try | `mandatory) as importance -> (importance, dep) :: acc - end deps [] in - Hashtbl.replace path_dependencies path - (List.union (try Hashtbl.find path_dependencies path with Not_found -> []) deps'); - deps' - end - in read - -let path_dependencies_of = memo read_path_dependencies diff --git a/ocamlbuild/ocaml_utils.mli b/ocamlbuild/ocaml_utils.mli deleted file mode 100644 index 5154a1ac..00000000 --- a/ocamlbuild/ocaml_utils.mli +++ /dev/null @@ -1,46 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -val stdlib_dir : Pathname.t Lazy.t -val module_name_of_filename : Pathname.t -> string -val module_name_of_pathname : Pathname.t -> string -val ignore_stdlib : string -> bool -val non_dependency : string -> string -> unit -val expand_module : - Pathname.t list -> Pathname.t -> string list -> Pathname.t list -val string_list_of_file : string -> string list -val ocaml_ppflags : Tags.t -> Command.spec -val ocaml_include_flags : Pathname.t -> Command.spec -val libraries_of : Pathname.t -> Pathname.t list -val use_lib : Pathname.t -> Pathname.t -> unit -val cmi_of : Pathname.t -> Pathname.t -val ocaml_add_include_flag : string -> Command.spec list -> Command.spec list -val flag_and_dep : Tags.elt list -> Command.spec -> unit -val pflag_and_dep : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> - unit - -exception Ocamldep_error of string - -(* Takes a path and returns a list of modules *) -val path_dependencies_of : Pathname.t -> ([ `mandatory | `just_try ] * string) list - -val info_libraries : (string, string * bool) Hashtbl.t - -val ocaml_lib : - ?extern:bool -> - ?byte:bool -> - ?native:bool -> - ?dir:Pathname.t -> - ?tag_name:string -> - Pathname.t -> unit diff --git a/ocamlbuild/ocamlbuild.ml b/ocamlbuild/ocamlbuild.ml deleted file mode 100644 index ce0f56f4..00000000 --- a/ocamlbuild/ocamlbuild.ml +++ /dev/null @@ -1,16 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -Ocamlbuild_unix_plugin.setup (); -Ocamlbuild_pack.Main.main () diff --git a/ocamlbuild/ocamlbuild.mli b/ocamlbuild/ocamlbuild.mli deleted file mode 100644 index 83cab501..00000000 --- a/ocamlbuild/ocamlbuild.mli +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(** Nothing to export for now *) diff --git a/ocamlbuild/ocamlbuild.mltop b/ocamlbuild/ocamlbuild.mltop deleted file mode 100644 index 41c1afb0..00000000 --- a/ocamlbuild/ocamlbuild.mltop +++ /dev/null @@ -1,3 +0,0 @@ -Ocamlbuild_pack -Ocamlbuild_plugin -Ocamlbuild_unix_plugin diff --git a/ocamlbuild/ocamlbuild.odocl b/ocamlbuild/ocamlbuild.odocl deleted file mode 100644 index fe0c1730..00000000 --- a/ocamlbuild/ocamlbuild.odocl +++ /dev/null @@ -1,41 +0,0 @@ -Log -My_unix -My_std -Signatures -Shell -Display -Command -Configuration -Discard_printf -Flags -Hygiene -Options -Pathname -Report -Resource -Rule -Slurp -Solver -Tags -Tools -Fda -Ocaml_specific -Ocaml_arch -Ocamlbuild_where -Ocamlbuild_Myocamlbuild_config -Lexers -Glob -Bool -Glob_ast -Glob_lexer -Plugin -Main -Hooks -Ocaml_utils -Ocaml_tools -Ocaml_compiler -Ocaml_dependencies -Exit_codes -Digest_cache -Ocamlbuild_plugin -Findlib diff --git a/ocamlbuild/ocamlbuild_executor.ml b/ocamlbuild/ocamlbuild_executor.ml deleted file mode 100644 index 298f9b4d..00000000 --- a/ocamlbuild/ocamlbuild_executor.ml +++ /dev/null @@ -1,350 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Ocamlbuild_executor *) - -open Unix;; - -type error = - | Subcommand_failed - | Subcommand_got_signal - | Io_error - | Exceptionl_condition - -type task = unit -> string;; - -type job = { - job_id : int * int; - job_command : string; - job_next : task list; - job_result : bool ref; (* Result of this sequence group *) - job_stdout : in_channel; - job_stdin : out_channel; - job_stderr : in_channel; - job_buffer : Buffer.t; - mutable job_dying : bool; -};; - -module JS = Set.Make(struct type t = job let compare = compare end);; -module FDM = Map.Make(struct type t = file_descr let compare = compare end);; - -let sf = Printf.sprintf;; -let fp = Printf.fprintf;; - -(*** print_unix_status *) -(* FIXME never called *) -let print_unix_status oc = function - | WEXITED x -> fp oc "exit %d" x - | WSIGNALED i -> fp oc "signal %d" i - | WSTOPPED i -> fp oc "stop %d" i -;; -(* ***) -(*** print_job_id *) -let print_job_id oc (x,y) = fp oc "%d.%d" x y;; -(* ***) -(*** output_lines *) -let output_lines prefix oc buffer = - let u = Buffer.contents buffer in - let m = String.length u in - let output_line i j = - output_string oc prefix; - output_substring oc u i (j - i); - output_char oc '\n' - in - let rec loop i = - if i < m then - let j = - try String.index_from u i '\n' - with Not_found -> m - in - output_line i j; - loop (j + 1) - else - () - in - loop 0 -;; -(* ***) -(*** execute *) -(* XXX: Add test for non reentrancy *) -let execute - ?(max_jobs=max_int) - ?(ticker=ignore) - ?(period=0.1) - ?(display=(fun f -> f Pervasives.stdout)) - ~exit - (commands : task list list) - = - let batch_id = ref 0 in - let env = environment () in - let jobs = ref JS.empty in - let jobs_active = ref 0 in - let jobs_to_terminate = Queue.create () in - let commands_to_execute = Queue.create () in - let all_ok = ref true in - let results = - List.map (fun tasks -> - let result = ref false in - Queue.add (tasks, result) commands_to_execute; - result) - commands - in - let outputs = ref FDM.empty in - let doi = descr_of_in_channel in - let doo = descr_of_out_channel in - (*** compute_fds *) - let compute_fds = - let fds = ref ([], [], []) in - let prev_jobs = ref JS.empty in - fun () -> - if not (!prev_jobs == !jobs) then - begin - prev_jobs := !jobs; - fds := - JS.fold - begin fun job (rfds, wfds, xfds) -> - let ofd = doi job.job_stdout - and ifd = doo job.job_stdin - and efd = doi job.job_stderr - in - (ofd :: efd :: rfds, wfds, ofd :: ifd :: efd :: xfds) - end - !jobs - ([], [], []) - end; - !fds - in - (* ***) - (*** add_job *) - let add_job cmd rest result id = - (*display begin fun oc -> fp oc "Job %a is %s\n%!" print_job_id id cmd; end;*) - let (stdout', stdin', stderr') = open_process_full cmd env in - incr jobs_active; - set_nonblock (doi stdout'); - set_nonblock (doi stderr'); - let job = - { job_id = id; - job_command = cmd; - job_next = rest; - job_result = result; - job_stdout = stdout'; - job_stdin = stdin'; - job_stderr = stderr'; - job_buffer = Buffer.create 1024; - job_dying = false } - in - outputs := FDM.add (doi stdout') job (FDM.add (doi stderr') job !outputs); - jobs := JS.add job !jobs; - in - (* ***) - (*** skip_empty_tasks *) - let rec skip_empty_tasks = function - | [] -> None - | task :: tasks -> - let cmd = task () in - if cmd = "" then skip_empty_tasks tasks else Some(cmd, tasks) - in - (* ***) - (*** add_some_jobs *) - let add_some_jobs () = - let (tasks, result) = Queue.take commands_to_execute in - match skip_empty_tasks tasks with - | None -> result := false - | Some(cmd, rest) -> - let b_id = !batch_id in - incr batch_id; - add_job cmd rest result (b_id, 0) - in - (* ***) - (*** terminate *) - let terminate ?(continue=true) job = - if not job.job_dying then - begin - job.job_dying <- true; - Queue.add (job, continue) jobs_to_terminate - end - else - () - in - (* ***) - (*** add_more_jobs_if_possible *) - let add_more_jobs_if_possible () = - while !jobs_active < max_jobs && not (Queue.is_empty commands_to_execute) do - add_some_jobs () - done - in - (* ***) - (*** do_read *) - let do_read = - let u = Bytes.create 4096 in - fun ?(loop=false) fd job -> - (*if job.job_dying then - () - else*) - try - let rec iteration () = - let m = - try - read fd u 0 (Bytes.length u) - with - | Unix.Unix_error(e,_,_) -> - let msg = error_message e in - display (fun oc -> fp oc - "Error while reading stdout/stderr: %s\n" msg); - 0 - in - if m = 0 then - if job.job_dying then - () - else - terminate job - else - begin - Buffer.add_subbytes job.job_buffer u 0 m; - if loop then - iteration () - else - () - end - in - iteration () - with - | x -> - display - begin fun oc -> - fp oc "Exception %s while reading output of command %S\n%!" job.job_command - (Printexc.to_string x); - end; - exit Io_error - in - (* ***) - (*** process_jobs_to_terminate *) - let process_jobs_to_terminate () = - while not (Queue.is_empty jobs_to_terminate) do - ticker (); - let (job, continue) = Queue.take jobs_to_terminate in - - (*display begin fun oc -> fp oc "Terminating job %a\n%!" print_job_id job.job_id; end;*) - - decr jobs_active; - - (* PR#5371: we would get EAGAIN below otherwise *) - clear_nonblock (doi job.job_stdout); - clear_nonblock (doi job.job_stderr); - - do_read ~loop:true (doi job.job_stdout) job; - do_read ~loop:true (doi job.job_stderr) job; - outputs := FDM.remove (doi job.job_stdout) (FDM.remove (doi job.job_stderr) !outputs); - jobs := JS.remove job !jobs; - let status = close_process_full (job.job_stdout, job.job_stdin, job.job_stderr) in - - let shown = ref false in - - let show_command () = - if !shown then - () - else - display - begin fun oc -> - shown := true; - fp oc "+ %s\n" job.job_command; - output_lines "" oc job.job_buffer - end - in - if Buffer.length job.job_buffer > 0 then show_command (); - begin - match status with - | Unix.WEXITED 0 -> - begin - if continue then - begin - match skip_empty_tasks job.job_next with - | None -> job.job_result := true - | Some(cmd, rest) -> - let (b_id, s_id) = job.job_id in - add_job cmd rest job.job_result (b_id, s_id + 1) - end - else - all_ok := false; - end - | Unix.WEXITED rc -> - show_command (); - display (fun oc -> fp oc "Command exited with code %d.\n" rc); - all_ok := false; - exit Subcommand_failed - | Unix.WSTOPPED s | Unix.WSIGNALED s -> - show_command (); - all_ok := false; - display (fun oc -> fp oc "Command got signal %d.\n" s); - exit Subcommand_got_signal - end - done - in - (* ***) - (*** terminate_all_jobs *) - let terminate_all_jobs () = - JS.iter (terminate ~continue:false) !jobs - in - (* ***) - (*** loop *) - let rec loop () = - (*display (fun oc -> fp oc "Total %d jobs\n" !jobs_active);*) - process_jobs_to_terminate (); - add_more_jobs_if_possible (); - if JS.is_empty !jobs then - () - else - begin - let (rfds, wfds, xfds) = compute_fds () in - ticker (); - let (chrfds, chwfds, chxfds) = select rfds wfds xfds period in - List.iter - begin fun (fdlist, hook) -> - List.iter - begin fun fd -> - try - let job = FDM.find fd !outputs in - ticker (); - hook fd job - with - | Not_found -> () (* XXX *) - end - fdlist - end - [chrfds, do_read ~loop:false; - chwfds, (fun _ _ -> ()); - chxfds, - begin fun _ _job -> - (*display (fun oc -> fp oc "Exceptional condition on command %S\n%!" job.job_command); - exit Exceptional_condition*) - () (* FIXME *) - end]; - loop () - end - in - try - loop (); - None - with - | x -> - begin - try - terminate_all_jobs () - with - | x' -> - display (fun oc -> fp oc "Extra exception %s\n%!" (Printexc.to_string x')) - end; - Some(List.map (!) results, x) -;; -(* ***) diff --git a/ocamlbuild/ocamlbuild_executor.mli b/ocamlbuild/ocamlbuild_executor.mli deleted file mode 100644 index 063b91ee..00000000 --- a/ocamlbuild/ocamlbuild_executor.mli +++ /dev/null @@ -1,55 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Ocamlbuild_executor *) - -(** UNIX-specific module for running tasks in parallel and properly multiplexing their outputs. *) - -type error = - | Subcommand_failed - | Subcommand_got_signal - | Io_error - | Exceptionl_condition - -(** [execute ~ticker ~period ~display ~exit commands] will execute the commands - in [commands] in parallel, correctly multiplexing their outputs. - - A command is a function that given a unit [()] returns the shell command - string to execute, commands are functions in order to do some job just - before executing the command. These functions will be called once. If - specified, it will call [ticker] at least every [period] seconds. If - specified, it will call [display f] when it wishes to print something; - [display] should then call [f] with then channel on which [f] should - print. - - Note that if the shell command to execute is the empty string [""], it's - considered as a no-op. - - Note that [f] must be idempotent as it may well be called twice, once for - the log file, once for the actual output. - - If one of the commands fails, it will exit with an appropriate error code, - calling [cleanup] before. - - All exits are done trough the call to the given [exit] function, if not - supplied Pervasives.exit is used. -*) -val execute : - ?max_jobs:int -> - ?ticker:(unit -> unit) -> - ?period:float -> - ?display:((out_channel -> unit) -> unit) -> - exit:(error -> unit) -> - ((unit -> string) list list) -> - (bool list * exn) option diff --git a/ocamlbuild/ocamlbuild_pack.mlpack b/ocamlbuild/ocamlbuild_pack.mlpack deleted file mode 100644 index 450592f5..00000000 --- a/ocamlbuild/ocamlbuild_pack.mlpack +++ /dev/null @@ -1,43 +0,0 @@ -Const -Loc -Log -My_unix -My_std -Signatures -Shell -Display -Command -Configuration -Discard_printf -Flags -Hygiene -Options -Pathname -Report -Resource -Rule -Slurp -Solver -Tags -Tools -Fda -Ocaml_specific -Ocaml_arch -Ocamlbuild_where -Ocamlbuild_Myocamlbuild_config -Lexers -Glob -Bool -Glob_ast -Glob_lexer -Plugin -Main -Hooks -Ocaml_utils -Ocaml_tools -Ocaml_compiler -Ocaml_dependencies -Exit_codes -Digest_cache -Findlib -Param_tags diff --git a/ocamlbuild/ocamlbuild_plugin.ml b/ocamlbuild/ocamlbuild_plugin.ml deleted file mode 100644 index 33c9c9df..00000000 --- a/ocamlbuild/ocamlbuild_plugin.ml +++ /dev/null @@ -1,63 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -open Ocamlbuild_pack -include Ocamlbuild_pack.My_std -module Arch = Ocamlbuild_pack.Ocaml_arch -module Command = Ocamlbuild_pack.Command -module Pathname = Ocamlbuild_pack.Pathname -module Tags = Ocamlbuild_pack.Tags -include Pathname.Operators -include Tags.Operators -module Rule = Ocamlbuild_pack.Rule -module Options = Ocamlbuild_pack.Options -module Findlib = Ocamlbuild_pack.Findlib -type command = Command.t = Seq of command list | Cmd of spec | Echo of string list * string | Nop -and spec = Command.spec = - | N | S of spec list | A of string | P of string | Px of string - | Sh of string | T of Tags.t | V of string | Quote of spec -include Rule.Common_commands -type env = Pathname.t -> Pathname.t -type builder = Pathname.t list list -> (Pathname.t, exn) Ocamlbuild_pack.My_std.Outcome.t list -type action = env -> builder -> Command.t -let rule = Rule.rule -let clear_rules = Rule.clear_rules -let dep = Command.dep -let pdep = Command.pdep -let copy_rule = Rule.copy_rule -let ocaml_lib = Ocamlbuild_pack.Ocaml_utils.ocaml_lib -let flag = Ocamlbuild_pack.Flags.flag ?deprecated:None -let pflag = Ocamlbuild_pack.Flags.pflag -let mark_tag_used = Ocamlbuild_pack.Flags.mark_tag_used -let flag_and_dep = Ocamlbuild_pack.Ocaml_utils.flag_and_dep -let pflag_and_dep = Ocamlbuild_pack.Ocaml_utils.pflag_and_dep -let non_dependency = Ocamlbuild_pack.Ocaml_utils.non_dependency -let use_lib = Ocamlbuild_pack.Ocaml_utils.use_lib -let module_name_of_pathname = Ocamlbuild_pack.Ocaml_utils.module_name_of_pathname -let string_list_of_file = Ocamlbuild_pack.Ocaml_utils.string_list_of_file -let expand_module = Ocamlbuild_pack.Ocaml_utils.expand_module -let tags_of_pathname = Ocamlbuild_pack.Tools.tags_of_pathname -let hide_package_contents = Ocamlbuild_pack.Ocaml_compiler.hide_package_contents -let tag_file = Ocamlbuild_pack.Configuration.tag_file -let tag_any = Ocamlbuild_pack.Configuration.tag_any -let run_and_read = Ocamlbuild_pack.My_unix.run_and_read -type hook = Ocamlbuild_pack.Hooks.message = - | Before_hygiene - | After_hygiene - | Before_options - | After_options - | Before_rules - | After_rules -let dispatch = Ocamlbuild_pack.Hooks.setup_hooks diff --git a/ocamlbuild/ocamlbuild_plugin.mli b/ocamlbuild/ocamlbuild_plugin.mli deleted file mode 100644 index f94f325f..00000000 --- a/ocamlbuild/ocamlbuild_plugin.mli +++ /dev/null @@ -1,17 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -include Ocamlbuild_pack.Signatures.PLUGIN - with module Pathname = Ocamlbuild_pack.Pathname - and module Outcome = Ocamlbuild_pack.My_std.Outcome - and module Tags = Ocamlbuild_pack.Tags - and module Command = Ocamlbuild_pack.Command diff --git a/ocamlbuild/ocamlbuild_unix_plugin.ml b/ocamlbuild/ocamlbuild_unix_plugin.ml deleted file mode 100644 index 2ed88b99..00000000 --- a/ocamlbuild/ocamlbuild_unix_plugin.ml +++ /dev/null @@ -1,95 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open Format -open Ocamlbuild_pack -open My_unix - -let report_error f = - function - | Unix.Unix_error(err, fun_name, arg) -> - fprintf f "%s: %S failed" Sys.argv.(0) fun_name; - if String.length arg > 0 then - fprintf f " on %S" arg; - fprintf f ": %s" (Unix.error_message err) - | exn -> raise exn - -let mkstat unix_stat x = - let st = - try unix_stat x - with Unix.Unix_error _ as e -> raise (Sys_error (My_std.sbprintf "%a" report_error e)) - in - { stat_key = sprintf "(%d,%d)" st.Unix.st_dev st.Unix.st_ino; - stat_file_kind = - match st.Unix.st_kind with - | Unix.S_LNK -> FK_link - | Unix.S_DIR -> FK_dir - | Unix.S_CHR | Unix.S_BLK | Unix.S_FIFO | Unix.S_SOCK -> FK_other - | Unix.S_REG -> FK_file } - -let is_link s = (Unix.lstat s).Unix.st_kind = Unix.S_LNK - -let at_exit_once callback = - let pid = Unix.getpid () in - at_exit begin fun () -> - if pid = Unix.getpid () then callback () - end - -let run_and_open s kont = - let ic = Unix.open_process_in s in - let close () = - match Unix.close_process_in ic with - | Unix.WEXITED 0 -> () - | Unix.WEXITED _ | Unix.WSIGNALED _ | Unix.WSTOPPED _ -> - failwith (Printf.sprintf "Error while running: %s" s) in - let res = try - kont ic - with e -> (close (); raise e) - in close (); res - -let stdout_isatty () = - Unix.isatty Unix.stdout && - try Unix.getenv "TERM" <> "dumb" with Not_found -> true - -let execute_many = - let exit i = raise (My_std.Exit_with_code i) in - let exit = function - | Ocamlbuild_executor.Subcommand_failed -> exit Exit_codes.rc_executor_subcommand_failed - | Ocamlbuild_executor.Subcommand_got_signal -> exit Exit_codes.rc_executor_subcommand_got_signal - | Ocamlbuild_executor.Io_error -> exit Exit_codes.rc_executor_io_error - | Ocamlbuild_executor.Exceptionl_condition -> exit Exit_codes.rc_executor_excetptional_condition - in - Ocamlbuild_executor.execute ~exit - -(* Ocamlbuild code assumes throughout that [readlink] will return a file name - relative to the current directory. Let's make it so. *) -let myunixreadlink x = - let y = Unix.readlink x in - if Filename.is_relative y then - Filename.concat (Filename.dirname x) y - else - y - -let setup () = - implem.is_degraded <- false; - implem.stdout_isatty <- stdout_isatty; - implem.gettimeofday <- Unix.gettimeofday; - implem.report_error <- report_error; - implem.execute_many <- execute_many; - implem.readlink <- myunixreadlink; - implem.run_and_open <- run_and_open; - implem.at_exit_once <- at_exit_once; - implem.is_link <- is_link; - implem.stat <- mkstat Unix.stat; - implem.lstat <- mkstat Unix.lstat;; diff --git a/ocamlbuild/ocamlbuild_unix_plugin.mli b/ocamlbuild/ocamlbuild_unix_plugin.mli deleted file mode 100644 index ecc4f62d..00000000 --- a/ocamlbuild/ocamlbuild_unix_plugin.mli +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -val setup : unit -> unit diff --git a/ocamlbuild/ocamlbuild_where.ml b/ocamlbuild/ocamlbuild_where.ml deleted file mode 100644 index 6cea4fdf..00000000 --- a/ocamlbuild/ocamlbuild_where.ml +++ /dev/null @@ -1,19 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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 bindir = ref Ocamlbuild_config.bindir;; -let libdir = ref begin - Filename.concat - (try Sys.getenv "OCAMLLIB" - with Not_found -> Ocamlbuild_config.libdir) - "ocamlbuild" -end;; diff --git a/ocamlbuild/ocamlbuild_where.mli b/ocamlbuild/ocamlbuild_where.mli deleted file mode 100644 index 6fa56787..00000000 --- a/ocamlbuild/ocamlbuild_where.mli +++ /dev/null @@ -1,18 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - - -(* Original author: Nicolas Pouillard *) - -val bindir : string ref -val libdir : string ref diff --git a/ocamlbuild/ocamlbuildlib.mllib b/ocamlbuild/ocamlbuildlib.mllib deleted file mode 100644 index 767ed32c..00000000 --- a/ocamlbuild/ocamlbuildlib.mllib +++ /dev/null @@ -1,4 +0,0 @@ -Ocamlbuild_pack -Ocamlbuild_plugin -Ocamlbuild_unix_plugin -Ocamlbuild_executor diff --git a/ocamlbuild/ocamlbuildlight.ml b/ocamlbuild/ocamlbuildlight.ml deleted file mode 100644 index f8226875..00000000 --- a/ocamlbuild/ocamlbuildlight.ml +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -Ocamlbuild_pack.Main.main ();; diff --git a/ocamlbuild/ocamlbuildlight.mli b/ocamlbuild/ocamlbuildlight.mli deleted file mode 100644 index 9f4d063d..00000000 --- a/ocamlbuild/ocamlbuildlight.mli +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Nothing *) diff --git a/ocamlbuild/ocamlbuildlightlib.mllib b/ocamlbuild/ocamlbuildlightlib.mllib deleted file mode 100644 index dc38da3d..00000000 --- a/ocamlbuild/ocamlbuildlightlib.mllib +++ /dev/null @@ -1,2 +0,0 @@ -Ocamlbuild_pack -Ocamlbuild_plugin diff --git a/ocamlbuild/options.ml b/ocamlbuild/options.ml deleted file mode 100644 index 3d4393d3..00000000 --- a/ocamlbuild/options.ml +++ /dev/null @@ -1,373 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -let version = "ocamlbuild "^(Sys.ocaml_version);; - -type command_spec = Command.spec - -open My_std -open Arg -open Format -open Command - -let entry = ref None -let project_root_dir = ref None -let build_dir = ref (Filename.concat (Sys.getcwd ()) "_build") -let include_dirs = ref [] -let exclude_dirs = ref [] -let nothing_should_be_rebuilt = ref false -let sanitize = ref true -let sanitization_script = ref "sanitize.sh" -let hygiene = ref true -let ignore_auto = ref true -let plugin = ref true -let just_plugin = ref false -let native_plugin = ref true -let make_links = ref true -let nostdlib = ref false -let use_menhir = ref false -let catch_errors = ref true -let use_ocamlfind = ref false - -(* Currently only ocamlfind and menhir is defined as no-core tool, - perhaps later we need something better *) -let is_core_tool = function "ocamlfind" | "menhir" -> false | _ -> true - -let find_tool cmd = - let dir = Ocamlbuild_where.bindir in - let core_tool = is_core_tool cmd in - let opt = cmd ^ ".opt" in - let search_in_path = memo Command.search_in_path in - if sys_file_exists !dir then - let long = filename_concat !dir cmd in - let long_opt = long ^ ".opt" in - (* This defines how the command will be found *) - let choices = - [(fun () -> if file_or_exe_exists long_opt then Some long_opt else None); - (fun () -> if file_or_exe_exists long then Some long else None)] in - (* For non core tool the preference is too look at PATH first *) - let choices' = - [fun () -> - try let _ = search_in_path opt in Some opt - with Not_found -> Some cmd] - in - let choices = if core_tool then choices @ choices' else choices' @ choices in - try - match (List.find (fun choice -> not (choice () = None)) choices) () with - Some cmd -> cmd - | None -> raise Not_found - with Not_found -> failwith (Printf.sprintf "Can't find tool: %s" cmd) - else - try let _ = search_in_path opt in opt - with Not_found -> cmd - -let mk_virtual_solvers = - List.iter begin fun cmd -> - let solver () = - A (find_tool cmd) - in Command.setup_virtual_command_solver (String.uppercase cmd) solver - end - -let () = - mk_virtual_solvers - ["ocamlc"; "ocamlopt"; "ocamldep"; "ocamldoc"; - "ocamlyacc"; "menhir"; "ocamllex"; "ocamlmklib"; "ocamlmktop"; "ocamlfind"] -let ocamlc = ref (V"OCAMLC") -let ocamlopt = ref (V"OCAMLOPT") -let ocamldep = ref (V"OCAMLDEP") -let ocamldoc = ref (V"OCAMLDOC") -let ocamlyacc = ref N -let ocamllex = ref (V"OCAMLLEX") -let ocamlmklib = ref (V"OCAMLMKLIB") -let ocamlmktop = ref (V"OCAMLMKTOP") -let ocamlrun = ref N -let ocamlfind_cmd = ref (V"OCAMLFIND") -let ocamlfind arg = S[!ocamlfind_cmd; arg] -let program_to_execute = ref false -let must_clean = ref false -let show_documentation = ref false -let recursive = ref false -let ext_lib = ref Ocamlbuild_config.a -let ext_obj = ref Ocamlbuild_config.o -let ext_dll = - let s = Ocamlbuild_config.ext_dll in - ref (String.sub s 1 (String.length s - 1)) -let exe = ref Ocamlbuild_config.exe - -let targets_internal = ref [] -let ocaml_libs_internal = ref [] -let ocaml_mods_internal = ref [] -let ocaml_pkgs_internal = ref [] -let ocaml_syntax = ref None -let ocaml_lflags_internal = ref [] -let ocaml_cflags_internal = ref [] -let ocaml_docflags_internal = ref [] -let ocaml_ppflags_internal = ref [] -let ocaml_yaccflags_internal = ref [] -let ocaml_lexflags_internal = ref [] -let program_args_internal = ref [] -let ignore_list_internal = ref [] -let tags_internal = ref [["quiet"]] -let tag_lines_internal = ref [] -let show_tags_internal = ref [] -let plugin_tags_internal = ref [] -let log_file_internal = ref "_log" - -let my_include_dirs = ref [[Filename.current_dir_name]] -let my_exclude_dirs = ref [[".svn"; "CVS"]] - -let dummy = "*invalid-dummy-string*";; (* Dummy string for delimiting the latest argument *) - -(* The JoCaml support will be in a plugin when the plugin system will support - * multiple/installed plugins *) -let use_jocaml () = - ocamlc := A "jocamlc"; - ocamlopt := A "jocamlopt"; - ocamldep := A "jocamldep"; - ocamlyacc := A "jocamlyacc"; - ocamllex := A "jocamllex"; - ocamlmklib := A "jocamlmklib"; - ocamlmktop := A "jocamlmktop"; - ocamlrun := A "jocamlrun"; -;; - -let add_to rxs x = - let xs = Lexers.comma_or_blank_sep_strings - Const.Source.command_line (Lexing.from_string x) in - rxs := xs :: !rxs -let add_to' rxs x = - if x <> dummy then - rxs := [x] :: !rxs - else - () -let set_cmd rcmd = String (fun s -> rcmd := Sh s) -let set_build_dir s = - make_links := false; - if Filename.is_relative s then - build_dir := Filename.concat (Sys.getcwd ()) s - else - build_dir := s -let spec = ref ( - Arg.align - [ - "-version", Unit (fun () -> print_endline version; raise Exit_OK), " Display the version"; - "-vnum", Unit (fun () -> print_endline Sys.ocaml_version; raise Exit_OK), - " Display the version number"; - "-quiet", Unit (fun () -> Log.level := 0), " Make as quiet as possible"; - "-verbose", Int (fun i -> Log.classic_display := true; Log.level := i + 2), " Set the verbosity level"; - "-documentation", Set show_documentation, " Show rules and flags"; - "-log", Set_string log_file_internal, " Set log file"; - "-no-log", Unit (fun () -> log_file_internal := ""), " No log file"; - "-clean", Set must_clean, " Remove build directory and other files, then exit"; - "-r", Set recursive, " Traverse directories by default (true: traverse)"; - - "-I", String (add_to' my_include_dirs), " Add to include directories"; - "-Is", String (add_to my_include_dirs), " (same as above, but accepts a (comma or blank)-separated list)"; - "-X", String (add_to' my_exclude_dirs), " Directory to ignore"; - "-Xs", String (add_to my_exclude_dirs), " (idem)"; - - "-lib", String (add_to' ocaml_libs_internal), " Link to this ocaml library"; - "-libs", String (add_to ocaml_libs_internal), " (idem)"; - "-mod", String (add_to' ocaml_mods_internal), " Link to this ocaml module"; - "-mods", String (add_to ocaml_mods_internal), " (idem)"; - "-pkg", String (add_to' ocaml_pkgs_internal), " Link to this ocaml findlib package"; - "-pkgs", String (add_to ocaml_pkgs_internal), " (idem)"; - "-package", String (add_to' ocaml_pkgs_internal), " (idem)"; - "-syntax", String (fun syntax -> ocaml_syntax := Some syntax), " Specify syntax using ocamlfind"; - "-lflag", String (add_to' ocaml_lflags_internal), " Add to ocamlc link flags"; - "-lflags", String (add_to ocaml_lflags_internal), " (idem)"; - "-cflag", String (add_to' ocaml_cflags_internal), " Add to ocamlc compile flags"; - "-cflags", String (add_to ocaml_cflags_internal), " (idem)"; - "-docflag", String (add_to' ocaml_docflags_internal), " Add to ocamldoc flags"; - "-docflags", String (add_to ocaml_docflags_internal), " (idem)"; - "-yaccflag", String (add_to' ocaml_yaccflags_internal), " Add to ocamlyacc flags"; - "-yaccflags", String (add_to ocaml_yaccflags_internal), " (idem)"; - "-lexflag", String (add_to' ocaml_lexflags_internal), " Add to ocamllex flags"; - "-lexflags", String (add_to ocaml_lexflags_internal), " (idem)"; - "-ppflag", String (add_to' ocaml_ppflags_internal), " Add to ocaml preprocessing flags"; - "-pp", String (add_to ocaml_ppflags_internal), " (idem)"; - "-tag", String (add_to' tags_internal), " Add to default tags"; - "-tags", String (add_to tags_internal), " (idem)"; - "-plugin-tag", String (add_to' plugin_tags_internal), " Use this tag when compiling the myocamlbuild.ml plugin"; - "-plugin-tags", String (add_to plugin_tags_internal), " (idem)"; - "-tag-line", String (add_to' tag_lines_internal), " Use this line of tags (as in _tags)"; - "-show-tags", String (add_to' show_tags_internal), " Show tags that applies on that pathname"; - - "-ignore", String (add_to ignore_list_internal), " Don't try to build these modules"; - "-no-links", Clear make_links, " Don't make links of produced final targets"; - "-no-skip", Clear ignore_auto, " Don't skip modules that are requested by ocamldep but cannot be built"; - "-no-hygiene", Clear hygiene, " Don't apply sanity-check rules"; - "-no-plugin", Clear plugin, " Don't build myocamlbuild.ml"; - "-no-stdlib", Set nostdlib, " Don't ignore stdlib modules"; - "-dont-catch-errors", Clear catch_errors, " Don't catch and display exceptions (useful to display the call stack)"; - "-just-plugin", Set just_plugin, " Just build myocamlbuild.ml"; - "-byte-plugin", Clear native_plugin, " Don't use a native plugin but bytecode"; - "-plugin-option", String ignore, " Use the option only when plugin is run"; - "-sanitization-script", Set_string sanitization_script, " Change the file name for the generated sanitization script"; - "-no-sanitize", Clear sanitize, " Do not generate sanitization script"; - "-nothing-should-be-rebuilt", Set nothing_should_be_rebuilt, " Fail if something needs to be rebuilt"; - "-classic-display", Set Log.classic_display, " Display executed commands the old-fashioned way"; - "-use-menhir", Set use_menhir, " Use menhir instead of ocamlyacc"; - "-use-jocaml", Unit use_jocaml, " Use jocaml compilers instead of ocaml ones"; - "-use-ocamlfind", Set use_ocamlfind, " Use the 'ocamlfind' wrapper instead of \ - using Findlib directly to determine command-line arguments. \ - Use -no-ocamlfind to disable."; - "-no-ocamlfind", Clear use_ocamlfind, " Don't use ocamlfind."; - - "-j", Set_int Command.jobs, " Allow N jobs at once (0 for unlimited)"; - - "-build-dir", String set_build_dir, " Set build directory (implies no-links)"; - "-install-lib-dir", Set_string Ocamlbuild_where.libdir, " Set the install library directory"; - "-install-bin-dir", Set_string Ocamlbuild_where.bindir, " Set the install binary directory"; - "-where", Unit (fun () -> print_endline !Ocamlbuild_where.libdir; raise Exit_OK), " Display the install library directory"; - "-which", String (fun cmd -> print_endline (find_tool cmd); raise Exit_OK), " Display path to the tool command"; - "-ocamlc", set_cmd ocamlc, " Set the OCaml bytecode compiler"; - "-ocamlopt", set_cmd ocamlopt, " Set the OCaml native compiler"; - "-ocamldep", set_cmd ocamldep, " Set the OCaml dependency tool"; - "-ocamldoc", set_cmd ocamldoc, " Set the OCaml documentation generator"; - "-ocamlyacc", set_cmd ocamlyacc, " Set the ocamlyacc tool"; - "-menhir", set_cmd ocamlyacc, " Set the menhir tool (use it after -use-menhir)"; - "-ocamllex", set_cmd ocamllex, " Set the ocamllex tool"; - "-ocamlmklib", set_cmd ocamlmklib, " Set the ocamlmklib tool"; - "-ocamlmktop", set_cmd ocamlmktop, " Set the ocamlmktop tool"; - "-ocamlrun", set_cmd ocamlrun, " Set the ocamlrun tool"; - - "--", Rest (fun x -> program_to_execute := true; add_to' program_args_internal x), - " Stop argument processing, remaining arguments are given to the user program"; - ]) - -let add x = - spec := !spec @ [x] - -let targets = ref [] -let ocaml_libs = ref [] -let ocaml_mods = ref [] -let ocaml_pkgs = ref [] -let ocaml_lflags = ref [] -let ocaml_cflags = ref [] -let ocaml_ppflags = ref [] -let ocaml_docflags = ref [] -let ocaml_yaccflags = ref [] -let ocaml_lexflags = ref [] -let program_args = ref [] -let ignore_list = ref [] -let tags = ref [] -let tag_lines = ref [] -let show_tags = ref [] -let plugin_tags = ref [] - -let init () = - let anon_fun = add_to' targets_internal in - let usage_msg = sprintf "Usage %s [options] " Sys.argv.(0) in - let argv' = Array.concat [Sys.argv; [|dummy|]] in - parse_argv argv' !spec anon_fun usage_msg; - Shell.mkdir_p !build_dir; - - project_root_dir := Some (Sys.getcwd ()); - - let () = - let log = !log_file_internal in - if log = "" then Log.init None - else if not (Filename.is_implicit log) then - failwith - (sprintf "Bad log file name: the file name must be implicit (not %S)" log) - else - let log = filename_concat !build_dir log in - Shell.mkdir_p (Filename.dirname log); - Shell.rm_f log; - let log = if !Log.level > 0 then Some log else None in - Log.init log - in - - if !use_ocamlfind then begin - begin try ignore(Command.search_in_path "ocamlfind") - with Not_found -> - failwith "ocamlfind not found on path, but -no-ocamlfind not used" - end; - - let with_ocamlfind (command_name, command_ref) = - command_ref := match !command_ref with - | Sh user_command -> - (* this command has been set by the user - using an -ocamlc, -ocamlopt, etc. flag; - - not all such combinations make sense (eg. "ocamlfind - /my/special/path/to/ocamlc" will make ocamlfind choke), - but the user will see the error and hopefully fix the - flags. *) - ocamlfind & (Sh user_command); - | _ -> ocamlfind & A command_name - in - (* Note that plugins can still modify these variables After_options. - This design decision can easily be changed. *) - List.iter with_ocamlfind [ - "ocamlc", ocamlc; - "ocamlopt", ocamlopt; - "ocamldep", ocamldep; - "ocamldoc", ocamldoc; - "ocamlmklib", ocamlmklib; - "ocamlmktop", ocamlmktop; - ] - end; - - let reorder x y = x := !x @ (List.concat (List.rev !y)) in - reorder targets targets_internal; - reorder ocaml_libs ocaml_libs_internal; - reorder ocaml_mods ocaml_mods_internal; - reorder ocaml_pkgs ocaml_pkgs_internal; - reorder ocaml_cflags ocaml_cflags_internal; - reorder ocaml_lflags ocaml_lflags_internal; - reorder ocaml_ppflags ocaml_ppflags_internal; - reorder ocaml_docflags ocaml_docflags_internal; - reorder ocaml_yaccflags ocaml_yaccflags_internal; - reorder ocaml_lexflags ocaml_lexflags_internal; - reorder program_args program_args_internal; - reorder tags tags_internal; - reorder tag_lines tag_lines_internal; - reorder ignore_list ignore_list_internal; - reorder show_tags show_tags_internal; - reorder plugin_tags plugin_tags_internal; - - let check_dir dir = - if Filename.is_implicit dir then - sys_file_exists dir - else - failwith - (sprintf "Included or excluded directories must be implicit (not %S)" dir) - in - let dir_reorder my dir = - let d = !dir in - reorder dir my; - dir := List.filter check_dir (!dir @ d) - in - dir_reorder my_include_dirs include_dirs; - dir_reorder my_exclude_dirs exclude_dirs; - - ignore_list := List.map String.capitalize !ignore_list -;; - -(* The current heuristic: we know we are in an ocamlbuild project if - either _tags or myocamlbuild.ml are present at the root. This - heuristic has been documented and explained to users, so it should - not be changed. *) -let ocamlbuild_project_heuristic () = - let root_dir = match !project_root_dir with - | None -> Sys.getcwd () - | Some dir -> dir in - let at_root file = Filename.concat root_dir file in - Sys.file_exists (* authorized since we're not in build *) - (at_root "_tags") - || Sys.file_exists (* authorized since we're not in build *) - (at_root "myocamlbuild.ml") diff --git a/ocamlbuild/options.mli b/ocamlbuild/options.mli deleted file mode 100644 index 0a0d39c4..00000000 --- a/ocamlbuild/options.mli +++ /dev/null @@ -1,34 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -include Signatures.OPTIONS with type command_spec = Command.spec - -(* This option is not in Signatures.OPTIONS yet because adding tags to - the compilation of the plugin is a recent feature that may still be - subject to change, so the interface may not be stable; besides, - there is obviously little to gain from tweaking that option from - inside the plugin itself... *) -val plugin_tags : string list ref - -(* Returns 'true' if we heuristically infer that we are run from an - ocamlbuild projet (either _tags or myocamlbuild.ml are present). - - This information is used to decide whether to enable recursive - traversal of subdirectories by default. -*) -val ocamlbuild_project_heuristic : unit -> bool - -val entry : bool Slurp.entry option ref -val init : unit -> unit diff --git a/ocamlbuild/param_tags.ml b/ocamlbuild/param_tags.ml deleted file mode 100644 index 45623903..00000000 --- a/ocamlbuild/param_tags.ml +++ /dev/null @@ -1,62 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -open My_std - -(* Original author: Romain Bardou *) - -module StringSet = Set.Make(String) - -(* tag name -> tag action (string -> unit) *) -let declared_tags = Hashtbl.create 17 - -let acknowledged_tags = ref [] - -let only_once f = - let instances = ref StringSet.empty in - fun param -> - if StringSet.mem param !instances then () - else begin - instances := StringSet.add param !instances; - f param - end - -let declare name action = - Hashtbl.add declared_tags name (only_once action) - -let parse source tag = Lexers.tag_gen source (lexbuf_of_string tag) - -let acknowledge source maybe_loc tag = - acknowledged_tags := (parse source tag, maybe_loc) :: !acknowledged_tags - -let really_acknowledge ?(quiet=false) ((name, param), maybe_loc) = - match param with - | None -> - if Hashtbl.mem declared_tags name && not quiet then - Log.eprintf "%aWarning: tag %S expects a parameter" - Loc.print_loc_option maybe_loc name - | Some param -> - let actions = List.rev (Hashtbl.find_all declared_tags name) in - if actions = [] && not quiet then - Log.eprintf "%aWarning: tag %S does not expect a parameter, \ - but is used with parameter %S" - Loc.print_loc_option maybe_loc name param; - List.iter (fun f -> f param) actions - -let partial_init ?quiet source tags = - let parse_noloc tag = (parse source tag, None) in - Tags.iter (fun tag -> really_acknowledge ?quiet (parse_noloc tag)) tags - -let init () = - List.iter really_acknowledge (My_std.List.ordered_unique !acknowledged_tags) - -let make = Printf.sprintf "%s(%s)" diff --git a/ocamlbuild/param_tags.mli b/ocamlbuild/param_tags.mli deleted file mode 100644 index 06113941..00000000 --- a/ocamlbuild/param_tags.mli +++ /dev/null @@ -1,50 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Romain Bardou *) - -val declare: string -> (string -> unit) -> unit - (** Declare a parameterized tag. - -[declare "name" action]: [action "param"] will be executed (once) by [init] -if a tag of the form [name(param)] is [acknowledge]d. - -A given tag may be declared several times with different actions. All actions -will be executed, in the order they were declared. *) - -val acknowledge: Loc.source -> Loc.location option -> string -> unit - (** Acknowledge a tag. - -If the tag is of the form [X(Y)], and have been declared using [declare], -then the actions given using [declare] will be executed with [Y] as parameter -when [init] is executed. The action will only be called once per -acknowledged parameter. *) - -val init: unit -> unit - (** Initialize parameterized tags. - -This will make effective all instantiations [foo(bar)] such that the -parametrized tag [foo] has been [declare]d and [foo(bar)] has been -[acknowledge]d after the last [init] call. *) - -val partial_init: ?quiet:bool -> Loc.source -> Tags.t -> unit -(** Initialize a list of tags - -This will make effective the instances [foo(bar)] appearing -in the given tag list, instead of those that have been -[acknowledged] previously. This is for system use only. *) - -val make: Tags.elt -> string -> Tags.elt - (** Make a parameterized tag instance. - -Example: [make "package" "unix"]: return the tag ["package(unix)"] *) diff --git a/ocamlbuild/pathname.ml b/ocamlbuild/pathname.ml deleted file mode 100644 index d0c73726..00000000 --- a/ocamlbuild/pathname.ml +++ /dev/null @@ -1,159 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log - -type t = string - -include Filename - -let print_strings = List.print String.print - -let concat = filename_concat - -let compare (x:t) y = compare x y - -let print = pp_print_string - -let mk s = s - -let pwd = Sys.getcwd () - -let add_extension ext x = x ^ "." ^ ext - -let check_extension x ext = - let lx = String.length x and lext = String.length ext in - lx > lext + 1 && x.[lx - lext - 1] = '.' && String.is_suffix x ext - -module Operators = struct - let ( / ) = concat - let ( -.- ) file ext = add_extension ext file -end -open Operators - -let equal x y = x = y - -let to_string x = x - -let is_link = Shell.is_link -let readlink = Shell.readlink -let is_directory x = - try (My_unix.stat x).My_unix.stat_file_kind = My_unix.FK_dir - with Sys_error _ -> false -let readdir x = Outcome.good (sys_readdir x) - -let dir_seps = ['/';'\\'] (* FIXME add more *) -let not_normal_form_re = Glob.parse "<**/{,.,..}/**>" - -let parent x = concat parent_dir_name x - -let split p = - let rec go p acc = - let dir = dirname p in - if dir = p then dir, acc - else go dir (basename p :: acc) - in go p [] - -let join root paths = - let root = if root = current_dir_name then "" else root in - List.fold_left (/) root paths - -let _H1 = assert (current_dir_name = ".") -let _H2 = assert (parent_dir_name = "..") - -(* Use H1, H2 *) -let rec normalize_list = function - | [] -> [] - | "." :: xs -> normalize_list xs - | ".." :: _ -> failwith "Pathname.normalize_list: .. is forbidden here" - | _ :: ".." :: xs -> normalize_list xs - | x :: xs -> x :: normalize_list xs - -let normalize x = - if Glob.eval not_normal_form_re x then - let root, paths = split x in - join root (normalize_list paths) - else x - -(* [is_prefix x y] is [x] a pathname prefix of [y] *) -let is_prefix x y = - let lx = String.length x and ly = String.length y in - if lx = ly then x = (String.before y lx) - else if lx < ly then x = (String.before y lx) && List.mem y.[lx] dir_seps - else false - -let link_to_dir p dir = is_link p && is_prefix dir (readlink p) - -let remove_extension x = - try chop_extension x - with Invalid_argument _ -> x -let get_extension x = - try - let pos = String.rindex x '.' in - String.after x (pos + 1) - with Not_found -> "" -let update_extension ext x = - add_extension ext (chop_extension x) - -let chop_extensions x = - let dirname = dirname x and basename = basename x in - try - let pos = String.index basename '.' in - dirname / (String.before basename pos) - with Not_found -> invalid_arg "chop_extensions: no extensions" -let remove_extensions x = - try chop_extensions x - with Invalid_argument _ -> x -let get_extensions x = - let basename = basename x in - try - let pos = String.index basename '.' in - String.after basename (pos + 1) - with Not_found -> "" -let update_extensions ext x = - add_extension ext (chop_extensions x) - -let exists = sys_file_exists - -let copy = Shell.cp -let remove = Shell.rm -let try_remove x = if exists x then Shell.rm x -let read = read_file - -let with_input_file = with_input_file - -let with_output_file = with_output_file - -let print_path_list = List.print print - -let context_table = Hashtbl.create 107 - -let rec include_dirs_of dir = - try Hashtbl.find context_table dir - with Not_found -> dir :: List.filter (fun dir' -> dir <> dir') !Options.include_dirs - -(* -let include_dirs_of s = - let res = include_dirs_of s in - let () = dprintf 0 "include_dirs_of %S ->@ %a" s (List.print print) res - in res -*) - -let define_context dir context = - let dir = if dir = "" then current_dir_name else dir in - Hashtbl.replace context_table dir& List.union context& include_dirs_of dir - -let same_contents x y = Digest.file x = Digest.file y diff --git a/ocamlbuild/pathname.mli b/ocamlbuild/pathname.mli deleted file mode 100644 index 4f77e6a4..00000000 --- a/ocamlbuild/pathname.mli +++ /dev/null @@ -1,17 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -include Signatures.PATHNAME -val link_to_dir : t -> t -> bool -val normalize : t -> t diff --git a/ocamlbuild/plugin.ml b/ocamlbuild/plugin.ml deleted file mode 100644 index e4d18363..00000000 --- a/ocamlbuild/plugin.ml +++ /dev/null @@ -1,262 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log -open Pathname.Operators -open Tags.Operators -open Rule -open Tools -open Command -;; - - -let plugin = "myocamlbuild" -let plugin_file = plugin^".ml" -let plugin_config_file = plugin^"_config.ml" -let plugin_config_file_interface = plugin^"_config.mli" -let we_need_a_plugin () = !Options.plugin && sys_file_exists plugin_file -let we_have_a_plugin () = sys_file_exists ((!Options.build_dir/plugin)^(!Options.exe)) -let we_have_a_config_file () = sys_file_exists plugin_config_file -let we_have_a_config_file_interface () = sys_file_exists plugin_config_file_interface - -module Make(U:sig end) = - struct - let we_need_a_plugin = we_need_a_plugin () - let we_have_a_plugin = we_have_a_plugin () - let we_have_a_config_file = we_have_a_config_file () - let we_have_a_config_file_interface = we_have_a_config_file_interface () - let up_to_date_or_copy fn = - let fn' = !Options.build_dir/fn in - Pathname.exists fn && - begin - Pathname.exists fn' && Pathname.same_contents fn fn' || - begin - Shell.cp fn fn'; - false - end - end - - let rebuild_plugin_if_needed () = - let a = up_to_date_or_copy plugin_file in - let b = (not we_have_a_config_file) || up_to_date_or_copy plugin_config_file in - let c = (not we_have_a_config_file_interface) || up_to_date_or_copy plugin_config_file_interface in - if a && b && c && we_have_a_plugin then - () (* Up to date *) - (* FIXME: remove ocamlbuild_config.ml in _build/ if removed in parent *) - else begin - if !Options.native_plugin - && not (sys_file_exists ((!Ocamlbuild_where.libdir)/"ocamlbuildlib.cmxa")) then - begin - Options.native_plugin := false; - eprintf "Warning: Won't be able to compile a native plugin" - end; - let plugin_config = - if we_have_a_config_file then - if we_have_a_config_file_interface then - S[P plugin_config_file_interface; P plugin_config_file] - else P plugin_config_file - else N in - - let cma, cmo, compiler, byte_or_native = - if !Options.native_plugin then - "cmxa", "cmx", !Options.ocamlopt, "native" - else - "cma", "cmo", !Options.ocamlc, "byte" - in - - - let (unix_spec, ocamlbuild_lib_spec, ocamlbuild_module_spec) = - - let use_light_mode = - not !Options.native_plugin && !*My_unix.is_degraded in - let use_ocamlfind_pkgs = - !Options.use_ocamlfind && !Options.plugin_tags <> [] in - (* The plugin has the following dependencies that must be - included during compilation: - - - unix.cmxa, if it is available - - ocamlbuildlib.cm{a,xa}, the library part of ocamlbuild - - ocamlbuild.cm{o,x}, the module that performs the - initialization work of the ocamlbuild executable, using - modules of ocamlbuildlib.cmxa - - We pass all this stuff to the compilation command for the - plugin, with two independent important details to handle: - - (1) ocamlbuild is designed to still work in environments - where Unix is not available for some reason; in this - case, we should not link unix, and use the - "ocamlbuildlight.cmo" initialization module, which runs - a "light" version of ocamlbuild without unix. There is - also an ocamlbuildlightlib.cma archive to be used in that - case. - - The boolean variable [use_light_mode] tells us whether we - are in this unix-deprived scenario. - - (2) there are risks of compilation error due to - double-linking of native modules when the user passes its - own tags to the plugin compilation process (as was added - to support modular construction of - ocamlbuild plugins). Indeed, if we hard-code linking to - unix.cmxa in all cases, and the user - enables -use-ocamlfind and - passes -plugin-tag "package(unix)" (or package(foo) for - any foo which depends on unix), the command-line finally - executed will be - - ocamlfind ocamlopt unix.cmxa -package unix myocamlbuild.ml - - which fails with a compilation error due to doubly-passed - native modules. - - To sanest way to solve this problem at the ocamlbuild level - is to pass "-package unix" instead of unix.cmxa when we - detect that such a situation may happen. OCamlfind will see - that the same package is demanded twice, and only request - it once to the compiler. Similarly, we use "-package - ocamlbuild" instead of linking ocamlbuildlib.cmxa[1]. - - We switch to this behavior when two conditions, embodied in - the boolean variable [use_ocamlfind_pkgs], are met: - (a) use-ocamlfind is enabled - (b) the user is passing some plugin tags - - Condition (a) is overly conservative as the double-linking - issue may also happen in non-ocamlfind situations, such as - "-plugin-tags use_unix" -- but it's unclear how one would - avoid the issue in that case, except by documenting that - people should not do that, or getting rid of the - hard-linking logic entirely, with the corresponding risks - of regression. - - Condition (b) should not be necessary (we expect using - ocamlfind packages to work whenever ocamlfind - is available), but allows the behavior in absence - of -plugin-tags to be completely unchanged, to reassure us - about potential regressions introduced by this option. - - [1]: we may wonder whether to use "-package ocamlbuildlight" - in unix-deprived situations, but currently ocamlfind - doesn't know about the ocamlbuildlight library. As - a compromise we always use "-package ocamlbuild" when - use_ocamlfind_pkgs is set. An ocamlfind and -plugin-tags - user in unix-deprived environment may want to mutate the - META of ocamlbuild to point to ocamlbuildlightlib instead - of ocamlbuildlib. - *) - - let unix_lib = - if use_ocamlfind_pkgs then `Package "unix" - else if use_light_mode then `Nothing - else `Lib "unix" in - - let ocamlbuild_lib = - if use_ocamlfind_pkgs then `Package "ocamlbuild" - else if use_light_mode then `Local_lib "ocamlbuildlightlib" - else `Local_lib "ocamlbuildlib" in - - let ocamlbuild_module = - if use_light_mode then `Local_mod "ocamlbuildlight" - else `Local_mod "ocamlbuild" in - - let dir = !Ocamlbuild_where.libdir in - let dir = if Pathname.is_implicit dir then Pathname.pwd/dir else dir in - - let in_dir file = - let path = dir/file in - if not (sys_file_exists path) then failwith - (sprintf "Cannot find %S in ocamlbuild -where directory" file); - path in - - let spec = function - | `Nothing -> N - | `Package pkg -> S[A "-package"; A pkg] - | `Lib lib -> P (lib -.- cma) - | `Local_lib llib -> S [A "-I"; A dir; P (in_dir (llib -.- cma))] - | `Local_mod lmod -> P (in_dir (lmod -.- cmo)) in - - (spec unix_lib, spec ocamlbuild_lib, spec ocamlbuild_module) - in - - let plugin_tags = - Tags.of_list !Options.plugin_tags - ++ "ocaml" ++ "program" ++ "link" ++ byte_or_native in - - (* The plugin is compiled before [Param_tags.init()] is called - globally, which means that parametrized tags have not been - made effective yet. The [partial_init] calls below initializes - precisely those that will be used during the compilation of - the plugin, and no more. - *) - Param_tags.partial_init Const.Source.plugin_tag plugin_tags; - - let cmd = - (* The argument order is important: we carefully put the - plugin source files before the ocamlbuild.cm{o,x} module - doing the main initialization, so that user global - side-effects (setting options, installing flags..) are - performed brefore ocamlbuild's main routine. This is - a fragile thing to rely upon and we insist that our users - use the more robust [dispatch] registration instead, but - we still aren't going to break that now. - - For the same reason we place the user plugin-tags after - the plugin libraries (in case a tag would, say, inject - a .cmo that also relies on them), but before the main - plugin source file and ocamlbuild's initialization. *) - Cmd(S[compiler; - unix_spec; ocamlbuild_lib_spec; - T plugin_tags; - plugin_config; P plugin_file; - ocamlbuild_module_spec; - A"-o"; Px (plugin^(!Options.exe))]) - in - Shell.chdir !Options.build_dir; - Shell.rm_f (plugin^(!Options.exe)); - Command.execute cmd; - if !Options.just_plugin then begin - Log.finish (); - raise Exit_OK; - end; - end - - let execute_plugin_if_needed () = - if we_need_a_plugin then - begin - rebuild_plugin_if_needed (); - Shell.chdir Pathname.pwd; - let runner = if !Options.native_plugin then N else !Options.ocamlrun in - let argv = List.tl (Array.to_list Sys.argv) in - let passed_argv = List.filter (fun s -> s <> "-plugin-option") argv in - let spec = S[runner; P(!Options.build_dir/plugin^(!Options.exe)); - A"-no-plugin"; atomize passed_argv] in - Log.finish (); - let rc = sys_command (Command.string_of_command_spec spec) in - raise (Exit_silently_with_code rc); - end - else if not (sys_file_exists plugin_file) && !Options.plugin_tags <> [] then - eprintf "Warning: option -plugin-tag(s) has no effect \ - in absence of plugin file %S" plugin_file - else - () - end -;; - -let execute_plugin_if_needed () = - let module P = Make(struct end) in - P.execute_plugin_if_needed () -;; diff --git a/ocamlbuild/plugin.mli b/ocamlbuild/plugin.mli deleted file mode 100644 index 37d135a1..00000000 --- a/ocamlbuild/plugin.mli +++ /dev/null @@ -1,18 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Plugin *) - -val execute_plugin_if_needed : unit -> unit -val we_need_a_plugin : unit -> bool diff --git a/ocamlbuild/ppcache.ml b/ocamlbuild/ppcache.ml deleted file mode 100644 index 2682f3e1..00000000 --- a/ocamlbuild/ppcache.ml +++ /dev/null @@ -1,91 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Command -open Pathname.Operators -let () = Log.level := -1000 - -let usage () = - Format.eprintf "Usage: %s @." Sys.argv.(0); - exit 4 - -let () = if Array.length Sys.argv < 2 then usage () - -let args = List.tl (Array.to_list Sys.argv) - -let buf = Buffer.create 2048 - -let digest_file file = - Buffer.add_string buf (Digest.file file) -let digest_string string = - Buffer.add_string buf (Digest.string string) - -let search_in_path x = - if Sys.file_exists x then x else - try search_in_path x - with Not_found -> (Format.eprintf "Command not found %s@." x; exit 3) - -let cmd = - match args with - | ocamlrun :: x :: _ when String.contains_string ocamlrun 0 "ocamlrun" <> None -> - digest_file (search_in_path ocamlrun); x - | x :: _ -> x - | _ -> usage () - -let output = ref "" - -let () = digest_file (search_in_path cmd) - -let rec loop = - function - | [] -> Digest.string (Buffer.contents buf) - | ("-impl"|"-intf") :: x :: xs -> - digest_string x; digest_file x; loop xs - | "-o" :: x :: xs -> - output := x; loop xs - | x :: xs -> - let ext = Pathname.get_extension x in - digest_string x; - (match ext with - | "cmo" | "cma" | "ml" | "mli" -> digest_file x - | _ -> ()); - loop xs - -let digest = loop args;; - -let cache_dir = "/tmp/ppcache";; (* FIXME *) - -let () = Shell.mkdir_p cache_dir;; - -let path = cache_dir/(Digest.to_hex digest);; - -let cat path = with_input_file ~bin:true path (fun ic -> copy_chan ic stdout);; - -if sys_file_exists path then - if !output = "" then - cat path - else - Shell.cp path !output -else - let cmd = atomize args in - if !output = "" then begin - let tmp = path^".tmp" in - Command.execute (Cmd(S[cmd; Sh ">"; A tmp])); - Shell.mv tmp path; - cat path - end else begin - Command.execute (Cmd cmd); - Shell.cp !output path - end diff --git a/ocamlbuild/ppcache.mli b/ocamlbuild/ppcache.mli deleted file mode 100644 index 35f3614b..00000000 --- a/ocamlbuild/ppcache.mli +++ /dev/null @@ -1,15 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* nothing to export *) diff --git a/ocamlbuild/report.ml b/ocamlbuild/report.ml deleted file mode 100644 index 439a270f..00000000 --- a/ocamlbuild/report.ml +++ /dev/null @@ -1,62 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Report *) - -open My_std -open Log -open Format -open Solver - -let sources_glob = Glob.parse "<*.ml> or <*.mli> or <*.c> or <*.h>";; - -let rec analyze f bt = - match bt with - | Leaf r -> - fprintf f "Ocamlbuild knows of no rules that apply to a target named %a. \ - This can happen if you ask Ocamlbuild to build a target with the \ - wrong extension (e.g. .opt instead of .native) or if the source \ - files live in directories that have not been specified as \ - include directories." - Resource.print r; - false - | Depth(r, bt) -> - if Glob.eval sources_glob r then - begin - fprintf f "Ocamlbuild cannot find or build %a. A file with such a name would \ - usually be a source file. I suspect you have given a wrong target \ - name to Ocamlbuild." - Resource.print r; - false - end - else - analyze f bt - | Choice bl -> List.for_all (analyze f) bl - | Target(_, bt) -> analyze f bt - -let rec print_backtrace f = - function - | Target (name, backtrace) -> - fprintf f "@\n- @[<2>Failed to build the target %s%a@]" name print_backtrace backtrace - | Leaf r -> - fprintf f "@\n- @[<2>Building %a@]" Resource.print r - | Depth (r, backtrace) -> - fprintf f "@\n- @[Building %a:%a@]" Resource.print r print_backtrace backtrace - | Choice [backtrace] -> print_backtrace f backtrace - | Choice backtraces -> - fprintf f "@\n- @[Failed to build all of these:"; - List.iter (print_backtrace f) backtraces; - fprintf f "@]" - -let print_backtrace_analyze f bt = ignore (analyze f bt) diff --git a/ocamlbuild/report.mli b/ocamlbuild/report.mli deleted file mode 100644 index 13448558..00000000 --- a/ocamlbuild/report.mli +++ /dev/null @@ -1,19 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Report *) - -val print_backtrace_analyze : Format.formatter -> Solver.backtrace -> unit - -val print_backtrace : Format.formatter -> Solver.backtrace -> unit diff --git a/ocamlbuild/resource.ml b/ocamlbuild/resource.ml deleted file mode 100644 index 229d7712..00000000 --- a/ocamlbuild/resource.ml +++ /dev/null @@ -1,400 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log -open Pathname.Operators - - -type t = Pathname.t -module Resources = Set.Make(Pathname) - -let print = Pathname.print - -let equal = (=) -let compare = compare - -let in_source_dir p = - if Pathname.is_implicit p then Pathname.pwd/p else invalid_arg (Printf.sprintf "in_source_dir: %S" p) - -let in_build_dir p = - if Pathname.is_relative p then p - else invalid_arg (Printf.sprintf "in_build_dir: %S" p) - -let clean_up_links entry = - if not !Options.make_links then entry else - Slurp.filter begin fun path name _ -> - let pathname = in_source_dir (path/name) in - if Pathname.link_to_dir pathname !Options.build_dir then - let z = Pathname.readlink pathname in - (* Here is one exception where one can use Sys.file_exists directly *) - (if not (Sys.file_exists z) then - Shell.rm pathname; false) - else true - end entry - -let clean_up_link_to_build () = - Options.entry := Some(clean_up_links (the !Options.entry)) - -let source_dir_path_set_without_links_to_build = - lazy begin - clean_up_link_to_build (); - Slurp.fold (fun path name _ -> StringSet.add (path/name)) - (the !Options.entry) StringSet.empty - end - -let clean_links () = - if !*My_unix.is_degraded then - () - else - ignore (clean_up_link_to_build ()) - -let exists_in_source_dir p = - if !*My_unix.is_degraded then sys_file_exists (in_source_dir p) - else StringSet.mem p !*source_dir_path_set_without_links_to_build - -let clean p = Shell.rm_f p - -module Cache = struct - - let clean () = Shell.chdir Pathname.pwd; Shell.rm_rf !Options.build_dir - - type knowledge = - | Yes - | No - | Unknown - - type suspension = (Command.t * (unit -> unit)) - - type build_status = - | Bbuilt - | Bcannot_be_built - | Bnot_built_yet - | Bsuspension of suspension - - type cache_entry = - { mutable built : build_status; - mutable changed : knowledge; - mutable dependencies : Resources.t } - - let empty () = - { built = Bnot_built_yet; - changed = Unknown; - dependencies = Resources.empty } - - let print_knowledge f = - function - | Yes -> pp_print_string f "Yes" - | No -> pp_print_string f "No" - | Unknown -> pp_print_string f "Unknown" - - let print_build_status f = - function - | Bbuilt -> pp_print_string f "Bbuilt" - | Bnot_built_yet -> pp_print_string f "Bnot_built_yet" - | Bcannot_be_built -> pp_print_string f "Bcannot_be_built" - | Bsuspension(cmd, _) -> - fprintf f "@[<2>Bsuspension(%a,@ ( : unit -> unit))@]" Command.print cmd - - let print_cache_entry f e = - fprintf f "@[<2>{ @[<2>built =@ %a@];@ @[<2>changed =@ %a@];@ @[<2>dependencies =@ %a@]@ }@]" - print_build_status e.built print_knowledge e.changed Resources.print e.dependencies - - let cache = Hashtbl.create 103 - - let get r = - try Hashtbl.find cache r - with Not_found -> - let cache_entry = empty () in - Hashtbl.add cache r cache_entry; cache_entry - - let fold_cache f x = Hashtbl.fold f cache x - - let print_cache f () = - fprintf f "@[@[{:"; - fold_cache begin fun k v () -> - fprintf f "@ @[<2>%a =>@ %a@];" print k print_cache_entry v - end (); - fprintf f "@]:}@]" - - let print_graph f () = - fprintf f "@[@[{:"; - fold_cache begin fun k v () -> - if not (Resources.is_empty v.dependencies) then - fprintf f "@ @[<2>%a =>@ %a@];" print k Resources.print v.dependencies - end (); - fprintf f "@]@ :}@]" - - let resource_changed r = - dprintf 10 "resource_changed:@ %a" print r; - (get r).changed <- Yes - - let external_is_up_to_date absolute_path = - let key = "Resource: " ^ absolute_path in - let digest = Digest.file absolute_path in - let is_up_to_date = - try - let digest' = Digest_cache.get key in - digest = digest' - with Not_found -> - false - in - is_up_to_date || (Digest_cache.put key digest; false) - - let source_is_up_to_date r_in_source_dir r_in_build_dir = - let key = "Resource: " ^ r_in_source_dir in - let digest = Digest.file r_in_source_dir in - let r_is_up_to_date = - Pathname.exists r_in_build_dir && - try - let digest' = Digest_cache.get key in - digest = digest' - with Not_found -> - false - in - r_is_up_to_date || (Digest_cache.put key digest; false) - - let prod_is_up_to_date p = - let x = in_build_dir p in - not (exists_in_source_dir p) || Pathname.exists x && Pathname.same_contents x (in_source_dir p) - - let rec resource_has_changed r = - let cache_entry = get r in - match cache_entry.changed with - | Yes -> true - | No -> false - | Unknown -> - let res = - match cache_entry.built with - | Bbuilt -> false - | Bsuspension _ -> assert false - | Bcannot_be_built -> false - | Bnot_built_yet -> not (prod_is_up_to_date r) in - let () = cache_entry.changed <- if res then Yes else No in res - - let resource_state r = (get r).built - - let resource_built r = (get r).built <- Bbuilt - - let resource_failed r = (get r).built <- Bcannot_be_built - - let import_in_build_dir r = - let cache_entry = get r in - let r_in_build_dir = in_build_dir r in - let r_in_source_dir = in_source_dir r in - if source_is_up_to_date r_in_source_dir r_in_build_dir then begin - dprintf 5 "%a exists and up to date" print r; - end else begin - dprintf 5 "%a exists in source dir -> import it" print r; - Shell.mkdir_p (Pathname.dirname r); - Pathname.copy r_in_source_dir r_in_build_dir; - cache_entry.changed <- Yes; - end; - cache_entry.built <- Bbuilt - - let suspend_resource r cmd kont prods = - let cache_entry = get r in - match cache_entry.built with - | Bsuspension _ -> () - | Bbuilt -> () - | Bcannot_be_built -> assert false - | Bnot_built_yet -> - let kont = begin fun () -> - kont (); - List.iter begin fun prod -> - (get prod).built <- Bbuilt - end prods - end in cache_entry.built <- Bsuspension(cmd, kont) - - let resume_suspension (cmd, kont) = - Command.execute cmd; - kont () - - let resume_resource r = - let cache_entry = get r in - match cache_entry.built with - | Bsuspension(s) -> resume_suspension s - | Bbuilt -> () - | Bcannot_be_built -> () - | Bnot_built_yet -> () - - let get_optional_resource_suspension r = - match (get r).built with - | Bsuspension cmd_kont -> Some cmd_kont - | Bbuilt | Bcannot_be_built | Bnot_built_yet -> None - - let clear_resource_failed r = (get r).built <- Bnot_built_yet - - let dependencies r = (get r).dependencies - - let fold_dependencies f = - fold_cache (fun k v -> Resources.fold (f k) v.dependencies) - - let add_dependency r s = - let cache_entry = get r in - cache_entry.dependencies <- Resources.add s cache_entry.dependencies - - let print_dependencies = print_graph - -end - -let digest p = - let f = Pathname.to_string (in_build_dir p) in - let buf = Buffer.create 1024 in - Buffer.add_string buf f; - (if sys_file_exists f then Buffer.add_string buf (Digest.file f)); - Digest.string (Buffer.contents buf) - -let exists_in_build_dir p = Pathname.exists (in_build_dir p) - -(* -type env = string - -let split_percent s = - try - let pos = String.index s '%' in - Some (String.before s pos, String.after s (pos + 1)) - with Not_found -> None - -let extract prefix suffix s = - let lprefix = String.length prefix in - let lsuffix = String.length suffix in - let ls = String.length s in - if lprefix + lsuffix > ls then None else - let s' = String.sub s lprefix (ls - lsuffix - lprefix) in - if equal (prefix ^ s' ^ suffix) s then Some s' else None - -let matchit r1 r2 = - match split_percent r1 with - | Some (x, y) -> extract x y r2 - | _ -> if equal r1 r2 then Some "" else None - -let rec subst percent r = - match split_percent r with - | Some (x, y) -> x ^ percent ^ y - | _ -> r - -let print_env = pp_print_string -*) - -(* Should normalize *) -let import x = Pathname.normalize x - -module MetaPath : sig - - type t - type env - - val mk : (bool * string) -> t - val matchit : t -> string -> env option - val subst : env -> t -> string - val print_env : Format.formatter -> env -> unit - -end = struct - open Glob_ast - - type atoms = A of string | V of string * Glob.globber - type t = atoms list - type env = (string * string) list - - exception No_solution - - let mk (pattern_allowed, s) = List.map begin function - | `Var(var_name, globber) -> V(var_name, globber) - | `Word s -> A s - end (Lexers.path_scheme pattern_allowed - Const.Source.target_pattern (lexbuf_of_string s)) - - let mk = memo mk - - let match_prefix s pos prefix = - match String.contains_string s pos prefix with - | Some(pos') -> if pos = pos' then pos' + String.length prefix else raise No_solution - | None -> raise No_solution - - let matchit p s = - let sl = String.length s in - let rec loop xs pos acc delta = - match xs with - | [] -> if pos = sl then acc else raise No_solution - | A prefix :: xs -> loop xs (match_prefix s pos prefix) acc 0 - | V(var, patt) :: A s2 :: xs' -> - begin match String.contains_string s (pos + delta) s2 with - | Some(pos') -> - let matched = String.sub s pos (pos' - pos) in - if Glob.eval patt matched - then - try loop xs' (pos' + String.length s2) ((var, matched) :: acc) 0 - with No_solution -> loop xs pos acc (pos' - pos + 1) - else loop xs pos acc (pos' - pos + 1) - | None -> raise No_solution - end - | [V(var, patt)] -> - let matched = String.sub s pos (sl - pos) in - if Glob.eval patt matched then (var, matched) :: acc else raise No_solution - | V _ :: _ -> assert false - in - try Some (loop p 0 [] 0) - with No_solution -> None - - let pp_opt pp_elt f = - function - | None -> pp_print_string f "None" - | Some x -> Format.fprintf f "Some(%a)" pp_elt x - - let print_env f env = - List.iter begin fun (k, v) -> - if k = "" then Format.fprintf f "%%=%s " v - else Format.fprintf f "%%(%s)=%s " k v - end env - - (* let matchit p s = - let res = matchit p s in - Format.eprintf "matchit %S %S = %a@." p s (pp_opt print_env) res; - res - - let _ = begin - assert (matchit "%(path)lib%(libname).a" "libfoo.a" <> None); - assert (matchit "%(path)lib%(libname).a" "path/libfoo.a" <> None); - assert (matchit "libfoo.a" "libfoo.a" <> None); - assert (matchit "lib%(libname).a" "libfoo.a" <> None); - assert (matchit "%(path)libfoo.a" "path/libfoo.a" <> None); - assert (matchit "foo%" "foobar" <> None); - exit 42 - end;; *) - - let subst env s = - String.concat "" begin - List.map begin fun x -> - match x with - | A atom -> atom - | V(var, _) -> try List.assoc var env with Not_found -> (* unbound variable *) "" - end s - end -end - -type env = MetaPath.env -type resource_pattern = (Pathname.t * MetaPath.t) - -let print_pattern f (x, _) = Pathname.print f x - -let import_pattern x = x, MetaPath.mk (true, x) -let matchit (_, p) x = MetaPath.matchit p x - -let subst env s = MetaPath.subst env (MetaPath.mk (false, s)) -let subst_any env s = MetaPath.subst env (MetaPath.mk (true, s)) -let subst_pattern env (_, p) = MetaPath.subst env p - -let print_env = MetaPath.print_env diff --git a/ocamlbuild/resource.mli b/ocamlbuild/resource.mli deleted file mode 100644 index eb75d3db..00000000 --- a/ocamlbuild/resource.mli +++ /dev/null @@ -1,77 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std - -open Pathname -type resource_pattern -type env - -type t = Pathname.t -module Resources : Set.S with type elt = t - -module Cache : - sig - type cache_entry - type suspension - - type build_status = - | Bbuilt - | Bcannot_be_built - | Bnot_built_yet - | Bsuspension of suspension - - val clean : unit -> unit - val resource_state : t -> build_status - val resource_changed : t -> unit - val resource_has_changed : t -> bool - val resource_built : t -> unit - val resource_failed : t -> unit - val import_in_build_dir : t -> unit - val suspend_resource : t -> Command.t -> (unit -> unit) -> t list -> unit - val resume_resource : t -> unit - val resume_suspension : suspension -> unit - val get_optional_resource_suspension : t -> (Command.t * (unit -> unit)) option - val clear_resource_failed : t -> unit - val add_dependency : t -> t -> unit - val fold_dependencies : (string -> string -> 'a -> 'a) -> 'a -> 'a - val external_is_up_to_date : t -> bool - - (* These are not currently used by others modules. *) - val dependencies : t -> Resources.t - val print_cache : Format.formatter -> unit -> unit - val print_dependencies : Format.formatter -> unit -> unit - end - -val digest : t -> string -val exists_in_source_dir : t -> bool -val exists_in_build_dir : t -> bool -val in_build_dir : t -> t -val in_source_dir : t -> t - -val clean_up_links : bool Slurp.entry -> bool Slurp.entry - -val compare : t -> t -> int -val print : Format.formatter -> t -> unit -val print_pattern : Format.formatter -> resource_pattern -> unit -val clean : t -> unit -val import : string -> t -val import_pattern : string -> resource_pattern - -val matchit : resource_pattern -> t -> env option -val subst : env -> t -> t -val subst_any : env -> t -> t -val subst_pattern : env -> resource_pattern -> t -(* val is_up_to_date : t -> bool *) -val print_env : Format.formatter -> env -> unit diff --git a/ocamlbuild/rule.ml b/ocamlbuild/rule.ml deleted file mode 100644 index d91360cc..00000000 --- a/ocamlbuild/rule.ml +++ /dev/null @@ -1,338 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Format -open Log -open Outcome -module Resources = Resource.Resources - -exception Exit_rule_error of string -exception Failed - -type env = Pathname.t -> Pathname.t -type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list -type action = env -> builder -> Command.t - -type digest_command = { digest : string; command : Command.t } - -type 'a gen_rule = - { name : string; - deps : Pathname.t list; (* These pathnames must be normalized *) - prods : 'a list; (* Note that prods also contains stamp *) - stamp : 'a option; - doc : string option; - code : env -> builder -> digest_command } - -type rule = Pathname.t gen_rule -type rule_scheme = Resource.resource_pattern gen_rule - -let name_of_rule r = r.name -let deps_of_rule r = r.deps -let prods_of_rule r = r.prods -let stamp_of_rule r = r.stamp -let doc_of_rule r = r.doc - -type 'a rule_printer = (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a gen_rule -> unit - -let compare _ _ = assert false - -let print_rule_name f r = pp_print_string f r.name - -let print_resource_list = List.print Resource.print - -let print_rule_contents ppelt f r = - fprintf f "@[{@ @[<2>name =@ %S@];@ @[<2>deps =@ %a@];@ @[<2>prods = %a@];@ @[<2>code = @];@ @[ doc = %s@]@]@ }" - r.name print_resource_list r.deps (List.print ppelt) - r.prods - (match r.doc with - | None -> "None" - | Some doc -> sprintf "Some %S" doc) - -let pretty_print ppelt f r = - fprintf f "@[rule %S@ ~deps:%a@ ~prods:%a@ " - r.name print_resource_list r.deps (List.print ppelt) r.prods; - begin match r.doc with - | None -> () - | Some doc -> fprintf f "~doc:\"@[%a@]\"@ " pp_print_text doc - end; - fprintf f "@]" - -let print = print_rule_name - -let subst env rule = - let subst_resources = List.map (Resource.subst env) in - let subst_resource_patterns = List.map (Resource.subst_pattern env) in - let finder next_finder p = next_finder (Resource.subst_any env p) in - let stamp = match rule.stamp with None -> None | Some x -> Some (Resource.subst_pattern env x) in - let prods = subst_resource_patterns rule.prods in - { name = sbprintf "%s (%a)" rule.name Resource.print_env env; - prods = prods; - deps = - (* The substition should preserve normalization of pathnames *) - subst_resources rule.deps; - stamp = stamp; - doc = rule.doc; - code = (fun env -> rule.code (finder env)) } - -exception Can_produce of rule - -let can_produce target rule = - try - List.iter begin fun resource -> - match Resource.matchit resource target with - | Some env -> raise (Can_produce (subst env rule)) - | None -> () - end rule.prods; None - with Can_produce r -> Some r - -let digest_prods r = - List.fold_right begin fun p acc -> - let f = Pathname.to_string (Resource.in_build_dir p) in - if sys_file_exists f then (f, Digest.file f) :: acc else acc - end r.prods [] - -let digest_deps r dyndeps = - let buf = Buffer.create 1024 in - let add_resource r = Buffer.add_string buf (Digest.to_hex (Resource.digest r)) in - Buffer.add_string buf "deps:"; - List.iter add_resource r.deps; - Buffer.add_string buf "dyndeps:"; - Resources.iter add_resource dyndeps; - Digest.to_hex (Digest.string (Buffer.contents buf)) - -let digest_rule r dyndeps action = - let buf = Buffer.create 1024 in - Buffer.add_string buf action.digest; - let add_resource r = Buffer.add_string buf (Resource.digest r) in - Buffer.add_string buf "prods:"; - List.iter add_resource r.prods; - Buffer.add_string buf "deps:"; - List.iter add_resource r.deps; - Buffer.add_string buf "dyndeps:"; - Resources.iter add_resource dyndeps; - Digest.string (Buffer.contents buf) - -let cached_digest r = - try Some (Digest_cache.get ("Rule: " ^ r.name)) - with Not_found -> None - -let store_digest r digest = Digest_cache.put ("Rule: " ^ r.name) digest - -let print_digest f x = pp_print_string f (Digest.to_hex x) - -let exists2 find p rs = - try Some (find p rs) with Not_found -> None - -let build_deps_of_tags builder tags = - match Command.deps_of_tags tags with - | [] -> [] - | deps -> List.map Outcome.good (builder (List.map (fun x -> [x]) deps)) - -let build_deps_of_tags_on_cmd builder = - Command.iter_tags begin fun tags -> - match Command.deps_of_tags tags with - | [] -> () - | deps -> List.iter ignore_good (builder (List.map (fun x -> [x]) deps)) - end - -let call builder r = - let dyndeps = ref Resources.empty in - let builder rs = - let results = builder rs in - List.map begin fun res -> - match res with - | Good res' -> - let () = dprintf 10 "new dyndep for %S(%a): %S" r.name print_resource_list r.prods res' in - dyndeps := Resources.add res' !dyndeps; - List.iter (fun x -> Resource.Cache.add_dependency x res') r.prods; - res - | Bad _ -> res - end results in - let () = dprintf 5 "start rule %a" print r in - let action = r.code (fun x -> x) builder in - build_deps_of_tags_on_cmd builder action.command; - let dyndeps = !dyndeps in - let () = dprintf 10 "dyndeps: %a" Resources.print dyndeps in - let (reason, cached) = - match exists2 List.find (fun r -> not (Resource.exists_in_build_dir r)) r.prods with - | Some r -> (`cache_miss_missing_prod r, false) - | _ -> - begin match exists2 List.find Resource.Cache.resource_has_changed r.deps with - | Some r -> (`cache_miss_changed_dep r, false) - | _ -> - begin match exists2 Resources.find_elt Resource.Cache.resource_has_changed dyndeps with - | Some r -> (`cache_miss_changed_dyn_dep r, false) - | _ -> - begin match cached_digest r with - | None -> (`cache_miss_no_digest, false) - | Some d -> - let rule_digest = digest_rule r dyndeps action in - if d = rule_digest then (`cache_hit, true) - else (`cache_miss_digest_changed(d, rule_digest), false) - end - end - end - in - let explain_reason l = - raw_dprintf (l+1) "mid rule %a: " print r; - match reason with - | `cache_miss_missing_prod r -> - dprintf l "cache miss: a product is not in build dir (%a)" Resource.print r - | `cache_miss_changed_dep r -> - dprintf l "cache miss: a dependency has changed (%a)" Resource.print r - | `cache_miss_changed_dyn_dep r -> - dprintf l "cache miss: a dynamic dependency has changed (%a)" Resource.print r - | `cache_miss_no_digest -> - dprintf l "cache miss: no digest found for %S (the command, a dependency, or a product)" - r.name - | `cache_hit -> dprintf (l+1) "cache hit" - | `cache_miss_digest_changed(old_d, new_d) -> - dprintf l "cache miss: the digest has changed for %S (the command, a dependency, or a product: %a <> %a)" - r.name print_digest old_d print_digest new_d - in - let prod_digests = digest_prods r in - (if not cached then List.iter Resource.clean r.prods); - (if !Options.nothing_should_be_rebuilt && not cached then - (explain_reason (-1); - let msg = sbprintf "Need to rebuild %a through the rule `%a'" print_resource_list r.prods print r in - raise (Exit_rule_error msg))); - explain_reason 3; - let thunk () = - try - if cached then Command.execute ~pretend:true action.command - else - begin match r.stamp with - | Some stamp -> - reset_filesys_cache (); - let digest_deps = digest_deps r dyndeps in - with_output_file stamp (fun oc -> output_string oc digest_deps) - | None -> () - end; - List.iter (fun r -> Resource.Cache.resource_built r) r.prods; - (if not cached then - let new_rule_digest = digest_rule r dyndeps action in - let new_prod_digests = digest_prods r in - let () = store_digest r new_rule_digest in - List.iter begin fun p -> - let f = Pathname.to_string (Resource.in_build_dir p) in - (try let digest = List.assoc f prod_digests in - let new_digest = List.assoc f new_prod_digests in - if digest <> new_digest then raise Not_found - with Not_found -> Resource.Cache.resource_changed p) - end r.prods); - dprintf 5 "end rule %a" print r - with exn -> (List.iter Resource.clean r.prods; raise exn) - in - if cached - then thunk () - else List.iter (fun x -> Resource.Cache.suspend_resource x action.command thunk r.prods) r.prods - -let (get_rules, add_rule, clear_rules) = - let rules = ref [] in - (fun () -> !rules), - begin fun pos r -> - try - let _ = List.find (fun x -> x.name = r.name) !rules in - raise (Exit_rule_error (sbprintf "Rule.add_rule: already exists: (%a)" print r)) - with Not_found -> - match pos with - | `bottom -> rules := !rules @ [r] - | `top -> rules := r :: !rules - | `after s -> - rules := - List.fold_right begin fun x acc -> - if x.name = s then x :: r :: acc else x :: acc - end !rules [] - | `before s -> - rules := - List.fold_right begin fun x acc -> - if x.name = s then r :: x :: acc else x :: acc - end !rules [] - end, - (fun () -> rules := []) - -let rule name ?tags ?(prods=[]) ?(deps=[]) ?prod ?dep ?stamp ?(insert = `bottom) ?doc code = - let () = - match tags with - | None -> () - | Some _ -> - Log.eprintf "Warning: your ocamlbuild rule %S uses the ~tags parameter, - which is deprecated and ignored." - name - in - let res_add import xs xopt = - let init = - match xopt with - | None -> [] - | Some r -> [import r] - in - List.fold_right begin fun x acc -> - let r = import x in - if List.mem r acc then - failwith (sprintf "in rule %s, multiple occurrences of the resource %s" name x) - else r :: acc - end xs init - in - if prods = [] && prod = None && stamp = None then raise (Exit_rule_error "Can't make a rule that produces nothing"); - let stamp, prods = - match stamp with - | None -> None, prods - | Some stamp -> - Some (Resource.import_pattern stamp), stamp :: prods - in - let prods = res_add Resource.import_pattern prods prod in - let code env build = - let cmd = code env build in - { digest = Command.digest cmd - ; command = cmd } - in - add_rule insert - { name = name; - deps = res_add Resource.import (* should normalize *) deps dep; - stamp = stamp; - doc = doc; - prods = prods; - code = code } - -module Common_commands = struct - open Command - let mv src dest = Cmd (S [A"mv"; P src; Px dest]) - let cp src dest = Cmd (S [A"cp"; P src; Px dest]) - let cp_p src dest = Cmd (S [A"cp"; A"-p"; P src; Px dest]) - let ln_f pointed pointer = Cmd (S [A"ln"; A"-f"; P pointed; Px pointer]) - let ln_s pointed pointer = Cmd (S[A"ln"; A"-s"; P pointed; Px pointer]) - let rm_f x = Cmd (S [A"rm"; A"-f"; Px x]) - let chmod opts file = Cmd (S[A"chmod"; opts; Px file]) - let cmp a b = Cmd (S[A"cmp"; P a; Px b]) -end -open Common_commands - -let copy_rule name ?insert src dest = - rule name ?insert ~prod:dest ~dep:src - begin fun env _ -> - let src = env src and dest = env dest in - Shell.mkdir_p (Pathname.dirname dest); - cp_p src dest - end - -let show_documentation () = - let pp fmt = Log.raw_dprintf (-1) fmt in - let rules = get_rules () in - List.iter - (fun rule -> pp "%a@\n@\n" (pretty_print Resource.print_pattern) rule) - rules; - pp "@." - - diff --git a/ocamlbuild/rule.mli b/ocamlbuild/rule.mli deleted file mode 100644 index 70a73569..00000000 --- a/ocamlbuild/rule.mli +++ /dev/null @@ -1,85 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Resource - -type env = Pathname.t -> Pathname.t -type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list -type action = env -> builder -> Command.t - -type 'a gen_rule - -type rule = Pathname.t gen_rule -type rule_scheme = resource_pattern gen_rule - -type 'a rule_printer = (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a gen_rule -> unit - -(** This exception can be raised inside the action of a rule to make the - algorithm skip this rule. *) -exception Failed - -val name_of_rule : 'a gen_rule -> string -val deps_of_rule : 'a gen_rule -> Pathname.t list -val prods_of_rule : 'a gen_rule -> 'a list -val doc_of_rule : 'a gen_rule -> string option - -val rule : string -> - ?tags:string list -> - ?prods:string list -> - ?deps:string list -> - ?prod:string -> - ?dep:string -> - ?stamp:string -> - ?insert:[`top | `before of string | `after of string | `bottom] -> - ?doc:string -> - action -> unit - -(** [copy_rule name ?insert source destination] *) -val copy_rule : string -> - ?insert:[`top | `before of string | `after of string | `bottom] -> - string -> string -> unit - -module Common_commands : sig - val mv : Pathname.t -> Pathname.t -> Command.t - val cp : Pathname.t -> Pathname.t -> Command.t - val cp_p : Pathname.t -> Pathname.t -> Command.t - val ln_f : Pathname.t -> Pathname.t -> Command.t - val ln_s : Pathname.t -> Pathname.t -> Command.t - val rm_f : Pathname.t -> Command.t - val chmod : Command.spec -> Pathname.t -> Command.t - val cmp : Pathname.t -> Pathname.t -> Command.t -end - -val print : Format.formatter -> rule -> unit -val pretty_print : 'a rule_printer - -(** For system use only *) - -val subst : Resource.env -> rule_scheme -> rule -val can_produce : Pathname.t -> rule_scheme -> rule option -(* val tags_matches : Tags.t -> t -> t option *) -val compare : 'a gen_rule -> 'a gen_rule -> int - -val print_rule_name : Format.formatter -> 'a gen_rule -> unit -val print_rule_contents : 'a rule_printer - -val get_rules : unit -> rule_scheme list -val clear_rules : unit -> unit - -val call : builder -> rule -> unit - -val build_deps_of_tags : builder -> Tags.t -> Pathname.t list - -val show_documentation : unit -> unit diff --git a/ocamlbuild/shell.ml b/ocamlbuild/shell.ml deleted file mode 100644 index 2809569f..00000000 --- a/ocamlbuild/shell.ml +++ /dev/null @@ -1,88 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std - -let is_simple_filename s = - let ls = String.length s in - ls <> 0 && - let rec loop pos = - if pos >= ls then true else - match s.[pos] with - | 'a'..'z' | 'A'..'Z' | '0'..'9' | '.' | '-' | '/' | '_' | ':' | '@' | '+' | ',' -> loop (pos + 1) - | _ -> false in - loop 0 -let quote_filename_if_needed s = - if is_simple_filename s then s - (* We should probably be using [Filename.unix_quote] except that function - * isn't exported. Users on Windows will have to live with not being able to - * install OCaml into c:\o'caml. Too bad. *) - else if Sys.os_type = "Win32" then Printf.sprintf "'%s'" s - else Filename.quote s -let chdir dir = - reset_filesys_cache (); - Sys.chdir dir -let run args target = - reset_readdir_cache (); - let cmd = String.concat " " (List.map quote_filename_if_needed args) in - if !*My_unix.is_degraded || Sys.os_type = "Win32" then - begin - Log.event cmd target Tags.empty; - let st = sys_command cmd in - if st <> 0 then - failwith (Printf.sprintf "Error during command `%s'.\nExit code %d.\n" cmd st) - else - () - end - else - match My_unix.execute_many ~ticker:Log.update ~display:Log.display [[(fun () -> cmd)]] with - | None -> () - | Some(_, x) -> - failwith (Printf.sprintf "Error during command %S: %s" cmd (Printexc.to_string x)) -let rm = sys_remove -let rm_f x = - if sys_file_exists x then rm x -let mkdir dir = - reset_filesys_cache_for_file dir; - (*Sys.mkdir dir (* MISSING in ocaml *) *) - run ["mkdir"; dir] dir -let try_mkdir dir = if not (sys_file_exists dir) then mkdir dir -let rec mkdir_p dir = - if sys_file_exists dir then () - else (mkdir_p (Filename.dirname dir); mkdir dir) - -let cp_pf src dest = - reset_filesys_cache_for_file dest; - run["cp";"-pf";src;dest] dest - -(* L'Arrete du 2007-03-07 prend en consideration - differement les archives. Pour les autres fichiers - le decret du 2007-02-01 est toujours valable :-) *) -let cp src dst = - if Filename.check_suffix src ".a" - && Filename.check_suffix dst ".a" - then cp_pf src dst - (* try to make a hard link *) - else copy_file src dst - -let readlink = My_unix.readlink -let is_link = My_unix.is_link -let rm_rf x = - reset_filesys_cache (); - run["rm";"-Rf";x] x -let mv src dest = - reset_filesys_cache_for_file src; - reset_filesys_cache_for_file dest; - run["mv"; src; dest] dest - (*Sys.rename src dest*) diff --git a/ocamlbuild/shell.mli b/ocamlbuild/shell.mli deleted file mode 100644 index b5abd85d..00000000 --- a/ocamlbuild/shell.mli +++ /dev/null @@ -1,31 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - -(* Original author: Nicolas Pouillard *) - -val is_simple_filename : string -> bool - -val quote_filename_if_needed : string -> string -(** This will quote using Unix conventions, even on Windows, because commands are - * always run through bash -c on Windows. *) - -val chdir : string -> unit -val rm : string -> unit -val rm_f : string -> unit -val rm_rf : string -> unit -val mkdir : string -> unit -val try_mkdir : string -> unit -val mkdir_p : string -> unit -val cp : string -> string -> unit -val mv : string -> string -> unit -val readlink : string -> string -val is_link : string -> bool diff --git a/ocamlbuild/signatures.mli b/ocamlbuild/signatures.mli deleted file mode 100644 index 0c323e20..00000000 --- a/ocamlbuild/signatures.mli +++ /dev/null @@ -1,797 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(** This module contains all module signatures that the user - could use to build an ocamlbuild plugin. *) - -module type OrderedTypePrintable = sig - type t - val compare : t -> t -> int - val print : Format.formatter -> t -> unit -end - -module type SET = sig - include Set.S - val find_elt : (elt -> bool) -> t -> elt - val map : (elt -> elt) -> t -> t - val of_list : elt list -> t - val print : Format.formatter -> t -> unit -end - -module type LIST = sig - (* Added functions *) - val print : (Format.formatter -> 'a -> 'b) -> Format.formatter -> 'a list -> unit - val filter_opt : ('a -> 'b option) -> 'a list -> 'b list - val union : 'a list -> 'a list -> 'a list - val ordered_unique : 'a list -> 'a list - (* Original functions *) - include module type of List -end - -module type STRING = sig - val print : Format.formatter -> string -> unit - val chomp : string -> string - - (** [before s n] returns the substring of all characters of [s] - that precede position [n] (excluding the character at - position [n]). - This is the same function as {!Str.string_before}. *) - val before : string -> int -> string - - (** [after s n] returns the substring of all characters of [s] - that follow position [n] (including the character at - position [n]). - This is the same function as {!Str.string_after}. *) - val after : string -> int -> string - - val first_chars : string -> int -> string - (** [first_chars s n] returns the first [n] characters of [s]. - This is the same function as {!before} ant {!Str.first_chars}. *) - - val last_chars : string -> int -> string - (** [last_chars s n] returns the last [n] characters of [s]. - This is the same function as {!Str.last_chars}. *) - - val eq_sub_strings : string -> int -> string -> int -> int -> bool - - (** [is_prefix u v] is u a prefix of v ? *) - val is_prefix : string -> string -> bool - (** [is_suffix u v] : is v a suffix of u ? *) - val is_suffix : string -> string -> bool - - (** [contains_string s1 p2 s2] Search in [s1] starting from [p1] if it - contains the [s2] string. Returns [Some position] where [position] - is the begining of the string [s2] in [s1], [None] otherwise. *) - val contains_string : string -> int -> string -> int option - - (** [subst patt repl text] *) - val subst : string -> string -> string -> string - - (** [tr patt repl text] *) - val tr : char -> char -> string -> string - - val rev : string -> string - - (* Convert a character list into a character string *) - val implode : char list -> string - - (* Convert a character string into a character list *) - val explode : string -> char list - - (** The following are original functions from the [String] module. *) - include module type of String -end - -module type TAGS = sig - include Set.S with type elt = string - (** [Tags.elt] represents a tag, which is simply a string, usually - lowercase, for example "ocaml" or "native". The set of tags - attached to a file is computed by applying the tagging rules to - the filename. Tagging rules are defined in _tags files in any - parent directory of a file, up to the main project directory. *) - - val of_list : string list -> t - val print : Format.formatter -> t -> unit - val does_match : t -> t -> bool - module Operators : sig - val ( ++ ) : t -> elt -> t - val ( -- ) : t -> elt -> t - val ( +++ ) : t -> elt option -> t - val ( --- ) : t -> elt option -> t - end -end - -module type PATHNAME = sig - type t = string - val concat : t -> t -> t - val compare : t -> t -> int - val equal : t -> t -> bool - val exists : t -> bool - val mk : string -> t - val define_context : string -> string list -> unit - val include_dirs_of : string -> string list - val copy : t -> t -> unit - val to_string : t -> string - val print : Format.formatter -> t -> unit - val current_dir_name : t - val parent_dir_name : t - val read : t -> string - val same_contents : t -> t -> bool - val basename : t -> t - val dirname : t -> t - val is_relative : t -> bool - val readlink : t -> t - val readdir : t -> t array - val is_link : t -> bool - val is_directory : t -> bool - - val add_extension : string -> t -> t - val check_extension : t -> string -> bool - - val get_extension : t -> string - val remove_extension : t -> t - val update_extension : string -> t -> t - - val get_extensions : t -> string - val remove_extensions : t -> t - val update_extensions : string -> t -> t - - val print_path_list : Format.formatter -> t list -> unit - val pwd : t - val parent : t -> t - (** [is_prefix x y] is [x] a pathname prefix of [y] *) - val is_prefix : t -> t -> bool - val is_implicit : t -> bool - module Operators : sig - val ( / ) : t -> t -> t - val ( -.- ) : t -> string -> t - end -end - -(** Provides an abstract type for easily building complex shell - commands without making quotation mistakes. *) -module type COMMAND = sig - type tags - type pathname - - (** The type [t] provides some basic combinators and command primitives. - Other commands can be made of command specifications ([spec]). *) - type t = - | Seq of t list (** A sequence of commands (like the `;' in shell) *) - | Cmd of spec (** A command is made of command specifications ([spec]) *) - | Echo of string list * pathname - (** Write the given strings (w/ any formatting) to the given file *) - | Nop (** The command that does nothing *) - - (** The type for command specifications. That is pieces of command. *) - and spec = - | N (** No operation. *) - | S of spec list (** A sequence. This gets flattened in the last stages *) - | A of string (** An atom. *) - | P of pathname (** A pathname. *) - | Px of pathname (** A pathname, that will also be given to the - call_with_target hook. *) - | Sh of string (** A bit of raw shell code, that will not be escaped. *) - | T of tags (** A set of tags, that describe properties and - some semantics information about the - command, afterward these tags will be - replaced by command [spec]s (flags for - instance). *) - | V of string (** A virtual command, that will be resolved at - execution using [resolve_virtuals] *) - | Quote of spec (** A string that should be quoted like a - filename but isn't really one. *) - - (*type v = [ `Seq of v list | `Cmd of vspec | `Nop ] - and vspec = - [ `N - | `S of vspec list - | `A of string - | `P of pathname - | `Px of pathname - | `Sh of string - | `Quote of vspec ] - - val spec_of_vspec : vspec -> spec - val vspec_of_spec : spec -> vspec - val t_of_v : v -> t - val v_of_t : t -> v*) - - (** Will convert a string list to a list of atoms by adding [A] constructors. *) - val atomize : string list -> spec - - (** Will convert a string list to a list of paths by adding [P] constructors. *) - val atomize_paths : string list -> spec - - (** Run the command. *) - val execute : ?quiet:bool -> ?pretend:bool -> t -> unit - - (** Run the commands in the given list, if possible in parallel. - See the module [Ocamlbuild_executor]. *) - val execute_many : ?quiet:bool -> ?pretend:bool -> t list -> (bool list * exn) option - - (** [setup_virtual_command_solver virtual_command solver] - the given solver can raise Not_found if it fails to find a valid - command for this virtual command. *) - val setup_virtual_command_solver : string -> (unit -> spec) -> unit - - (** Search the given command in the command path and return its absolute - pathname. *) - val search_in_path : string -> string - - (** Simplify a command by flattening the sequences and resolving the tags - into command-line options. *) - val reduce : spec -> spec - - (** Print a command (the format is not suitable to running the command). *) - val print : Format.formatter -> t -> unit - - (** Convert a command to a string (same format as print). *) - val to_string : t -> string - - (** Build a string representation of a command that can be passed to the - system calls. *) - val string_of_command_spec : spec -> string -end - -(** A self-contained module implementing extended shell glob patterns who have an expressive power - equal to boolean combinations of regular expressions. *) -module type GLOB = sig - - (** A globber is a boolean combination of basic expressions indented to work on - pathnames. Known operators - are [or], [and] and [not], which may also be written [|], [&] and [~]. There are - also constants [true] and [false] (or [1] and [0]). Expression can be grouped - using parentheses. - - [true] matches anything, - - [false] matches nothing, - - {i basic} [or] {i basic} matches strings matching either one of the basic expressions, - - {i basic} [and] {i basic} matches strings matching both basic expressions, - - not {i basic} matches string that don't match the basic expression, - - {i basic} matches strings that match the basic expression. - - A basic expression can be a constant string enclosed in double quotes, in which - double quotes must be preceded by backslashes, or a glob pattern enclosed between a [<] and a [>], - - ["]{i string}["] matches the literal string {i string}, - - [<]{i glob}[>] matches the glob pattern {i glob}. - - A glob pattern is an anchored regular expression in a shell-like syntax. Most characters stand for themselves. - Character ranges are given in usual shell syntax between brackets. The star [*] stands for any sequence of - characters. The joker '?' stands for exactly one, unspecified character. Alternation is achieved using braces [{]. - - {i glob1}{i glob2} matches strings who have a prefix matching {i glob1} and the corresponding suffix - matching {i glob2}. - - [a] matches the string consisting of the single letter [a]. - - [{]{i glob1},{i glob2}[}] matches strings matching {i glob1} or {i glob2}. - - [?] any one-letter string, excluding the slash. - - [*] matches all strings not containing a slash, including the empty one. - - [**/] the empty string, or any string ending with a slash. - - [/**] any string starting with a slash, or the empty string. - - [/**/] any string starting and ending with a slash. - - [\[]{i c1}-{i c2}{i c3}-{i c4}...[\]] matches characters in the range {i c1} to {i c2} inclusive, - or in the range {i c3} to {i c4} inclusive. For instance [\[a-fA-F0-9\]] matches hexadecimal digits. - To match the dash, put it at the end. - *) - - (** The type representing globbers. Do not attempt to compare them, as they get on-the-fly optimizations. *) - type globber - - (** [parse ~dir pattern] will parse the globber pattern [pattern], optionally prefixing its patterns with [dir]. *) - val parse : ?dir:string -> string -> globber - - (** A descriptive exception raised when an invalid glob pattern description is given. *) - exception Parse_error of string - - (** [eval g u] returns [true] if and only if the string [u] matches the given glob expression. Avoid reparsing - the same pattern, since the automaton implementing the pattern is optimized on the fly. The first few evaluations - are done using a time-inefficient but memory-efficient algorithm. It then compiles the pattern into an efficient - but more memory-hungry data structure. *) - val eval : globber -> string -> bool -end - -(** Module for modulating the logging output with the logging level. *) -module type LOG = sig - (** Current logging (debugging) level. *) - val level : int ref - - (** [dprintf level fmt args...] formats the logging information [fmt] - with the arguments [args...] on the logging output if the logging - level is greater than or equal to [level]. The default level is 1. - More obscure debugging information should have a higher logging - level. Youre formats are wrapped inside these two formats - ["@\[<2>"] and ["@\]@."]. *) - val dprintf : int -> ('a, Format.formatter, unit) format -> 'a - - (** Equivalent to calling [dprintf] with a level [< 0]. *) - val eprintf : ('a, Format.formatter, unit) format -> 'a - - (** Same as dprintf but without the format wrapping. *) - val raw_dprintf : int -> ('a, Format.formatter, unit) format -> 'a -end - -module type OUTCOME = sig - type ('a,'b) t = - | Good of 'a - | Bad of 'b - - val wrap : ('a -> 'b) -> 'a -> ('b, exn) t - val ignore_good : ('a, exn) t -> unit - val good : ('a, exn) t -> 'a -end - -module type MISC = sig - val opt_print : - (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit - val the : 'a option -> 'a - val getenv : ?default:string -> string -> string - val with_input_file : ?bin:bool -> string -> (in_channel -> 'a) -> 'a - val with_output_file : ?bin:bool -> string -> (out_channel -> 'a) -> 'a - val with_temp_file : string -> string -> (string -> 'a) -> 'a - val read_file : string -> string - val copy_chan : in_channel -> out_channel -> unit - val copy_file : string -> string -> unit - val print_string_list : Format.formatter -> string list -> unit - - (** A shortcut to force lazy value (See {Lazy.force}). *) - val ( !* ) : 'a Lazy.t -> 'a - - (** The right associative application. - Useful when writing to much parentheses: - << f (g x ... t) >> becomes << f& g x ... t >> - << f (g (h x)) >> becomes << f& g& h x >> *) - val ( & ) : ('a -> 'b) -> 'a -> 'b - - (** The reversed application combinator. - Useful to describe some operations chaining. - << f x (g y (h z)) >> becomes << z |> h |> g y |> f x >> *) - val ( |> ) : 'a -> ('a -> 'b) -> 'b - - (** [r @:= l] is equivalent to [r := !r @ l] *) - val ( @:= ) : 'a list ref -> 'a list -> unit - - val memo : ('a -> 'b) -> ('a -> 'b) - - val memo2 : ('a -> 'b -> 'c) -> ('a -> 'b -> 'c) - - val memo3 : ('a -> 'b -> 'c -> 'd) -> ('a -> 'b -> 'c -> 'd) -end - -module type OPTIONS = sig - type command_spec - - val build_dir : string ref - val include_dirs : string list ref - val exclude_dirs : string list ref - val nothing_should_be_rebuilt : bool ref - val ocamlc : command_spec ref - val ocamlopt : command_spec ref - val ocamldep : command_spec ref - val ocamldoc : command_spec ref - val ocamlyacc : command_spec ref - val ocamllex : command_spec ref - val ocamlrun : command_spec ref - val ocamlmklib : command_spec ref - val ocamlmktop : command_spec ref - val hygiene : bool ref - val sanitize : bool ref - val sanitization_script : string ref - val ignore_auto : bool ref - val plugin : bool ref - val just_plugin : bool ref - val native_plugin : bool ref - val make_links : bool ref - val nostdlib : bool ref - val program_to_execute : bool ref - val must_clean : bool ref - val catch_errors : bool ref - val use_menhir : bool ref - val show_documentation : bool ref - val recursive : bool ref - val use_ocamlfind : bool ref - - val targets : string list ref - val ocaml_libs : string list ref - val ocaml_mods : string list ref - val ocaml_pkgs : string list ref - val ocaml_syntax : string option ref - val ocaml_cflags : string list ref - val ocaml_lflags : string list ref - val ocaml_ppflags : string list ref - val ocaml_docflags : string list ref - val ocaml_yaccflags : string list ref - val ocaml_lexflags : string list ref - val program_args : string list ref - val ignore_list : string list ref - val tags : string list ref - val tag_lines : string list ref - val show_tags : string list ref - - val ext_obj : string ref - val ext_lib : string ref - val ext_dll : string ref - val exe : string ref - - val add : string * Arg.spec * string -> unit -end - -module type ARCH = sig - type 'a arch = private - | Arch_dir of string * 'a * 'a arch list - | Arch_dir_pack of string * 'a * 'a arch list - | Arch_file of string * 'a - - val dir : string -> unit arch list -> unit arch - val dir_pack : string -> unit arch list -> unit arch - val file : string -> unit arch - - type info = private { - current_path : string; - include_dirs : string list; - for_pack : string; - } - - val annotate : 'a arch -> info arch - - val print : (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a arch -> unit - val print_include_dirs : Format.formatter -> string list -> unit - val print_info : Format.formatter -> info -> unit - - val iter_info : ('a -> unit) -> 'a arch -> unit - val fold_info : ('a -> 'b -> 'b) -> 'a arch -> 'b -> 'b - - val iter_include_dirs : info arch -> (string -> unit) -> unit - - val mk_tables : - info arch -> (string, string list) Hashtbl.t * (string, string) Hashtbl.t - val print_table : - (Format.formatter -> 'a -> unit) -> Format.formatter -> (string, 'a) Hashtbl.t -> unit -end - -module type FINDLIB = sig - (** Findlib / Ocamlfind tools. *) - - type command_spec - - type error = - | Cannot_run_ocamlfind - | Dependency_not_found of string * string (* package, dependency *) - | Package_not_found of string - | Cannot_parse_query of string * string (* package, explaination *) - - exception Findlib_error of error - - val string_of_error: error -> string - (** Return a string message describing an error. *) - - val report_error: error -> 'a - (** Report an error on the standard error and exit with code 2. *) - - type package = { - name: string; - description: string; - version: string; - archives_byte: string; - (** Archive names, with the .cma extension, but without the directory. *) - archives_native: string; - (** Archive names, with the .cmxa extension, but without the directory. *) - link_options: string; - location: string; - dependencies: package list; - (** Transitive closure, as returned by [ocamlfind query -r]. *) - } - (** Package information. *) - - val query: string -> package - (** Query information about a package, given its name. May raise -[Not_found]. *) - - val list: unit -> string list - (** Return the names of all known packages. *) - - val topological_closure: package list -> package list - (** Computes the transitive closure of a list of -packages and sort them in topological order. -Given any list of package [l], [topological_closure l] returns a list of -packages including [l] and their dependencies, in an order where any element -may only depend on the previous ones. *) - - val compile_flags_byte: package list -> command_spec - (** Return the flags to add when compiling in byte mode (include -directories). *) - - val compile_flags_native: package list -> command_spec - (** Same as [link_flags_byte] but for native mode. *) - - val link_flags_byte: package list -> command_spec - (** Return the flags to add when linking in byte mode. It includes: -include directories, libraries and special link options. *) - - val link_flags_native: package list -> command_spec - (** Same as [link_flags_byte] but for native mode. *) -end - -(** This module contains the functions and values that can be used by - plugins. *) -module type PLUGIN = sig - module Pathname : PATHNAME - module Tags : TAGS - module Command : COMMAND with type tags = Tags.t and type pathname = Pathname.t - module Outcome : OUTCOME - module String : STRING - module List : LIST - module StringSet : Set.S with type elt = String.t - module Options : OPTIONS with type command_spec = Command.spec - module Arch : ARCH - module Findlib : FINDLIB with type command_spec = Command.spec - include MISC - - (** See {!COMMAND.t} for the description of this type. *) - type command = Command.t = - | Seq of command list - | Cmd of spec - | Echo of string list * Pathname.t - | Nop - - (** See {!COMMAND.spec} for the description of this type. *) - and spec = Command.spec = - | N | S of spec list | A of string | P of string | Px of string - | Sh of string | T of Tags.t | V of string | Quote of spec - - (** [path1/path2] Join the given path names. *) - val ( / ) : Pathname.t -> Pathname.t -> Pathname.t - - (** [path-.-extension] Add the given extension to the given pathname. *) - val ( -.- ) : Pathname.t -> string -> Pathname.t - - (** [tags++tag] Add the given tag to the given set of tags. *) - val ( ++ ) : Tags.t -> Tags.elt -> Tags.t - - (** [tags--tag] Remove the given tag to the given set of tags. *) - val ( -- ) : Tags.t -> Tags.elt -> Tags.t - - (** [tags+++optional_tag] Add the given optional tag to the given set of tags - if the given option is Some. *) - val ( +++ ) : Tags.t -> Tags.elt option -> Tags.t - - (** [tags---optional_tag] Remove the given optional tag to the given - set of tags if the given option is Some. *) - val ( --- ) : Tags.t -> Tags.elt option -> Tags.t - - (** The type of the builder environments. Here an environment is just the - lookup function of it. Basically this function will resolve path variables - like % or more generally %(var_name). *) - type env = Pathname.t -> Pathname.t - - (** A builder is a function that waits for conjonction of alternative targets. - The alternatives are here to support some choices, for instance for an - OCaml module an alternatives can be foo.cmo, foo.cmi, Foo.cmo, Foo.cmi. - Conjonctions are here to help making parallelism, indeed commands that are - independant will be run concurently. *) - type builder = Pathname.t list list -> (Pathname.t, exn) Outcome.t list - - (** This is the type for rule actions. An action receive as argument, the - environment lookup function (see {!env}), and a function to dynamically - build more targets (see {!builder}). An action should return the command - to run in order to build the rule productions using the rule dependencies. - *) - type action = env -> builder -> Command.t - - (** This is the main function for adding a rule to the ocamlbuild engine. - - The first argument is the name of the rule (should be unique). - - It takes files that the rule produces. - Use ~prod for one file, ~prods for list of files. - - It also takes files that the rule uses. - Use ~dep for one file, ~deps for list of files. - - It finally takes the action to perform in order to produce the - productions files using the dependencies (see [action]). - - There are some more optional parameters: - - The ~insert argument allow to insert the rules precisely between other - rules. - - The ~stamp argument specify the name of a file that will be - automatically produced by ocamlbuild. This file can serve as a virtual - target (or phony target), since it will be filled up by a digest of - it dependencies. - - The ~tags argument in deprecated, don't use it. - - Finally, the optional ~doc argument allows to give an informal - explanation of the rule purpose and behavior, that will be - displayed by [ocamlbuild -documentation]. For example, it is - a good place to specify the commands that will be called, any - new tags introduced by the rule, and dynamic dependencies. - *) - val rule : string -> - ?tags:string list -> - ?prods:string list -> - ?deps:string list -> - ?prod:string -> - ?dep:string -> - ?stamp:string -> - ?insert:[`top | `before of string | `after of string | `bottom] -> - ?doc:string -> - action -> unit - - (** [copy_rule name ?insert source destination] *) - val copy_rule : string -> - ?insert:[`top | `before of string | `after of string | `bottom] -> - string -> string -> unit - - (** Empties the list of rules of the ocamlbuild engine. *) - val clear_rules : unit -> unit - - (** [dep tags deps] Will build [deps] when all [tags] will be activated. - If you do not know which tags to use, have a look to the file - _build/_log after trying to compile your code. *) - val dep : Tags.elt list -> Pathname.t list -> unit - - (** [pdep tags ptag deps] is equivalent to [dep tags deps], with an - additional parameterized tag [ptag]. [deps] is now a function - which takes the parameter of the tag [ptag] as an argument. - - Example: - [pdep ["ocaml"; "compile"] "autodep" (fun param -> param)] - says that the tag [autodep(file)] can now be used to automatically - add [file] as a dependency when compiling an OCaml program. *) - val pdep : Tags.elt list -> Tags.elt -> (string -> Pathname.t list) -> unit - - (** [flag tags command_spec] Will inject the given piece of command - ([command_spec]) when all [tags] will be activated. - If you do not know which tags to use, have a look to the file - _build/_log after trying to compile your code. *) - val flag : Tags.elt list -> Command.spec -> unit - - (** Allows to use [flag] with a parametrized tag (as [pdep] for [dep]). - - Example: - [pflag ["ocaml"; "compile"] "inline" - (fun count -> S [A "-inline"; A count])] - says that command line option ["-inline 42"] should be added - when compiling OCaml modules tagged with ["inline(42)"]. *) - val pflag : Tags.elt list -> Tags.elt -> (string -> Command.spec) -> unit - - (** [flag_and_dep tags command_spec] - Combines [flag] and [dep] function. - Basically it calls [flag tags command_spec], and calls [dep tags files] - where [files] is the list of all pathnames in [command_spec]. - Pathnames selected are those in the constructor [P] or [Px], or the - pathname argument of builtins like [Echo]. *) - val flag_and_dep : Tags.elt list -> Command.spec -> unit - - (** Allows to use [flag_and_dep] with a parameterized tag - (as [pdep] for [dep]). *) - val pflag_and_dep : Tags.elt list -> Tags.elt -> - (string -> Command.spec) -> unit - - (** manually mark the tag as "useful" to silence the warning about - tags that are not part of any flag declaration. - - This is useful, - for example, if the tag is used in a flag declaration that is - only perfored in a conditional branch: - [if we_are_on_Windows then flag ["libfoo"] (A "bar");] - - When [we_are_on_Windows] is not true, you could get a warning about - "libfoo" not used in any flag declaration. - *) - val mark_tag_used : Tags.elt -> unit - - (** [non_dependency module_path module_name] - Example: - [non_dependency "foo/bar/baz" "Goo"] - Says that the module [Baz] in the file [foo/bar/baz.*] does - not depend on [Goo]. *) - val non_dependency : Pathname.t -> string -> unit - - (** [use_lib module_path lib_path]*) - val use_lib : Pathname.t -> Pathname.t -> unit - - (** [ocaml_lib library_pathname] Declare an ocaml library. - This informs ocamlbuild and produce tags to use the library; - they are named by default use_#{library_name}. - - Example: [ocaml_lib "foo/bar"] will setup the tag use_bar. - At link time it will include: - foo/bar.cma or foo/bar.cmxa - @param dir supply the [~dir:"boo"] option to add '-I boo' - at link and compile time. - @param extern use ~extern:true for non-ocamlbuild handled libraries. - Set this to add libraries whose sources are not in your project. - @param byte use ~byte:false to disable byte mode. - @param native use ~native:false to disable native mode. - @param tag_name Use ~tag_name:"usebar" to override the default - tag name. *) - val ocaml_lib : - ?extern:bool -> - ?byte:bool -> - ?native:bool -> - ?dir:Pathname.t -> - ?tag_name:string -> - Pathname.t -> unit - - (** [expand_module include_dirs module_name extensions] - Example: - [expand_module ["a";"b";"c"] "Foo" ["cmo";"cmi"] = - ["a/foo.cmo"; "a/Foo.cmo"; "a/foo.cmi"; "a/Foo.cmi"; - "b/foo.cmo"; "b/Foo.cmo"; "b/foo.cmi"; "b/Foo.cmi"; - "c/foo.cmo"; "c/Foo.cmo"; "c/foo.cmi"; "c/Foo.cmi"]] *) - val expand_module : - Pathname.t list -> Pathname.t -> string list -> Pathname.t list - - (** Reads the given file, parse it has list of words separated by blanks. - It ignore lines that begins with a '#' character. *) - val string_list_of_file : Pathname.t -> string list - - (** Takes a pathname and returns an OCaml module name. Basically it will - remove directories and extensions, and then capitalize the string. *) - val module_name_of_pathname : Pathname.t -> string - - (** The Unix mv command. *) - val mv : Pathname.t -> Pathname.t -> Command.t - - (** The Unix cp command. *) - val cp : Pathname.t -> Pathname.t -> Command.t - - (** The Unix ln -f command. *) - val ln_f : Pathname.t -> Pathname.t -> Command.t - - (** The Unix ln -s command. *) - val ln_s : Pathname.t -> Pathname.t -> Command.t - - (** The Unix rm -f command. *) - val rm_f : Pathname.t -> Command.t - - (** The Unix chmod command (almost deprecated). *) - val chmod : Command.spec -> Pathname.t -> Command.t - - (** The Unix cmp command (almost deprecated). *) - val cmp : Pathname.t -> Pathname.t -> Command.t - - (** [hide_package_contents pack_name] - Don't treat the given package as an open package. - So a module will not be replaced during linking by - this package even if it contains that module. *) - val hide_package_contents : string -> unit - - (** [tag_file filename tag_list] Tag the given filename with all - given tags. Prefix a tag with the minus sign to remove it. - This is usually used as an [After_rules] hook. - For example [tag_file "bla.ml" ["use_unix"]] tags the file - "bla.ml" with "use_unix" and [tag_file "bla.ml" ["-use_unix"]] - removes the tag "use_unix" from the file "bla.ml". *) - val tag_file : Pathname.t -> Tags.elt list -> unit - - (** [tag_any tag_list] Tag anything with all given tags. *) - val tag_any : Tags.elt list -> unit - - (** Returns the set of tags that applies to the given pathname. *) - val tags_of_pathname : Pathname.t -> Tags.t - - (** Run the given command and returns it's output as a string. *) - val run_and_read : string -> string - - (** Here is the list of hooks that the dispatch function have to handle. - Generally one responds to one or two hooks (like After_rules) and do - nothing in the default case. *) - type hook = - | Before_hygiene - | After_hygiene - | Before_options - | After_options - | Before_rules - | After_rules - - (** [dispatch hook_handler] Is the entry point for ocamlbuild plugins. Every - plugin must call it with a [hook_handler] where all calls to plugin - functions lives. *) - val dispatch : (hook -> unit) -> unit -end diff --git a/ocamlbuild/slurp.ml b/ocamlbuild/slurp.ml deleted file mode 100644 index d6c2846a..00000000 --- a/ocamlbuild/slurp.ml +++ /dev/null @@ -1,188 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Slurp *) -open My_std -open Outcome - -type 'a entry = - | Dir of string * string * My_unix.stats Lazy.t * 'a * 'a entry list Lazy.t - | File of string * string * My_unix.stats Lazy.t * 'a - | Error of exn - | Nothing - -let (/) = filename_concat - -let rec filter predicate = function - | Dir(path, name, st, attr, entries) -> - if predicate path name attr then - Dir(path, name, st, attr, lazy (List.map (filter predicate) !*entries)) - else - Nothing - | File(path, name, _, attr) as f -> - if predicate path name attr then - f - else - Nothing - | Nothing -> Nothing - | Error _ as e -> e - -let real_slurp path = - let cwd = Sys.getcwd () in - let abs x = if Filename.is_implicit x || Filename.is_relative x then cwd/x else x in - let visited = Hashtbl.create 1024 in - let rec scandir path names = - let (file_acc, dir_acc) = - Array.fold_left begin fun ((file_acc, dir_acc) as acc) name -> - match do_entry true path name with - | None -> acc - | Some((Dir _|Error _) as entry) -> (file_acc, entry :: dir_acc) - | Some((File _) as entry) -> (entry :: file_acc, dir_acc) - | Some Nothing -> acc - end - ([], []) - names - in - file_acc @ dir_acc - and do_entry link_mode path name = - let fn = path/name in - let absfn = abs fn in - match - try - Good(if link_mode then My_unix.lstat absfn else My_unix.stat absfn) - with - | x -> Bad x - with - | Bad x -> Some(Error x) - | Good st -> - let key = st.My_unix.stat_key in - if try Hashtbl.find visited key with Not_found -> false - then None - else - begin - Hashtbl.add visited key true; - let res = - match st.My_unix.stat_file_kind with - | My_unix.FK_link -> - let fn' = My_unix.readlink absfn in - if sys_file_exists (abs fn') then - do_entry false path name - else - Some(File(path, name, lazy st, ())) - | My_unix.FK_dir -> - (match sys_readdir absfn with - | Good names -> Some(Dir(path, name, lazy st, (), lazy (scandir fn names))) - | Bad exn -> Some(Error exn)) - | My_unix.FK_other -> None - | My_unix.FK_file -> Some(File(path, name, lazy st, ())) in - Hashtbl.replace visited key false; - res - end - in - match do_entry true "" path with - | None -> raise Not_found - | Some entry -> entry - -let split path = - let rec aux path = - if path = Filename.current_dir_name then [] - else (Filename.basename path) :: aux (Filename.dirname path) - in List.rev (aux path) - -let rec join = - function - | [] -> assert false - | [x] -> x - | x :: xs -> x/(join xs) - -let rec add root path entries = - match path, entries with - | [], _ -> entries - | xpath :: xspath, (Dir(dpath, dname, dst, dattr, dentries) as d) :: entries -> - if xpath = dname then - Dir(dpath, dname, dst, dattr, lazy (add (root/xpath) xspath !*dentries)) :: entries - else d :: add root path entries - | [xpath], [] -> - [File(root, xpath, lazy (My_unix.stat (root/xpath)), ())] - | xpath :: xspath, [] -> - [Dir(root/(join xspath), xpath, - lazy (My_unix.stat (root/(join path))), (), - lazy (add (root/xpath) xspath []))] - | _, Nothing :: entries -> add root path entries - | _, Error _ :: _ -> entries - | [xpath], (File(_, fname, _, _) as f) :: entries' -> - if xpath = fname then entries - else f :: add root path entries' - | xpath :: xspath, (File(fpath, fname, fst, fattr) as f) :: entries' -> - if xpath = fname then - Dir(fpath, fname, fst, fattr, lazy (add (root/xpath) xspath [])) :: entries' - else f :: add root path entries' - -let slurp_with_find path = - let find_cmd = try Sys.getenv "OCAMLBUILD_FIND" with _ -> "find" in - let lines = - My_unix.run_and_open (Printf.sprintf "%s %s" find_cmd (Filename.quote path)) begin fun ic -> - let acc = ref [] in - try while true do acc := input_line ic :: !acc done; [] - with End_of_file -> !acc - end in - let res = - List.fold_right begin fun line acc -> - add path (split line) acc - end lines [] in - match res with - | [] -> Nothing - | [entry] -> entry - | entries -> Dir(path, Filename.basename path, lazy (My_unix.stat path), (), lazy entries) - -let slurp x = if !*My_unix.is_degraded then slurp_with_find x else real_slurp x - -let rec print print_attr f entry = - match entry with - | Dir(path, name, _, attr, entries) -> - Format.fprintf f "@[<2>Dir(%S,@ %S,@ _,@ %a,@ %a)@]" - path name print_attr attr (List.print (print print_attr)) !*entries - | File(path, name, _, attr) -> - Format.fprintf f "@[<2>File(%S,@ %S,@ _,@ %a)@]" path name print_attr attr - | Nothing -> - Format.fprintf f "Nothing" - | Error(_) -> - Format.fprintf f "Error(_)" - -let rec fold f entry acc = - match entry with - | Dir(path, name, _, attr, contents) -> - f path name attr (List.fold_right (fold f) !*contents acc) - | File(path, name, _, attr) -> - f path name attr acc - | Nothing | Error _ -> acc - -let map f entry = - let rec self entry = - match entry with - | Dir(path, name, st, attr, contents) -> - Dir(path, name, st, f path name attr, lazy (List.map self !*contents)) - | File(path, name, st, attr) -> - File(path, name, st, f path name attr) - | Nothing -> Nothing - | Error e -> Error e - in self entry - -let rec force = - function - | Dir(_, _, st, _, contents) -> - let _ = !*st in List.iter force !*contents - | File(_, _, st, _) -> - ignore !*st - | Nothing | Error _ -> () diff --git a/ocamlbuild/slurp.mli b/ocamlbuild/slurp.mli deleted file mode 100644 index 45d34fc7..00000000 --- a/ocamlbuild/slurp.mli +++ /dev/null @@ -1,49 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Berke Durak *) -(* Slurp *) - -(** Scans a directory lazily to build a tree that can be user-decorated. *) - -type 'a entry = - Dir of string * string * My_unix.stats Lazy.t * 'a * 'a entry list Lazy.t - (** [Dir(path, name, lst, decoration, lentries)] is a directory named [name] whose path is [path]. - Its stat is lazily stored in [lst] and its entries are lazily scanned in [lentries]. [decoration] - is of type 'a. *) - | File of string * string * My_unix.stats Lazy.t * 'a - (** [File(path, name, lst, decoration)] is a file named [name] whose path is [path]. - Its stat is lazily stored in [lst]. [decoration] is of type 'a. *) - | Error of exn - (** [Error x] means that the exception [x] was raised while scanning or statting an entry. *) - | Nothing - (** Convenient when filtering out entries. *) - -(** Recursively scan the filesystem starting at the given directory. *) -val slurp : string -> unit entry - -(** [filter f entry] only retains from [entry] the nodes for which - [f path name] returns [true]. *) -val filter : (string -> string -> 'a -> bool) -> 'a entry -> 'a entry - -(** [map f entries] changes the decoration in [entries] by applying - [f] to them. [f] is called as [f path name decoration]. *) -val map : (string -> string -> 'a -> 'b) -> 'a entry -> 'b entry - -(** [fold f entry x] iterates [f] over the entries and an accumulator - initially containing [x]; at each iteration, [f] gets the current - value of the accumulator and returns its new value. *) -val fold : (string -> string -> 'b -> 'a -> 'a) -> 'b entry -> 'a -> 'a - -(** Force the evaluation of the whole entry. *) -val force : 'a entry -> unit diff --git a/ocamlbuild/solver.ml b/ocamlbuild/solver.ml deleted file mode 100644 index aaaa36b0..00000000 --- a/ocamlbuild/solver.ml +++ /dev/null @@ -1,132 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -open My_std -open Log -open Format -open Outcome - -type backtrace = - | Leaf of Pathname.t - | Choice of backtrace list - | Depth of Pathname.t * backtrace - | Target of string * backtrace -exception Failed of backtrace -exception Circular of Pathname.t * Pathname.t list - -let failed target backtrace = - Resource.Cache.resource_failed target; - raise (Failed backtrace) - -let rec pp_repeat f (n, s) = - if n > 0 then (pp_print_string f s; pp_repeat f (n - 1, s)) - -(* Targets must be normalized pathnames. - * Recursive calls are either on input targets - * or dependencies of these targets (returned by Rule.deps_of_rule). - *) -let rec self depth on_the_go_orig target = - let rules = Rule.get_rules () in - let on_the_go = target :: on_the_go_orig in - - dprintf 4 "==%a> %a" pp_repeat (depth, "==") Resource.print target; - if List.mem target on_the_go_orig then raise (Circular(target, on_the_go_orig)); - match Resource.Cache.resource_state target with - | Resource.Cache.Bbuilt -> - (dprintf 5 "%a already built" Resource.print target) - | Resource.Cache.Bcannot_be_built -> - (dprintf 5 "%a already failed" Resource.print target; failed target (Leaf target)) - | Resource.Cache.Bsuspension(s) -> - (dprintf 5 "%a was suspended -> resuming" Resource.print target; - Resource.Cache.resume_suspension s) - | Resource.Cache.Bnot_built_yet -> - if not (Pathname.is_relative target) && Pathname.exists target then - if Resource.Cache.external_is_up_to_date target then () - else (* perhaps the error can be refined *) failed target (Leaf target) - else - if Resource.exists_in_source_dir target then - Resource.Cache.import_in_build_dir target - else - match List.filter_opt (Rule.can_produce target) rules with - | [] -> failed target (Leaf target) - | matching_rules -> - let rec until_works rs backtraces = - match rs with - | [] -> assert false - | r :: rs -> - try - List.iter (force_self (depth + 1) on_the_go) (Rule.deps_of_rule r); - try - Rule.call (self_firsts (depth + 1) on_the_go) r - with Rule.Failed -> raise (Failed (Leaf target)) - with Failed backtrace -> - if rs = [] then failed target (Depth (target, Choice (backtrace :: backtraces))) - else - let () = - match backtrace with - | Depth (top_prod, _) -> Resource.Cache.clear_resource_failed top_prod - | Target _ | Choice _ | Leaf _ -> () - in until_works rs (backtrace :: backtraces) - in until_works matching_rules [] - -(* Build the first target that is buildable *) -and self_first depth on_the_go already_failed rs = - match rs with - | [] -> Bad (Failed (Choice already_failed)) - | r :: rs -> - try self depth on_the_go r; Good r - with Failed backtrace -> self_first depth on_the_go (backtrace :: already_failed) rs - -(* This variant is the one (once partially applied) called the 'build' - * function in the rule actions. - * - * This one takes a list of list of pathnames to build. - * This is a parallel conjonction of sequential alternatives. - * This means that in each sublist of pathnames, the first - * target that is buildable will be picked. The outer list - * denotes that one can build each target in parallel. - *) -and self_firsts depth on_the_go rss = - let results = List.map (self_first depth on_the_go []) rss in - let cmds, thunks = - List.fold_right begin fun res ((acc1, acc2) as acc) -> - match res with - | Bad _ -> acc - | Good res -> - match Resource.Cache.get_optional_resource_suspension res with - | None -> acc - | Some (cmd, thunk) -> (cmd :: acc1, thunk :: acc2) - end results ([], []) in - let count = List.length cmds in - let job_debug = if !Command.jobs = 1 then 10 else 5 in - if count > 1 then dprintf job_debug ">>> PARALLEL: %d" count; - let opt_exn = Command.execute_many cmds in - if count > 1 then dprintf job_debug "<<< PARALLEL"; - begin match opt_exn with - | Some(res, exn) -> - List.iter2 (fun res thunk -> if res then thunk ()) res thunks; - Log.finish ~how:`Error (); - raise exn - | None -> - List.iter (fun thunk -> thunk ()) thunks - end; - results -and force_self depth on_the_go x = self depth on_the_go x; Resource.Cache.resume_resource x - -let solve = force_self 0 [] -let solve_target name rs = - match self_first 0 [] [] rs with - | Good res -> Resource.Cache.resume_resource res; res - | Bad (Failed backtrace) -> raise (Failed (Target (name, backtrace))) - | Bad exn -> raise exn diff --git a/ocamlbuild/solver.mli b/ocamlbuild/solver.mli deleted file mode 100644 index 5f47a652..00000000 --- a/ocamlbuild/solver.mli +++ /dev/null @@ -1,24 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -type backtrace = private - | Leaf of Pathname.t - | Choice of backtrace list - | Depth of Pathname.t * backtrace - | Target of string * backtrace -exception Failed of backtrace -exception Circular of Pathname.t * Pathname.t list - -val solve : Pathname.t -> unit -val solve_target : string -> Pathname.t list -> Pathname.t diff --git a/ocamlbuild/start.sh b/ocamlbuild/start.sh deleted file mode 100755 index 1d1fa3ce..00000000 --- a/ocamlbuild/start.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/sh - -######################################################################### -# # -# OCaml # -# # -# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2007 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. # -# # -######################################################################### - - - -set -e -set -x -rm -rf _start -mkdir _start -cp *.ml* _start -cd _start -cat >> ocamlbuild_Myocamlbuild_config.ml < ok - does_match {foo, bar, baz} {foo, boo} => ko - does_match {foo, bar, baz} {} => ok - does_match {foo, bar, baz} {foo, bar, baz} => ok -*) -let does_match x y = subset y x - -let of_list l = List.fold_right add l empty - -open Format - -let print f s = - let () = fprintf f "@[<0>" in - let _ = - fold begin fun elt first -> - if not first then fprintf f ",@ "; - pp_print_string f elt; - false - end s true in - fprintf f "@]" - -module Operators = struct - let ( ++ ) x y = add y x - let ( -- ) x y = remove y x - let ( +++ ) x = function Some y -> add y x | None -> x - let ( --- ) x = function Some y -> remove y x | None -> x -end diff --git a/ocamlbuild/tags.mli b/ocamlbuild/tags.mli deleted file mode 100644 index 1fd1285b..00000000 --- a/ocamlbuild/tags.mli +++ /dev/null @@ -1,16 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) - -include Signatures.TAGS diff --git a/ocamlbuild/testsuite/README b/ocamlbuild/testsuite/README deleted file mode 100644 index 08e68d90..00000000 --- a/ocamlbuild/testsuite/README +++ /dev/null @@ -1,13 +0,0 @@ -The organization of tests is the following: - -- internal.ml contains the tests that should be runnable from a bare - OCaml installation -- always passing the -no-ocamlfind option. - -- findlibonly.ml contains the tests that should be runnable from a bare - OCaml installation, with only ocamlfind/findlib on top. The only - ocamlfind packages it relies over are those of the OCaml - distribution. - -- external.ml contains the tests that rely on other findlib packages - or external tools to run. Each test will only run if the findlib - package it depends on is present. \ No newline at end of file diff --git a/ocamlbuild/testsuite/external.ml b/ocamlbuild/testsuite/external.ml deleted file mode 100644 index ce8dc9e7..00000000 --- a/ocamlbuild/testsuite/external.ml +++ /dev/null @@ -1,22 +0,0 @@ -#use "internal_test_header.ml";; -#use "findlibonly_test_header.ml";; -#use "external_test_header.ml";; - -let () = test "SubtoolOptions" - ~description:"Options that come from tags that needs to be spliced \ - to the subtool invocation (PR#5763)" - (* testing for the 'menhir' executable directly - is too hard to do in a portable way; test the ocamlfind package instead *) - ~requirements:(package_exists "menhirLib") - ~options:[`use_ocamlfind; `use_menhir; `tags["package\\(camlp4.fulllib\\)"]] - ~tree:[T.f "parser.mly" - ~content:"%{ %} - %token DUMMY - %start test - %% - test: {None}"] - ~matching:[M.f "parser.native"; M.f "parser.byte"] - ~targets:("parser.native",["parser.byte"]) - ();; - -run ~root:"_test_external";; diff --git a/ocamlbuild/testsuite/external_test_header.ml b/ocamlbuild/testsuite/external_test_header.ml deleted file mode 100644 index 2b890e35..00000000 --- a/ocamlbuild/testsuite/external_test_header.ml +++ /dev/null @@ -1,7 +0,0 @@ -(* Fullfilled and Missing are defined in ocamlbuild_test.ml - Findlib was loaded in findlibonly_test_header.ml *) -let package_exists package = - let open Findlib in - try ignore (package_directory package); Fullfilled - with No_such_package _ -> - Missing (Printf.sprintf "the ocamlfind package %s" package) diff --git a/ocamlbuild/testsuite/findlibonly.ml b/ocamlbuild/testsuite/findlibonly.ml deleted file mode 100644 index d159ad47..00000000 --- a/ocamlbuild/testsuite/findlibonly.ml +++ /dev/null @@ -1,42 +0,0 @@ -#use "internal_test_header.ml";; -#use "findlibonly_test_header.ml";; - -let () = test "camlp4.opt" - ~description:"Fixes PR#5652" - ~options:[`package "camlp4.macro";`tags ["camlp4o.opt"; "syntax\\(camp4o\\)"]; - `ppflag "camlp4o.opt"; `ppflag "-parser"; `ppflag "macro"; - `ppflag "-DTEST"] - ~tree:[T.f "dummy.ml" - ~content:"IFDEF TEST THEN\nprint_endline \"Hello\";;\nENDIF;;"] - ~matching:[M.x "dummy.native" ~output:"Hello"] - ~targets:("dummy.native",[]) ();; - -let () = test "ThreadAndArchive" - ~description:"Fixes PR#6058" - ~options:[`use_ocamlfind; `package "threads"; `tag "thread"] - ~tree:[T.f "t.ml" ~content:""] - ~matching:[M.f "_build/t.cma"] - ~targets:("t.cma",[]) ();; - -let () = test "SyntaxFlag" - ~options:[`use_ocamlfind; `package "camlp4.macro"; `syntax "camlp4o"] - ~description:"-syntax for ocamlbuild" - ~tree:[T.f "dummy.ml" ~content:"IFDEF TEST THEN\nprint_endline \"Hello\";;\nENDIF;;"] - ~matching:[M.f "dummy.native"] - ~targets:("dummy.native",[]) ();; - -let () = test "PredicateFlag" - ~description:"ocamlfind ocamldep does not support the -predicate option" - ~options:[`use_ocamlfind; `tag "\"predicate(byte)\""] - ~tree:[T.f "test.ml" ~content:"let x = List.map"] - ~matching:[_build [M.f "test.ml.depends"]] - ~targets:("test.ml.depends", []) ();; - -let () = test "ToolsFlagsConflict" - ~description:"PR#6300: conflicts between -ocamlc and -use-ocamlfind options" - ~options:[`use_ocamlfind; `ocamlc "\"ocamlc -annot\""] - ~tree:[T.f "test.ml" ~content:"let x = 1"] - ~matching:[_build [M.f "test.annot"; M.f "test.byte"]] - ~targets:("test.byte", []) ();; - -run ~root:"_test_findlibonly";; diff --git a/ocamlbuild/testsuite/findlibonly_test_header.ml b/ocamlbuild/testsuite/findlibonly_test_header.ml deleted file mode 100644 index 5b147820..00000000 --- a/ocamlbuild/testsuite/findlibonly_test_header.ml +++ /dev/null @@ -1,9 +0,0 @@ -match Sys.command "ocamlfind ocamlc" with - | 0 -> () - | _ -> - prerr_endline "Having ocamlfind installed is a prerequisite \ - for running these tests. Aborting."; - exit 1; -;; - -#use "topfind";; diff --git a/ocamlbuild/testsuite/internal.ml b/ocamlbuild/testsuite/internal.ml deleted file mode 100644 index 9b48af52..00000000 --- a/ocamlbuild/testsuite/internal.ml +++ /dev/null @@ -1,324 +0,0 @@ -#use "internal_test_header.ml";; - -let () = test "BasicNativeTree" - ~options:[`no_ocamlfind] - ~description:"Output tree for native compilation" - ~tree:[T.f "dummy.ml"] - ~matching:[M.Exact - (_build - (M.lf - ["_digests"; - "dummy.cmi"; - "dummy.cmo"; - "dummy.cmx"; - "dummy.ml"; - "dummy.ml.depends"; - "dummy.native"; - "dummy.o"; - "_log"]))] - ~targets:("dummy.native",[]) ();; - -let () = test "BasicByteTree" - ~options:[`no_ocamlfind] - ~description:"Output tree for byte compilation" - ~tree:[T.f "dummy.ml"] - ~matching:[M.Exact - (_build - (M.lf - ["_digests"; - "dummy.cmi"; - "dummy.cmo"; - "dummy.ml"; - "dummy.ml.depends"; - "dummy.byte"; - "_log"]))] - ~targets:("dummy.byte",[]) ();; - -let () = test "SeveralTargets" - ~options:[`no_ocamlfind] - ~description:"Several targets" - ~tree:[T.f "dummy.ml"] - ~matching:[_build (M.lf ["dummy.byte"; "dummy.native"])] - ~targets:("dummy.byte",["dummy.native"]) ();; - -let alt_build_dir = "BuIlD2";; - -let () = test "BuildDir" - ~options:[`no_ocamlfind; `build_dir alt_build_dir] - ~description:"Different build directory" - ~tree:[T.f "dummy.ml"] - ~matching:[M.d alt_build_dir (M.lf ["dummy.byte"])] - ~targets:("dummy.byte",[]) ();; - -let tag_pat_msgs = - ["*:a", "File \"_tags\", line 1, characters 0-2:\n\ - Lexing error: Invalid globbing pattern \"*\"."; - - "\n<*{>:a", "File \"_tags\", line 2, characters 0-5:\n\ - Lexing error: Invalid globbing pattern \"<*{>\"."; - - "<*>: ~@a,# ~a", "File \"_tags\", line 1, characters 10-11:\n\ - Lexing error: Only ',' separated tags are alllowed."];; - -List.iteri (fun i (content,failing_msg) -> - let () = test (Printf.sprintf "TagsErrorMessage_%d" (i+1)) - ~options:[`no_ocamlfind] - ~description:"Confirm relevance of an error message due to erronous _tags" - ~failing_msg - ~tree:[T.f "_tags" ~content; T.f "dummy.ml"] - ~targets:("dummy.native",[]) () - in ()) tag_pat_msgs;; - -let () = test "Itarget" - ~options:[`no_ocamlfind] - ~description:".itarget building with dependencies between the modules (PR#5686)" - ~tree:[T.f "foo.itarget" ~content:"a.cma\nb.byte\n"; T.f "a.ml"; T.f "b.ml" ~content:"open A\n"] - ~matching:[M.f "a.cma"; M.f "b.byte"] - ~targets:("foo.otarget",[]) ();; - -let () = test "PackAcross" - ~options:[`no_ocamlfind] - ~description:"Pack using a module from the other tree (PR#4592)" - ~tree:[T.f "main.ml" ~content:"let _ = Pack.Packed.g ()\n"; - T.f "Pack.mlpack" ~content:"pack/Packed"; - T.f "_tags" ~content:": include\n: for-pack(Pack)\n"; - T.d "lib" [T.f "Lib.ml" ~content:"let f()=()"; - T.f "Lib.mli" ~content:"val f : unit -> unit"]; - T.d "pack" [T.f "Packed.ml" ~content:"let g() = Lib.f ()"]] - ~matching:[M.f "main.byte"; M.f "main.native"] - ~targets:("main.byte", ["main.native"]) - ();; - -let () = test "PackAcross2" - ~options:[`no_ocamlfind] - ~description:"Pack using a module from the other tree (PR#4592)" - ~tree:[T.f "a2.mli" ~content:"val f : unit -> unit"; - T.f "a2.ml" ~content:"let f _ = ()"; - T.f "lib.ml" ~content:"module A = A2"; - T.f "b.ml" ~content:"let g = Lib.A.f"; - T.f "sup.mlpack" ~content:"B"; - T.f "prog.ml" ~content:"Sup.B.g"] - ~matching:[M.f "prog.byte"] - ~targets:("prog.byte",[]) ();; - -let () = test "PackAcross3" - ~options:[`no_ocamlfind] - ~description:"Pack using a module from the other tree (PR#4592)" - ~tree:[T.d "foo" [ T.f "bar.ml" ~content:"let baz = Quux.xyzzy"]; - T.f "foo.mlpack" ~content:"foo/Bar"; - T.f "main.ml" ~content:"prerr_endline Foo.Bar.baz"; - T.f "myocamlbuild.ml"; - T.f "quux.ml" ~content:"let xyzzy = \"xyzzy\""; - T.f "quux.mli" ~content:"val xyzzy : string"] - ~matching:[M.f "main.byte"] - ~targets:("main.byte",[]) ();; - -let () = test "NativeMliCmi" - ~options:[`no_ocamlfind; `ocamlc "toto" (*using ocamlc would fail*); - `tags["native"]] - ~description:"check that ocamlopt is used for .mli->.cmi \ - when tag 'native' is set (part of PR#4613)" - ~tree:[T.f "foo.mli" ~content:"val bar : int"] - ~matching:[_build [M.f "foo.cmi"]] - ~targets:("foo.cmi",[]) ();; - -let () = test "NoIncludeNoHygiene1" - ~options:[`no_ocamlfind] - ~description:"check that hygiene checks are only done in traversed directories\ - (PR#4502)" - ~tree:[T.d "must_ignore" [ T.f "dirty.mli" ~content:"val bug : int"]; - T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; - T.f "_tags" ~content:": -traverse"] - ~pre_cmd:"ocamlc -c must_ignore/dirty.mli" - (* will make hygiene fail if must_ignore/ is checked *) - ~targets:("hello.byte",[]) ();; - -let () = test "NoIncludeNoHygiene2" - ~options:[`no_ocamlfind; `build_dir "must_ignore"] - ~description:"check that hygiene checks are not done on the -build-dir \ - (PR#4502)" - ~tree:[T.d "must_ignore" [ T.f "dirty.mli" ~content:"val bug : int"]; - T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; - T.f "_tags" ~content:""] - ~pre_cmd:"ocamlc -c must_ignore/dirty.mli" - (* will make hygiene fail if must_ignore/ is checked *) - ~targets:("hello.byte",[]) ();; - -let () = test "NoIncludeNoHygiene3" - ~options:[`no_ocamlfind; `X "must_ignore"] - ~description:"check that hygiene checks are not done on excluded dirs (PR#4502)" - ~tree:[T.d "must_ignore" [ T.f "dirty.mli" ~content:"val bug : int"]; - T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; - T.f "_tags" ~content:""] - ~pre_cmd:"ocamlc -c must_ignore/dirty.mli" - (* will make hygiene fail if must_ignore/ is checked *) - ~targets:("hello.byte",[]) ();; - -let () = test "OutputObj" - ~options:[`no_ocamlfind] - ~description:"output_obj targets for native and bytecode (PR #6049)" - ~tree:[T.f "hello.ml" ~content:"print_endline \"Hello, World!\""] - ~targets:("hello.byte.o",["hello.byte.c";"hello.native.o"]) ();; - -let () = test "OutputShared" - ~options:[`no_ocamlfind] - ~description:"output_shared targets for native and bytecode (PR #6733)" - ~tree:[T.f "hello.ml" ~content:"print_endline \"Hello, World!\""; - T.f "_tags" ~content:"<*.so>: runtime_variant(_pic)"] - ~targets:("hello.byte.so",["hello.native.so"]) ();; - -let () = test "StrictSequenceFlag" - ~options:[`no_ocamlfind; `quiet] - ~description:"strict_sequence tag" - ~tree:[T.f "hello.ml" ~content:"let () = 1; ()"; - T.f "_tags" ~content:"true: strict_sequence\n"] - ~failing_msg:"File \"hello.ml\", line 1, characters 9-10: -Error: This expression has type int but an expression was expected of type - unit\nCommand exited with code 2." - ~targets:("hello.byte",[]) ();; - -let () = test "StrictFormatsFlag" - ~options:[`no_ocamlfind; `quiet] - ~description:"strict_format tag" - ~tree:[T.f "hello.ml" ~content:"let _ = Printf.printf \"%.10s\""; - T.f "_tags" ~content:"true: strict_formats\n"] - ~failing_msg:"File \"hello.ml\", line 1, characters 22-29: -Error: invalid format \"%.10s\": at character number 0, \ -`precision' is incompatible with 's' in sub-format \"%.10s\" -Command exited with code 2." - ~targets:("hello.byte",[]) ();; - -let () = test "PrincipalFlag" - ~options:[`no_ocamlfind; `quiet] - ~description:"-principal tag" - ~tree:[T.f "hello.ml" - ~content:"type s={foo:int;bar:unit} type t={foo:int} - let f x = (x.bar; x.foo)"; - T.f "_tags" ~content:"true: principal\n"] - ~failing_msg:"File \"hello.ml\", line 2, characters 42-45: -Warning 18: this type-based field disambiguation is not principal." - ~targets:("hello.byte",[]) ();; - -let () = test "ModularPlugin1" - ~description:"test a plugin with dependency on external libraries" - ~options:[`no_ocamlfind; `quiet; `plugin_tag "use_str"] - ~tree:[T.f "main.ml" ~content:"let x = 1"; - T.f "myocamlbuild.ml" ~content:"ignore (Str.quote \"\");;"] - ~matching:[M.f "main.byte"] - ~targets:("main.byte",[]) ();; - -let () = test "ModularPlugin2" - ~description:"check that parametrized tags defined by the plugin \ - do not warn at plugin-compilation time" - ~options:[`no_ocamlfind; `quiet] - ~tree:[T.f "main.ml" ~content:"let x = 1"; - T.f "_tags" ~content:": toto(-g)"; - T.f "myocamlbuild.ml" - ~content:"open Ocamlbuild_plugin;; - pflag [\"link\"] \"toto\" (fun arg -> A arg);;"] - ~failing_msg:"" - ~matching:[M.f "main.byte"] - ~targets:("main.byte",[]) ();; - -let () = test "ModularPlugin3" - ~description:"check that unknown parametrized tags encountered \ - during plugin compilation still warn" - ~options:[`no_ocamlfind; `quiet; `plugin_tag "'toto(-g)'"] - ~tree:[T.f "main.ml" ~content:"let x = 1"; - T.f "myocamlbuild.ml" - ~content:"open Ocamlbuild_plugin;; - pflag [\"link\"] \"toto\" (fun arg -> A arg);;"] - ~failing_msg:"Warning: tag \"toto\" does not expect a parameter, \ - but is used with parameter \"-g\"" - ~matching:[M.f "main.byte"] - ~targets:("main.byte",[]) ();; - -let () = test "PluginCompilation1" - ~description:"check that the plugin is not compiled when -no-plugin is passed" - ~options:[`no_ocamlfind; `no_plugin] - ~tree:[T.f "main.ml" ~content:"let x = 1"; - T.f "myocamlbuild.ml" ~content:"prerr_endline \"foo\";;"] - ~matching:[_build [M.Not (M.f "myocamlbuild")]] - ~targets:("main.byte",[]) ();; - -let () = test "PluginCompilation2" - ~description:"check that the plugin is compiled when -just-plugin is passed" - ~options:[`no_ocamlfind; `just_plugin] - ~tree:[T.f "main.ml" ~content:"let x = 1"; - T.f "myocamlbuild.ml" ~content:"print_endline \"foo\";;"] - ~matching:[_build [M.f "myocamlbuild"]] - ~targets:("", []) ();; - -let () = test "PluginCompilation3" - ~description:"check that the plugin is not executed \ - when -just-plugin is passed" - ~options:[`no_ocamlfind; `quiet; `just_plugin] - ~tree:[T.f "main.ml" ~content:"let x = 1"; - T.f "myocamlbuild.ml" ~content:"print_endline \"foo\";;"] - (* if the plugin were executed we'd get "foo" in failing_msg *) - ~failing_msg:"" - ~targets:("main.byte", []) ();; - -let () = test "PluginTagsWarning" - ~description:"check that a warning is raised if -plugin-tags \ - is used without a plugin file" - ~options:[`no_ocamlfind; `plugin_tag "use_str"] - ~tree:[T.f "main.ml" ~content:""] - ~matching:[_build [M.f "main.cmo"]] - ~failing_msg:"Warning: option -plugin-tag(s) has no effect \ - in absence of plugin file \"myocamlbuild.ml\"" - ~targets:("main.ml", []) ();; - -let () = test "TagsInNonHygienic" - ~description:"Regression test for PR#6482, where a _tags \ - in a non-traversed directory would cause \ - ocamlbuild to abort" - ~options:[`no_ocamlfind] - ~tree:[ - T.f "main.ml" ~content:""; - T.d "deps" [T.f "_tags" ~content:""]; - T.f "_tags" ~content:": not_hygienic\n"; - ] - ~matching:[M.f "main.byte"] - ~targets:("main.byte",[]) ();; - -let () = test "TagsNewlines" - ~description:"Regression test for PR#6087 about placement \ - of newline-escaping backslashes" - ~options:[`no_ocamlfind] - ~tree:[ - T.f "main.ml" ~content:""; - T.f "_tags" ~content: -": debug,\\ -rectypes -: \\ -debug, rectypes -\\ -: debug, rectypes -"; - ] - ~matching:[M.f "main.byte"] - ~targets:("main.byte",[]) ();; - -let () = test "OpenTag" - ~description:"Test the parametrized tag for the new -open feature" - ~options:[`no_ocamlfind] - ~tree:[ - T.f "test.ml" ~content:"let _ = map rev [ []; [3;2] ]"; - T.f "_tags" ~content: ": open(List)"; - ] - ~matching:[M.f "test.byte"] - ~targets:("test.byte",[]) ();; - -let () = test "OpenDependencies" - ~description:"Test dependency computation for the new -open feature (PR#6584)" - ~options:[`no_ocamlfind] - ~tree:[ - T.f "a.ml" ~content:"let x = 1"; - T.f "b.ml" ~content:"print_int x; print_newline ()"; - T.f "_tags" ~content: ": open(A)"; - ] - ~matching:[M.f "b.byte"] - ~targets:("b.byte",[]) ();; - -run ~root:"_test_internal";; diff --git a/ocamlbuild/testsuite/internal_test_header.ml b/ocamlbuild/testsuite/internal_test_header.ml deleted file mode 100644 index da78c726..00000000 --- a/ocamlbuild/testsuite/internal_test_header.ml +++ /dev/null @@ -1,10 +0,0 @@ -#load "unix.cma";; - -let ocamlbuild = try Sys.getenv "OCAMLBUILD" with Not_found -> "ocamlbuild";; - -#use "ocamlbuild_test.ml";; - -module M = Match;; -module T = Tree;; - -let _build = M.d "_build";; diff --git a/ocamlbuild/testsuite/ocamlbuild_test.ml b/ocamlbuild/testsuite/ocamlbuild_test.ml deleted file mode 100644 index e3f44c55..00000000 --- a/ocamlbuild/testsuite/ocamlbuild_test.ml +++ /dev/null @@ -1,536 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Wojciech Meyer *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) - -open Format - -external (|>) : 'a -> ('a -> 'b) -> 'b = "%revapply" - -let print_list ~sep f ppf = function -| [] -> () -| x :: [] -> f ppf x -| x :: xs -> f ppf x; List.iter (fun x -> sep ppf (); f ppf x) xs - -let print_list_com f = - print_list ~sep:(fun ppf () -> pp_print_string ppf ",") f -let print_list_blank f = - print_list ~sep:(fun ppf () -> pp_print_string ppf " ") f - -let print_string_list = print_list_com pp_print_string -let print_string_list_com = print_list_com pp_print_string -let print_string_list_blank = print_list_blank pp_print_string - -let exists filename = - try ignore(Unix.stat filename); true - with Unix.Unix_error ((Unix.ENOENT),_,_) -> false - -let execute cmd = - let ic = Unix.open_process_in cmd and lst = ref [] in - try while true do lst := input_line ic :: !lst done; assert false - with End_of_file -> - let ret_code = Unix.close_process_in ic - in ret_code, List.rev !lst - -let rm f = - if exists f then - ignore(Sys.command (Printf.sprintf "rm -r %s" f)) - -module Match = struct - - type atts = unit - - (* File consists of file attribute and name *) - type file = atts * string - - (* Result is an outcome of execution, if consists of returned exit code, - and stream from stdout *) - type result = int * string - - type t = - (* Represents file in the tree *) - | F of file - (* Directory, consists of name and sub entries *) - | D of file * t list - (* Like file, but will be executed, and the result will compared *) - | X of file * result - (* Symlink; currently not supported *) - (* | L of file * file *) - (* We request that everything below should match exactly *) - | Exact of t - (* Here we want just the tree contained entities but we allow some - other stuff to be there too *) - | Contains of t - (* matching on Empty always fail *) - | Empty - (* matches the negation of its argument: fails when it succeeds - and vice versa; Any can be expressed as (Not Empty) *) - | Not of t - - (* Type of error, we either expect something or something is un-expected *) - type error = - Expected of string - | Unexpected of string - | Structure of string * string list - | Output of string * string * string - - (* This will print the tree *) - let print ppf tree = - let rec lines ppf lst = - List.iter (fun line -> pp_print_space ppf (); item ppf line) lst - and item ppf = function - | F (_, name) -> fprintf ppf "@[%s@]" name - | D ((_, name), children) -> - fprintf ppf "@[@[%s/@]%a@]" name lines children - | X ((_,name), _) -> fprintf ppf "@[%s@]" name - (* | L ((_,src), (_,dst)) -> fprintf ppf "@[%s->%s@]@" src dst *) - | Exact content -> fprintf ppf "{%a}" item content - | Contains content -> fprintf ppf "<%a>" item content - | Empty -> pp_print_char ppf '#' - | Not t -> fprintf ppf "not(@[%a@])" item t - in - pp_open_vbox ppf 0; - item ppf tree; - pp_close_box ppf () - - let f ?(atts=()) name = F (atts, name) - let d ?(atts=()) name children = D ((atts, name), children) - let lf ?(atts=()) lst = List.map (fun nm -> F (atts,nm)) lst - let x ?(atts=()) name ~output = X ((atts,name), (0,output)) - - let match_with_fs ~root m = - let rec visit ~exact ~successes ~errors path m = - let string_of_path path = "./" ^ String.concat "/" (List.rev path) in - let file name = string_of_path (name :: path) in - let push li x = li := x :: !li in - let exists_assert filename = - push (if exists filename then successes else errors) (Expected filename) - in - let rec take_name = function - | F (_, name) - | D ((_, name), _) - | X ((_, name), _) -> [name] - | Exact sub - | Contains sub - | Not sub -> take_name sub - | Empty -> [] - in - match m with - | F ((),name) -> - exists_assert (file name) - | D (((),name), sub) -> - exists_assert (file name); - let lst = List.flatten (List.map take_name sub) in - let lst' = Sys.readdir name |> Array.to_list in - let lst' = List.filter (fun x -> not (List.mem x lst)) lst' in - (if exact && lst' <> [] then - errors := Structure ((file name), lst') :: !errors); - List.iter (visit ~exact ~successes ~errors (name :: path)) sub - | X (((), name), (retcode, output)) -> - let _,output' = execute (file name) in - let output' = String.concat "\n" output' in - push (if output <> output' then errors else successes) - (Output (file name, output, output')); - | Exact sub -> visit ~exact:true ~successes ~errors path sub - | Contains sub -> visit ~exact:false ~successes ~errors path sub - | Empty -> push errors (Unexpected (string_of_path path)) - | Not sub -> visit ~exact ~errors:successes ~successes:errors path sub - in - let dir = Sys.getcwd () in - Unix.chdir root; - let successes = ref [] in - let errors = ref [] in - visit ~exact:false ~successes ~errors [] m; - Unix.chdir dir; - List.rev !errors - - let string_of_error = function - | Expected s -> Printf.sprintf "expected '%s' on a file system" s - | Unexpected s -> Printf.sprintf "un-expected '%s' on a file system" s - | Structure (s,l) -> - Printf.sprintf "directory structure '%s' has un-expected files %s" - s (String.concat ", " l) - | Output (s, e, p) -> - Printf.sprintf "executable %s expected output %S but got %S" - s e p -end - -module Option = struct - - type flag = string - type path = string - type level = int - type package = string - type file = string - type command = string - type _module = string - type tag = string - - type t = - [ `version - | `vnum - | `quiet - | `verbose of level - | `documentation - | `log of file - | `no_log - | `clean - | `r - | `I of path - | `Is of path list - | `X of path - | `Xs of path list - | `lib of flag - | `libs of flag list - | `_mod of _module - | `mods of _module list - | `pkg of package - | `pkgs of package list - | `package of package - | `syntax of string - | `lflag of flag - | `lflags of flag list - | `cflag of flag - | `cflags of flag list - | `docflag of flag - | `docflags of flag list - | `yaccflag of flag - | `yaccflags of flag list - | `lexflag of flag - | `lexflags of flag list - | `ppflag of flag - | `pp of flag list - | `tag of tag - | `tags of tag list - | `plugin_tag of tag - | `plugin_tags of tag list - | `tag_line of tag - | `show_tags of path - | `ignore of _module list - | `no_links - | `no_skip - | `no_hygiene - | `no_ocamlfind - | `no_plugin - | `no_stdlib - | `dont_catch_errors - | `just_plugin - | `byte_plugin - | `plugin_option - | `sanitization_script - | `no_sanitize - | `nothing_should_be_rebuilt - | `classic_display - | `use_menhir - | `use_jocaml - | `use_ocamlfind - | `j of level - | `build_dir of path - | `install_lib_dir of path - | `install_bin_dir of path - | `where - | `ocamlc of command - | `ocamlopt of command - | `ocamldep of command - | `ocamldoc of command - | `ocamlyacc of command - | `menhir of command - | `ocamllex of command - | `ocamlmktop of command - | `ocamlrun of command - | `help ] - - type arg = string * string list - - let print_level = pp_print_int - let print_flag = pp_print_string - let print_package = pp_print_string - let print_tag = pp_print_string - let print_tags = print_string_list_com - let print_path = pp_print_string - let print_paths = print_string_list_com - let print_flags = print_string_list_com - let print_module = pp_print_string - let print_modules = print_string_list_com - let print_packages = print_string_list_com - let print_command = pp_print_string - - let print_opt ppf o = - fprintf ppf "-"; - match o with - | `version -> fprintf ppf "version" - | `vnum -> fprintf ppf "vnum" - | `quiet -> fprintf ppf "quiet" - | `verbose level -> fprintf ppf "verbose %a" print_level level - | `documentation -> fprintf ppf "documentation" - | `log file -> fprintf ppf "log" - | `no_log -> fprintf ppf "no-log" - | `clean -> fprintf ppf "clean" - | `r -> fprintf ppf "r" - | `I path -> fprintf ppf "I %a" print_path path - | `Is paths -> fprintf ppf "Is %a" print_paths paths - | `X path -> fprintf ppf "X %a" print_path path - | `Xs paths -> fprintf ppf "Xs %a" print_paths paths - | `lib flag -> fprintf ppf "lib %a" print_flag flag - | `libs flags -> fprintf ppf "libs %a" print_flags flags - | `_mod _module -> fprintf ppf "mod %a" print_module _module - | `mods _modules -> fprintf ppf "mods %a" print_modules _modules - | `pkg package -> fprintf ppf "pkg %a" print_package package - | `pkgs packages -> fprintf ppf "pkgs %a" print_packages packages - | `package package -> fprintf ppf "package %a" print_package package - | `syntax syntax -> fprintf ppf "syntax %a" pp_print_string syntax - | `lflag flag -> fprintf ppf "lflag %a" print_flag flag - | `lflags flags -> fprintf ppf "lflags %a" print_flags flags - | `cflag flag -> fprintf ppf "cflag %a" print_flag flag - | `cflags flags -> fprintf ppf "cflags %a" print_flags flags - | `docflag flag -> fprintf ppf "docflag %a" print_flag flag - | `docflags flags -> fprintf ppf "docflags %a" print_flags flags - | `yaccflag flag -> fprintf ppf "yaccflag %a" print_flag flag - | `yaccflags flags -> fprintf ppf "yaccflags %a" print_flags flags - | `lexflag flag -> fprintf ppf "lexflag %a" print_flag flag - | `lexflags flags -> fprintf ppf "lexflags %a" print_flags flags - | `ppflag flag -> fprintf ppf "ppflag %a" print_flag flag - | `pp flags -> fprintf ppf "pp %a" print_flags flags - | `tag tag -> fprintf ppf "tag %a" print_tag tag - | `tags tags -> fprintf ppf "tags %a" print_tags tags - | `plugin_tag tag -> fprintf ppf "plugin-tag %a" print_tag tag - | `plugin_tags tags -> fprintf ppf "plugin-tags %a" print_tags tags - | `tag_line tag -> fprintf ppf "tag-line %a" print_tag tag - | `show_tags path -> fprintf ppf "show-tags %a" print_path path - | `ignore _modules -> fprintf ppf "ignore %a" print_modules _modules - | `no_links -> fprintf ppf "no-links" - | `no_skip -> fprintf ppf "no-skip" - | `no_hygiene -> fprintf ppf "no-hygiene" - | `no_ocamlfind -> fprintf ppf "no-ocamlfind" - | `no_plugin -> fprintf ppf "no-plugin" - | `no_stdlib -> fprintf ppf "no-stdlib" - | `dont_catch_errors -> fprintf ppf "dont" - | `just_plugin -> fprintf ppf "just-plugin" - | `byte_plugin -> fprintf ppf "byte-plugin" - | `plugin_option -> fprintf ppf "plugin-option" - | `sanitization_script -> fprintf ppf "sanitization-script" - | `no_sanitize -> fprintf ppf "no-sanitze" - | `nothing_should_be_rebuilt -> fprintf ppf "nothing_should_be_rebuilt" - | `classic_display -> fprintf ppf "classic-display" - | `use_menhir -> fprintf ppf "use-menhir" - | `use_jocaml -> fprintf ppf "use-jocaml" - | `use_ocamlfind -> fprintf ppf "use-ocamlfind" - | `j level -> fprintf ppf "j %a" print_level level - | `build_dir path -> fprintf ppf "build-dir %a" print_path path - | `install_lib_dir path -> fprintf ppf "install %a" print_path path - | `install_bin_dir path -> fprintf ppf "install %a" print_path path - | `where -> fprintf ppf "where" - | `ocamlc command -> fprintf ppf "ocamlc %a" print_command command - | `ocamlopt command -> fprintf ppf "ocamlopt %a" print_command command - | `ocamldep command -> fprintf ppf "ocamldep %a" print_command command - | `ocamldoc command -> fprintf ppf "ocamldoc %a" print_command command - | `ocamlyacc command -> fprintf ppf "ocamlyacc %a" print_command command - | `menhir command -> fprintf ppf "menhir %a" print_command command - | `ocamllex command -> fprintf ppf "ocamllex %a" print_command command - | `ocamlmktop command -> fprintf ppf "ocamlmktop %a" print_command command - | `ocamlrun command -> fprintf ppf "ocamlrun %a" print_command command - | `help -> fprintf ppf "help" - -end - -module Tree = struct - - type name = string - type content = string - - type t = - F of name * content - | D of name * t list - | E - - let f ?(content="") name = F (name, content) - let d name children = D (name, children) - - let create_on_fs ~root f = - - let rec visit path f = - let file name = - List.rev (name :: path) - |> String.concat "/" - in - match f with - | F (name, content) -> - let ch = file name |> open_out in - output_string ch content; - close_out ch - | D (name, sub) -> - (* print_endline ("mking " ^ (file name)); *) - Unix.mkdir (file name) 0o750; - List.iter (visit (name :: path)) sub - | E -> () - in - - let dir = Sys.getcwd () in - Unix.chdir root; - visit [] f; - Unix.chdir dir - -end - -type content = string -type filename = string -type run = filename * content - -type requirements = Fullfilled | Missing of string - -type test = { name : string - ; description : string - ; requirements : requirements option - ; tree : Tree.t list - ; matching : Match.t list - ; options : Option.t list - ; targets : string * string list - ; pre_cmd : string option - ; failing_msg : string option - ; run : run list } - -let tests = ref [] - -let test name - ~description - ?requirements - ?(options=[]) ?(run=[]) ?pre_cmd ?failing_msg - ?(tree=[]) - ?(matching=[]) - ~targets () - = - tests := !tests @ [{ - name; - description; - requirements; - tree; - matching; - options; - targets; - pre_cmd; - failing_msg; - run; - }] - -let print_colored header_color header name body_color body = - let color_code = function - | `Red -> "31" - | `Green -> "32" - | `Yellow -> "33" - | `Blue -> "34" - | `Magenta -> "35" - | `Cyan -> "36" - in - Printf.printf "\x1b[0;%sm\x1b[1m[%s]\x1b[0m \ - \x1b[1m%-20s\x1b[0;%sm%s.\n\x1b[m%!" - (color_code header_color) header name - (color_code body_color) body - -let run ~root = - let dir = Sys.getcwd () in - let root = dir ^ "/" ^ root in - rm root; - Unix.mkdir root 0o750; - - let command opts args = - let b = Buffer.create 127 in - let f = Format.formatter_of_buffer b in - fprintf f "%s %a %a" ocamlbuild (print_list_blank Option.print_opt) opts (print_list_blank pp_print_string) args; - Format.pp_print_flush f (); - Buffer.contents b - in - - let one_test - { name - ; description - ; requirements - ; tree - ; matching - ; options - ; targets - ; failing_msg - ; pre_cmd - ; run } = - - let full_name = root ^ "/" ^ name in - rm full_name; - Unix.mkdir full_name 0o750; - List.iter (Tree.create_on_fs ~root:full_name) tree; - Unix.chdir full_name; - - match requirements with - | Some (Missing req) -> - print_colored `Yellow "SKIPPED" name `Yellow - (Printf.sprintf "%s is required and missing" req) - - | Some Fullfilled | None -> begin - - (match pre_cmd with - | None -> () - | Some str -> ignore(Sys.command str)); - - let log_name = full_name ^ ".log" in - - let cmd = command options (fst targets :: snd targets) in - let allow_failure = failing_msg <> None in - - let open Unix in - - match execute cmd with - | WEXITED n,lines - | WSIGNALED n,lines - | WSTOPPED n,lines when allow_failure || n <> 0 -> - begin match failing_msg with - | None -> - let ch = open_out log_name in - List.iter - (fun l -> output_string ch l; output_string ch "\n") - lines; - close_out ch; - print_colored `Red "FAILED" name `Yellow - (Printf.sprintf "Command '%s' with error code %n \ - output written to %s" cmd n log_name); - | Some failing_msg -> - let starts_with_plus s = String.length s > 0 && s.[0] = '+' in - let lines = - (* filter out -classic-display output *) - List.filter (fun s -> not (starts_with_plus s)) lines in - let msg = String.concat "\n" lines in - if failing_msg = msg then - print_colored `Green "PASSED" name `Cyan description - else - print_colored `Red "FAILED" name `Yellow - ((Printf.sprintf "Failure with not matching message:\n\ - %s\n!=\n%s\n") msg failing_msg) - end; - | _ -> - let errors = - List.concat - (List.map (Match.match_with_fs ~root:full_name) matching) in - begin if errors == [] then - print_colored `Green "PASSED" name `Cyan description - else begin - let ch = open_out log_name in - output_string ch ("Run '" ^ cmd ^ "'\n"); - List.iter - (fun e -> - output_string ch (Match.string_of_error e); - output_string ch ".\n") - errors; - close_out ch; - print_colored `Red "FAILED" name `Yellow - (Printf.sprintf "Some system checks failed, \ - output written to %s" - log_name) - end - end - end - - in List.iter one_test !tests diff --git a/ocamlbuild/tools.ml b/ocamlbuild/tools.ml deleted file mode 100644 index ce28c970..00000000 --- a/ocamlbuild/tools.ml +++ /dev/null @@ -1,46 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Tools *) - -open My_std -open Format -open Log -open Pathname.Operators -open Tags.Operators -open Rule - -let pp_l = List.print String.print - -let tags_of_pathname p = - Configuration.tags_of_filename (Pathname.to_string p) - ++("file:"^p) - ++("extension:"^Pathname.get_extension p) - -let opt_print elt ppf = - function - | Some x -> fprintf ppf "@[<2>Some@ %a@]" elt x - | None -> pp_print_string ppf "None" - -let path_and_context_of_string s = - if Pathname.is_implicit s then - let b = Pathname.basename s in - let d = Pathname.dirname s in - if d <> Pathname.current_dir_name then - let () = Pathname.define_context d [d] in - [s] - else - let include_dirs = Pathname.include_dirs_of d in - List.map (fun include_dir -> include_dir/b) include_dirs - else [s] diff --git a/ocamlbuild/tools.mli b/ocamlbuild/tools.mli deleted file mode 100644 index 9c2763f9..00000000 --- a/ocamlbuild/tools.mli +++ /dev/null @@ -1,19 +0,0 @@ -(***********************************************************************) -(* *) -(* ocamlbuild *) -(* *) -(* Nicolas Pouillard, Berke Durak, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) - - -(* Original author: Nicolas Pouillard *) -(* Tools *) - -val tags_of_pathname : Pathname.t -> Tags.t -val path_and_context_of_string : Pathname.t -> Pathname.t list -val pp_l : Format.formatter -> string list -> unit diff --git a/ocamldoc/.depend b/ocamldoc/.depend index b98bb57f..c66b0750 100644 --- a/ocamldoc/.depend +++ b/ocamldoc/.depend @@ -12,16 +12,16 @@ odoc_analyse.cmo : ../utils/warnings.cmi ../typing/types.cmi \ odoc_sig.cmi odoc_module.cmo odoc_misc.cmi odoc_messages.cmo \ odoc_merge.cmi odoc_global.cmi odoc_dep.cmo odoc_cross.cmi \ odoc_comments.cmi odoc_class.cmo odoc_ast.cmi ../utils/misc.cmi \ - ../parsing/location.cmi ../typing/env.cmi ../utils/config.cmi \ - ../utils/clflags.cmi odoc_analyse.cmi + ../parsing/location.cmi ../parsing/lexer.cmi ../typing/env.cmi \ + ../utils/config.cmi ../utils/clflags.cmi odoc_analyse.cmi odoc_analyse.cmx : ../utils/warnings.cmx ../typing/types.cmx \ ../typing/typemod.cmx ../typing/typedtree.cmx ../parsing/syntaxerr.cmx \ ../driver/pparse.cmx ../parsing/parse.cmx odoc_types.cmx odoc_text.cmx \ odoc_sig.cmx odoc_module.cmx odoc_misc.cmx odoc_messages.cmx \ odoc_merge.cmx odoc_global.cmx odoc_dep.cmx odoc_cross.cmx \ odoc_comments.cmx odoc_class.cmx odoc_ast.cmx ../utils/misc.cmx \ - ../parsing/location.cmx ../typing/env.cmx ../utils/config.cmx \ - ../utils/clflags.cmx odoc_analyse.cmi + ../parsing/location.cmx ../parsing/lexer.cmx ../typing/env.cmx \ + ../utils/config.cmx ../utils/clflags.cmx odoc_analyse.cmi odoc_args.cmo : ../utils/warnings.cmi odoc_types.cmi odoc_texi.cmo \ odoc_messages.cmo odoc_man.cmo odoc_latex.cmo odoc_html.cmo \ odoc_global.cmi odoc_gen.cmi odoc_dot.cmo odoc_config.cmi \ @@ -88,12 +88,14 @@ odoc_env.cmo : ../typing/types.cmi ../typing/printtyp.cmi \ odoc_env.cmx : ../typing/types.cmx ../typing/printtyp.cmx \ ../typing/predef.cmx ../typing/path.cmx odoc_name.cmx ../utils/misc.cmx \ ../typing/btype.cmx odoc_env.cmi -odoc_exception.cmo : ../typing/types.cmi odoc_types.cmi odoc_name.cmi -odoc_exception.cmx : ../typing/types.cmx odoc_types.cmx odoc_name.cmx -odoc_extension.cmo : ../typing/types.cmi odoc_types.cmi odoc_name.cmi \ - ../parsing/asttypes.cmi -odoc_extension.cmx : ../typing/types.cmx odoc_types.cmx odoc_name.cmx \ - ../parsing/asttypes.cmi +odoc_exception.cmo : ../typing/types.cmi odoc_types.cmi odoc_type.cmo \ + odoc_name.cmi +odoc_exception.cmx : ../typing/types.cmx odoc_types.cmx odoc_type.cmx \ + odoc_name.cmx +odoc_extension.cmo : ../typing/types.cmi odoc_types.cmi odoc_type.cmo \ + odoc_name.cmi ../parsing/asttypes.cmi +odoc_extension.cmx : ../typing/types.cmx odoc_types.cmx odoc_type.cmx \ + odoc_name.cmx ../parsing/asttypes.cmi odoc_gen.cmo : odoc_texi.cmo odoc_module.cmo odoc_man.cmo odoc_latex.cmo \ odoc_html.cmo odoc_dot.cmo odoc_gen.cmi odoc_gen.cmx : odoc_texi.cmx odoc_module.cmx odoc_man.cmx odoc_latex.cmx \ @@ -229,9 +231,9 @@ odoc_type.cmx : ../typing/types.cmx odoc_types.cmx odoc_name.cmx \ odoc_types.cmo : odoc_messages.cmo ../parsing/location.cmi odoc_types.cmi odoc_types.cmx : odoc_messages.cmx ../parsing/location.cmx odoc_types.cmi odoc_value.cmo : ../typing/types.cmi ../typing/printtyp.cmi odoc_types.cmi \ - odoc_parameter.cmo odoc_name.cmi + odoc_parameter.cmo odoc_name.cmi odoc_misc.cmi ../parsing/asttypes.cmi odoc_value.cmx : ../typing/types.cmx ../typing/printtyp.cmx odoc_types.cmx \ - odoc_parameter.cmx odoc_name.cmx + odoc_parameter.cmx odoc_name.cmx odoc_misc.cmx ../parsing/asttypes.cmi odoc_analyse.cmi : odoc_module.cmo odoc_global.cmi odoc_args.cmi : odoc_gen.cmi odoc_ast.cmi : ../typing/types.cmi ../typing/typedtree.cmi \ @@ -248,9 +250,10 @@ odoc_global.cmi : odoc_types.cmi odoc_info.cmi : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \ odoc_type.cmo odoc_search.cmi odoc_parameter.cmo odoc_module.cmo \ odoc_global.cmi odoc_extension.cmo odoc_exception.cmo odoc_class.cmo \ - ../parsing/location.cmi + ../parsing/location.cmi ../parsing/asttypes.cmi odoc_merge.cmi : odoc_types.cmi odoc_module.cmo -odoc_misc.cmi : ../typing/types.cmi odoc_types.cmi ../parsing/longident.cmi +odoc_misc.cmi : ../typing/types.cmi odoc_types.cmi ../parsing/longident.cmi \ + ../parsing/asttypes.cmi odoc_name.cmi : ../typing/path.cmi ../parsing/longident.cmi \ ../typing/ident.cmi odoc_parser.cmi : odoc_types.cmi diff --git a/ocamldoc/.ignore b/ocamldoc/.ignore deleted file mode 100644 index 720ee641..00000000 --- a/ocamldoc/.ignore +++ /dev/null @@ -1,16 +0,0 @@ -ocamldoc -ocamldoc.opt -odoc_crc.ml -odoc_lexer.ml -odoc_ocamlhtml.ml -odoc_parser.ml -odoc_parser.mli -odoc_see_lexer.ml -odoc_text_lexer.ml -odoc_text_parser.ml -odoc_text_parser.mli -stdlib_man -*.output -test_stdlib -test_latex -test diff --git a/ocamldoc/Makefile b/ocamldoc/Makefile index 7c6d9885..2eba14c1 100644 --- a/ocamldoc/Makefile +++ b/ocamldoc/Makefile @@ -1,14 +1,17 @@ -#(***********************************************************************) -#(* *) -#(* OCamldoc *) -#(* *) -#(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -#(* *) -#(* Copyright 2001 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. *) -#(* *) -#(***********************************************************************) +#************************************************************************** +#* * +#* OCaml * +#* * +#* Maxence Guesdon, projet Cristal, INRIA Rocquencourt * +#* * +#* 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. * +#* * +#************************************************************************** include ../config/Makefile CAMLRUN ?= ../boot/ocamlrun @@ -30,8 +33,16 @@ OCAMLPP=-pp './remove_DEBUG' ############## MKDIR=mkdir -p CP=cp -f -OCAMLDOC=ocamldoc -OCAMLDOC_RUN=sh ./runocamldoc $(SUPPORTS_SHARED_LIBRARIES) +OCAMLDOC=./ocamldoc +ifeq "$(TARGET)" "$(HOST)" + ifeq "$(SUPPORTS_SHARED_LIBRARIES)" "true" + OCAMLDOC_RUN=$(CAMLRUN) -I ../otherlibs/unix -I ../otherlibs/str $(OCAMLDOC) + else + OCAMLDOC_RUN=$(OCAMLDOC) + endif +else + OCAMLDOC_RUN=$(CAMLRUN) $(OCAMLDOC) +endif OCAMLDOC_OPT=$(OCAMLDOC).opt OCAMLDOC_LIBCMA=odoc_info.cma OCAMLDOC_LIBCMI=odoc_info.cmi @@ -164,7 +175,11 @@ exe: $(OCAMLDOC) lib: $(OCAMLDOC_LIBCMA) $(OCAMLDOC_LIBCMI) $(ODOC_TEST) generators: $(GENERATORS_CMOS) -opt.opt: exeopt libopt generatorsopt +opt.opt: + $(MAKE) exeopt + $(MAKE) libopt + $(MAKE) generatorsopt + exeopt: $(OCAMLDOC_OPT) libopt: $(OCAMLDOC_LIBCMXA) $(OCAMLDOC_LIBCMI) generatorsopt: $(GENERATORS_CMXS) @@ -241,24 +256,24 @@ odoc_see_lexer.ml: odoc_see_lexer.mll # 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 - $(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 - if test -d stdlib_man; then $(CP) stdlib_man/* $(INSTALL_MANODIR); else : ; fi + 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 + $(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 + if test -d stdlib_man; then $(CP) stdlib_man/* "$(INSTALL_MANODIR)"; else : ; fi installopt: if test -f $(OCAMLDOC_OPT); then $(MAKE) installopt_really ; fi installopt_really: - if test -d $(INSTALL_BINDIR); then : ; else $(MKDIR) $(INSTALL_BINDIR); fi - if test -d $(INSTALL_LIBDIR); then : ; else $(MKDIR) $(INSTALL_LIBDIR); fi - $(CP) $(OCAMLDOC_OPT) $(INSTALL_BINDIR)/$(OCAMLDOC_OPT)$(EXE) - $(CP) ocamldoc.hva $(OCAMLDOC_LIBA) $(OCAMLDOC_LIBCMXA) $(INSTALL_LIBDIR) - $(CP) $(INSTALL_MLIS) $(INSTALL_CMIS) $(INSTALL_LIBDIR) + if test -d "$(INSTALL_BINDIR)"; then : ; else $(MKDIR) "$(INSTALL_BINDIR)"; fi + if test -d "$(INSTALL_LIBDIR)"; then : ; else $(MKDIR) "$(INSTALL_LIBDIR)"; fi + $(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)" # Testing : ########### @@ -290,7 +305,8 @@ test_framed: dummy test_latex: dummy $(MKDIR) $@ - $(OCAMLDOC_RUN) -latex -sort -o $@/test.tex -d $@ $(INCLUDES) odoc*.ml odoc*.mli test2.txt ../stdlib/*.mli ../otherlibs/unix/unix.mli + $(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 $(MKDIR) $@ diff --git a/ocamldoc/Makefile.nt b/ocamldoc/Makefile.nt index 9c009596..6a993e32 100644 --- a/ocamldoc/Makefile.nt +++ b/ocamldoc/Makefile.nt @@ -1,14 +1,17 @@ -#(***********************************************************************) -#(* *) -#(* OCamldoc *) -#(* *) -#(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -#(* *) -#(* Copyright 2001 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. *) -#(* *) -#(***********************************************************************) +#************************************************************************** +#* * +#* OCaml * +#* * +#* Maxence Guesdon, projet Cristal, INRIA Rocquencourt * +#* * +#* 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. * +#* * +#************************************************************************** include ../config/Makefile CAMLRUN ?= ../boot/ocamlrun @@ -18,7 +21,13 @@ CAMLYACC ?= ../boot/ocamlyacc ########################## ROOTDIR = .. OCAMLC = $(CAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib -OCAMLOPT = $(CAMLRUN) $(ROOTDIR)/ocamlopt -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) @@ -210,21 +219,22 @@ odoc_see_lexer.ml: odoc_see_lexer.mll # 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) + $(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) + $(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 : diff --git a/ocamldoc/generators/odoc_literate.ml b/ocamldoc/generators/odoc_literate.ml index 0e2718a3..da71b9ef 100644 --- a/ocamldoc/generators/odoc_literate.ml +++ b/ocamldoc/generators/odoc_literate.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open Odoc_info module Naming = Odoc_html.Naming @@ -59,7 +62,14 @@ class html = method private code_block b code = code_id <- code_id + 1; Printf.bprintf b - "\"+/-\"/" code_id code_id code_id; + "\ + \"+/-\"/" + code_id code_id code_id; Printf.bprintf b "
    " code_id; self#html_of_code b code; Printf.bprintf b "
    " diff --git a/ocamldoc/generators/odoc_todo.ml b/ocamldoc/generators/odoc_todo.ml index 9dbf9f37..01d3d94a 100644 --- a/ocamldoc/generators/odoc_todo.ml +++ b/ocamldoc/generators/odoc_todo.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, 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 Q Public License version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, 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. *) +(* *) +(**************************************************************************) (** An OCamldoc generator to retrieve information in "todo" tags and generate an html page with all todo items. *) diff --git a/ocamldoc/ocamldoc.hva b/ocamldoc/ocamldoc.hva index 1fb271ad..2bbddc06 100644 --- a/ocamldoc/ocamldoc.hva +++ b/ocamldoc/ocamldoc.hva @@ -1,14 +1,17 @@ -%(***********************************************************************) -%(* *) -%(* OCamldoc *) -%(* *) -%(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -%(* *) -%(* Copyright 2001 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. *) -%(* *) -%(***********************************************************************) +%************************************************************************** +%* * +%* OCaml * +%* * +%* Maxence Guesdon, projet Cristal, INRIA Rocquencourt * +%* * +%* 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. * +%* * +%************************************************************************** \usepackage{alltt} \newenvironment{ocamldoccode}{\begin{alltt}}{\end{alltt}} diff --git a/ocamldoc/odoc.ml b/ocamldoc/odoc.ml index 483db75f..45c3847a 100644 --- a/ocamldoc/odoc.ml +++ b/ocamldoc/odoc.ml @@ -1,17 +1,20 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Main module for bytecode. -@todo coucou le todo*) +@todo todo*) open Config open Clflags diff --git a/ocamldoc/odoc_analyse.ml b/ocamldoc/odoc_analyse.ml index fd69b0a7..c0b88bee 100644 --- a/ocamldoc/odoc_analyse.ml +++ b/ocamldoc/odoc_analyse.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of source files. This module is strongly inspired from driver/main.ml :-) *) @@ -59,17 +62,24 @@ let (++) x f = f x let tool_name = "ocamldoc" +(** Deactivate the generation of docstrings in the lexer *) +let no_docstring f x = + Lexer.handle_docstrings := false; + let result = f x in + Lexer.handle_docstrings := true; + result + let process_implementation_file ppf sourcefile = init_path (); let prefixname = Filename.chop_extension sourcefile in - let modulename = String.capitalize(Filename.basename prefixname) in + let modulename = String.capitalize_ascii(Filename.basename prefixname) in Env.set_unit_name modulename; let inputfile = preprocess sourcefile in let env = initial_env () in try let parsetree = Pparse.file ~tool_name Format.err_formatter inputfile - Parse.implementation ast_impl_magic_number + (no_docstring Parse.implementation) ast_impl_magic_number in let typedtree = Typemod.type_implementation @@ -95,12 +105,12 @@ let process_implementation_file ppf sourcefile = let process_interface_file ppf sourcefile = init_path (); let prefixname = Filename.chop_extension sourcefile in - let modulename = String.capitalize(Filename.basename prefixname) in + let modulename = String.capitalize_ascii(Filename.basename prefixname) in Env.set_unit_name modulename; let inputfile = preprocess sourcefile in let ast = Pparse.file ~tool_name Format.err_formatter inputfile - Parse.interface ast_intf_magic_number + (no_docstring Parse.interface) ast_intf_magic_number in let sg = Typemod.type_interface (initial_env()) ast in Warnings.check_fatal (); @@ -205,7 +215,7 @@ let process_file ppf sourcefile = try Filename.chop_extension file with _ -> file in - String.capitalize (Filename.basename s) + String.capitalize_ascii (Filename.basename s) in let txt = try Odoc_text.Texter.text_of_string (Odoc_misc.input_file_as_string file) @@ -431,7 +441,7 @@ let analyse_files ?(init=[]) files = print_string Odoc_messages.cross_referencing; print_newline () ); - let _ = Odoc_cross.associate modules_list in + Odoc_cross.associate modules_list; if !Odoc_global.verbose then ( diff --git a/ocamldoc/odoc_analyse.mli b/ocamldoc/odoc_analyse.mli index c155e81a..52e9cf58 100644 --- a/ocamldoc/odoc_analyse.mli +++ b/ocamldoc/odoc_analyse.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of source files. *) diff --git a/ocamldoc/odoc_args.ml b/ocamldoc/odoc_args.ml index 77b59025..f2d7862e 100644 --- a/ocamldoc/odoc_args.ml +++ b/ocamldoc/odoc_args.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Command-line arguments. *) @@ -197,7 +200,9 @@ module Options = Main_args.Make_ocamldoc_options(struct let _intf s = Odoc_global.files := !Odoc_global.files @ [Odoc_global.Intf_file s] let _intf_suffix s = Config.interface_suffix := s let _labels = unset Clflags.classic + let _alias_deps = unset Clflags.transparent_modules let _no_alias_deps = set Clflags.transparent_modules + let _app_funct = set Clflags.applicative_functors let _no_app_funct = unset Clflags.applicative_functors let _noassert = set Clflags.noassert let _nolabels = set Clflags.classic @@ -206,11 +211,15 @@ module Options = Main_args.Make_ocamldoc_options(struct let _pp s = Clflags.preprocessor := Some s let _ppx s = Clflags.all_ppx := s :: !Clflags.all_ppx let _principal = set Clflags.principal + let _no_principal = unset Clflags.principal let _rectypes = set Clflags.recursive_types + let _no_rectypes = unset Clflags.recursive_types let _safe_string = unset Clflags.unsafe_string let _short_paths = unset Clflags.real_paths let _strict_sequence = set Clflags.strict_sequence + let _no_strict_sequence = unset Clflags.strict_sequence let _strict_formats = set Clflags.strict_formats + let _no_strict_formats = unset Clflags.strict_formats let _thread = set Clflags.use_threads let _vmthread = set Clflags.use_vmthreads let _unsafe () = assert false @@ -229,6 +238,7 @@ module Options = Main_args.Make_ocamldoc_options(struct let _dtypedtree = set Clflags.dump_typedtree let _drawlambda = set Clflags.dump_rawlambda let _dlambda = set Clflags.dump_lambda + let _dflambda = set Clflags.dump_flambda let _dinstr = set Clflags.dump_instr let anonymous = anonymous end) @@ -264,20 +274,35 @@ let default_options = Options.list @ "\n\n *** choosing a generator ***\n"; (* generators *) - "-html", Arg.Unit (fun () -> set_generator - (Odoc_gen.Html (module Odoc_html.Generator : Odoc_html.Html_generator))), + "-html", Arg.Unit (fun () -> + match !current_generator with + Some (Odoc_gen.Html _) -> () + | _ -> set_generator + (Odoc_gen.Html (module Odoc_html.Generator : Odoc_html.Html_generator))), M.generate_html ; - "-latex", Arg.Unit (fun () -> set_generator - (Odoc_gen.Latex (module Odoc_latex.Generator : Odoc_latex.Latex_generator))), + "-latex", Arg.Unit (fun () -> + match !current_generator with + Some (Odoc_gen.Latex _) -> () + | _ -> set_generator + (Odoc_gen.Latex (module Odoc_latex.Generator : Odoc_latex.Latex_generator))), M.generate_latex ; - "-texi", Arg.Unit (fun () -> set_generator - (Odoc_gen.Texi (module Odoc_texi.Generator : Odoc_texi.Texi_generator))), + "-texi", Arg.Unit (fun () -> + match !current_generator with + Some (Odoc_gen.Texi _) -> () + | _ -> set_generator + (Odoc_gen.Texi (module Odoc_texi.Generator : Odoc_texi.Texi_generator))), M.generate_texinfo ; - "-man", Arg.Unit (fun () -> set_generator - (Odoc_gen.Man (module Odoc_man.Generator : Odoc_man.Man_generator))), + "-man", Arg.Unit (fun () -> + match !current_generator with + Some (Odoc_gen.Man _) -> () + | _ -> set_generator + (Odoc_gen.Man (module Odoc_man.Generator : Odoc_man.Man_generator))), M.generate_man ; - "-dot", Arg.Unit (fun () -> set_generator - (Odoc_gen.Dot (module Odoc_dot.Generator : Odoc_dot.Dot_generator))), + "-dot", Arg.Unit (fun () -> + match !current_generator with + Some (Odoc_gen.Dot _) -> () + | _ -> set_generator + (Odoc_gen.Dot (module Odoc_dot.Generator : Odoc_dot.Dot_generator))), M.generate_dot ; "-customdir", Arg.Unit (fun () -> Printf.printf "%s\n" Odoc_config.custom_generators_path; exit 0), M.display_custom_generators_dir ; @@ -384,10 +409,9 @@ let add_option o = let parse () = if modified_options () then append_last_doc "\n"; let options = !options @ !help_options in - let _ = Arg.parse (Arg.align ~limit:13 options) + Arg.parse (Arg.align ~limit:13 options) anonymous - (M.usage^M.options_are) - in + (M.usage^M.options_are); (* we sort the hidden modules by name, to be sure that for example, A.B is before A, so we will match against A.B before A in Odoc_name.hide_modules.*) diff --git a/ocamldoc/odoc_args.mli b/ocamldoc/odoc_args.mli index c348dfa0..a4812b9a 100644 --- a/ocamldoc/odoc_args.mli +++ b/ocamldoc/odoc_args.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of the command line arguments. *) diff --git a/ocamldoc/odoc_ast.ml b/ocamldoc/odoc_ast.ml index 2e6d1ded..d5817612 100644 --- a/ocamldoc/odoc_ast.ml +++ b/ocamldoc/odoc_ast.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of implementation files. *) open Misc @@ -60,7 +63,7 @@ module Typedtree_search = let iter_val_pattern = function | Typedtree.Tpat_any -> None | Typedtree.Tpat_var (name, _) -> Some (Name.from_ident name) - | Typedtree.Tpat_tuple _ -> None (* A VOIR quand on traitera les tuples *) + | Typedtree.Tpat_tuple _ -> None (* FIXME when we will handle tuples *) | _ -> None let add_to_hashes table table_values tt = @@ -83,17 +86,17 @@ module Typedtree_search = end | Typedtree.Tstr_exception ext -> Hashtbl.add table (E (Name.from_ident ext.ext_id)) tt - | Typedtree.Tstr_type ident_type_decl_list -> + | Typedtree.Tstr_type (rf, ident_type_decl_list) -> List.iter (fun td -> Hashtbl.add table (T (Name.from_ident td.typ_id)) - (Typedtree.Tstr_type [td])) + (Typedtree.Tstr_type (rf, [td]))) ident_type_decl_list | Typedtree.Tstr_class info_list -> List.iter - (fun (ci, m, s) -> + (fun (ci, s) -> Hashtbl.add table (C (Name.from_ident ci.ci_id_class)) - (Typedtree.Tstr_class [ci, m, s])) + (Typedtree.Tstr_class [ci, s])) info_list | Typedtree.Tstr_class_type info_list -> List.iter @@ -145,12 +148,12 @@ module Typedtree_search = let search_type_declaration table name = match Hashtbl.find table (T name) with - | (Typedtree.Tstr_type [td]) -> td + | (Typedtree.Tstr_type (_, [td])) -> td | _ -> assert false let search_class_exp table name = match Hashtbl.find table (C name) with - | (Typedtree.Tstr_class [(ci, _, _ )]) -> + | (Typedtree.Tstr_class [(ci, _ )]) -> let ce = ci.ci_expr in ( try @@ -303,7 +306,7 @@ module Analyser = | {c_lhs=pattern_param} :: second_ele :: q -> (* implicit pattern matching -> anonymous parameter and no more parameter *) - (* A VOIR : le label ? *) + (* FIXME : label ? *) let parameter = Odoc_parameter.Tuple ([], Odoc_env.subst_type env pattern_param.pat_type) in [ parameter ] @@ -406,11 +409,11 @@ module Analyser = | (Typedtree.Tpat_tuple lpat, _) -> (* new identifiers are defined *) - (* A VOIR : by now we don't accept to have global variables defined in tuples *) + (* FIXME : by now we don't accept to have global variables defined in tuples *) [] | _ -> - (* something else, we don't care ? A VOIR *) + (* something else, we don't care ? FIXME *) [] (** This function takes a Typedtree.class_expr and returns a string which can stand for the class name. @@ -454,7 +457,7 @@ module Analyser = | l -> match l with [] -> - (* cas impossible, on l'a filtre avant *) + (* impossible case, it has already been filtered *) assert false | {c_lhs=pattern_param} :: second_ele :: q -> (* implicit pattern matching -> anonymous parameter *) @@ -699,11 +702,11 @@ module Analyser = Typedtree.Tcl_ident (p,_,_) -> Name.from_path p | _ -> (* we try to get the name from the environment. *) - (* A VOIR : dommage qu'on n'ait pas un Tclass_ident :-( meme quand on a class tutu = toto *) + (* FIXME : Unfortunately, we don't have a Tclass_ident :-( even for a class tutu = toto *) Name.from_longident lid.txt in - (* On n'a pas ici les parametres de type sous forme de Types.type_expr, - par contre on peut les trouver dans le class_type *) + (* Here, type parameters are not present as Types.type_expr, + however they can be found in the class_type *) let params = match tt_class_exp.Typedtree.cl_type with Types.Cty_constr (p2, type_exp_list, cltyp) -> @@ -786,9 +789,9 @@ module Analyser = (* we want an ident, or else the class applied will appear in the form object ... end, because if the class applied has no name, the code is kinda ugly, isn't it ? *) match tt_class_expr2.Typedtree.cl_desc with - Typedtree.Tcl_ident (p,_,_) -> Name.from_path p (* A VOIR : obtenir le nom complet *) + Typedtree.Tcl_ident (p,_,_) -> Name.from_path p (* FIXME : obtain the full name *) | _ -> - (* A VOIR : dommage qu'on n'ait pas un Tclass_ident :-( meme quand on a class tutu = toto *) + (* FIXME : Unfortunately, we don't have a Tclass_ident :-( even for a class tutu = toto *) match p_class_expr2.Parsetree.pcl_desc with Parsetree.Pcl_constr (lid, _) -> (* we try to get the name from the environment. *) @@ -797,7 +800,7 @@ module Analyser = Odoc_messages.object_end in let param_exps = List.fold_left - (fun acc -> fun (_, exp_opt, _) -> + (fun acc -> fun (_, exp_opt) -> match exp_opt with None -> acc | Some e -> acc @ [e]) @@ -832,7 +835,7 @@ module Analyser = env current_class_name comment_opt last_pos p_class_expr2 tt_class_expr2 table in - (* A VOIR : analyse du class type ? on n'a pas toutes les infos. cf. Odoc_sig.analyse_class_type_kind *) + (* FIXME analysis of the class type ? We don't have all the infos. cf. Odoc_sig.analyse_class_type_kind *) let class_type_kind = (*Sig.analyse_class_type_kind env @@ -867,19 +870,16 @@ module Analyser = tt_class_exp table in - let cl = - { - cl_name = complete_name ; - cl_info = comment_opt ; - cl_type = cltype ; - cl_virtual = virt ; - cl_type_parameters = type_parameters ; - cl_kind = kind ; - cl_parameters = parameters ; - cl_loc = { loc_impl = Some loc ; loc_inter = None } ; - } - in - cl + { + cl_name = complete_name ; + cl_info = comment_opt ; + cl_type = cltype ; + cl_virtual = virt ; + cl_type_parameters = type_parameters ; + cl_kind = kind ; + cl_parameters = parameters ; + cl_loc = { loc_impl = Some loc ; loc_inter = None } ; + } (** Get a name from a module expression, or "struct ... end" if the module expression is not an ident of a constraint on an ident. *) @@ -899,7 +899,7 @@ module Analyser = match item.str_desc with Typedtree.Tstr_include incl -> acc @ [ - { (* A VOIR : chercher dans les modules et les module types, avec quel env ? *) + { (* FIXME : search within modules and module types, with which env ? *) im_name = tt_name_from_module_expr incl.incl_mod ; im_module = None ; im_info = None ; @@ -981,7 +981,7 @@ module Analyser = | Element_type t -> (function Types.Sig_type (ident,_,_) -> - (* A VOIR: il est possible que le detail du type soit cache *) + (* FIXME: type details can be hidden *) let n1 = Name.simple t.ty_name and n2 = Ident.name ident in n1 = n2 @@ -1043,18 +1043,15 @@ module Analyser = [] -> let s = get_string_of_file last_pos pos_limit in let (_, ele_coms) = My_ir.all_special !file_name s in - let ele_comments = - List.fold_left - (fun acc -> fun sc -> - match sc.Odoc_types.i_desc with - None -> - acc - | Some t -> - acc @ [Element_module_comment t]) - [] - ele_coms - in - ele_comments + List.fold_left + (fun acc -> fun sc -> + match sc.Odoc_types.i_desc with + None -> + acc + | Some t -> + acc @ [Element_module_comment t]) + [] + ele_coms | item :: q -> let (comment_opt, ele_comments) = get_comments_in_module last_pos item.Parsetree.pstr_loc.Location.loc_start.Lexing.pos_cnum @@ -1098,7 +1095,7 @@ module Analyser = let rec iter_pat = function | Parsetree.Ppat_any -> None | Parsetree.Ppat_var name -> Some name - | Parsetree.Ppat_tuple _ -> None (* A VOIR quand on traitera les tuples *) + | Parsetree.Ppat_tuple _ -> None (* FIXME when we will handle tuples *) | Parsetree.Ppat_constraint (pat, _) -> iter_pat pat.Parsetree.ppat_desc | _ -> None in @@ -1179,7 +1176,7 @@ module Analyser = let new_env = Odoc_env.add_value env new_value.val_name in (0, new_env, [Element_value new_value]) - | Parsetree.Pstr_type name_typedecl_list -> + | Parsetree.Pstr_type (rf, name_typedecl_list) -> (* of (string * type_declaration) list *) let extended_env = List.fold_left @@ -1191,14 +1188,9 @@ module Analyser = name_typedecl_list in let env = - let is_nonrec = - List.exists - (fun td -> - List.exists (fun (n, _) -> n.txt = "nonrec") - td.Parsetree.ptype_attributes) - name_typedecl_list - in - if is_nonrec then env else extended_env + match rf with + | Recursive -> extended_env + | Nonrecursive -> env in let rec f ?(first=false) maybe_more_acc last_pos name_type_decl_list = match name_type_decl_list with @@ -1325,10 +1317,14 @@ module Analyser = let new_xt = match tt_ext.ext_kind with Text_decl(args, ret_type) -> + let xt_args = + match args with + | Cstr_tuple l -> Cstr_tuple (List.map (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) l) + | Cstr_record _ -> assert false + in { xt_name = complete_name; - xt_args = - List.map (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) args; + xt_args; xt_ret = may_map (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) ret_type; xt_type_extension = new_te; @@ -1339,7 +1335,7 @@ module Analyser = | Text_rebind(path, _) -> { xt_name = complete_name; - xt_args = []; + xt_args = Cstr_tuple []; xt_ret = None; xt_type_extension = new_te; xt_alias = @@ -1382,13 +1378,15 @@ module Analyser = Text_decl(tt_args, tt_ret_type) -> let loc_start = loc.Location.loc_start.Lexing.pos_cnum in let loc_end = loc.Location.loc_end.Lexing.pos_cnum in + let ex_args = + match tt_args with + | Cstr_tuple l -> Cstr_tuple (List.map (fun c -> Odoc_env.subst_type env c.ctyp_type) l) + | Cstr_record l -> assert false (* TODO *) + in { ex_name = complete_name ; ex_info = comment_opt ; - ex_args = - List.map - (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) - tt_args; + ex_args; ex_ret = Misc.may_map (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) @@ -1407,7 +1405,7 @@ module Analyser = { ex_name = complete_name ; ex_info = comment_opt ; - ex_args = [] ; + ex_args = Cstr_tuple [] ; ex_ret = None ; ex_alias = Some { ea_name = @@ -1448,7 +1446,7 @@ module Analyser = let new_env = Odoc_env.add_module env new_module.m_name in let new_env2 = match new_module.m_type with - (* A VOIR : cela peut-il etre Tmty_ident ? dans ce cas, on aurait pas la signature *) + (* FIXME : can this be Tmty_ident? In this case, we would'nt have the signature *) Types.Mty_signature s -> Odoc_env.add_signature new_env new_module.m_name ~rel: (Name.simple new_module.m_name) s @@ -1463,8 +1461,8 @@ module Analyser = ) | Parsetree.Pstr_recmodule mods -> - (* A VOIR ICI pb: pas de lien avec les module type - dans les contraintes sur les modules *) + (* FIXME Here problem: no link with module types + in module constraints *) let new_env = List.fold_left (fun acc_env {Parsetree.pmb_name=name;pmb_expr=mod_exp} -> @@ -1552,7 +1550,7 @@ module Analyser = let new_env = Odoc_env.add_module_type env mt.mt_name in let new_env2 = match sig_mtype with - (* A VOIR : cela peut-il etre Tmty_ident ? dans ce cas, on n'aurait pas la signature *) + (* FIXME : can this be Tmty_ident? In this case, we would'nt have the signature *) Some (Types.Mty_signature s) -> Odoc_env.add_signature new_env mt.mt_name ~rel: (Name.simple mt.mt_name) s | _ -> @@ -1561,7 +1559,7 @@ module Analyser = (0, new_env2, [ Element_module_type mt ]) | Parsetree.Pstr_open _ -> - (* A VOIR : enrichir l'environnement quand open ? *) + (* FIXME : extend the environment after open? *) let ele_comments = match comment_opt with None -> [] | Some i -> @@ -1681,7 +1679,7 @@ module Analyser = im_info = comment_opt ; } in - (0, env, [ Element_included_module im ]) (* A VOIR : etendre l'environnement ? avec quoi ? *) + (0, env, [ Element_included_module im ]) (* FIXME: extend the environment? With what? *) (** Analysis of a [Parsetree.module_expr] and a name to return a [t_module].*) and analyse_module env current_module_name module_name comment_opt p_module_expr tt_module_expr = @@ -1690,7 +1688,7 @@ module Analyser = let pos_start = loc.Location.loc_start.Lexing.pos_cnum in let pos_end = loc.Location.loc_end.Lexing.pos_cnum in let modtype = - (* A VOIR : Odoc_env.subst_module_type env ? *) + (* FIXME : Odoc_env.subst_module_type env ? *) tt_module_expr.Typedtree.mod_type in let m_code_intf = @@ -1760,7 +1758,7 @@ module Analyser = } in let dummy_complete_name = (*Name.concat "__"*) param.mp_name in - (* TODO: A VOIR CE __ *) + (* TODO: FIX THIS __ *) let new_env = Odoc_env.add_module env dummy_complete_name in let m_base2 = analyse_module new_env @@ -1907,7 +1905,7 @@ module Analyser = in prepare_file complete_source_file input_file; (* We create the t_module for this file. *) - let mod_name = String.capitalize (Filename.basename (Filename.chop_extension source_file)) in + 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 (* we must complete the included modules *) diff --git a/ocamldoc/odoc_ast.mli b/ocamldoc/odoc_ast.mli index c3db304e..d77842d7 100644 --- a/ocamldoc/odoc_ast.mli +++ b/ocamldoc/odoc_ast.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The module for analysing the typed abstract syntax tree and source code and creating modules, classes, ..., elements.*) diff --git a/ocamldoc/odoc_class.ml b/ocamldoc/odoc_class.ml index ce9902eb..5f9ca827 100644 --- a/ocamldoc/odoc_class.ml +++ b/ocamldoc/odoc_class.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of classes and class types.*) @@ -113,9 +116,9 @@ let rec class_elements ?(trans=true) cl = Class_structure (_, elements) -> elements | Class_constraint (c_kind, ct_kind) -> iter_kind c_kind - (* A VOIR : utiliser le c_kind ou le ct_kind ? - Pour l'instant, comme le ct_kind n'est pas analyse, - on cherche dans le c_kind + (* FIXME : use c_kind or ct_kind ? + For now, as ct_kind is not analyzed, + we search inside c_kind class_type_elements ~trans: trans { clt_name = "" ; clt_info = None ; clt_type_parameters = [] ; diff --git a/ocamldoc/odoc_comments.ml b/ocamldoc/odoc_comments.ml index c39cb51b..a8ef04e1 100644 --- a/ocamldoc/odoc_comments.ml +++ b/ocamldoc/odoc_comments.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of comments. *) @@ -28,7 +31,7 @@ module type Texter = module Info_retriever = functor (MyTexter : Texter) -> struct - let create_see s = + let create_see file s = try let lexbuf = Lexing.from_string s in let (see_ref, s) = Odoc_parser.see_info Odoc_see_lexer.main lexbuf in @@ -41,7 +44,7 @@ module Info_retriever = let retrieve_info fun_lex file (s : string) = try - let _ = Odoc_comments_global.init () in + Odoc_comments_global.init (); Odoc_lexer.comments_level := 0; let lexbuf = Lexing.from_string s in match Odoc_parser.main fun_lex lexbuf with @@ -49,22 +52,21 @@ module Info_retriever = (0, None) | Some (desc, remain_opt) -> let mem_nb_chars = !Odoc_comments_global.nb_chars in - let _ = - match remain_opt with + begin match remain_opt with None -> () | Some s -> (*DEBUG*)print_string ("remain: "^s); print_newline(); let lexbuf2 = Lexing.from_string s in Odoc_parser.info_part2 Odoc_lexer.elements lexbuf2 - in + end; (mem_nb_chars, Some { i_desc = (match desc with "" -> None | _ -> Some (MyTexter.text_of_string desc)); i_authors = !Odoc_comments_global.authors; i_version = !Odoc_comments_global.version; - i_sees = (List.map create_see !Odoc_comments_global.sees) ; + i_sees = (List.map (create_see file) !Odoc_comments_global.sees) ; i_since = !Odoc_comments_global.since; i_before = Odoc_merge.merge_before_tags (List.map (fun (n, s) -> @@ -87,19 +89,16 @@ module Info_retriever = !Odoc_comments_global.customs) } ) - with - Failure s -> - incr Odoc_global.errors ; - Printf.eprintf "File %S, line %d:\n%s\n%!" file (!Odoc_lexer.line_number + 1) s; - (0, None) - | Odoc_text.Text_syntax (l, c, s) -> - incr Odoc_global.errors ; - prerr_endline (file^" : "^(Odoc_messages.text_parse_error l c s)); - (0, None) - | _ -> - incr Odoc_global.errors ; - prerr_endline (file^" : "^Odoc_messages.parse_error^"\n"); - (0, None) + with e -> + let (l, c, message) = match e with + | Failure s -> (!Odoc_lexer.line_number + 1, 0, s) + | Odoc_text.Text_syntax (l, c, s) -> (l, c, Odoc_messages.text_parse_error l c s) + | _other -> (0, 0, Odoc_messages.parse_error) + in begin + incr Odoc_global.errors; + prerr_endline (Odoc_messages.error_location file l c ^ message); + (0, None) + end (** This function takes a string where a simple comment may has been found. It returns false if there is a blank line or the first comment is a special one, or if there is @@ -141,7 +140,7 @@ module Info_retriever = retrieve_info Odoc_lexer.main file s let retrieve_info_simple file (s : string) = - let _ = Odoc_comments_global.init () in + Odoc_comments_global.init (); Odoc_lexer.comments_level := 0; let lexbuf = Lexing.from_string s in match Odoc_parser.main Odoc_lexer.simple lexbuf with diff --git a/ocamldoc/odoc_comments.mli b/ocamldoc/odoc_comments.mli index 6aeb91de..1b42fb15 100644 --- a/ocamldoc/odoc_comments.mli +++ b/ocamldoc/odoc_comments.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of comments. *) diff --git a/ocamldoc/odoc_comments_global.ml b/ocamldoc/odoc_comments_global.ml index 5fbe6406..abd7cd59 100644 --- a/ocamldoc/odoc_comments_global.ml +++ b/ocamldoc/odoc_comments_global.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The global variables used by the special comment parser.*) diff --git a/ocamldoc/odoc_comments_global.mli b/ocamldoc/odoc_comments_global.mli index 291673c0..6d1fa48a 100644 --- a/ocamldoc/odoc_comments_global.mli +++ b/ocamldoc/odoc_comments_global.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The global variables used by the special comment parser.*) diff --git a/ocamldoc/odoc_config.ml b/ocamldoc/odoc_config.ml index 4250f514..82ca4477 100644 --- a/ocamldoc/odoc_config.ml +++ b/ocamldoc/odoc_config.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) let custom_generators_path = Filename.concat Config.standard_library diff --git a/ocamldoc/odoc_config.mli b/ocamldoc/odoc_config.mli index 59ffc098..9ea9eede 100644 --- a/ocamldoc/odoc_config.mli +++ b/ocamldoc/odoc_config.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Ocamldoc configuration contants. *) diff --git a/ocamldoc/odoc_control.ml b/ocamldoc/odoc_control.ml index 30a1f393..d47351e9 100644 --- a/ocamldoc/odoc_control.ml +++ b/ocamldoc/odoc_control.ml @@ -1,11 +1,14 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) diff --git a/ocamldoc/odoc_cross.ml b/ocamldoc/odoc_cross.ml index 28e6ae5b..6949d339 100644 --- a/ocamldoc/odoc_cross.ml +++ b/ocamldoc/odoc_cross.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Cross referencing. *) @@ -465,7 +468,8 @@ and associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module and associate_in_module_element module_list m_name (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) element = match element with Element_module m -> associate_in_module module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) m - | Element_module_type mt -> associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) mt + | Element_module_type mt -> + associate_in_module_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) mt | Element_included_module im -> ( match im.im_module with @@ -492,9 +496,11 @@ and associate_in_module_element module_list m_name (acc_b_modif, acc_incomplete_ (true, acc_incomplete_top_module_names, acc_names_not_found) ) | Element_class cl -> associate_in_class module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) cl - | Element_class_type ct -> associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct + | Element_class_type ct -> + associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct | Element_value _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) - | Element_type_extension te -> associate_in_type_extension module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) te + | Element_type_extension te -> + associate_in_type_extension module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) te | Element_exception ex -> ( match ex.ex_alias with @@ -509,7 +515,9 @@ and associate_in_module_element module_list m_name (acc_b_modif, acc_incomplete_ with Not_found -> None in match ex_opt with - None -> (acc_b_modif, (Name.head m_name) :: acc_incomplete_top_module_names, (NF_ex ea.ea_name) :: acc_names_not_found) + None -> (acc_b_modif, + (Name.head m_name) :: acc_incomplete_top_module_names, + (NF_ex ea.ea_name) :: acc_names_not_found) | Some e -> ea.ea_ex <- Some e ; (true, acc_incomplete_top_module_names, acc_names_not_found) @@ -661,7 +669,9 @@ and associate_in_type_extension module_list (acc_b_modif, acc_incomplete_top_mod with Not_found -> None in match xt_opt with - None -> (acc_b_modif, (Name.head xt.xt_name) :: acc_incomplete_top_module_names, (NF_xt xa.xa_name) :: acc_names_not_found) + None -> (acc_b_modif, + (Name.head xt.xt_name) :: acc_incomplete_top_module_names, + (NF_xt xa.xa_name) :: acc_names_not_found) | Some x -> xa.xa_xt <- Some x ; (true, acc_incomplete_top_module_names, acc_names_not_found)) diff --git a/ocamldoc/odoc_cross.mli b/ocamldoc/odoc_cross.mli index 57fff657..ca0ad7dc 100644 --- a/ocamldoc/odoc_cross.mli +++ b/ocamldoc/odoc_cross.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Cross-referencing. *) diff --git a/ocamldoc/odoc_dag2html.ml b/ocamldoc/odoc_dag2html.ml index 74119e6e..834aa595 100644 --- a/ocamldoc/odoc_dag2html.ml +++ b/ocamldoc/odoc_dag2html.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The types and functions to create a html table representing a dag. Thanks to Daniel De Rauglaudre. *) @@ -938,14 +941,16 @@ let tablify phony no_optim no_group d = let t = {table = Array.append t.table [| Array.of_list new_row |]} in let t = if no_group && not (has_phony_children phony d t) then t - else - let _ = if no_optim then () else equilibrate t in - let _ = group_elem t in - let _ = group_ghost t in - let _ = group_children t in - let _ = group_span_by_common_children d t in + else begin + if no_optim then () else equilibrate t; + group_elem t; + group_ghost t; + group_children t; + group_span_by_common_children d t; let t = if no_optim then t else treat_gaps d t in - let _ = group_span_last_row t in t + group_span_last_row t; + t + end in loop t in @@ -1442,7 +1447,7 @@ let table_of_dag phony no_optim invert no_group d = let d = if invert then invert_dag d else d in let t = tablify phony no_optim no_group d in let t = if invert then invert_table t else t in - let _ = fall () t in + fall () t; let t = fall2_right t in let t = fall2_left t in let t = shorten_too_long t in diff --git a/ocamldoc/odoc_dag2html.mli b/ocamldoc/odoc_dag2html.mli index d59148c7..767c1ec3 100644 --- a/ocamldoc/odoc_dag2html.mli +++ b/ocamldoc/odoc_dag2html.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The types and functions to create a html table representing a dag. Thanks to Daniel de Rauglaudre. *) diff --git a/ocamldoc/odoc_dep.ml b/ocamldoc/odoc_dep.ml index c2949d73..ad750a04 100644 --- a/ocamldoc/odoc_dep.ml +++ b/ocamldoc/odoc_dep.ml @@ -1,18 +1,22 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Top modules dependencies. *) module StrS = Depend.StringSet +module StrM = Depend.StringMap module Module = Odoc_module module Type = Odoc_type @@ -23,12 +27,12 @@ let set_to_list s = let impl_dependencies ast = Depend.free_structure_names := StrS.empty; - Depend.add_use_file StrS.empty [Parsetree.Ptop_def ast]; + Depend.add_use_file StrM.empty [Parsetree.Ptop_def ast]; set_to_list !Depend.free_structure_names let intf_dependencies ast = Depend.free_structure_names := StrS.empty; - Depend.add_signature StrS.empty ast; + Depend.add_signature StrM.empty ast; set_to_list !Depend.free_structure_names @@ -48,8 +52,8 @@ module Dep = type node = { id : id ; - mutable near : S.t ; (** fils directs *) - mutable far : (id * S.t) list ; (** fils indirects, par quel fils *) + mutable near : S.t ; (** direct children *) + mutable far : (id * S.t) list ; (** indirect children, from which children path *) reflex : bool ; (** reflexive or not, we keep information here to remove the node itself from its direct children *) } @@ -77,7 +81,7 @@ module Dep = if S.mem n.id acc then acc else - (* optimisation plus tard : utiliser le champ far si non vide ? *) + (* potential optimisation: use far field if nonempty? *) S.fold (fun child -> fun acc2 -> trans_closure graph acc2 (get_node graph child)) @@ -147,41 +151,31 @@ let type_deps t = l := s2 :: !l ; s2 in + let ty t = + let s = Odoc_print.string_of_type_expr t in + ignore (Str.global_substitute re f s) + in (match t.T.ty_kind with T.Type_abstract -> () | T.Type_variant cl -> List.iter (fun c -> - List.iter - (fun e -> - let s = Odoc_print.string_of_type_expr e in - ignore (Str.global_substitute re f s) - ) - c.T.vc_args + match c.T.vc_args with + | T.Cstr_tuple l -> List.iter ty l + | T.Cstr_record l -> List.iter (fun r -> ty r.T.rf_type) l ) cl | T.Type_record rl -> - List.iter - (fun r -> - let s = Odoc_print.string_of_type_expr r.T.rf_type in - ignore (Str.global_substitute re f s) - ) - rl + List.iter (fun r -> ty r.T.rf_type) rl | T.Type_open -> () ); (match t.T.ty_manifest with None -> () | Some (T.Object_type fields) -> - List.iter - (fun r -> - let s = Odoc_print.string_of_type_expr r.T.of_type in - ignore (Str.global_substitute re f s) - ) - fields + List.iter (fun r -> ty r.T.of_type) fields | Some (T.Other e) -> - let s = Odoc_print.string_of_type_expr e in - ignore (Str.global_substitute re f s) + ty e ); !l @@ -208,22 +202,19 @@ let kernel_deps_of_modules modules = *) let deps_of_types ?(kernel=false) types = let deps_pre = List.map (fun t -> (t, type_deps t)) types in - let deps = - if kernel then - ( - let graph = List.map - (fun (t, names) -> Dep.make_node t.Type.ty_name names) - deps_pre - in - let k = Dep.kernel graph in - List.map - (fun t -> + if kernel then + ( + let graph = List.map + (fun (t, names) -> Dep.make_node t.Type.ty_name names) + deps_pre + in + let k = Dep.kernel graph in + List.map + (fun t -> let node = Dep.get_node k t.Type.ty_name in (t, Dep.set_to_list node.Dep.near) - ) - types - ) - else - deps_pre - in - deps + ) + types + ) + else + deps_pre diff --git a/ocamldoc/odoc_dot.ml b/ocamldoc/odoc_dot.ml index 60d6cd7e..75cf4c80 100644 --- a/ocamldoc/odoc_dot.ml +++ b/ocamldoc/odoc_dot.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Definition of a class which outputs a dot file showing top modules dependencies.*) diff --git a/ocamldoc/odoc_env.ml b/ocamldoc/odoc_env.ml index 3e059058..caa2999f 100644 --- a/ocamldoc/odoc_env.ml +++ b/ocamldoc/odoc_env.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Environment for finding complete names from relative names. *) @@ -55,7 +58,7 @@ let rec add_signature env root ?rel signat = | Types.Sig_typext (ident, _, _) -> { env with env_extensions = (rel_name ident, qualify ident) :: env.env_extensions } | Types.Sig_module (ident, md, _) -> let env2 = - match md.Types.md_type with (* A VOIR : le cas ou c'est un identificateur, dans ce cas on n'a pas de signature *) + match md.Types.md_type with (* FIXME: we don't have signature for identifiers *) Types.Mty_signature s -> add_signature env (qualify ident) ~rel: (rel_name ident) s | _ -> env in @@ -67,7 +70,7 @@ let rec add_signature env root ?rel signat = env | Some modtype -> match modtype with - (* A VOIR : le cas ou c'est un identificateur, dans ce cas on n'a pas de signature *) + (* FIXME: we don't have signature for identifiers *) Types.Mty_signature s -> add_signature env (qualify ident) ~rel: (rel_name ident) s | _ -> env in @@ -237,7 +240,7 @@ let subst_class_type env t = let new_ct = iter ct in Types.Cty_constr (new_p, new_texp_list, new_ct) | Types.Cty_signature cs -> - (* on ne s'occupe pas des vals et methods *) + (* we don't handle vals and methods *) t | Types.Cty_arrow (l, texp, ct) -> let new_texp = subst_type env texp in diff --git a/ocamldoc/odoc_env.mli b/ocamldoc/odoc_env.mli index 4e1e8606..16f5fb53 100644 --- a/ocamldoc/odoc_env.mli +++ b/ocamldoc/odoc_env.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Environment for finding complete names from relative names. *) diff --git a/ocamldoc/odoc_exception.ml b/ocamldoc/odoc_exception.ml index b0e21196..9cfeb279 100644 --- a/ocamldoc/odoc_exception.ml +++ b/ocamldoc/odoc_exception.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of exceptions. *) @@ -22,7 +25,7 @@ type exception_alias = { and t_exception = { ex_name : Name.t ; mutable ex_info : Odoc_types.info option ; (** optional user information *) - ex_args : Types.type_expr list ; (** the types of the parameters *) + ex_args : Odoc_type.constructor_args ; (** the types of the parameters *) ex_ret: Types.type_expr option ; (** the optional return type *) ex_alias : exception_alias option ; mutable ex_loc : Odoc_types.location ; diff --git a/ocamldoc/odoc_extension.ml b/ocamldoc/odoc_extension.ml index 0a084195..73ebfdda 100644 --- a/ocamldoc/odoc_extension.ml +++ b/ocamldoc/odoc_extension.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) - -(* $Id$ *) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of type extensions. *) @@ -25,7 +27,7 @@ type extension_alias = { and t_extension_constructor = { xt_name : Name.t ; - xt_args: Types.type_expr list ; (** the types of the parameters *) + xt_args: Odoc_type.constructor_args; xt_ret: Types.type_expr option ; (** the optional return type of the extension *) xt_type_extension: t_type_extension ; (** the type extension containing this constructor *) xt_alias: extension_alias option ; diff --git a/ocamldoc/odoc_gen.ml b/ocamldoc/odoc_gen.ml index a36ffbea..2ff122dd 100644 --- a/ocamldoc/odoc_gen.ml +++ b/ocamldoc/odoc_gen.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Gallium, 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 Q Public License version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Gallium, 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. *) +(* *) +(**************************************************************************) (** *) diff --git a/ocamldoc/odoc_gen.mli b/ocamldoc/odoc_gen.mli index 04987cf0..ba74da89 100644 --- a/ocamldoc/odoc_gen.mli +++ b/ocamldoc/odoc_gen.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Gallium, 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 Q Public License version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Gallium, 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. *) +(* *) +(**************************************************************************) (** The types of generators. *) diff --git a/ocamldoc/odoc_global.ml b/ocamldoc/odoc_global.ml index 9c3efb98..08f1c548 100644 --- a/ocamldoc/odoc_global.ml +++ b/ocamldoc/odoc_global.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Global variables. *) diff --git a/ocamldoc/odoc_global.mli b/ocamldoc/odoc_global.mli index 641d40c0..a3af6afe 100644 --- a/ocamldoc/odoc_global.mli +++ b/ocamldoc/odoc_global.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Global variables. *) diff --git a/ocamldoc/odoc_html.ml b/ocamldoc/odoc_html.ml index 9ed06c0f..c666afe9 100644 --- a/ocamldoc/odoc_html.ml +++ b/ocamldoc/odoc_html.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Generation of html documentation.*) @@ -168,8 +171,7 @@ module Naming = (** Return the complete filename for the code of the given value. *) let file_code_value_complete_target v = - let f = code_prefix^mark_value^(subst_infix_symbols v.val_name)^".html" in - f + code_prefix^mark_value^(subst_infix_symbols v.val_name)^".html" (** Return the link target for the given attribute. *) let attribute_target a = target mark_attribute (Name.simple a.att_value.val_name) @@ -179,8 +181,7 @@ module Naming = (** Return the complete filename for the code of the given attribute. *) let file_code_attribute_complete_target a = - let f = code_prefix^mark_attribute^a.att_value.val_name^".html" in - f + code_prefix^mark_attribute^a.att_value.val_name^".html" (** Return the link target for the given method. *) let method_target m = target mark_method (Name.simple m.met_value.val_name) @@ -190,8 +191,7 @@ module Naming = (** Return the complete filename for the code of the given method. *) let file_code_method_complete_target m = - let f = code_prefix^mark_method^m.met_value.val_name^".html" in - f + code_prefix^mark_method^m.met_value.val_name^".html" (** Return the link target for the given label section. *) let label_target l = target "" l @@ -202,20 +202,17 @@ module Naming = (** Return the complete filename for the code of the type of the given module or module type name. *) let file_type_module_complete_target name = - let f = type_prefix^name^".html" in - f + type_prefix^name^".html" (** Return the complete filename for the code of the given module name. *) let file_code_module_complete_target name = - let f = code_prefix^name^".html" in - f + code_prefix^name^".html" (** Return the complete filename for the code of the type of the given class or class type name. *) let file_type_class_complete_target name = - let f = type_prefix^name^".html" in - f + type_prefix^name^".html" end module StringSet = Set.Make (struct @@ -259,8 +256,7 @@ class virtual text = method label_of_text t= let t2 = Odoc_info.first_sentence_of_text t in let s = Odoc_info.string_of_text t2 in - let s2 = self#keep_alpha_num s in - s2 + self#keep_alpha_num s (** Create a label for the associated title. Return the label specified by the user or a label created @@ -307,7 +303,7 @@ class virtual text = method html_of_custom_text b s t = () method html_of_Target b ~target ~code = - if String.lowercase target = "html" then bs b code else () + if String.lowercase_ascii target = "html" then bs b code else () method html_of_Raw b s = bs b (self#escape s) @@ -791,8 +787,6 @@ class html = val mutable default_style_options = [ ".keyword { font-weight : bold ; color : Red }" ; ".keywordsign { color : #C04600 }" ; - ".superscript { font-size : 4 }" ; - ".subscript { font-size : 4 }" ; ".comment { color : Green }" ; ".constructor { color : Blue }" ; ".type { color : #5C6585 }" ; @@ -1178,12 +1172,10 @@ class html = else s_final in - let s2 = Str.global_substitute - (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)") - f - s - in - s2 + Str.global_substitute + (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)") + f + s (** Take a string and return the string where fully qualified module idents have been replaced by links to the module referenced by the ident.*) @@ -1202,12 +1194,10 @@ class html = else s_final in - let s2 = Str.global_substitute - (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\)\\(\\.[A-Z][a-zA-Z_'0-9]*\\)*") - f - s - in - s2 + Str.global_substitute + (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\)\\(\\.[A-Z][a-zA-Z_'0-9]*\\)*") + f + s (** Print html code to display a [Types.type_expr]. *) method html_of_type_expr b m_name t = @@ -1218,12 +1208,18 @@ class html = bs b "" (** Print html code to display a [Types.type_expr list]. *) - method html_of_type_expr_list ?par b m_name sep l = - print_DEBUG "html#html_of_type_expr_list"; - let s = Odoc_info.string_of_type_list ?par sep l in - print_DEBUG "html#html_of_type_expr_list: 1"; + method html_of_cstr_args ?par b m_name sep l = + print_DEBUG "html#html_of_cstr_args"; + let s = + match l with + | Cstr_tuple l -> + Odoc_info.string_of_type_list ?par sep l + | Cstr_record l -> + Odoc_info.string_of_record l + in + print_DEBUG "html#html_of_cstr_args: 1"; let s2 = newline_to_indented_br s in - print_DEBUG "html#html_of_type_expr_list: 2"; + print_DEBUG "html#html_of_cstr_args: 2"; bs b ""; bs b (self#create_fully_qualified_idents_links m_name s2); bs b "" @@ -1297,8 +1293,8 @@ class html = if not !html_short_functors then bs b "" | Module_apply (k1, k2) -> - (* TODO: l'application n'est pas correcte dans un .mli. - Que faire ? -> afficher le module_type du typedtree *) + (* TODO: application is not correct in a .mli. + What to do -> print typedtree module_type *) self#html_of_module_kind b father k1; self#html_of_text b [Code "("]; self#html_of_module_kind b father k2; @@ -1310,7 +1306,7 @@ class html = bs b (self#create_fully_qualified_module_idents_links father s); bs b "" | Module_constraint (k, tk) -> - (* TODO: on affiche quoi ? *) + (* TODO: what to print ? *) self#html_of_module_kind b father ?modu k | Module_typeof s -> bs b "module type of "; @@ -1478,16 +1474,16 @@ class html = (Name.simple x.xt_name); ( match x.xt_args, x.xt_ret with - [], None -> () + Cstr_tuple [], None -> () | l,None -> bs b (" " ^ (self#keyword "of") ^ " "); - self#html_of_type_expr_list ~par: false b father " * " l; - | [],Some r -> + self#html_of_cstr_args ~par: false b father " * " l; + | Cstr_tuple [],Some r -> bs b (" " ^ (self#keyword ":") ^ " "); self#html_of_type_expr b father r; | l,Some r -> bs b (" " ^ (self#keyword ":") ^ " "); - self#html_of_type_expr_list ~par: false b father " * " l; + self#html_of_cstr_args ~par: false b father " * " l; bs b (" " ^ (self#keyword "->") ^ " "); self#html_of_type_expr b father r; ); @@ -1539,17 +1535,17 @@ class html = bs b ""; ( match e.ex_args, e.ex_ret with - [], None -> () + Cstr_tuple [], None -> () | l,None -> bs b (" "^(self#keyword "of")^" "); - self#html_of_type_expr_list + self#html_of_cstr_args ~par: false b (Name.father e.ex_name) " * " e.ex_args - | [],Some r -> + | Cstr_tuple [],Some r -> bs b (" " ^ (self#keyword ":") ^ " "); self#html_of_type_expr b (Name.father e.ex_name) r; | l,Some r -> bs b (" " ^ (self#keyword ":") ^ " "); - self#html_of_type_expr_list + self#html_of_cstr_args ~par: false b (Name.father e.ex_name) " * " l; bs b (" " ^ (self#keyword "->") ^ " "); self#html_of_type_expr b (Name.father e.ex_name) r; @@ -1659,16 +1655,16 @@ class html = (self#constructor constr.vc_name); ( match constr.vc_args, constr.vc_ret with - [], None -> () + Cstr_tuple [], None -> () | l,None -> bs b (" " ^ (self#keyword "of") ^ " "); - self#html_of_type_expr_list ~par: false b father " * " l; - | [],Some r -> + self#html_of_cstr_args ~par: false b father " * " l; + | Cstr_tuple [],Some r -> bs b (" " ^ (self#keyword ":") ^ " "); self#html_of_type_expr b father r; | l,Some r -> bs b (" " ^ (self#keyword ":") ^ " "); - self#html_of_type_expr_list ~par: false b father " * " l; + self#html_of_cstr_args ~par: false b father " * " l; bs b (" " ^ (self#keyword "->") ^ " "); self#html_of_type_expr b father r; ); @@ -2306,7 +2302,7 @@ class html = [] -> () | e :: _ -> let s = - match (Char.uppercase (Name.simple (name e)).[0]) with + match (Char.uppercase_ascii (Name.simple (name e)).[0]) with 'A'..'Z' as c -> String.make 1 c | _ -> "" in diff --git a/ocamldoc/odoc_info.ml b/ocamldoc/odoc_info.ml index c576e100..19d04314 100644 --- a/ocamldoc/odoc_info.ml +++ b/ocamldoc/odoc_info.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Interface for analysing documented OCaml source files and to the collected information. *) @@ -143,6 +146,7 @@ let string_of_text t = Odoc_misc.string_of_text t let string_of_info i = Odoc_misc.string_of_info i let string_of_type t = Odoc_str.string_of_type t +let string_of_record t = Odoc_str.string_of_record t let string_of_type_extension te = Odoc_str.string_of_type_extension te diff --git a/ocamldoc/odoc_info.mli b/ocamldoc/odoc_info.mli index e9a9705c..f0146472 100644 --- a/ocamldoc/odoc_info.mli +++ b/ocamldoc/odoc_info.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Interface to the information collected in source files. *) @@ -187,7 +190,7 @@ module Extension : and t_extension_constructor = Odoc_extension.t_extension_constructor = { xt_name : Name.t ; - xt_args: Types.type_expr list ; (** the types of the parameters *) + xt_args: Odoc_type.constructor_args; xt_ret: Types.type_expr option ; (** the optional return type of the extension *) xt_type_extension: t_type_extension ; (** the type extension containing this constructor *) xt_alias: extension_alias option ; (** [None] when the extension is not a rebind. *) @@ -226,7 +229,7 @@ module Exception : { ex_name : Name.t ; mutable ex_info : info option ; (** Information found in the optional associated comment. *) - ex_args : Types.type_expr list ; (** The types of the parameters. *) + ex_args : Odoc_type.constructor_args; ex_ret : Types.type_expr option ; (** The the optional return type of the exception. *) ex_alias : exception_alias option ; (** [None] when the exception is not a rebind. *) mutable ex_loc : location ; @@ -240,15 +243,6 @@ module Type : type private_flag = Odoc_type.private_flag = Private | Public - (** Description of a variant type constructor. *) - type variant_constructor = Odoc_type.variant_constructor = - { - vc_name : string ; (** Name of the constructor. *) - vc_args : Types.type_expr list ; (** Arguments of the constructor. *) - vc_ret : Types.type_expr option ; - mutable vc_text : info option ; (** Optional description in the associated comment. *) - } - (** Description of a record type field. *) type record_field = Odoc_type.record_field = { @@ -258,6 +252,19 @@ module Type : mutable rf_text : info option ; (** Optional description in the associated comment.*) } + (** Description of a variant type constructor. *) + type constructor_args = Odoc_type.constructor_args = + | Cstr_record of record_field list + | Cstr_tuple of Types.type_expr list + + type variant_constructor = Odoc_type.variant_constructor = + { + vc_name : string ; (** Name of the constructor. *) + vc_args : constructor_args; + vc_ret : Types.type_expr option ; + mutable vc_text : info option ; (** Optional description in the associated comment. *) + } + (** The various kinds of a type. *) type type_kind = Odoc_type.type_kind = Type_abstract (** Type is abstract, for example [type t]. *) @@ -400,7 +407,7 @@ module Class : { cta_name : Name.t ; (** Complete name of the target class type. *) mutable cta_class : cct option ; (** The target t_class or t_class_type, if we found it.*) - cta_type_parameters : Types.type_expr list ; (** The type parameters. A VOIR : mettre des string ? *) + cta_type_parameters : Types.type_expr list ; (** The type parameters. FIXME : use strings? *) } and class_type_kind = Odoc_class.class_type_kind = @@ -721,6 +728,8 @@ val string_of_info : info -> string (** @return a string to describe the given type. *) val string_of_type : Type.t_type -> string +val string_of_record : Type.record_field list -> string + (** @return a string to describe the given type extension. *) val string_of_type_extension : Extension.t_type_extension -> string @@ -774,11 +783,11 @@ val create_index_lists : 'a list -> ('a -> string) -> 'a list list val remove_option : Types.type_expr -> Types.type_expr (** Return [true] if the given label is optional.*) -val is_optional : string -> bool +val is_optional : Asttypes.arg_label -> bool (** Return the label name for the given label, i.e. removes the beginning '?' if present.*) -val label_name : string -> string +val label_name : Asttypes.arg_label -> string (** Return the given name where the module name or part of it was removed, according to the list of modules diff --git a/ocamldoc/odoc_inherit.ml b/ocamldoc/odoc_inherit.ml index 30a1f393..d47351e9 100644 --- a/ocamldoc/odoc_inherit.ml +++ b/ocamldoc/odoc_inherit.ml @@ -1,11 +1,14 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) diff --git a/ocamldoc/odoc_latex.ml b/ocamldoc/odoc_latex.ml index d0ef4310..10a10ada 100644 --- a/ocamldoc/odoc_latex.ml +++ b/ocamldoc/odoc_latex.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Generation of LaTeX documentation. *) @@ -293,7 +296,7 @@ class text = method latex_of_custom_text fmt s t = () method latex_of_Target fmt ~target ~code = - if String.lowercase target = "latex" then + if String.lowercase_ascii target = "latex" then self#latex_of_Latex fmt code else () @@ -599,16 +602,16 @@ class latex = let s_cons = p fmt2 "@[ | %s" constr.vc_name ; begin match constr.vc_args, constr.vc_ret with - | [], None -> () + | Cstr_tuple [], None -> () | l, None -> p fmt2 " of@ %s" - (self#normal_type_list ~par: false mod_name " * " l) - | [], Some r -> + (self#normal_cstr_args ~par: false mod_name l) + | Cstr_tuple [], Some r -> p fmt2 " :@ %s" (self#normal_type mod_name r) | l, Some r -> p fmt2 " :@ %s@ %s@ %s" - (self#normal_type_list ~par: false mod_name " * " l) + (self#normal_cstr_args ~par: false mod_name l) "->" (self#normal_type mod_name r) end ; @@ -682,19 +685,19 @@ class latex = p fmt2 "@[ | %s" (Name.simple x.xt_name); ( match x.xt_args, x.xt_ret with - [], None -> () + Cstr_tuple [], None -> () | l, None -> p fmt2 " %s@ %s" "of" - (self#normal_type_list ~par: false father " * " l) - | [], Some r -> + (self#normal_cstr_args ~par: false father l) + | Cstr_tuple [], Some r -> p fmt2 " %s@ %s" ":" (self#normal_type father r) | l, Some r -> p fmt2 " %s@ %s@ %s@ %s" ":" - (self#normal_type_list ~par: false father " * " l) + (self#normal_cstr_args ~par: false father l) "->" (self#normal_type father r) ); @@ -798,21 +801,21 @@ class latex = self#latex_of_module_parameter fmt father p; self#latex_of_module_kind fmt father k | Module_apply (k1, k2) -> - (* TODO: l'application n'est pas correcte dans un .mli. - Que faire ? -> afficher le module_type du typedtree *) + (* TODO: application is not correct in a .mli. + Fix? -> print the typedtree module_type *) self#latex_of_module_kind fmt father k1; self#latex_of_text fmt [Code "("]; self#latex_of_module_kind fmt father k2; self#latex_of_text fmt [Code ")"] | Module_with (k, s) -> - (* TODO: a modifier quand Module_with sera plus detaille *) + (* TODO: modify when Module_with will be more detailled *) self#latex_of_module_type_kind fmt father k; self#latex_of_text fmt [ Code " "; Code (self#relative_idents father s) ; ] | Module_constraint (k, tk) -> - (* TODO: on affiche quoi ? *) + (* TODO: what should we print? *) self#latex_of_module_kind fmt father k | Module_typeof s -> self#latex_of_text fmt @@ -834,7 +837,7 @@ class latex = self#latex_of_text fmt [Latex "\\end{ocamldocobjectend}\n"] | Class_apply capp -> - (* TODO: afficher le type final a partir du typedtree *) + (* TODO: print final type from typedtree *) self#latex_of_text fmt [Raw "class application not handled yet"] | Class_constr cco -> diff --git a/ocamldoc/odoc_latex_style.ml b/ocamldoc/odoc_latex_style.ml index 713e72e8..e3453e2e 100644 --- a/ocamldoc/odoc_latex_style.ml +++ b/ocamldoc/odoc_latex_style.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The content of the LaTeX style to generate when generating LaTeX code. *) diff --git a/ocamldoc/odoc_lexer.mll b/ocamldoc/odoc_lexer.mll index 998d31bd..8749d123 100644 --- a/ocamldoc/odoc_lexer.mll +++ b/ocamldoc/odoc_lexer.mll @@ -1,14 +1,18 @@ { -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The lexer for special comments. *) @@ -20,16 +24,16 @@ let line_number = ref 0 let string_buffer = Buffer.create 32 -(** Fonction de remise a zero de la chaine de caracteres tampon *) +(** Reset the buffer *) let reset_string_buffer () = Buffer.reset string_buffer -(** Fonction d'ajout d'un caractere dans la chaine de caracteres tampon *) -let ajout_char_string = Buffer.add_char string_buffer +(** Add a character to the buffer *) +let add_char_string = Buffer.add_char string_buffer (** Add a string to the buffer. *) -let ajout_string = Buffer.add_string string_buffer +let add_string = Buffer.add_string string_buffer -let lecture_string () = Buffer.contents string_buffer +let read_string () = Buffer.contents string_buffer (** The variable which will contain the description string. Is initialized when we encounter the start of a special comment. *) @@ -87,8 +91,7 @@ let remove_blanks s = (** Remove first blank characters of each line of a string, until the first '*' *) let remove_stars s = - let s2 = Str.global_replace (Str.regexp ("^"^blank^"*\\*")) "" s in - s2 + Str.global_replace (Str.regexp ("^"^blank^"*\\*")) "" s } let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_'] @@ -173,7 +176,7 @@ and special_comment = parse if !comments_level = 1 then ( (* there is just a description *) - let s2 = lecture_string () in + let s2 = read_string () in let s3 = remove_blanks s2 in let s4 = if !Odoc_global.remove_stars then @@ -185,7 +188,7 @@ and special_comment = parse ) else ( - ajout_string s; + add_string s; decr comments_level; special_comment lexbuf ) @@ -196,7 +199,7 @@ and special_comment = parse let s = Lexing.lexeme lexbuf in Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s); incr comments_level ; - ajout_string s; + add_string s; special_comment lexbuf } @@ -204,7 +207,7 @@ and special_comment = parse { let s = Lexing.lexeme lexbuf in let c = (Lexing.lexeme_char lexbuf 1) in - ajout_char_string c; + add_char_string c; Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s); special_comment lexbuf } @@ -212,7 +215,7 @@ and special_comment = parse | "@"lowercase+ { (* we keep the description before we go further *) - let s = lecture_string () in + let s = read_string () in description := remove_blanks s; reset_string_buffer (); let len = String.length (Lexing.lexeme lexbuf) in @@ -228,7 +231,7 @@ and special_comment = parse | _ { let c = (Lexing.lexeme_char lexbuf 0) in - ajout_char_string c; + add_char_string c; if c = '\010' then incr line_number; incr Odoc_comments_global.nb_chars; special_comment lexbuf @@ -247,7 +250,7 @@ and special_comment_part2 = parse else !description in - let remain = lecture_string () in + let remain = read_string () in let remain2 = if !Odoc_global.remove_stars then remove_stars remain @@ -257,7 +260,7 @@ and special_comment_part2 = parse Description (desc, Some remain2) else ( - ajout_string s ; + add_string s ; decr comments_level ; special_comment_part2 lexbuf ) @@ -267,7 +270,7 @@ and special_comment_part2 = parse { let s = Lexing.lexeme lexbuf in Odoc_comments_global.nb_chars := !Odoc_comments_global.nb_chars + (String.length s); - ajout_string s; + add_string s; incr comments_level ; special_comment_part2 lexbuf } @@ -275,7 +278,7 @@ and special_comment_part2 = parse | _ { let c = (Lexing.lexeme_char lexbuf 0) in - ajout_char_string c; + add_char_string c; if c = '\010' then incr line_number; incr Odoc_comments_global.nb_chars; special_comment_part2 lexbuf @@ -396,7 +399,7 @@ and simple = parse ) else ( - ajout_string s; + add_string s; simple lexbuf ) } diff --git a/ocamldoc/odoc_man.ml b/ocamldoc/odoc_man.ml index e97db4bc..79ee5b17 100644 --- a/ocamldoc/odoc_man.ml +++ b/ocamldoc/odoc_man.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The man pages generator. *) open Odoc_info @@ -340,7 +343,7 @@ class man = method man_of_custom_text b s t = () method man_of_Target b ~target ~code = - if String.lowercase target = "man" then bs b code else () + if String.lowercase_ascii target = "man" then bs b code else () (** Print groff string to display code. *) method man_of_code b s = self#man_of_text b [ Code s ] @@ -355,12 +358,10 @@ class man = match_s (Name.get_relative m_name match_s) in - let s2 = Str.global_substitute - (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)") - f - s - in - s2 + Str.global_substitute + (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)") + f + s (** Print groff string to display a [Types.type_expr].*) method man_of_type_expr b m_name t = @@ -383,8 +384,14 @@ class man = bs b "\n" (** Print groff string to display a [Types.type_expr list].*) - method man_of_type_expr_list ?par b m_name sep l = - let s = Odoc_str.string_of_type_list ?par sep l in + method man_of_cstr_args ?par b m_name sep l = + let s = + match l with + | Cstr_tuple l -> + Odoc_str.string_of_type_list ?par sep l + | Cstr_record l -> + Odoc_str.string_of_record l + in let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in bs b "\n.B "; bs b (self#relative_idents m_name s2); @@ -448,16 +455,16 @@ class man = bs b ("| "^(Name.simple x.xt_name)); ( match x.xt_args, x.xt_ret with - | [], None -> bs b "\n" + | Cstr_tuple [], None -> bs b "\n" | l, None -> bs b "\n.B of "; - self#man_of_type_expr_list ~par: false b father " * " l; - | [], Some r -> + self#man_of_cstr_args ~par: false b father " * " l; + | Cstr_tuple [], Some r -> bs b "\n.B : "; self#man_of_type_expr b father r; | l, Some r -> bs b "\n.B : "; - self#man_of_type_expr_list ~par: false b father " * " l; + self#man_of_cstr_args ~par: false b father " * " l; bs b ".B -> "; self#man_of_type_expr b father r; ); @@ -498,18 +505,18 @@ class man = bs b " \n"; ( match e.ex_args, e.ex_ret with - | [], None -> () + | Cstr_tuple [], None -> () | l, None -> bs b ".B of "; - self#man_of_type_expr_list + self#man_of_cstr_args ~par: false b (Name.father e.ex_name) " * " e.ex_args - | [], Some r -> + | Cstr_tuple [], Some r -> bs b ".B : "; self#man_of_type_expr b (Name.father e.ex_name) r | l, Some r -> bs b ".B : "; - self#man_of_type_expr_list + self#man_of_cstr_args ~par: false b (Name.father e.ex_name) " * " l; bs b ".B -> "; @@ -586,36 +593,36 @@ class man = bs b " *)\n " in match constr.vc_args, constr.vc_text,constr.vc_ret with - | [], None, None -> bs b "\n " - | [], (Some t), None -> + | Cstr_tuple [], None, None -> bs b "\n " + | Cstr_tuple [], (Some t), None -> print_text t | l, None, None -> bs b "\n.B of "; - self#man_of_type_expr_list ~par: false b father " * " l; + self#man_of_cstr_args ~par: false b father " * " l; bs b " " | l, (Some t), None -> bs b "\n.B of "; - self#man_of_type_expr_list ~par: false b father " * " l; + self#man_of_cstr_args ~par: false b father " * " l; bs b ".I \" \"\n"; print_text t - | [], None, Some r -> + | Cstr_tuple [], None, Some r -> bs b "\n.B : "; self#man_of_type_expr b father r; bs b " " - | [], (Some t), Some r -> + | Cstr_tuple [], (Some t), Some r -> bs b "\n.B : "; self#man_of_type_expr b father r; bs b ".I \" \"\n"; print_text t | l, None, Some r -> bs b "\n.B : "; - self#man_of_type_expr_list ~par: false b father " * " l; + self#man_of_cstr_args ~par: false b father " * " l; bs b ".B -> "; self#man_of_type_expr b father r; bs b " " | l, (Some t), Some r -> bs b "\n.B of "; - self#man_of_type_expr_list ~par: false b father " * " l; + self#man_of_cstr_args ~par: false b father " * " l; bs b ".B -> "; self#man_of_type_expr b father r; bs b ".I \" \"\n"; @@ -822,8 +829,8 @@ class man = bs b ".I "; bs b (c.vc_name^" "); (match c.vc_args with - [] -> () - | h::q -> + | Cstr_tuple [] -> () + | Cstr_tuple (h::q) -> bs b "of "; self#man_of_type_expr b modname h; List.iter @@ -831,6 +838,7 @@ class man = bs b " * "; self#man_of_type_expr b modname ty) q + | Cstr_record _ -> bs b "{ ... }" ); bs b "\n.sp\n"; self#man_of_info b c.vc_text; @@ -857,14 +865,13 @@ class man = (** Generate the man page for the given class.*) method generate_for_class cl = Odoc_info.reset_type_names () ; - let date = Unix.time () in let file = self#file_name cl.cl_name in try let chanout = self#open_out file in let b = new_buf () in bs b (".TH \""^cl.cl_name^"\" "); bs b !man_section ; - bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" "); + bs b (" source: "^Odoc_misc.current_date^" "); bs b "OCamldoc "; bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n"); @@ -916,14 +923,13 @@ class man = (** Generate the man page for the given class type.*) method generate_for_class_type ct = Odoc_info.reset_type_names () ; - let date = Unix.time () in let file = self#file_name ct.clt_name in try let chanout = self#open_out file in let b = new_buf () in bs b (".TH \""^ct.clt_name^"\" "); bs b !man_section ; - bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" "); + bs b (" source: "^Odoc_misc.current_date^" "); bs b "OCamldoc "; bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n"); @@ -1009,14 +1015,13 @@ class man = (** Generate the man file for the given module type. @raise Failure if an error occurs.*) method generate_for_module_type mt = - let date = Unix.time () in let file = self#file_name mt.mt_name in try let chanout = self#open_out file in let b = new_buf () in bs b (".TH \""^mt.mt_name^"\" "); bs b !man_section ; - bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" "); + bs b (" source: "^Odoc_misc.current_date^" "); bs b "OCamldoc "; bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n"); @@ -1092,14 +1097,13 @@ class man = (** Generate the man file for the given module. @raise Failure if an error occurs.*) method generate_for_module m = - let date = Unix.time () in let file = self#file_name m.m_name in try let chanout = self#open_out file in let b = new_buf () in bs b (".TH \""^m.m_name^"\" "); bs b !man_section ; - bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" "); + bs b (" source: "^Odoc_misc.current_date^" "); bs b "OCamldoc "; bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n"); @@ -1199,14 +1203,13 @@ class man = | Res_const (_,f) -> f.vc_name ) in - let date = Unix.time () in let file = self#file_name name in try let chanout = self#open_out file in let b = new_buf () in bs b (".TH \""^name^"\" "); bs b !man_section ; - bs b (" "^(Odoc_misc.string_of_date ~hour: false date)^" "); + bs b (" source: "^Odoc_misc.current_date^" "); bs b "OCamldoc "; bs b ("\""^(match !Global.title with Some t -> t | None -> "")^"\"\n"); bs b ".SH NAME\n"; @@ -1277,7 +1280,7 @@ class man = self#man_of_module_type_body b mt | Res_section _ -> - (* normalement on ne peut pas avoir de module ici. *) + (* normaly, we cannot have modules here. *) () in List.iter f l; diff --git a/ocamldoc/odoc_merge.ml b/ocamldoc/odoc_merge.ml index 443cc3d8..9a981e00 100644 --- a/ocamldoc/odoc_merge.ml +++ b/ocamldoc/odoc_merge.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Merge of information from [.ml] and [.mli] for a module.*) diff --git a/ocamldoc/odoc_merge.mli b/ocamldoc/odoc_merge.mli index 2b6b857b..8614ecfc 100644 --- a/ocamldoc/odoc_merge.mli +++ b/ocamldoc/odoc_merge.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Merge of information from [.ml] and [.mli] for a module.*) diff --git a/ocamldoc/odoc_messages.ml b/ocamldoc/odoc_messages.ml index 0ac45ba9..762e2666 100644 --- a/ocamldoc/odoc_messages.ml +++ b/ocamldoc/odoc_messages.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The messages of the application. *) @@ -233,6 +236,9 @@ let help = " Display this list of options" let warning = "Warning" +let error_location file l c = + Printf.sprintf "File \"%s\", line %d, character %d:\n" file l c + let bad_magic_number = "Bad magic number for this ocamldoc dump!\n"^ "This dump was not created by this version of OCamldoc." @@ -244,10 +250,7 @@ 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 - "Syntax error in text:\n"^s^"\n"^ - "line "^(string_of_int l)^", character "^(string_of_int c)^":\n"^ - (List.nth lines l)^"\n"^ - (String.make c ' ')^"^" + (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" @@ -255,7 +258,8 @@ let file_not_found_in_paths paths name = (String.concat "\n" paths) let tag_not_handled tag = "Tag @"^tag^" not handled by this generator" -let should_escape_at_sign = "The character @ has a special meaning in ocamldoc comments, for commands such as @raise or @since. If you want to write a single @, you must escape it as \\@." +let should_escape_at_sign = "The character @ has a special meaning in ocamldoc comments, for commands such as @raise or @since. \ +If you want to write a single @, you must escape it as \\@." let bad_tree = "Incorrect tree structure." let not_a_valid_tag s = s^" is not a valid tag." let fun_without_param f = "Function "^f^" has no parameter.";; @@ -293,7 +297,8 @@ let module_type_not_found_in_typedtree mt = "Module type "^mt^" was not found in let module_not_found_in_typedtree m = "Module "^m^" was not found in typed tree." let class_not_found_in_typedtree c = "Class "^c^" was not found in typed tree." let class_type_not_found_in_typedtree ct = "Class type "^ct^" was not found in typed tree." -let inherit_classexp_not_found_in_typedtree n = "Inheritance class expression number "^(string_of_int n)^" was not found in typed tree." +let inherit_classexp_not_found_in_typedtree n = + "Inheritance class expression number "^(string_of_int n)^" was not found in typed tree." let attribute_not_found_in_typedtree att = "Class attribute "^att^" was not found in typed tree." let method_not_found_in_typedtree met = "Class method "^met^" was not found in typed tree." let misplaced_comment file pos = diff --git a/ocamldoc/odoc_misc.ml b/ocamldoc/odoc_misc.ml index e938dbe6..a95c2a9f 100644 --- a/ocamldoc/odoc_misc.ml +++ b/ocamldoc/odoc_misc.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) let no_blanks s = let len = String.length s in @@ -223,9 +226,9 @@ let apply_opt f v_opt = None -> None | Some v -> Some (f v) -let string_of_date ?(hour=true) d = +let string_of_date ?(absolute=false) ?(hour=true) d = let add_0 s = if String.length s < 2 then "0"^s else s in - let t = Unix.localtime d in + let t = (if absolute then Unix.gmtime else Unix.localtime) d in (string_of_int (t.Unix.tm_year + 1900))^"-"^ (add_0 (string_of_int (t.Unix.tm_mon + 1)))^"-"^ (add_0 (string_of_int t.Unix.tm_mday))^ @@ -238,6 +241,14 @@ let string_of_date ?(hour=true) d = "" ) +let current_date = + let time = + try + float_of_string (Sys.getenv "SOURCE_DATE_EPOCH") + with + Not_found -> Unix.time () + in string_of_date ~absolute: true ~hour: false time + let rec text_list_concat sep l = match l with @@ -333,7 +344,7 @@ let rec get_before_dot s = let len = String.length s in let n = String.index s '.' in if n + 1 >= len then - (* le point est le dernier caractere *) + (* The dot is the last character *) (true, s, "") else match s.[n+1] with @@ -454,7 +465,7 @@ let create_index_lists elements string_of_ele = match s with "" -> f current acc0 acc1 (acc2 @ [ele]) q | _ -> - let first = Char.uppercase s.[0] in + let first = Char.uppercase_ascii s.[0] in match first with 'A' .. 'Z' -> if current = first then diff --git a/ocamldoc/odoc_misc.mli b/ocamldoc/odoc_misc.mli index 5958be91..03918f8a 100644 --- a/ocamldoc/odoc_misc.mli +++ b/ocamldoc/odoc_misc.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Miscellaneous functions *) @@ -62,7 +65,12 @@ val apply_opt : ('a -> 'b) -> 'a option -> 'b option (** Return a string representing a date given as a number of seconds since 1970. The hour is optionnaly displayed. *) -val string_of_date : ?hour:bool -> float -> string +val string_of_date : ?absolute:bool -> ?hour:bool -> float -> string + +(* Value returned by string_of_date for current time. + * Uses environment variable SOURCE_DATE_EPOCH if set; falls back to + * current timestamp otherwise. *) +val current_date : string (** Return the first sentence (until the first dot) of a text. Don't stop in the middle of [Code], [Verbatim], [List], [Lnum], @@ -107,8 +115,8 @@ val search_string_backward : pat: string -> s: string -> int val remove_option : Types.type_expr -> Types.type_expr (** Return [true] if the given label is optional.*) -val is_optional : string -> bool +val is_optional : Asttypes.arg_label -> bool (** Return the label name for the given label, i.e. removes the beginning '?' if present.*) -val label_name : string -> string +val label_name : Asttypes.arg_label -> string diff --git a/ocamldoc/odoc_module.ml b/ocamldoc/odoc_module.ml index 9ed2b177..5c8cafbc 100644 --- a/ocamldoc/odoc_module.ml +++ b/ocamldoc/odoc_module.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of modules and module types. *) @@ -245,7 +248,7 @@ let rec module_elements ?(trans=true) m = } | Module_constraint (k, tk) -> print_DEBUG "Odoc_module.module_element: Module_constraint"; - (* A VOIR : utiliser k ou tk ? *) + (* FIXME : use k or tk ? *) module_elements ~trans: trans { m_name = "" ; m_info = None ; diff --git a/ocamldoc/odoc_name.ml b/ocamldoc/odoc_name.ml index 296331ad..f6d5b7e4 100644 --- a/ocamldoc/odoc_name.ml +++ b/ocamldoc/odoc_name.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation of element names. *) @@ -28,6 +31,7 @@ let infix_chars = [ '|' ; ':' ; '~' ; '!' ; + '.' ; '#' ; ] diff --git a/ocamldoc/odoc_name.mli b/ocamldoc/odoc_name.mli index 9c0e51ec..2ca47a80 100644 --- a/ocamldoc/odoc_name.mli +++ b/ocamldoc/odoc_name.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation of element names. *) diff --git a/ocamldoc/odoc_ocamlhtml.mll b/ocamldoc/odoc_ocamlhtml.mll index 975229da..56b94afd 100644 --- a/ocamldoc/odoc_ocamlhtml.mll +++ b/ocamldoc/odoc_ocamlhtml.mll @@ -1,15 +1,18 @@ - { -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Generation of html code to display OCaml code. *) open Lexing @@ -37,7 +40,6 @@ let base_escape_strings = [ let pre_escape_strings = [ (" ", " ") ; - ("\n", "
    \n") ; ("\t", "        ") ; ] @@ -199,8 +201,7 @@ let string_buffer = Buffer.create 32 let reset_string_buffer () = Buffer.reset string_buffer let store_string_char = Buffer.add_char string_buffer let get_stored_string () = - let s = Buffer.contents string_buffer in - s + Buffer.contents string_buffer (** To translate escape sequences *) @@ -518,7 +519,7 @@ let html_of_code b ?(with_pre=true) code = try print ~esc: false start ; let lexbuf = Lexing.from_string code in - let _ = token lexbuf in + token lexbuf; print ~esc: false ending ; Format.pp_print_flush !fmt () ; Buffer.contents buf diff --git a/ocamldoc/odoc_parameter.ml b/ocamldoc/odoc_parameter.ml index be98ef41..6775b884 100644 --- a/ocamldoc/odoc_parameter.ml +++ b/ocamldoc/odoc_parameter.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of method / function / class parameters. *) diff --git a/ocamldoc/odoc_parser.mly b/ocamldoc/odoc_parser.mly index ea7d9a57..faa98c87 100644 --- a/ocamldoc/odoc_parser.mly +++ b/ocamldoc/odoc_parser.mly @@ -1,14 +1,18 @@ %{ -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open Odoc_types open Odoc_comments_global diff --git a/ocamldoc/odoc_print.ml b/ocamldoc/odoc_print.ml index 56a85e5f..4ff1b29a 100644 --- a/ocamldoc/odoc_print.ml +++ b/ocamldoc/odoc_print.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open Format @@ -78,8 +81,8 @@ let simpl_class_type t = match t with Types.Cty_constr (p,texp_list,ct) -> t | Types.Cty_signature cs -> - (* on vire les vals et methods pour ne pas qu'elles soient imprimees - quand on affichera le type *) + (* we delete vals and methods in order to not print them when + displaying the type *) let tnil = { Types.desc = Types.Tnil ; Types.level = 0; Types.id = 0 } in Types.Cty_signature { Types.csig_self = { cs.Types.csig_self with Types.desc = Types.Tobject (tnil, ref None) }; @@ -95,6 +98,6 @@ let simpl_class_type t = let string_of_class_type ?(complete=false) t = let t2 = if complete then t else simpl_class_type t in - (* A VOIR : ma propre version de Printtyp.class_type pour ne pas faire reset_names *) + (* FIXME : my own Printtyp.class_type variant to avoid reset_names *) Printtyp.class_type modtype_fmt t2; flush_modtype_fmt () diff --git a/ocamldoc/odoc_print.mli b/ocamldoc/odoc_print.mli index f7c59013..f56d541e 100644 --- a/ocamldoc/odoc_print.mli +++ b/ocamldoc/odoc_print.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Printing functions. *) diff --git a/ocamldoc/odoc_scan.ml b/ocamldoc/odoc_scan.ml index e6c19f29..0975cdf1 100644 --- a/ocamldoc/odoc_scan.ml +++ b/ocamldoc/odoc_scan.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Scanning of modules and elements. diff --git a/ocamldoc/odoc_search.ml b/ocamldoc/odoc_search.ml index 763b7160..93dcbafe 100644 --- a/ocamldoc/odoc_search.ml +++ b/ocamldoc/odoc_search.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Research of elements through modules. *) @@ -157,8 +160,7 @@ module Search = [] (Odoc_class.class_comments c) in - let l = res_att @ res_met @ res_sec in - l + res_att @ res_met @ res_sec else [] in @@ -189,8 +191,7 @@ module Search = [] (Odoc_class.class_type_comments ct) in - let l = res_att @ res_met @ res_sec in - l + res_att @ res_met @ res_sec else [] in @@ -252,10 +253,8 @@ module Search = [] (Odoc_module.module_type_comments mt) in - let l = res_val @ res_typ @ res_ext @ res_exc @ res_mod @ + res_val @ res_typ @ res_ext @ res_exc @ res_mod @ res_modtyp @ res_cl @ res_cltyp @ res_sec - in - l else [] in @@ -317,10 +316,8 @@ module Search = [] (Odoc_module.module_comments m) in - let l = res_val @ res_typ @ res_ext @ res_exc @ res_mod @ + res_val @ res_typ @ res_ext @ res_exc @ res_mod @ res_modtyp @ res_cl @ res_cltyp @ res_sec - in - l else [] in diff --git a/ocamldoc/odoc_search.mli b/ocamldoc/odoc_search.mli index e0d9f2c2..a4681c60 100644 --- a/ocamldoc/odoc_search.mli +++ b/ocamldoc/odoc_search.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Research of elements through modules. *) diff --git a/ocamldoc/odoc_see_lexer.mll b/ocamldoc/odoc_see_lexer.mll index 59ffc937..b676154d 100644 --- a/ocamldoc/odoc_see_lexer.mll +++ b/ocamldoc/odoc_see_lexer.mll @@ -1,14 +1,18 @@ { -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) let print_DEBUG2 s = print_string s ; print_newline () diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml index ee65748a..8859ca2e 100644 --- a/ocamldoc/odoc_sig.ml +++ b/ocamldoc/odoc_sig.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Analysis of interface files. *) @@ -136,8 +139,7 @@ module Analyser = prepare_file must have been called to fill the file global variable.*) let get_string_of_file the_start the_end = try - let s = String.sub !file the_start (the_end-the_start) in - s + String.sub !file the_start (the_end-the_start) with Invalid_argument _ -> "" @@ -220,6 +222,7 @@ module Analyser = let (len, comment_opt) = My_ir.just_after_special !file_name s in (len, acc @ [ (pcd.pcd_name.txt, comment_opt) ]) | pcd :: (pcd2 :: _ as q) -> + (* TODO: support annotations on fields for inline records *) let pos_end_first = pcd.pcd_loc.Location.loc_end.Lexing.pos_cnum in let pos_start_second = pcd2.pcd_loc.Location.loc_start.Lexing.pos_cnum in let s = get_string_of_file pos_end_first pos_start_second in @@ -266,20 +269,40 @@ module Analyser = Object_type (List.map f @@ fst @@ Ctype.flatten_fields fields) | _ -> Other (Odoc_env.subst_type env type_expr) + let get_field env name_comment_list {Types.ld_id=field_name;ld_mutable=mutable_flag;ld_type=type_expr} = + let field_name = Ident.name field_name in + let comment_opt = + try List.assoc field_name name_comment_list + with Not_found -> None + in + { + rf_name = field_name ; + rf_mutable = mutable_flag = Mutable ; + rf_type = Odoc_env.subst_type env type_expr ; + rf_text = comment_opt + } + let get_type_kind env name_comment_list type_kind = match type_kind with Types.Type_abstract -> Odoc_type.Type_abstract | Types.Type_variant l -> - let f {Types.cd_id=constructor_name;cd_args=type_expr_list;cd_res=ret_type} = + let f {Types.cd_id=constructor_name;cd_args;cd_res=ret_type} = let constructor_name = Ident.name constructor_name in let comment_opt = - try List.assoc constructor_name name_comment_list + try match List.assoc constructor_name name_comment_list with + | Some { i_desc = None | Some []; _ } -> None + | x -> x with Not_found -> None in + let vc_args = + match cd_args with + | Cstr_tuple l -> Cstr_tuple (List.map (Odoc_env.subst_type env) l) + | Cstr_record l -> Cstr_record (List.map (get_field env []) l) + in { vc_name = constructor_name ; - vc_args = List.map (Odoc_env.subst_type env) type_expr_list ; + vc_args; vc_ret = may_map (Odoc_env.subst_type env) ret_type; vc_text = comment_opt } @@ -287,20 +310,7 @@ module Analyser = Odoc_type.Type_variant (List.map f l) | Types.Type_record (l, _) -> - let f {Types.ld_id=field_name;ld_mutable=mutable_flag;ld_type=type_expr} = - let field_name = Ident.name field_name in - let comment_opt = - try List.assoc field_name name_comment_list - with Not_found -> None - in - { - rf_name = field_name ; - rf_mutable = mutable_flag = Mutable ; - rf_type = Odoc_env.subst_type env type_expr ; - rf_text = comment_opt - } - in - Odoc_type.Type_record (List.map f l) + Odoc_type.Type_record (List.map (get_field env name_comment_list) l) | Types.Type_open -> Odoc_type.Type_open @@ -329,10 +339,10 @@ module Analyser = | Parsetree.Psig_include _ | Parsetree.Psig_class _ | Parsetree.Psig_class_type _ as tp -> take_item tp - | Parsetree.Psig_type types -> + | Parsetree.Psig_type (rf, types) -> (match List.filter (fun td -> not (Name.Set.mem td.Parsetree.ptype_name.txt erased)) types with | [] -> acc - | types -> take_item (Parsetree.Psig_type types)) + | types -> take_item (Parsetree.Psig_type (rf, types))) | Parsetree.Psig_module {Parsetree.pmd_name=name} | Parsetree.Psig_modtype {Parsetree.pmtd_name=name} as m -> if Name.Set.mem name.txt erased then acc else take_item m @@ -469,7 +479,7 @@ module Analyser = | (Parsetree.Pctf_constraint (_, _)) -> (* of (core_type * core_type) *) - (* A VOIR : cela correspond aux contraintes, non ? on ne les garde pas pour l'instant *) + (* FIXME: this corresponds to constraints, isn't it? We don't keep them for now *) let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in let (inher_l, eles) = f loc.Location.loc_end.Lexing.pos_cnum q in (inher_l, eles_comments @ eles) @@ -493,14 +503,11 @@ module Analyser = Parsetree.Pcty_constr (longident, _) -> (*of Longident.t * core_type list*) let name = Name.from_longident longident.txt in - let ic = - { - ic_name = Odoc_env.full_class_or_class_type_name env name ; - ic_class = None ; - ic_text = text_opt ; - } - in - ic + { + ic_name = Odoc_env.full_class_or_class_type_name env name ; + ic_class = None ; + ic_text = text_opt ; + } | Parsetree.Pcty_signature _ | Parsetree.Pcty_arrow _ -> @@ -567,15 +574,10 @@ module Analyser = ele.Parsetree.psig_desc in let new_pos = - match ele.Parsetree.psig_desc with - | Parsetree.Psig_attribute ({Asttypes.txt = "ocaml.text"}, _) -> last_pos - (* This "signature item" is actually a doc comment; the item is ignored - but don't skip the comment. *) - | _ -> - (ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum + maybe_more) - (* for the comments of constructors in types, - which are after the constructor definition and can - go beyond ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum *) + ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum + maybe_more + (* for the comments of constructors in types, + which are after the constructor definition and can + go beyond ele.Parsetree.psig_loc.Location.loc_end.Lexing.pos_cnum *) in f (acc_eles @ (ele_comments @ elements)) new_env @@ -666,10 +668,15 @@ module Analyser = [] -> (maybe_more, List.rev exts_acc) | (name, types_ext) :: q -> let ext_loc_end = types_ext.Types.ext_loc.Location.loc_end.Lexing.pos_cnum in + let xt_args = + match types_ext.ext_args with + | Cstr_tuple l -> Cstr_tuple (List.map (Odoc_env.subst_type new_env) l) + | Cstr_record l -> Cstr_record (List.map (get_field new_env []) l) + in let new_x = { xt_name = Name.concat current_module_name name ; - xt_args = List.map (Odoc_env.subst_type new_env) types_ext.ext_args ; + xt_args; xt_ret = may_map (Odoc_env.subst_type new_env) types_ext.ext_ret_type ; xt_type_extension = new_te; xt_alias = None ; @@ -704,11 +711,16 @@ module Analyser = with Not_found -> raise (Failure (Odoc_messages.exception_not_found current_module_name name.txt)) in + let ex_args = + match types_ext.ext_args with + | Cstr_tuple l -> Cstr_tuple (List.map (Odoc_env.subst_type env) l) + | Cstr_record l -> Cstr_record (List.map (get_field env []) l) + in let e = { ex_name = Name.concat current_module_name name.txt ; ex_info = comment_opt ; - ex_args = List.map (Odoc_env.subst_type env) types_ext.ext_args ; + ex_args; ex_ret = may_map (Odoc_env.subst_type env) types_ext.ext_ret_type ; ex_alias = None ; ex_loc = { loc_impl = None ; loc_inter = Some sig_item_loc } ; @@ -730,7 +742,7 @@ module Analyser = let new_env = Odoc_env.add_extension env e.ex_name in (maybe_more, new_env, [ Element_exception e ]) - | Parsetree.Psig_type name_type_decl_list -> + | Parsetree.Psig_type (rf, name_type_decl_list) -> let extended_env = List.fold_left (fun acc_env td -> @@ -741,14 +753,9 @@ module Analyser = name_type_decl_list in let env = - let is_nonrec = - List.exists - (fun td -> - List.exists (fun (n, _) -> n.txt = "nonrec") - td.Parsetree.ptype_attributes) - name_type_decl_list - in - if is_nonrec then env else extended_env + match rf with + | Recursive -> extended_env + | Nonrecursive -> env in let rec f ?(first=false) acc_maybe_more last_pos name_type_decl_list = match name_type_decl_list with @@ -775,9 +782,23 @@ module Analyser = pos_limit2 type_decl in - print_DEBUG ("Type "^name.txt^" : "^(match assoc_com with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c)); - let f_DEBUG (name, c_opt) = print_DEBUG ("constructor/field "^name^": "^(match c_opt with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c)) in - List.iter f_DEBUG name_comment_list; +(* DEBUG *) begin +(* DEBUG *) let comm = +(* DEBUG *) match assoc_com with +(* DEBUG *) | None -> "sans commentaire" +(* DEBUG *) | Some c -> Odoc_misc.string_of_info c +(* DEBUG *) in +(* DEBUG *) print_DEBUG ("Type "^name.txt^" : "^comm); +(* DEBUG *) let f_DEBUG (name, c_opt) = +(* DEBUG *) let comm = +(* DEBUG *) match c_opt with +(* DEBUG *) | None -> "sans commentaire" +(* DEBUG *) | Some c -> Odoc_misc.string_of_info c +(* DEBUG *) in +(* DEBUG *) print_DEBUG ("constructor/field "^name^": "^comm) +(* DEBUG *) in +(* DEBUG *) List.iter f_DEBUG name_comment_list; +(* DEBUG *) end; (* get the information for the type in the signature *) let sig_type_decl = try Signature_search.search_type table name.txt @@ -833,7 +854,7 @@ module Analyser = let (maybe_more, types) = f ~first: true 0 pos_start_ele name_type_decl_list in (maybe_more, extended_env, types) - | Parsetree.Psig_open _ -> (* A VOIR *) + | Parsetree.Psig_open _ -> (* FIXME *) let ele_comments = match comment_opt with None -> [] | Some i -> @@ -884,7 +905,7 @@ module Analyser = new_module.m_info <- merge_infos new_module.m_info info_after_opt ; let new_env = Odoc_env.add_module env new_module.m_name in let new_env2 = - match new_module.m_type with (* A VOIR : cela peut-il etre Tmty_ident ? dans ce cas, on aurait pas la signature *) + match new_module.m_type with (* FIXME : can this be a Tmty_ident? in this case, we would'nt have the signature *) Types.Mty_signature s -> Odoc_env.add_signature new_env new_module.m_name ~rel: (Name.simple new_module.m_name) s | _ -> new_env in @@ -904,7 +925,7 @@ module Analyser = raise (Failure (Odoc_messages.module_not_found current_module_name name)) in match sig_module_type with - (* A VOIR : cela peut-il etre Tmty_ident ? dans ce cas, on aurait pas la signature *) + (* FIXME : can this be a Tmty_ident? in this case, we would'nt have the signature *) Types.Mty_signature s -> Odoc_env.add_signature e complete_name ~rel: name s | _ -> @@ -1019,7 +1040,7 @@ module Analyser = mt.mt_info <- merge_infos mt.mt_info info_after_opt ; let new_env = Odoc_env.add_module_type env mt.mt_name in let new_env2 = - match sig_mtype with (* A VOIR : cela peut-il etre Tmty_ident ? dans ce cas, on aurait pas la signature *) + match sig_mtype with (* FIXME : can this be a Tmty_ident? in this case, we would'nt have the signature *) Some (Types.Mty_signature s) -> Odoc_env.add_signature new_env mt.mt_name ~rel: (Name.simple mt.mt_name) s | _ -> new_env in @@ -1053,7 +1074,7 @@ module Analyser = im_info = comment_opt; } in - (0, env, [ Element_included_module im ]) (* A VOIR : etendre l'environnement ? avec quoi ? *) + (0, env, [ Element_included_module im ]) (* FIXME : extend the environment? How? *) | Parsetree.Psig_class class_description_list -> (* we start by extending the environment *) @@ -1216,7 +1237,7 @@ module Analyser = match sig_module_type with Types.Mty_ident path -> Name.from_path path | _ -> Name.from_longident longident.txt - (* A VOIR cela arrive quand on fait module type F : functor ... -> Toto, Toto n'est pas un ident mais une structure *) + (* FIXME this happens for module type F : functor ... -> Toto, Toto is not an ident but a structure *) in Module_type_alias { mta_name = Odoc_env.full_module_type_name env name ; mta_module = None } @@ -1423,8 +1444,8 @@ module Analyser = ([], Class_structure (inher_l, ele)) | (Parsetree.Pcty_arrow (parse_label, _, pclass_type), Types.Cty_arrow (label, type_expr, class_type)) -> - (* label = string. Dans les signatures, pas de nom de parametres a l'interieur des tuples *) - (* si label = "", pas de label. ici on a l'information pour savoir si on a un label explicite. *) + (* label = string. In signature, there is no parameter names inside tuples *) + (* if label = "", no label . Here we have the information to determine if a label is explicit or not. *) if parse_label = label then ( let new_param = Simple_name @@ -1451,15 +1472,12 @@ module Analyser = (Parsetree.Pcty_constr (_, _) (*of Longident.t * core_type list *), Types.Cty_constr (p, typ_list, _) (*of Path.t * type_expr list * class_type*)) -> print_DEBUG "Cty_constr _"; - let k = - Class_type - { - cta_name = Odoc_env.full_class_or_class_type_name env (Name.from_path p) ; - cta_class = None ; - cta_type_parameters = List.map (Odoc_env.subst_type env) typ_list - } - in - k + Class_type + { + cta_name = Odoc_env.full_class_or_class_type_name env (Name.from_path p) ; + cta_class = None ; + cta_type_parameters = List.map (Odoc_env.subst_type env) typ_list + } | (Parsetree.Pcty_signature { Parsetree.pcsig_fields = class_type_field_list; @@ -1478,7 +1496,7 @@ module Analyser = (* | (Parsetree.Pcty_constr (longident, _) (*of Longident.t * core_type list *), Types.Cty_signature class_signature) -> - (* A VOIR : c'est pour le cas des contraintes de classes : + (* FIXME : this for the case of class contraints : class type cons = object method m : int end @@ -1521,7 +1539,7 @@ module Analyser = in prepare_file complete_source_file input_file; (* We create the t_module for this file. *) - let mod_name = String.capitalize + let mod_name = String.capitalize_ascii (Filename.basename (try Filename.chop_extension source_file with _ -> source_file)) in let (len,info_opt) = My_ir.first_special !file_name !file in diff --git a/ocamldoc/odoc_sig.mli b/ocamldoc/odoc_sig.mli index 5dc4b4c8..65e7b373 100644 --- a/ocamldoc/odoc_sig.mli +++ b/ocamldoc/odoc_sig.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The module for analysing a signature and source code and creating modules, classes, ..., elements.*) diff --git a/ocamldoc/odoc_str.ml b/ocamldoc/odoc_str.ml index 7d99ff10..bfaea763 100644 --- a/ocamldoc/odoc_str.ml +++ b/ocamldoc/odoc_str.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The functions to get a string from different kinds of elements (types, modules, ...). *) @@ -148,8 +151,8 @@ let string_of_class_params c = Printf.bprintf b "%s%s%s%s -> " ( match label with - "" -> "" - | s -> s^":" + Asttypes.Nolabel -> "" + | s -> Printtyp.string_of_label s ^":" ) (if parent then "(" else "") (Odoc_print.string_of_type_expr @@ -171,13 +174,27 @@ let bool_of_private = function | Asttypes.Private -> true | _ -> false +let field_doc_str = function + | None -> "" + | Some t -> Printf.sprintf "(* %s *)" (Odoc_misc.string_of_info t) + +let string_of_record l = + let module M = Odoc_type in + let module P = Printf in + P.sprintf "{\n%s\n}" ( + String.concat "\n" ( + List.map (fun field -> + P.sprintf " %s%s : %s;%s" + (if field.M.rf_mutable then "mutable " else "") field.M.rf_name + (Odoc_print.string_of_type_expr field.M.rf_type) + (field_doc_str field.M.rf_text) + ) l + ) + ) + let string_of_type t = let module M = Odoc_type in let module P = Printf in - let field_doc_str = function - | None -> "" - | Some t -> P.sprintf "(* %s *)" (Odoc_misc.string_of_info t) - in let priv = bool_of_private t.M.ty_private in let parameters_str = String.concat " " ( @@ -215,16 +232,19 @@ let string_of_type t = | None -> "" | Some t -> P.sprintf "(* %s *)" (Odoc_misc.string_of_info t) in - let string_of_parameters lst = - String.concat " * " ( - List.map (fun t -> "("^Odoc_print.string_of_type_expr t^")") lst - ) + let string_of_parameters = function + | M.Cstr_tuple l -> + String.concat " * " ( + List.map (fun t -> "("^Odoc_print.string_of_type_expr t^")") l + ) + | M.Cstr_record l -> + string_of_record l in P.sprintf " | %s%s%s" cons.M.vc_name ( match cons.M.vc_args, cons.M.vc_ret with - | [], None -> "" + | M.Cstr_tuple [], None -> "" | li, None -> " of " ^ (string_of_parameters li) - | [], Some r -> " : " ^ Odoc_print.string_of_type_expr r + | M.Cstr_tuple [], Some r -> " : " ^ Odoc_print.string_of_type_expr r | li, Some r -> P.sprintf " : %s -> %s" (string_of_parameters li) (Odoc_print.string_of_type_expr r) @@ -237,16 +257,8 @@ let string_of_type t = "= .." (* FIXME MG: when introducing new constuctors next time, thanks to setup a minimal correct output *) | M.Type_record l -> - P.sprintf "= %s{\n%s\n}\n" (if priv then "private " else "") ( - String.concat "\n" ( - List.map (fun field -> - P.sprintf " %s%s : %s;%s" - (if field.M.rf_mutable then "mutable " else "") field.M.rf_name - (Odoc_print.string_of_type_expr field.M.rf_type) - (field_doc_str field.M.rf_text) - ) l - ) - ) + P.sprintf "= %s{\n%s\n}\n" (if priv then "private " else "") + (string_of_record l) in P.sprintf "type %s %s %s%s%s" parameters_str (Name.simple t.M.ty_name) manifest_str type_kind_str @@ -256,6 +268,7 @@ let string_of_type t = let string_of_type_extension te = let module M = Odoc_extension in + let module T = Odoc_type in "type " ^(String.concat "" (List.map @@ -272,19 +285,21 @@ let string_of_type_extension te = " | " ^(Name.simple x.M.xt_name) ^(match x.M.xt_args, x.M.xt_ret with - | [], None -> "" - | l, None -> + | T.Cstr_tuple [], None -> "" + | T.Cstr_tuple l, None -> " of " ^ (String.concat " * " (List.map (fun t -> "("^Odoc_print.string_of_type_expr t^")") l)) - | [], Some r -> " : " ^ Odoc_print.string_of_type_expr r - | l, Some r -> + | T.Cstr_tuple [], Some r -> " : " ^ Odoc_print.string_of_type_expr r + | T.Cstr_tuple l, Some r -> " : " ^ (String.concat " * " (List.map (fun t -> "("^Odoc_print.string_of_type_expr t^")") l)) ^ " -> " ^ Odoc_print.string_of_type_expr r + | T.Cstr_record _, _ -> + assert false ) ^(match x.M.xt_alias with None -> "" @@ -309,23 +324,26 @@ let string_of_type_extension te = ) let string_of_exception e = + let module T = Odoc_type in let module M = Odoc_exception in "exception "^(Name.simple e.M.ex_name)^ (match e.M.ex_args, e.M.ex_ret with - [], None -> "" - | l,None -> + T.Cstr_tuple [], None -> "" + | T.Cstr_tuple l,None -> " of "^ (String.concat " * " (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") l)) - | [],Some r -> + | T.Cstr_tuple [],Some r -> " : "^ (Odoc_print.string_of_type_expr r) - | l,Some r -> + | T.Cstr_tuple l,Some r -> " : "^ (String.concat " * " (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") l))^ " -> "^ (Odoc_print.string_of_type_expr r) + | T.Cstr_record _, _ -> + assert false )^ (match e.M.ex_alias with None -> "" diff --git a/ocamldoc/odoc_str.mli b/ocamldoc/odoc_str.mli index 402a82d5..3cb52b4b 100644 --- a/ocamldoc/odoc_str.mli +++ b/ocamldoc/odoc_str.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The functions to get a string from different kinds of elements (types, modules, ...). *) @@ -37,6 +40,8 @@ val string_of_class_type_param_list : Types.type_expr list -> string (** @return a string to describe the given type. *) val string_of_type : Odoc_type.t_type -> string +val string_of_record : Odoc_type.record_field list -> string + (** @return a string to display the parameters of the given class, in the same form as the compiler. *) val string_of_class_params : Odoc_class.t_class -> string diff --git a/ocamldoc/odoc_test.ml b/ocamldoc/odoc_test.ml index c68e8532..dd026475 100644 --- a/ocamldoc/odoc_test.ml +++ b/ocamldoc/odoc_test.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2004 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2004 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. *) +(* *) +(**************************************************************************) (** Custom generator to perform test on ocamldoc. *) diff --git a/ocamldoc/odoc_texi.ml b/ocamldoc/odoc_texi.ml index 10d45c1c..eeaa2105 100644 --- a/ocamldoc/odoc_texi.ml +++ b/ocamldoc/odoc_texi.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Olivier Andrieu, base sur du code de Maxence Guesdon *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Olivier Andrieu, base sur du code de Maxence Guesdon *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Generation of Texinfo documentation. *) @@ -311,7 +314,7 @@ class text = method texi_of_custom_text s t = "" method texi_of_Target ~target ~code = - if String.lowercase target = "texi" then code else "" + if String.lowercase_ascii target = "texi" then code else "" method texi_of_Verbatim s = s method texi_of_Raw s = self#escape s @@ -638,12 +641,16 @@ class texi = Printf.sprintf "(%s) " (String.concat ", " (List.map f l)) - method string_of_type_args (args:Types.type_expr list) (ret:Types.type_expr option) = + method string_of_type_args (args:constructor_args) (ret:Types.type_expr option) = + let f = function + | Cstr_tuple l -> Odoc_info.string_of_type_list " * " l + | Cstr_record l -> Odoc_info.string_of_record l + in match args, ret with - | [], None -> "" - | args, None -> " of " ^ (Odoc_info.string_of_type_list " * " args) - | [], Some r -> " : " ^ (Odoc_info.string_of_type_expr r) - | args, Some r -> " : " ^ (Odoc_info.string_of_type_list " * " args) ^ + | Cstr_tuple [], None -> "" + | args, None -> " of " ^ (f args) + | Cstr_tuple [], Some r -> " : " ^ (Odoc_info.string_of_type_expr r) + | args, Some r -> " : " ^ (f args) ^ " -> " ^ (Odoc_info.string_of_type_expr r) (** Return Texinfo code for a type. *) diff --git a/ocamldoc/odoc_text.ml b/ocamldoc/odoc_text.ml index eb3c5626..889bb5fb 100644 --- a/ocamldoc/odoc_text.ml +++ b/ocamldoc/odoc_text.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) exception Text_syntax of int * int * string (* line, char, string *) diff --git a/ocamldoc/odoc_text.mli b/ocamldoc/odoc_text.mli index fc4f3306..409acaad 100644 --- a/ocamldoc/odoc_text.mli +++ b/ocamldoc/odoc_text.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** A module with a function to parse strings to obtain a [Odoc_types.text] value. *) diff --git a/ocamldoc/odoc_text_lexer.mll b/ocamldoc/odoc_text_lexer.mll index c8dda36a..62f996cb 100644 --- a/ocamldoc/odoc_text_lexer.mll +++ b/ocamldoc/odoc_text_lexer.mll @@ -1,14 +1,18 @@ { -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** The lexer for string to build text structures. *) @@ -20,16 +24,16 @@ let char_number = ref 0 let string_buffer = Buffer.create 32 -(** Fonction de remise a zero de la chaine de caracteres tampon *) +(** Reset the buffer *) let reset_string_buffer () = Buffer.reset string_buffer -(** Fonction d'ajout d'un caractere dans la chaine de caracteres tampon *) -let ajout_char_string = Buffer.add_char string_buffer +(** Add a character to the buffer *) +let add_char_string = Buffer.add_char string_buffer (** Add a string to the buffer. *) -let ajout_string = Buffer.add_string string_buffer +let add_string = Buffer.add_string string_buffer -let lecture_string () = Buffer.contents string_buffer +let read_string () = Buffer.contents string_buffer (** the variable which will contain the description string. @@ -190,12 +194,11 @@ rule main = parse if !verb_mode || !target_mode || !code_pre_mode || (!open_brackets >= 1) then Char (Lexing.lexeme lexbuf) - else - let _ = - if !ele_ref_mode then - ele_ref_mode := false - in + else begin + if !ele_ref_mode then + ele_ref_mode := false; END + end } | begin_title { @@ -846,6 +849,7 @@ rule main = parse else LBRACE } +| '\r' { main lexbuf } | _ { incr_cpts lexbuf ; diff --git a/ocamldoc/odoc_text_parser.mly b/ocamldoc/odoc_text_parser.mly index b4118c4f..5e0c7127 100644 --- a/ocamldoc/odoc_text_parser.mly +++ b/ocamldoc/odoc_text_parser.mly @@ -1,14 +1,18 @@ %{ -(***********************************************************************) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open Odoc_types @@ -173,7 +177,7 @@ text_element: ; list: -| string { [] (* A VOIR : un test pour voir qu'il n'y a que des blancs *) } +| string { [] (* TODO: a test to check that there is only space characters *) } | string list { $2 } | list string { $1 } | item { [ $1 ] } diff --git a/ocamldoc/odoc_to_text.ml b/ocamldoc/odoc_to_text.ml index 1c7f6ba7..a602da61 100644 --- a/ocamldoc/odoc_to_text.ml +++ b/ocamldoc/odoc_to_text.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Text generation. @@ -96,13 +99,10 @@ class virtual info = (** Return [text] value for the given "see also" reference. *) method text_of_see (see_ref, t) = - let t_ref = - match see_ref with - Odoc_info.See_url s -> [ Odoc_info.Link (s, t) ] - | Odoc_info.See_file s -> (Odoc_info.Code s) :: (Odoc_info.Raw " ") :: t - | Odoc_info.See_doc s -> (Odoc_info.Italic [Odoc_info.Raw s]) :: (Odoc_info.Raw " ") :: t - in - t_ref + match see_ref with + Odoc_info.See_url s -> [ Odoc_info.Link (s, t) ] + | Odoc_info.See_file s -> (Odoc_info.Code s) :: (Odoc_info.Raw " ") :: t + | Odoc_info.See_doc s -> (Odoc_info.Italic [Odoc_info.Raw s]) :: (Odoc_info.Raw " ") :: t (** Return [text] value for the given list of "see also" references.*) method text_of_sees l = @@ -192,12 +192,10 @@ class virtual to_text = let rel = Name.get_relative m_name match_s in Odoc_info.apply_if_equal Odoc_info.use_hidden_modules match_s rel in - let s2 = Str.global_substitute - (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)") - f - s - in - s2 + Str.global_substitute + (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([a-z][a-zA-Z_'0-9]*\\)") + f + s (** Take a string and return the string where fully qualified idents have been replaced by idents relative to the given module name. @@ -208,12 +206,10 @@ class virtual to_text = let rel = Name.get_relative m_name match_s in Odoc_info.apply_if_equal Odoc_info.use_hidden_modules match_s rel in - let s2 = Str.global_substitute - (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([A-Z][a-zA-Z_'0-9]*\\)") - f - s - in - s2 + Str.global_substitute + (Str.regexp "\\([A-Z]\\([a-zA-Z_'0-9]\\)*\\.\\)+\\([A-Z][a-zA-Z_'0-9]*\\)") + f + s (** Get a string for a [Types.class_type] where all idents are relative. *) method normal_class_type m_name t = @@ -231,6 +227,10 @@ class virtual to_text = method normal_type_list ?par m_name sep t = self#relative_idents m_name (Odoc_info.string_of_type_list ?par sep t) + method normal_cstr_args ?par m_name = function + | Cstr_tuple l -> self#normal_type_list ?par m_name " * " l + | Cstr_record _ -> "{...}" (* TODO *) + (** Get a string for a list of class or class type type parameters where all idents are relative. *) method normal_class_type_param_list m_name t = @@ -244,14 +244,12 @@ class virtual to_text = (** @return [text] value to represent a [Types.type_expr].*) method text_of_type_expr module_name t = - let t = List.flatten - (List.map - (fun s -> [Code s ; Newline ]) - (Str.split (Str.regexp "\n") - (self#normal_type module_name t)) - ) - in - t + List.flatten + (List.map + (fun s -> [Code s ; Newline ]) + (Str.split (Str.regexp "\n") + (self#normal_type module_name t)) + ) (** Return [text] value for a given short [Types.type_expr].*) method text_of_short_type_expr module_name t = @@ -269,15 +267,13 @@ class virtual to_text = (** @return [text] value to represent parameters of a class (with arraows).*) method text_of_class_params module_name c = - let t = Odoc_info.text_concat - [Newline] - (List.map - (fun s -> [Code s]) - (Str.split (Str.regexp "\n") - (self#normal_class_params module_name c)) - ) - in - t + Odoc_info.text_concat + [Newline] + (List.map + (fun s -> [Code s]) + (Str.split (Str.regexp "\n") + (self#normal_class_params module_name c)) + ) (** @return [text] value to represent a [Types.module_type]. *) method text_of_module_type t = @@ -339,21 +335,23 @@ class virtual to_text = let father = Name.father e.ex_name in Format.fprintf Format.str_formatter "@[exception %s" s_name ; (match e.ex_args, e.ex_ret with - [], None -> () - | l, None -> + Cstr_tuple [], None -> () + | Cstr_tuple l, None -> Format.fprintf Format.str_formatter " %s@ %s" "of" (self#normal_type_list ~par: false father " * " l) - | [], Some r -> + | Cstr_tuple [], Some r -> Format.fprintf Format.str_formatter " %s@ %s" ":" (self#normal_type father r) - | l, Some r -> + | Cstr_tuple l, Some r -> Format.fprintf Format.str_formatter " %s@ %s@ %s@ %s" ":" (self#normal_type_list ~par: false father " * " l) "->" (self#normal_type father r) + | Cstr_record _, _ -> + assert false ); (match e.ex_alias with None -> () diff --git a/ocamldoc/odoc_type.ml b/ocamldoc/odoc_type.ml index dadc6b1b..7320f550 100644 --- a/ocamldoc/odoc_type.ml +++ b/ocamldoc/odoc_type.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of a type, but not class nor module type.*) @@ -17,14 +20,6 @@ module Name = Odoc_name type private_flag = Asttypes.private_flag = Private | Public -(** Description of a variant type constructor. *) -type variant_constructor = { - vc_name : string ; - vc_args : Types.type_expr list ; (** arguments of the constructor *) - vc_ret : Types.type_expr option ; - mutable vc_text : Odoc_types.info option ; (** optional user description *) - } - (** Description of a record type field. *) type record_field = { rf_name : string ; @@ -33,6 +28,18 @@ type record_field = { mutable rf_text : Odoc_types.info option ; (** optional user description *) } +type constructor_args = + | Cstr_record of record_field list + | Cstr_tuple of Types.type_expr list + +(** Description of a variant type constructor. *) +type variant_constructor = { + vc_name : string ; + vc_args : constructor_args ; + vc_ret : Types.type_expr option ; + mutable vc_text : Odoc_types.info option ; (** optional user description *) + } + (** The various kinds of type. *) type type_kind = Type_abstract diff --git a/ocamldoc/odoc_types.ml b/ocamldoc/odoc_types.ml index 9d7824aa..2baf1f2f 100644 --- a/ocamldoc/odoc_types.ml +++ b/ocamldoc/odoc_types.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) type ref_kind = RK_module diff --git a/ocamldoc/odoc_types.mli b/ocamldoc/odoc_types.mli index f9456ccd..fddd6d2f 100644 --- a/ocamldoc/odoc_types.mli +++ b/ocamldoc/odoc_types.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Types for the information collected in comments. *) diff --git a/ocamldoc/odoc_value.ml b/ocamldoc/odoc_value.ml index b35f2c6b..d939f64e 100644 --- a/ocamldoc/odoc_value.ml +++ b/ocamldoc/odoc_value.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCamldoc *) -(* *) -(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Maxence Guesdon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Representation and manipulation of values, class attributes and class methods. *) @@ -95,22 +98,16 @@ let parameter_list_from_arrows typ = so there is nothing to merge. With this dummy list we can merge the parameter names from the .ml and the type from the .mli file. *) let dummy_parameter_list typ = - let normal_name s = - match s with - "" -> s - | _ -> - match s.[0] with - '?' -> String.sub s 1 ((String.length s) - 1) - | _ -> s - in + let normal_name = Odoc_misc.label_name in Printtyp.mark_loops typ; let liste_param = parameter_list_from_arrows typ in let rec iter (label, t) = match t.Types.desc with | Types.Ttuple l -> - if label = "" then + let open Asttypes in + if label = Nolabel then Odoc_parameter.Tuple - (List.map (fun t2 -> iter ("", t2)) l, t) + (List.map (fun t2 -> iter (Nolabel, t2)) l, t) else (* if there is a label, then we don't want to decompose the tuple *) Odoc_parameter.Simple_name diff --git a/ocamldoc/remove_DEBUG b/ocamldoc/remove_DEBUG index bca6ba04..3cb47bb8 100755 --- a/ocamldoc/remove_DEBUG +++ b/ocamldoc/remove_DEBUG @@ -1,15 +1,19 @@ #!/bin/sh -#(***********************************************************************) -#(* OCamldoc *) -#(* *) -#(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -#(* *) -#(* Copyright 2003 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. *) -#(* *) -#(***********************************************************************) +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Moscova, INRIA Rocquencourt * +#* * +#* Copyright 2003 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. * +#* * +#************************************************************************** # usage: remove_DEBUG # remove from every line that contains the string "DEBUG", diff --git a/ocamldoc/runocamldoc b/ocamldoc/runocamldoc deleted file mode 100644 index d2112e9c..00000000 --- a/ocamldoc/runocamldoc +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -####################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2002 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. # -# # -####################################################################### - -case "$1" in - true) shift - exec ../boot/ocamlrun -I ../otherlibs/unix -I ../otherlibs/str \ - ./ocamldoc "$@" - ;; - *) shift - exec ./ocamldoc "$@" - ;; -esac diff --git a/otherlibs/Makefile b/otherlibs/Makefile index 3ca2a487..8846cd23 100644 --- a/otherlibs/Makefile +++ b/otherlibs/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Common Makefile for otherlibs on the Unix ports diff --git a/otherlibs/Makefile.nt b/otherlibs/Makefile.nt index 6d16f8d2..e81590ac 100644 --- a/otherlibs/Makefile.nt +++ b/otherlibs/Makefile.nt @@ -1,21 +1,27 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Common Makefile for otherlibs on the Win32/MinGW ports include ../Makefile -# The Unix version now works fine under Windows +ifeq "$(wildcard $(ROOTDIR)/flexdll/Makefile)" "" +export OCAML_FLEXLINK:= +else +export OCAML_FLEXLINK:=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/flexdll/flexlink.exe +endif # Note .. is the current directory (this makefile is included from # a subdirectory) diff --git a/otherlibs/Makefile.shared b/otherlibs/Makefile.shared index cb8bf174..58e97c22 100644 --- a/otherlibs/Makefile.shared +++ b/otherlibs/Makefile.shared @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Common Makefile for otherlibs @@ -20,7 +22,13 @@ CAMLYACC ?= $(ROOTDIR)/boot/ocamlyacc # Compilation options CC=$(BYTECC) -COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string $(EXTRACAMLFLAGS) +COMPFLAGS=-w +33..39+50 -warn-error A -bin-annot -g -safe-string \ + $(EXTRACAMLFLAGS) +ifeq "$(FLAMBDA)" "true" +OPTCOMPFLAGS=-O3 +else +OPTCOMPFLAGS= +endif MKLIB=$(CAMLRUN) $(ROOTDIR)/tools/ocamlmklib # Variables to be defined by individual libraries: @@ -62,16 +70,18 @@ INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR) install:: if test -f dll$(CLIBNAME)$(EXT_DLL); then \ - 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)/ - if test -n "$(HEADERS)"; then cp $(HEADERS) $(INSTALL_LIBDIR)/caml/; fi + 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)/" + if test -n "$(HEADERS)"; then \ + cp $(HEADERS) "$(INSTALL_LIBDIR)/caml/"; fi installopt: - cp $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) $(INSTALL_LIBDIR)/ - cd $(INSTALL_LIBDIR); $(RANLIB) $(LIBNAME).a - if test -f $(LIBNAME).cmxs; then cp $(LIBNAME).cmxs $(INSTALL_LIBDIR)/; fi + cp $(CAMLOBJS_NAT) $(LIBNAME).cmxa $(LIBNAME).$(A) "$(INSTALL_LIBDIR)/" + cd "$(INSTALL_LIBDIR)"; $(RANLIB) $(LIBNAME).a + if test -f $(LIBNAME).cmxs; then \ + cp $(LIBNAME).cmxs "$(INSTALL_LIBDIR)/"; fi partialclean: rm -f *.cm* @@ -88,7 +98,7 @@ clean:: partialclean $(CAMLC) -c $(COMPFLAGS) $< .ml.cmx: - $(CAMLOPT) -c $(COMPFLAGS) $< + $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< .c.$(O): $(BYTECC) $(BYTECCCOMPOPTS) $(CFLAGS) -c $< diff --git a/otherlibs/bigarray/.depend b/otherlibs/bigarray/.depend index 97c6fb72..2f419862 100644 --- a/otherlibs/bigarray/.depend +++ b/otherlibs/bigarray/.depend @@ -1,27 +1,25 @@ 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/../../config/s.h \ - ../../byterun/caml/mlvalues.h bigarray.h ../../byterun/caml/config.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/custom.h \ - ../../byterun/caml/fail.h ../../byterun/caml/intext.h \ - ../../byterun/caml/io.h ../../byterun/caml/hash.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/../../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 \ + ../../byterun/caml/hash.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 mmap_unix.o: mmap_unix.c bigarray.h ../../byterun/caml/config.h \ - ../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \ - ../../byterun/caml/mlvalues.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/mlvalues.h ../../byterun/caml/fail.h \ - ../../byterun/caml/io.h ../../byterun/caml/sys.h \ - ../../byterun/caml/signals.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 ../../byterun/caml/../../config/s.h \ - ../../byterun/caml/mlvalues.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/mlvalues.h ../../byterun/caml/custom.h \ - ../../byterun/caml/fail.h ../../byterun/caml/sys.h \ - ../unix/unixsupport.h + ../../byterun/caml/custom.h ../../byterun/caml/fail.h \ + ../../byterun/caml/sys.h ../unix/unixsupport.h bigarray.cmi : bigarray.cmo : bigarray.cmi bigarray.cmx : bigarray.cmi diff --git a/otherlibs/bigarray/Makefile b/otherlibs/bigarray/Makefile index 3bcc7a40..5bee2817 100644 --- a/otherlibs/bigarray/Makefile +++ b/otherlibs/bigarray/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** LIBNAME=bigarray EXTRACFLAGS=-I../$(UNIXLIB) -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE diff --git a/otherlibs/bigarray/Makefile.nt b/otherlibs/bigarray/Makefile.nt index baeaa7a1..64f4a967 100644 --- a/otherlibs/bigarray/Makefile.nt +++ b/otherlibs/bigarray/Makefile.nt @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** LIBNAME=bigarray EXTRACFLAGS=-I../win32unix -DIN_OCAML_BIGARRAY -DCAML_NAME_SPACE diff --git a/otherlibs/bigarray/bigarray.h b/otherlibs/bigarray/bigarray.h index 23bde233..46a3a6a3 100644 --- a/otherlibs/bigarray/bigarray.h +++ b/otherlibs/bigarray/bigarray.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_BIGARRAY_H #define CAML_BIGARRAY_H diff --git a/otherlibs/bigarray/bigarray.ml b/otherlibs/bigarray/bigarray.ml index 960c9724..77c200e2 100644 --- a/otherlibs/bigarray/bigarray.ml +++ b/otherlibs/bigarray/bigarray.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Manuel Serrano et Xavier Leroy, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Manuel Serrano et Xavier Leroy, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* Module [Bigarray]: large, multi-dimensional, numerical arrays *) @@ -62,6 +64,21 @@ let complex32 = Complex32 let complex64 = Complex64 let char = Char +let kind_size_in_bytes : type a b. (a, b) kind -> int = function + | Float32 -> 4 + | Float64 -> 8 + | Int8_signed -> 1 + | Int8_unsigned -> 1 + | Int16_signed -> 2 + | Int16_unsigned -> 2 + | Int32 -> 4 + | Int64 -> 8 + | Int -> Sys.word_size / 8 + | Nativeint -> Sys.word_size / 8 + | Complex32 -> 8 + | Complex64 -> 16 + | Char -> 1 + type c_layout = C_layout_typ type fortran_layout = Fortran_layout_typ @@ -90,9 +107,13 @@ module Genarray = struct let d = Array.make n 0 in for i = 0 to n-1 do d.(i) <- nth_dim a i done; d + 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)) * (Array.fold_left ( * ) 1 (dims arr)) + external sub_left: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) t = "caml_ba_sub" external sub_right: ('a, 'b, fortran_layout) t -> int -> int -> @@ -126,6 +147,10 @@ module Array1 = struct external dim: ('a, 'b, 'c) t -> int = "%caml_ba_dim_1" 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)) * (dim arr) + external sub: ('a, 'b, 'c) t -> int -> int -> ('a, 'b, 'c) t = "caml_ba_sub" 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" @@ -156,6 +181,10 @@ module Array2 = struct external dim2: ('a, 'b, 'c) t -> int = "%caml_ba_dim_2" 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)) * (dim1 arr) * (dim2 arr) + external sub_left: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) t = "caml_ba_sub" external sub_right: @@ -203,6 +232,10 @@ module Array3 = struct external dim3: ('a, 'b, 'c) t -> int = "%caml_ba_dim_3" 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)) * (dim1 arr) * (dim2 arr) * (dim3 arr) + external sub_left: ('a, 'b, c_layout) t -> int -> int -> ('a, 'b, c_layout) t = "caml_ba_sub" external sub_right: diff --git a/otherlibs/bigarray/bigarray.mli b/otherlibs/bigarray/bigarray.mli index 6bde90a9..6b9c6239 100644 --- a/otherlibs/bigarray/bigarray.mli +++ b/otherlibs/bigarray/bigarray.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (** Large, multi-dimensional, numerical arrays. @@ -83,7 +85,7 @@ type ('a, 'b) kind = | Nativeint : (nativeint, nativeint_elt) kind | Complex32 : (Complex.t, complex32_elt) kind | Complex64 : (Complex.t, complex64_elt) kind - | Char : (char, int8_unsigned_elt) kind + | Char : (char, int8_unsigned_elt) kind (**) (** To each element kind is associated an OCaml type, which is the type of OCaml values that can be stored in the big array or read back from it. This type is not necessarily the same @@ -168,12 +170,16 @@ val char : (char, int8_unsigned_elt) kind characters instead of arrays of small integers, by using the kind value [char] instead of [int8_unsigned]. *) +val kind_size_in_bytes : ('a, 'b) kind -> int +(** [kind_size_in_bytes k] is the number of bytes used to store + an element of type [k]. *) + (** {6 Array layouts} *) -type c_layout = C_layout_typ +type c_layout = C_layout_typ (**) (** See {!Bigarray.fortran_layout}.*) -type fortran_layout = Fortran_layout_typ +type fortran_layout = Fortran_layout_typ (**) (** To facilitate interoperability with existing C and Fortran code, this library supports two different memory layouts for big arrays, one compatible with the C conventions, @@ -280,6 +286,10 @@ module Genarray : 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 the number of elements in [a] multiplied + by [a]'s {!kind_size_in_bytes}.*) + external get: ('a, 'b, 'c) t -> int array -> 'a = "caml_ba_get_generic" (** Read an element of a generic big array. [Genarray.get a [|i1; ...; iN|]] returns the element of [a] @@ -490,6 +500,10 @@ module Array1 : sig 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 the number of elements in [a] + multiplied by [a]'s {!kind_size_in_bytes}. *) + external get: ('a, 'b, 'c) t -> int -> 'a = "%caml_ba_ref_1" (** [Array1.get a x], or alternatively [a.{x}], returns the element of [a] at index [x]. @@ -572,6 +586,10 @@ module Array2 : 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 the number of elements in [a] + multiplied by [a]'s {!kind_size_in_bytes}. *) + external get: ('a, 'b, 'c) t -> int -> int -> 'a = "%caml_ba_ref_2" (** [Array2.get a x y], also written [a.{x,y}], returns the element of [a] at coordinates ([x], [y]). @@ -678,6 +696,10 @@ module Array3 : 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 the number of elements in [a] + multiplied by [a]'s {!kind_size_in_bytes}. *) + external get: ('a, 'b, 'c) t -> int -> int -> int -> 'a = "%caml_ba_ref_3" (** [Array3.get a x y z], also written [a.{x,y,z}], returns the element of [a] at coordinates ([x], [y], [z]). diff --git a/otherlibs/bigarray/bigarray_stubs.c b/otherlibs/bigarray/bigarray_stubs.c index c98a92f0..6a885d08 100644 --- a/otherlibs/bigarray/bigarray_stubs.c +++ b/otherlibs/bigarray/bigarray_stubs.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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 #include @@ -22,6 +24,7 @@ #include "caml/hash.h" #include "caml/memory.h" #include "caml/mlvalues.h" +#include "caml/signals.h" #define int8 caml_ba_int8 #define uint8 caml_ba_uint8 @@ -279,9 +282,9 @@ value caml_ba_get_N(value vb, value * vind, int nind) case CAML_BA_UINT16: return Val_int(((uint16 *) b->data)[offset]); case CAML_BA_INT32: - return caml_copy_int32(((int32 *) b->data)[offset]); + return caml_copy_int32(((int32_t *) b->data)[offset]); case CAML_BA_INT64: - return caml_copy_int64(((int64 *) b->data)[offset]); + return caml_copy_int64(((int64_t *) b->data)[offset]); case CAML_BA_NATIVE_INT: return caml_copy_nativeint(((intnat *) b->data)[offset]); case CAML_BA_CAML_INT: @@ -388,7 +391,7 @@ CAMLprim value caml_ba_uint8_get32(value vb, value vind) CAMLprim value caml_ba_uint8_get64(value vb, value vind) { - uint64 res; + uint64_t res; unsigned char b1, b2, b3, b4, b5, b6, b7, b8; intnat idx = Long_val(vind); struct caml_ba_array * b = Caml_ba_array_val(vb); @@ -402,15 +405,15 @@ CAMLprim value caml_ba_uint8_get64(value vb, value vind) b7 = ((unsigned char*) b->data)[idx+6]; b8 = ((unsigned char*) b->data)[idx+7]; #ifdef ARCH_BIG_ENDIAN - res = (uint64) b1 << 56 | (uint64) b2 << 48 - | (uint64) b3 << 40 | (uint64) b4 << 32 - | (uint64) b5 << 24 | (uint64) b6 << 16 - | (uint64) b7 << 8 | (uint64) b8; + res = (uint64_t) b1 << 56 | (uint64_t) b2 << 48 + | (uint64_t) b3 << 40 | (uint64_t) b4 << 32 + | (uint64_t) b5 << 24 | (uint64_t) b6 << 16 + | (uint64_t) b7 << 8 | (uint64_t) b8; #else - res = (uint64) b8 << 56 | (uint64) b7 << 48 - | (uint64) b6 << 40 | (uint64) b5 << 32 - | (uint64) b4 << 24 | (uint64) b3 << 16 - | (uint64) b2 << 8 | (uint64) b1; + res = (uint64_t) b8 << 56 | (uint64_t) b7 << 48 + | (uint64_t) b6 << 40 | (uint64_t) b5 << 32 + | (uint64_t) b4 << 24 | (uint64_t) b3 << 16 + | (uint64_t) b2 << 8 | (uint64_t) b1; #endif return caml_copy_int64(res); } @@ -447,9 +450,9 @@ static value caml_ba_set_aux(value vb, value * vind, intnat nind, value newval) case CAML_BA_UINT16: ((int16 *) b->data)[offset] = Int_val(newval); break; case CAML_BA_INT32: - ((int32 *) b->data)[offset] = Int32_val(newval); break; + ((int32_t *) b->data)[offset] = Int32_val(newval); break; case CAML_BA_INT64: - ((int64 *) b->data)[offset] = Int64_val(newval); break; + ((int64_t *) b->data)[offset] = Int64_val(newval); break; case CAML_BA_NATIVE_INT: ((intnat *) b->data)[offset] = Nativeint_val(newval); break; case CAML_BA_CAML_INT: @@ -577,7 +580,7 @@ CAMLprim value caml_ba_uint8_set64(value vb, value vind, value newval) { unsigned char b1, b2, b3, b4, b5, b6, b7, b8; intnat idx = Long_val(vind); - int64 val; + int64_t val; struct caml_ba_array * b = Caml_ba_array_val(vb); if (idx < 0 || idx >= b->dim[0] - 7) caml_array_bound_error(); val = Int64_val(newval); @@ -760,9 +763,9 @@ static int caml_ba_compare(value v1, value v2) case CAML_BA_UINT16: DO_INTEGER_COMPARISON(uint16); case CAML_BA_INT32: - DO_INTEGER_COMPARISON(int32); + DO_INTEGER_COMPARISON(int32_t); case CAML_BA_INT64: - DO_INTEGER_COMPARISON(int64); + DO_INTEGER_COMPARISON(int64_t); case CAML_BA_CAML_INT: case CAML_BA_NATIVE_INT: DO_INTEGER_COMPARISON(intnat); @@ -780,7 +783,7 @@ static intnat caml_ba_hash(value v) { struct caml_ba_array * b = Caml_ba_array_val(v); intnat num_elts, n; - uint32 h, w; + uint32_t h, w; int i; num_elts = 1; @@ -820,7 +823,7 @@ static intnat caml_ba_hash(value v) } case CAML_BA_INT32: { - uint32 * p = b->data; + uint32_t * p = b->data; if (num_elts > 64) num_elts = 64; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_uint32(h, *p); break; @@ -835,7 +838,7 @@ static intnat caml_ba_hash(value v) } case CAML_BA_INT64: { - int64 * p = b->data; + int64_t * p = b->data; if (num_elts > 32) num_elts = 32; for (n = 0; n < num_elts; n++, p++) h = caml_hash_mix_int64(h, *p); break; @@ -878,7 +881,7 @@ static void caml_ba_serialize_longarray(void * data, } else { caml_serialize_int_1(0); for (n = 0, p = data; n < num_elts; n++, p++) - caml_serialize_int_4((int32) *p); + caml_serialize_int_4((int32_t) *p); } #else caml_serialize_int_1(0); @@ -1120,12 +1123,19 @@ CAMLprim value caml_ba_sub(value vb, value vofs, value vlen) /* Copying a big array into another one */ +#define LEAVE_RUNTIME_OP_CUTOFF 4096 +#define is_mmapped(ba) ((ba)->flags & CAML_BA_MAPPED_FILE) + CAMLprim value caml_ba_blit(value vsrc, value vdst) { + CAMLparam2(vsrc, vdst); struct caml_ba_array * src = Caml_ba_array_val(vsrc); struct caml_ba_array * dst = Caml_ba_array_val(vdst); + void *src_data = src->data; + void *dst_data = dst->data; int i; intnat num_bytes; + int leave_runtime; /* Check same numbers of dimensions and same dimensions */ if (src->num_dims != dst->num_dims) goto blit_error; @@ -1135,19 +1145,44 @@ CAMLprim value caml_ba_blit(value vsrc, value vdst) num_bytes = caml_ba_num_elts(src) * caml_ba_element_size[src->flags & CAML_BA_KIND_MASK]; + leave_runtime = + ( + (num_bytes >= LEAVE_RUNTIME_OP_CUTOFF*sizeof(long)) + || is_mmapped(src) + || is_mmapped(dst) + ); /* Do the copying */ - memmove (dst->data, src->data, num_bytes); - return Val_unit; + if (leave_runtime) caml_enter_blocking_section(); + memmove (dst_data, src_data, num_bytes); + if (leave_runtime) caml_leave_blocking_section(); + CAMLreturn (Val_unit); blit_error: caml_invalid_argument("Bigarray.blit: dimension mismatch"); - return Val_unit; /* not reached */ + CAMLreturn (Val_unit); /* not reached */ } /* Filling a big array with a given value */ +#define FILL_GEN_LOOP(n_ops, loop) do{ \ + int leave_runtime = ((n_ops >= LEAVE_RUNTIME_OP_CUTOFF) || is_mmapped(b)); \ + if (leave_runtime) caml_enter_blocking_section(); \ + loop; \ + if (leave_runtime) caml_leave_blocking_section(); \ +}while(0) + +#define FILL_SCALAR_LOOP \ + FILL_GEN_LOOP(num_elts, \ + for (p = data; num_elts > 0; p++, num_elts--) *p = init) + +#define FILL_COMPLEX_LOOP \ + FILL_GEN_LOOP(num_elts + num_elts, \ + for (p = data; num_elts > 0; num_elts--) { *p++ = init0; *p++ = init1; }) + CAMLprim value caml_ba_fill(value vb, value vinit) { + CAMLparam1(vb); struct caml_ba_array * b = Caml_ba_array_val(vb); + void *data = b->data; intnat num_elts = caml_ba_num_elts(b); switch (b->flags & CAML_BA_KIND_MASK) { @@ -1156,13 +1191,13 @@ CAMLprim value caml_ba_fill(value vb, value vinit) case CAML_BA_FLOAT32: { float init = Double_val(vinit); float * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + FILL_SCALAR_LOOP; break; } case CAML_BA_FLOAT64: { double init = Double_val(vinit); double * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + FILL_SCALAR_LOOP; break; } case CAML_BA_CHAR: @@ -1170,56 +1205,56 @@ CAMLprim value caml_ba_fill(value vb, value vinit) case CAML_BA_UINT8: { int init = Int_val(vinit); unsigned char * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + FILL_SCALAR_LOOP; break; } case CAML_BA_SINT16: case CAML_BA_UINT16: { int init = Int_val(vinit); int16 * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + FILL_SCALAR_LOOP; break; } case CAML_BA_INT32: { - int32 init = Int32_val(vinit); - int32 * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + int32_t init = Int32_val(vinit); + int32_t * p; + FILL_SCALAR_LOOP; break; } case CAML_BA_INT64: { - int64 init = Int64_val(vinit); - int64 * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + int64_t init = Int64_val(vinit); + int64_t * p; + FILL_SCALAR_LOOP; break; } case CAML_BA_NATIVE_INT: { intnat init = Nativeint_val(vinit); intnat * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + FILL_SCALAR_LOOP; break; } case CAML_BA_CAML_INT: { intnat init = Long_val(vinit); intnat * p; - for (p = b->data; num_elts > 0; p++, num_elts--) *p = init; + FILL_SCALAR_LOOP; break; } case CAML_BA_COMPLEX32: { float init0 = Double_field(vinit, 0); float init1 = Double_field(vinit, 1); float * p; - for (p = b->data; num_elts > 0; num_elts--) { *p++ = init0; *p++ = init1; } + FILL_COMPLEX_LOOP; break; } case CAML_BA_COMPLEX64: { double init0 = Double_field(vinit, 0); double init1 = Double_field(vinit, 1); double * p; - for (p = b->data; num_elts > 0; num_elts--) { *p++ = init0; *p++ = init1; } + FILL_COMPLEX_LOOP; break; } } - return Val_unit; + CAMLreturn (Val_unit); } /* Reshape an array: change dimensions and number of dimensions, preserving diff --git a/otherlibs/bigarray/libbigarray.clib b/otherlibs/bigarray/libbigarray.clib deleted file mode 100644 index 4dc96a4f..00000000 --- a/otherlibs/bigarray/libbigarray.clib +++ /dev/null @@ -1 +0,0 @@ -bigarray_stubs.o mmap_unix.o diff --git a/otherlibs/bigarray/libbigarraywin32.clib b/otherlibs/bigarray/libbigarraywin32.clib deleted file mode 100644 index 16661bb8..00000000 --- a/otherlibs/bigarray/libbigarraywin32.clib +++ /dev/null @@ -1 +0,0 @@ -bigarray_stubs.o mmap_win32.o diff --git a/otherlibs/bigarray/mmap_unix.c b/otherlibs/bigarray/mmap_unix.c index 027b1e5c..69a83361 100644 --- a/otherlibs/bigarray/mmap_unix.c +++ b/otherlibs/bigarray/mmap_unix.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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. */ +/* */ +/**************************************************************************/ /* Needed (under Linux at least) to get pwrite's prototype in unistd.h. Must be defined before the first system .h is included. */ diff --git a/otherlibs/bigarray/mmap_win32.c b/otherlibs/bigarray/mmap_win32.c index 5d7ec6bb..89ac6a45 100644 --- a/otherlibs/bigarray/mmap_win32.c +++ b/otherlibs/bigarray/mmap_win32.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ -/* */ -/* Copyright 2000 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Manuel Serrano and Xavier Leroy, INRIA Rocquencourt */ +/* */ +/* Copyright 2000 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 #include diff --git a/otherlibs/dynlink/.ignore b/otherlibs/dynlink/.ignore deleted file mode 100644 index 5ea9775e..00000000 --- a/otherlibs/dynlink/.ignore +++ /dev/null @@ -1 +0,0 @@ -extract_crc diff --git a/otherlibs/dynlink/Makefile b/otherlibs/dynlink/Makefile index acff7a7a..8f57196c 100644 --- a/otherlibs/dynlink/Makefile +++ b/otherlibs/dynlink/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the dynamic link library @@ -26,17 +28,26 @@ OCAMLOPT = $(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib -I $(ROOTDIR)/stdlib INCLUDES=-I ../../utils -I ../../typing -I ../../bytecomp -I ../../asmcomp COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string \ -I ../../stdlib $(INCLUDES) +ifeq "$(FLAMBDA)" "true" +OPTCOMPFLAGS=-O3 +else +OPTCOMPFLAGS= +endif OBJS=dynlinkaux.cmo dynlink.cmo COMPILEROBJS=\ - ../../utils/misc.cmo ../../utils/config.cmo ../../utils/clflags.cmo \ + ../../utils/misc.cmo ../../utils/config.cmo \ + ../../utils/identifiable.cmo ../../utils/numbers.cmo \ + ../../utils/arg_helper.cmo ../../utils/clflags.cmo \ ../../utils/tbl.cmo ../../utils/consistbl.cmo \ ../../utils/terminfo.cmo ../../utils/warnings.cmo \ ../../parsing/asttypes.cmi \ ../../parsing/location.cmo ../../parsing/longident.cmo \ ../../parsing/docstrings.cmo ../../parsing/ast_helper.cmo \ - ../../parsing/ast_mapper.cmo \ + ../../parsing/ast_mapper.cmo ../../parsing/ast_iterator.cmo \ + ../../parsing/attr_helper.cmo \ + ../../parsing/builtin_attributes.cmo \ ../../typing/ident.cmo ../../typing/path.cmo \ ../../typing/primitive.cmo ../../typing/types.cmo \ ../../typing/btype.cmo ../../typing/subst.cmo ../../typing/predef.cmo \ @@ -77,13 +88,13 @@ extract_crc: dynlink.cma extract_crc.cmo INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) install: - cp dynlink.cmi dynlink.cma dynlink.mli $(INSTALL_LIBDIR) - cp extract_crc $(INSTALL_LIBDIR)/extract_crc$(EXE) + cp dynlink.cmi dynlink.cma dynlink.mli "$(INSTALL_LIBDIR)" + cp extract_crc "$(INSTALL_LIBDIR)/extract_crc$(EXE)" installopt: if $(NATDYNLINK); then \ - cp $(NATOBJS) dynlink.cmxa dynlink.$(A) $(INSTALL_LIBDIR) && \ - cd $(INSTALL_LIBDIR) && $(RANLIB) dynlink.$(A); \ + cp $(NATOBJS) dynlink.cmxa dynlink.$(A) "$(INSTALL_LIBDIR)" && \ + cd "$(INSTALL_LIBDIR)" && $(RANLIB) dynlink.$(A); \ fi partialclean: @@ -101,9 +112,10 @@ clean: partialclean $(OCAMLC) -c $(COMPFLAGS) $< .ml.cmx: - $(OCAMLOPT) -c $(COMPFLAGS) $< + $(OCAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< depend: -dynlink.cmo: dynlinkaux.cmi dynlink.cmi +dynlink.cmi: dynlinkaux.cmi +dynlink.cmo: dynlink.cmi dynlinkaux.cmo extract_crc.cmo: dynlink.cmi diff --git a/otherlibs/dynlink/Makefile.nt b/otherlibs/dynlink/Makefile.nt index c041c2f7..2fb4e17b 100644 --- a/otherlibs/dynlink/Makefile.nt +++ b/otherlibs/dynlink/Makefile.nt @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the dynamic link library diff --git a/otherlibs/dynlink/dynlink.ml b/otherlibs/dynlink/dynlink.ml index 47409ad3..c9a0a3e1 100644 --- a/otherlibs/dynlink/dynlink.ml +++ b/otherlibs/dynlink/dynlink.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Dynamic loading of .cmo files *) @@ -139,6 +141,9 @@ let inited = ref false let init () = if not !inited then begin + if !Sys.interactive then (* PR#6802 *) + invalid_arg "The dynlink.cma library cannot be used \ + inside the OCaml toplevel"; default_crcs := Symtable.init_toplevel(); default_available_units (); inited := true; @@ -237,6 +242,13 @@ let load_compunit ic file_name file_digest compunit = Unit name is needed for .cma files, which produce several code fragments.*) let digest = Digest.string (file_digest ^ compunit.cu_name) in register_code_fragment code code_size digest; + let events = + if compunit.cu_debug = 0 then [| |] + else begin + seek_in ic compunit.cu_debug; + [| input_value ic |] + end in + Meta.add_debug_info code code_size events; begin try ignore((Meta.reify_bytecode code code_size) ()) with exn -> diff --git a/otherlibs/dynlink/dynlink.mli b/otherlibs/dynlink/dynlink.mli index 98ded877..39b3ea62 100644 --- a/otherlibs/dynlink/dynlink.mli +++ b/otherlibs/dynlink/dynlink.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Dynamic loading of object files. *) diff --git a/otherlibs/dynlink/dynlinkaux.mlpack b/otherlibs/dynlink/dynlinkaux.mlpack deleted file mode 100644 index 67b9538e..00000000 --- a/otherlibs/dynlink/dynlinkaux.mlpack +++ /dev/null @@ -1,5 +0,0 @@ -Misc Config Clflags Tbl Consistbl -Terminfo Warnings Asttypes Location Longident -Ident Path Primitive Types Btype Subst Predef -Datarepr Cmi_format Env Lambda Instruct Cmo_format Opcodes -Runtimedef Bytesections Dll Meta Symtable diff --git a/otherlibs/dynlink/extract_crc.ml b/otherlibs/dynlink/extract_crc.ml index 4a6a310a..9b9dc66c 100644 --- a/otherlibs/dynlink/extract_crc.ml +++ b/otherlibs/dynlink/extract_crc.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Print the digests of unit interfaces *) @@ -20,7 +22,7 @@ let print_crc unit = try let crc = Dynlink.digest_interface unit (!load_path @ ["."]) in if !first then first := false else print_string ";\n"; - print_string " \""; print_string (String.capitalize unit); + print_string " \""; print_string (String.capitalize_ascii unit); print_string "\",\n \""; for i = 0 to String.length crc - 1 do Printf.printf "\\%03d" (Char.code crc.[i]) diff --git a/otherlibs/dynlink/natdynlink.ml b/otherlibs/dynlink/natdynlink.ml index 597d60fb..5a70b1d3 100644 --- a/otherlibs/dynlink/natdynlink.ml +++ b/otherlibs/dynlink/natdynlink.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Dynamic loading of .cmx files *) diff --git a/otherlibs/graph/.depend b/otherlibs/graph/.depend index 48b345b7..06ba20b8 100644 --- a/otherlibs/graph/.depend +++ b/otherlibs/graph/.depend @@ -13,7 +13,7 @@ draw.o: draw.c libgraph.h \ ../../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/alloc.h ../../byterun/caml/mlvalues.h + ../../byterun/caml/alloc.h dump_img.o: dump_img.c libgraph.h \ \ \ @@ -21,10 +21,10 @@ dump_img.o: dump_img.c libgraph.h \ ../../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 image.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.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/alloc.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 events.o: events.c libgraph.h \ \ \ @@ -32,8 +32,7 @@ events.o: events.c libgraph.h \ ../../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/alloc.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/signals.h + ../../byterun/caml/alloc.h ../../byterun/caml/signals.h fill.o: fill.c libgraph.h \ \ \ @@ -42,9 +41,8 @@ fill.o: fill.c libgraph.h \ ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/major_gc.h ../../byterun/caml/freelist.h \ + ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h image.o: image.c libgraph.h \ \ \ @@ -52,8 +50,7 @@ image.o: image.c libgraph.h \ ../../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 image.h \ - ../../byterun/caml/alloc.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/custom.h + ../../byterun/caml/alloc.h ../../byterun/caml/custom.h make_img.o: make_img.c libgraph.h \ \ \ @@ -62,9 +59,8 @@ make_img.o: make_img.c libgraph.h \ ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h image.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/major_gc.h ../../byterun/caml/freelist.h \ + ../../byterun/caml/minor_gc.h ../../byterun/caml/address_class.h open.o: open.c libgraph.h \ \ \ @@ -72,11 +68,11 @@ open.o: open.c libgraph.h \ ../../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/alloc.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/callback.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/alloc.h ../../byterun/caml/callback.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 point_col.o: point_col.c libgraph.h \ \ \ @@ -105,7 +101,7 @@ text.o: text.c libgraph.h \ ../../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/alloc.h ../../byterun/caml/mlvalues.h + ../../byterun/caml/alloc.h graphics.cmi : graphicsX11.cmi : graphics.cmo : graphics.cmi diff --git a/otherlibs/graph/Makefile b/otherlibs/graph/Makefile index 850e0251..4e844d74 100644 --- a/otherlibs/graph/Makefile +++ b/otherlibs/graph/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the portable graphics library diff --git a/otherlibs/graph/color.c b/otherlibs/graph/color.c index 5b940605..5d7bafc7 100644 --- a/otherlibs/graph/color.c +++ b/otherlibs/graph/color.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include diff --git a/otherlibs/graph/draw.c b/otherlibs/graph/draw.c index 195860fa..6e0f9373 100644 --- a/otherlibs/graph/draw.c +++ b/otherlibs/graph/draw.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include diff --git a/otherlibs/graph/dump_img.c b/otherlibs/graph/dump_img.c index 26f81607..38fab8be 100644 --- a/otherlibs/graph/dump_img.c +++ b/otherlibs/graph/dump_img.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include "image.h" diff --git a/otherlibs/graph/events.c b/otherlibs/graph/events.c index a8fe119b..4a685f04 100644 --- a/otherlibs/graph/events.c +++ b/otherlibs/graph/events.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "libgraph.h" diff --git a/otherlibs/graph/fill.c b/otherlibs/graph/fill.c index 8dc2f877..dc7baf0f 100644 --- a/otherlibs/graph/fill.c +++ b/otherlibs/graph/fill.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include diff --git a/otherlibs/graph/graphics.ml b/otherlibs/graph/graphics.ml index 441c6760..84cea7d5 100644 --- a/otherlibs/graph/graphics.ml +++ b/otherlibs/graph/graphics.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) exception Graphic_failure of string diff --git a/otherlibs/graph/graphics.mli b/otherlibs/graph/graphics.mli index 81cd4eeb..c32ff39e 100644 --- a/otherlibs/graph/graphics.mli +++ b/otherlibs/graph/graphics.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Machine-independent graphics primitives. *) diff --git a/otherlibs/graph/graphics.mllib b/otherlibs/graph/graphics.mllib deleted file mode 100644 index d5e8f9eb..00000000 --- a/otherlibs/graph/graphics.mllib +++ /dev/null @@ -1 +0,0 @@ -Graphics GraphicsX11 diff --git a/otherlibs/graph/graphicsX11.ml b/otherlibs/graph/graphicsX11.ml index 33ef1bc9..10f39f32 100644 --- a/otherlibs/graph/graphicsX11.ml +++ b/otherlibs/graph/graphicsX11.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Pierre Weis and Jun Furuse, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Weis and Jun Furuse, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (* Module [GraphicsX11]: additional graphics primitives for the X Windows system *) diff --git a/otherlibs/graph/graphicsX11.mli b/otherlibs/graph/graphicsX11.mli index 918f9d50..e0229996 100644 --- a/otherlibs/graph/graphicsX11.mli +++ b/otherlibs/graph/graphicsX11.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Pierre Weis and Jun Furuse, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Weis and Jun Furuse, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (** Additional graphics primitives for the X Windows system. *) diff --git a/otherlibs/graph/image.c b/otherlibs/graph/image.c index 12588bf7..ffd6a95e 100644 --- a/otherlibs/graph/image.c +++ b/otherlibs/graph/image.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include "image.h" diff --git a/otherlibs/graph/image.h b/otherlibs/graph/image.h index 806f1fd2..acb85110 100644 --- a/otherlibs/graph/image.h +++ b/otherlibs/graph/image.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ struct grimage { int width, height; /* Dimensions of the image */ diff --git a/otherlibs/graph/libgraph.h b/otherlibs/graph/libgraph.h index 9b2972bc..5eb397af 100644 --- a/otherlibs/graph/libgraph.h +++ b/otherlibs/graph/libgraph.h @@ -1,20 +1,23 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include #include +#include struct canvas { int w, h; /* Dimensions of the drawable */ @@ -73,7 +76,10 @@ extern int caml_gr_bits_per_pixel; #endif #endif -extern void caml_gr_fail(char *fmt, char *arg); +CAMLnoreturn_start +extern void caml_gr_fail(char *fmt, char *arg) +CAMLnoreturn_end; + extern void caml_gr_check_open(void); extern unsigned long caml_gr_pixel_rgb(int rgb); extern int caml_gr_rgb_pixel(long unsigned int pixel); diff --git a/otherlibs/graph/libgraphics.clib b/otherlibs/graph/libgraphics.clib deleted file mode 100644 index d3b5b7b6..00000000 --- a/otherlibs/graph/libgraphics.clib +++ /dev/null @@ -1,3 +0,0 @@ -open.o draw.o fill.o color.o text.o -image.o make_img.o dump_img.o point_col.o sound.o events.o -subwindow.o diff --git a/otherlibs/graph/make_img.c b/otherlibs/graph/make_img.c index b9c4bfca..f1cd761d 100644 --- a/otherlibs/graph/make_img.c +++ b/otherlibs/graph/make_img.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include "image.h" diff --git a/otherlibs/graph/open.c b/otherlibs/graph/open.c index e8d26acf..eb94fc78 100644 --- a/otherlibs/graph/open.c +++ b/otherlibs/graph/open.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/graph/point_col.c b/otherlibs/graph/point_col.c index da1e8799..3c3d33db 100644 --- a/otherlibs/graph/point_col.c +++ b/otherlibs/graph/point_col.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" diff --git a/otherlibs/graph/sound.c b/otherlibs/graph/sound.c index 4ce11010..75ab2a57 100644 --- a/otherlibs/graph/sound.c +++ b/otherlibs/graph/sound.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" diff --git a/otherlibs/graph/subwindow.c b/otherlibs/graph/subwindow.c index 952dccb8..8ccd78fb 100644 --- a/otherlibs/graph/subwindow.c +++ b/otherlibs/graph/subwindow.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Jun Furuse, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jun Furuse, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #include "libgraph.h" diff --git a/otherlibs/graph/text.c b/otherlibs/graph/text.c index 7450df89..3fccaa01 100644 --- a/otherlibs/graph/text.c +++ b/otherlibs/graph/text.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "libgraph.h" #include diff --git a/otherlibs/num/.depend b/otherlibs/num/.depend index ce7cc9b8..7e8a3999 100644 --- a/otherlibs/num/.depend +++ b/otherlibs/num/.depend @@ -1,6 +1,7 @@ bng.o: bng.c bng.h ../../byterun/caml/config.h \ - ../../byterun/caml/../../config/m.h ../../byterun/caml/../../config/s.h \ - ../../byterun/caml/compatibility.h bng_amd64.c bng_digit.c + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/compatibility.h \ + bng_amd64.c bng_digit.c bng_amd64.o: bng_amd64.c bng_arm64.o: bng_arm64.c bng_digit.o: bng_digit.c @@ -11,13 +12,12 @@ nat_stubs.o: nat_stubs.c ../../byterun/caml/alloc.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 \ - ../../byterun/caml/config.h ../../byterun/caml/custom.h \ - ../../byterun/caml/intext.h ../../byterun/caml/io.h \ - ../../byterun/caml/fail.h ../../byterun/caml/hash.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/mlvalues.h bng.h nat.h + ../../byterun/caml/custom.h ../../byterun/caml/intext.h \ + ../../byterun/caml/io.h ../../byterun/caml/fail.h \ + ../../byterun/caml/hash.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 bng.h nat.h arith_flags.cmi : arith_status.cmi : big_int.cmi : nat.cmi diff --git a/otherlibs/num/Makefile b/otherlibs/num/Makefile index e08e0294..344789b1 100644 --- a/otherlibs/num/Makefile +++ b/otherlibs/num/Makefile @@ -1,17 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### - -# $Id$ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the "num" (exact rational arithmetic) library diff --git a/otherlibs/num/Makefile.nt b/otherlibs/num/Makefile.nt index 4ac69c7c..2b0fab0a 100644 --- a/otherlibs/num/Makefile.nt +++ b/otherlibs/num/Makefile.nt @@ -1,17 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### - -# $Id$ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the "num" (exact rational arithmetic) library diff --git a/otherlibs/num/arith_flags.ml b/otherlibs/num/arith_flags.ml index df109ae9..a1ca0b02 100644 --- a/otherlibs/num/arith_flags.ml +++ b/otherlibs/num/arith_flags.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let error_when_null_denominator_flag = ref true;; diff --git a/otherlibs/num/arith_flags.mli b/otherlibs/num/arith_flags.mli index 791446c2..7dd6bc79 100644 --- a/otherlibs/num/arith_flags.mli +++ b/otherlibs/num/arith_flags.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) val error_when_null_denominator_flag : bool ref val normalize_ratio_flag : bool ref diff --git a/otherlibs/num/arith_status.ml b/otherlibs/num/arith_status.ml index 585db9d0..2fbdd4a6 100644 --- a/otherlibs/num/arith_status.ml +++ b/otherlibs/num/arith_status.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Arith_flags;; diff --git a/otherlibs/num/arith_status.mli b/otherlibs/num/arith_status.mli index cc0289da..9bbc7828 100644 --- a/otherlibs/num/arith_status.mli +++ b/otherlibs/num/arith_status.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Flags that control rational arithmetic. *) @@ -18,6 +20,7 @@ val arith_status: unit -> unit val get_error_when_null_denominator : unit -> bool (** See {!Arith_status.set_error_when_null_denominator}.*) + val set_error_when_null_denominator : bool -> unit (** Get or set the flag [null_denominator]. When on, attempting to create a rational with a null denominator raises an exception. @@ -26,6 +29,7 @@ val set_error_when_null_denominator : bool -> unit val get_normalize_ratio : unit -> bool (** See {!Arith_status.set_normalize_ratio}.*) + val set_normalize_ratio : bool -> unit (** Get or set the flag [normalize_ratio]. When on, rational numbers are normalized after each operation. When off, @@ -34,6 +38,7 @@ val set_normalize_ratio : bool -> unit val get_normalize_ratio_when_printing : unit -> bool (** See {!Arith_status.set_normalize_ratio_when_printing}.*) + val set_normalize_ratio_when_printing : bool -> unit (** Get or set the flag [normalize_ratio_when_printing]. When on, rational numbers are normalized before being printed. @@ -42,6 +47,7 @@ val set_normalize_ratio_when_printing : bool -> unit val get_approx_printing : unit -> bool (** See {!Arith_status.set_approx_printing}.*) + val set_approx_printing : bool -> unit (** Get or set the flag [approx_printing]. When on, rational numbers are printed as a decimal approximation. @@ -50,6 +56,7 @@ val set_approx_printing : bool -> unit val get_floating_precision : unit -> int (** See {!Arith_status.set_floating_precision}.*) + val set_floating_precision : int -> unit (** Get or set the parameter [floating_precision]. This parameter is the number of digits displayed when diff --git a/otherlibs/num/big_int.ml b/otherlibs/num/big_int.ml index 847d1583..6fb030d5 100644 --- a/otherlibs/num/big_int.ml +++ b/otherlibs/num/big_int.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Int_misc open Nat @@ -41,6 +43,15 @@ let unit_big_int = let num_digits_big_int bi = num_digits_nat (bi.abs_value) 0 (length_nat bi.abs_value) +(* Number of bits in a big_int *) +let num_bits_big_int bi = + let nd = num_digits_nat (bi.abs_value) 0 (length_nat bi.abs_value) in + (* nd = 1 if bi = 0 *) + let lz = num_leading_zero_bits_in_digit bi.abs_value (nd - 1) in + (* lz = length_of_digit if bi = 0 *) + nd * length_of_digit - lz + (* = 0 if bi = 0 *) + (* Opposite of a big_int *) let minus_big_int bi = { sign = - bi.sign; @@ -201,7 +212,7 @@ let mult_big_int bi1 bi2 = else (ignore (mult_nat res 0 size_res (bi1.abs_value) 0 size_bi1 (bi2.abs_value) 0 size_bi2);res) } -(* (quotient, rest) of the euclidian division of 2 big_int *) +(* (quotient, remainder ) of the euclidian division of 2 big_int *) let quomod_big_int bi1 bi2 = if bi2.sign = 0 then raise Division_by_zero else @@ -209,8 +220,8 @@ let quomod_big_int bi1 bi2 = and size_bi2 = num_digits_big_int bi2 in match compare_nat (bi1.abs_value) 0 size_bi1 (bi2.abs_value) 0 size_bi2 with - -1 -> (* 1/2 -> 0, reste 1, -1/2 -> -1, reste 1 *) - (* 1/-2 -> 0, reste 1, -1/-2 -> 1, reste 1 *) + -1 -> (* 1/2 -> 0, remains 1, -1/2 -> -1, remains 1 *) + (* 1/-2 -> 0, remains 1, -1/-2 -> 1, remains 1 *) if bi1.sign >= 0 then (big_int_of_int 0, bi1) else if bi2.sign >= 0 then @@ -429,9 +440,12 @@ let sys_big_int_of_string_base s ofs len sgn = if len < 2 then sys_big_int_of_string_aux s ofs len sgn 10 else match (s.[ofs], s.[ofs+1]) with - | ('0', 'x') | ('0', 'X') -> sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 16 - | ('0', 'o') | ('0', 'O') -> sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 8 - | ('0', 'b') | ('0', 'B') -> sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 2 + | ('0', 'x') | ('0', 'X') -> + sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 16 + | ('0', 'o') | ('0', 'O') -> + sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 8 + | ('0', 'b') | ('0', 'B') -> + sys_big_int_of_string_aux s (ofs+2) (len-2) sgn 2 | _ -> sys_big_int_of_string_aux s ofs len sgn 10 ;; @@ -593,13 +607,6 @@ let base_power_big_int base n bi = then zero_big_int else create_big_int (bi.sign) res -(* Coercion with float type *) - -let float_of_big_int bi = - float_of_string (string_of_big_int bi) - -(* XL: suppression de big_int_of_float et nat_of_float. *) - (* Other functions needed *) (* Integer part of the square root of a big_int *) @@ -717,10 +724,11 @@ let two_power_m1_big_int n = if n < 0 then invalid_arg "two_power_m1_big_int" else if n = 0 then zero_big_int else begin - let size_res = (n + length_of_digit - 1) / length_of_digit in + let idx = n / length_of_digit in + let size_res = idx + 1 in let res = make_nat size_res in - set_digit_nat_native res (n / length_of_digit) - (Nativeint.shift_left 1n (n mod length_of_digit)); + set_digit_nat_native res idx + (Nativeint.shift_left 1n (n mod length_of_digit)); ignore (decr_nat res 0 size_res 0); { sign = 1; abs_value = res } end @@ -730,7 +738,8 @@ let two_power_m1_big_int n = let shift_right_big_int bi n = if n < 0 then invalid_arg "shift_right_big_int" else if bi.sign >= 0 then shift_right_towards_zero_big_int bi n - else shift_right_towards_zero_big_int (sub_big_int bi (two_power_m1_big_int n)) n + else + shift_right_towards_zero_big_int (sub_big_int bi (two_power_m1_big_int n)) n (* Extract N bits starting at ofs. Treats bi in two's complement. @@ -836,3 +845,39 @@ let xor_big_int a b = then zero_big_int else { sign = 1; abs_value = res } end + +(* Coercion with float type *) + +(* Consider a real number [r] such that + - the integral part of [r] is the bigint [x] + - 2^54 <= |x| < 2^63 + - the fractional part of [r] is 0 if [exact = true], + nonzero if [exact = false]. + Then, the following function returns [r] correctly rounded to + the nearest double-precision floating-point number. + This is an instance of the "round to odd" technique formalized in + "When double rounding is odd" by S. Boldo and G. Melquiond. + The claim above is lemma Fappli_IEEE_extra.round_odd_fix + from the CompCert Coq development. *) + +let round_big_int_to_float x exact = + assert (let n = num_bits_big_int x in 55 <= n && n <= 63); + let m = int64_of_big_int x in + (* Unless the fractional part is exactly 0, round m to an odd integer *) + let m = if exact then m else Int64.logor m 1L in + (* Then convert m to float, with the normal rounding mode. *) + Int64.to_float m + +let float_of_big_int x = + let n = num_bits_big_int x in + if n <= 63 then + Int64.to_float (int64_of_big_int x) + else begin + let n = n - 55 in + (* Extract top 55 bits of x *) + let top = shift_right_big_int x n in + (* Check if the other bits are all zero *) + let exact = eq_big_int x (shift_left_big_int top n) in + (* Round to float and apply exponent *) + ldexp (round_big_int_to_float top exact) n + end diff --git a/otherlibs/num/big_int.mli b/otherlibs/num/big_int.mli index 738730a7..011b83c3 100644 --- a/otherlibs/num/big_int.mli +++ b/otherlibs/num/big_int.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Operations on arbitrary-precision integers. @@ -23,6 +25,7 @@ type big_int val zero_big_int : big_int (** The big integer [0]. *) + val unit_big_int : big_int (** The big integer [1]. *) @@ -30,28 +33,39 @@ val unit_big_int : big_int val minus_big_int : big_int -> big_int (** Unary negation. *) + val abs_big_int : big_int -> big_int (** Absolute value. *) + val add_big_int : big_int -> big_int -> big_int (** Addition. *) + val succ_big_int : big_int -> big_int (** Successor (add 1). *) + val add_int_big_int : int -> big_int -> big_int (** Addition of a small integer to a big integer. *) + val sub_big_int : big_int -> big_int -> big_int (** Subtraction. *) + val pred_big_int : big_int -> big_int (** Predecessor (subtract 1). *) + val mult_big_int : big_int -> big_int -> big_int (** Multiplication of two big integers. *) + val mult_int_big_int : int -> big_int -> big_int (** Multiplication of a big integer by a small integer *) + val square_big_int: big_int -> big_int (** Return the square of the given big integer *) + val sqrt_big_int: big_int -> big_int (** [sqrt_big_int a] returns the integer square root of [a], that is, the largest big integer [r] such that [r * r <= a]. Raise [Invalid_argument] if [a] is negative. *) + val quomod_big_int : big_int -> big_int -> big_int * big_int (** Euclidean division of two big integers. The first part of the result is the quotient, @@ -59,14 +73,18 @@ val quomod_big_int : big_int -> big_int -> big_int * big_int Writing [(q,r) = quomod_big_int a b], we have [a = q * b + r] and [0 <= r < |b|]. Raise [Division_by_zero] if the divisor is zero. *) + val div_big_int : big_int -> big_int -> big_int (** Euclidean quotient of two big integers. This is the first result [q] of [quomod_big_int] (see above). *) + val mod_big_int : big_int -> big_int -> big_int (** Euclidean modulus of two big integers. This is the second result [r] of [quomod_big_int] (see above). *) + val gcd_big_int : big_int -> big_int -> big_int (** Greatest common divisor of two big integers. *) + val power_int_positive_int: int -> int -> big_int val power_big_int_positive_int: big_int -> int -> big_int val power_int_positive_big_int: int -> big_int -> big_int @@ -82,29 +100,41 @@ val power_big_int_positive_big_int: big_int -> big_int -> big_int val sign_big_int : big_int -> int (** Return [0] if the given big integer is zero, [1] if it is positive, and [-1] if it is negative. *) + val compare_big_int : big_int -> big_int -> int (** [compare_big_int a b] returns [0] if [a] and [b] are equal, [1] if [a] is greater than [b], and [-1] if [a] is smaller than [b]. *) + val eq_big_int : big_int -> big_int -> bool val le_big_int : big_int -> big_int -> bool val ge_big_int : big_int -> big_int -> bool val lt_big_int : big_int -> big_int -> bool val gt_big_int : big_int -> big_int -> bool (** Usual boolean comparisons between two big integers. *) + val max_big_int : big_int -> big_int -> big_int (** Return the greater of its two arguments. *) + val min_big_int : big_int -> big_int -> big_int (** Return the smaller of its two arguments. *) + val num_digits_big_int : big_int -> int (** Return the number of machine words used to store the given big integer. *) +val num_bits_big_int : big_int -> int + (** Return the number of significant bits in the absolute + value of the given big integer. [num_bits_big_int a] + returns 0 if [a] is 0; otherwise it returns a positive + integer [n] such that [2^(n-1) <= |a| < 2^n]. *) + (** {6 Conversions to and from strings} *) val string_of_big_int : big_int -> string (** Return the string representation of the given big integer, in decimal (base 10). *) + 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, @@ -114,6 +144,7 @@ val big_int_of_string : string -> big_int val big_int_of_int : int -> big_int (** Convert a small integer to a big integer. *) + val is_int_big_int : big_int -> bool (** Test whether the given big integer is small enough to be representable as a small integer (type [int]) @@ -122,6 +153,7 @@ val is_int_big_int : big_int -> bool [a] is between 2{^30} and 2{^30}-1. On a 64-bit platform, [is_int_big_int a] returns [true] if and only if [a] is between -2{^62} and 2{^62}-1. *) + val int_of_big_int : big_int -> int (** Convert a big integer to a small integer (type [int]). Raises [Failure "int_of_big_int"] if the big integer @@ -129,22 +161,27 @@ val int_of_big_int : big_int -> int val big_int_of_int32 : int32 -> big_int (** Convert a 32-bit integer to a big integer. *) + val big_int_of_nativeint : nativeint -> big_int (** Convert a native integer to a big integer. *) + val big_int_of_int64 : int64 -> big_int (** Convert a 64-bit integer to a big integer. *) + val int32_of_big_int : big_int -> int32 (** Convert a big integer to a 32-bit integer. Raises [Failure] if the big integer is outside the - range [[-2{^31}, 2{^31}-1]]. *) + range \[-2{^31}, 2{^31}-1\]. *) + 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 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]]. *) + range \[-2{^63}, 2{^63}-1\]. *) val float_of_big_int : big_int -> float (** Returns a floating-point number approximating the @@ -155,25 +192,31 @@ val float_of_big_int : big_int -> float val and_big_int : big_int -> big_int -> big_int (** Bitwise logical 'and'. The arguments must be positive or zero. *) + val or_big_int : big_int -> big_int -> big_int (** Bitwise logical 'or'. The arguments must be positive or zero. *) + val xor_big_int : big_int -> big_int -> big_int (** Bitwise logical 'exclusive or'. The arguments must be positive or zero. *) + val shift_left_big_int : big_int -> int -> big_int (** [shift_left_big_int b n] returns [b] shifted left by [n] bits. - Equivalent to multiplication by [2^n]. *) + Equivalent to multiplication by 2^n. *) + val shift_right_big_int : big_int -> int -> big_int (** [shift_right_big_int b n] returns [b] shifted right by [n] bits. - Equivalent to division by [2^n] with the result being + Equivalent to division by 2^n with the result being rounded towards minus infinity. *) + val shift_right_towards_zero_big_int : big_int -> int -> big_int (** [shift_right_towards_zero_big_int b n] returns [b] shifted right by [n] bits. The shift is performed on the absolute value of [b], and the result has the same sign as [b]. - Equivalent to division by [2^n] with the result being + Equivalent to division by 2^n with the result being rounded towards zero. *) + val extract_big_int : big_int -> int -> int -> big_int (** [extract_big_int bi ofs n] returns a nonnegative number corresponding to bits [ofs] to [ofs + n - 1] of the @@ -189,3 +232,4 @@ val base_power_big_int: int -> int -> big_int -> big_int val sys_big_int_of_string: string -> int -> int -> big_int 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 diff --git a/otherlibs/num/bng.c b/otherlibs/num/bng.c index 585e434e..c4d0ea1a 100644 --- a/otherlibs/num/bng.c +++ b/otherlibs/num/bng.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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 "bng.h" #include "caml/config.h" diff --git a/otherlibs/num/bng.h b/otherlibs/num/bng.h index 527bee6a..406117dd 100644 --- a/otherlibs/num/bng.h +++ b/otherlibs/num/bng.h @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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 #include "caml/config.h" diff --git a/otherlibs/num/bng_amd64.c b/otherlibs/num/bng_amd64.c index ecf9f253..585900e9 100644 --- a/otherlibs/num/bng_amd64.c +++ b/otherlibs/num/bng_amd64.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /* Code specific to the AMD x86_64 architecture. */ diff --git a/otherlibs/num/bng_arm64.c b/otherlibs/num/bng_arm64.c index 50843a0e..b900b803 100644 --- a/otherlibs/num/bng_arm64.c +++ b/otherlibs/num/bng_arm64.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ -/* */ -/* Copyright 2013 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2013 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. */ +/* */ +/**************************************************************************/ /* Code specific for the ARM 64 (AArch64) architecture */ diff --git a/otherlibs/num/bng_digit.c b/otherlibs/num/bng_digit.c index fc10c8a3..6983af65 100644 --- a/otherlibs/num/bng_digit.c +++ b/otherlibs/num/bng_digit.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /**** Generic operations on digits ****/ diff --git a/otherlibs/num/bng_ia32.c b/otherlibs/num/bng_ia32.c index b4981cd4..6b6cabd2 100644 --- a/otherlibs/num/bng_ia32.c +++ b/otherlibs/num/bng_ia32.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /* Code specific to the Intel IA32 (x86) architecture. */ diff --git a/otherlibs/num/bng_ppc.c b/otherlibs/num/bng_ppc.c index 6bbf108e..f4c098cf 100644 --- a/otherlibs/num/bng_ppc.c +++ b/otherlibs/num/bng_ppc.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /* Code specific to the PowerPC architecture. */ @@ -79,7 +79,7 @@ : "=&r" (res), "=&r" (carryaccu) \ : "r" (arg1), "r" (arg2), "r" (arg3), "1" (carryaccu)) -#ifdef __ppc64__ +#if defined(__ppc64__) || defined(__PPC64__) #define BngMult(resh,resl,arg1,arg2) \ asm("mulld %0, %2, %3 \n\t" \ "mulhdu %1, %2, %3" \ diff --git a/otherlibs/num/bng_sparc.c b/otherlibs/num/bng_sparc.c index 4e46a316..c007cb77 100644 --- a/otherlibs/num/bng_sparc.c +++ b/otherlibs/num/bng_sparc.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/**************************************************************************/ /* Code specific to the SPARC (V8 and above) architecture. */ diff --git a/otherlibs/num/int_misc.ml b/otherlibs/num/int_misc.ml index f8a91ee3..d7d7190e 100644 --- a/otherlibs/num/int_misc.ml +++ b/otherlibs/num/int_misc.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Some extra operations on integers *) diff --git a/otherlibs/num/int_misc.mli b/otherlibs/num/int_misc.mli index 6146732d..1ee11ba5 100644 --- a/otherlibs/num/int_misc.mli +++ b/otherlibs/num/int_misc.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Some extra operations on integers *) diff --git a/otherlibs/num/libnums.clib b/otherlibs/num/libnums.clib deleted file mode 100644 index 47c751f5..00000000 --- a/otherlibs/num/libnums.clib +++ /dev/null @@ -1 +0,0 @@ -bng.o nat_stubs.o diff --git a/otherlibs/num/nat.h b/otherlibs/num/nat.h index 62c7ac98..45e7b957 100644 --- a/otherlibs/num/nat.h +++ b/otherlibs/num/nat.h @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* 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 Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ /* Nats are represented as unstructured blocks with tag Custom_tag. */ diff --git a/otherlibs/num/nat.ml b/otherlibs/num/nat.ml index 5ea5fda7..c0edabd9 100644 --- a/otherlibs/num/nat.ml +++ b/otherlibs/num/nat.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Int_misc @@ -20,28 +22,44 @@ external set_to_zero_nat: nat -> int -> int -> unit = "set_to_zero_nat" external blit_nat: nat -> int -> nat -> int -> int -> unit = "blit_nat" external set_digit_nat: nat -> int -> int -> unit = "set_digit_nat" external nth_digit_nat: nat -> int -> int = "nth_digit_nat" -external set_digit_nat_native: nat -> int -> nativeint -> unit = "set_digit_nat_native" +external set_digit_nat_native: nat -> int -> nativeint -> unit + = "set_digit_nat_native" external nth_digit_nat_native: nat -> int -> nativeint = "nth_digit_nat_native" external num_digits_nat: nat -> int -> int -> int = "num_digits_nat" -external num_leading_zero_bits_in_digit: nat -> int -> int = "num_leading_zero_bits_in_digit" +external num_leading_zero_bits_in_digit: nat -> int -> int + = "num_leading_zero_bits_in_digit" external is_digit_int: nat -> int -> bool = "is_digit_int" external is_digit_zero: nat -> int -> bool = "is_digit_zero" external is_digit_normalized: nat -> int -> bool = "is_digit_normalized" external is_digit_odd: nat -> int -> bool = "is_digit_odd" external incr_nat: nat -> int -> int -> int -> int = "incr_nat" -external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "add_nat" "add_nat_native" +external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int + = "add_nat" "add_nat_native" external complement_nat: nat -> int -> int -> unit = "complement_nat" external decr_nat: nat -> int -> int -> int -> int = "decr_nat" -external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "sub_nat" "sub_nat_native" -external mult_digit_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int = "mult_digit_nat" "mult_digit_nat_native" -external mult_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int = "mult_nat" "mult_nat_native" -external square_nat: nat -> int -> int -> nat -> int -> int -> int = "square_nat" "square_nat_native" -external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_left_nat" "shift_left_nat_native" -external div_digit_nat: nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit = "div_digit_nat" "div_digit_nat_native" -external div_nat: nat -> int -> int -> nat -> int -> int -> unit = "div_nat" "div_nat_native" -external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_right_nat" "shift_right_nat_native" -external compare_digits_nat: nat -> int -> nat -> int -> int = "compare_digits_nat" -external compare_nat: nat -> int -> int -> nat -> int -> int -> int = "compare_nat" "compare_nat_native" +external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int + = "sub_nat" "sub_nat_native" +external mult_digit_nat: + nat -> int -> int -> nat -> int -> int -> nat -> int -> int + = "mult_digit_nat" "mult_digit_nat_native" +external mult_nat: + nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int + = "mult_nat" "mult_nat_native" +external square_nat: nat -> int -> int -> nat -> int -> int -> int + = "square_nat" "square_nat_native" +external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit + = "shift_left_nat" "shift_left_nat_native" +external div_digit_nat: + nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit + = "div_digit_nat" "div_digit_nat_native" +external div_nat: nat -> int -> int -> nat -> int -> int -> unit + = "div_nat" "div_nat_native" +external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit + = "shift_right_nat" "shift_right_nat_native" +external compare_digits_nat: nat -> int -> nat -> int -> int + = "compare_digits_nat" +external compare_nat: nat -> int -> int -> nat -> int -> int -> int + = "compare_nat" "compare_nat_native" external land_digit_nat: nat -> int -> nat -> int -> unit = "land_digit_nat" external lor_digit_nat: nat -> int -> nat -> int -> unit = "lor_digit_nat" external lxor_digit_nat: nat -> int -> nat -> int -> unit = "lxor_digit_nat" @@ -183,18 +201,18 @@ let gcd_nat nat1 off1 len1 nat2 off2 len2 = !real_len1 end -(* Racine carrée entière par la méthode de Newton (entière par défaut). *) +(* Integer square root using newton method (nearest integer by default) *) -(* Théorème: la suite xn+1 = (xn + a/xn) / 2 converge vers la racine *) -(* carrée entière de a par défaut, si on part d'une valeur x0 *) -(* strictement plus grande que la racine de a, sauf quand a est un *) -(* carré - 1, cas auquel la suite alterne entre la racine par défaut *) -(* et par excès. Dans tous les cas, le dernier terme de la partie *) -(* strictement décroissante de la suite est le résultat cherché. *) +(* Theorem: the sequence x_{n+1} = ( x_n + a/x_n )/2 converges toward + the integer square root (by default) of a for any starting value x_0 + strictly greater than the square root of a except if a + 1 is a + perfect square. In this situation, the sequence alternates between + the excess and default integer square root. In any case, the last + strictly decreasing term is the expected result *) let sqrt_nat rad off len = let len = num_digits_nat rad off len in - (* Copie de travail du radicande *) + (* Working copy of radicand *) let len_parity = len mod 2 in let rad_len = len + 1 + len_parity in let rad = @@ -205,17 +223,18 @@ let sqrt_nat rad off len = res in let cand_len = (len + 1) / 2 in (* ceiling len / 2 *) let cand_rest = rad_len - cand_len in - (* Racine carrée supposée cand = "|FFFF .... |" *) + (* Candidate square root cand = "|FFFF .... |" *) let cand = make_nat cand_len in - (* Amélioration de la racine de départ: - on calcule nbb le nombre de bits significatifs du premier digit du candidat - (la moitié du nombre de bits significatifs dans les deux premiers - digits du radicande étendu à une longueur paire). - shift_cand est word_size - nbb *) + (* Improve starting square root: + We compute nbb, the number of significant bits of the first digit of the + candidate + (half of the number of significant bits in the first two digits + of the radicand extended to an even length). + shift_cand is word_size - nbb *) let shift_cand = ((num_leading_zero_bits_in_digit rad (len-1)) + Sys.word_size * len_parity) / 2 in - (* Tous les bits du radicande sont à 0, on rend 0. *) + (* All radicand bits are zeroed, we give back 0. *) if shift_cand = Sys.word_size then cand else begin complement_nat cand 0 cand_len; @@ -227,7 +246,7 @@ let sqrt_nat rad off len = blit_nat next_cand 0 rad 0 rad_len; (* next_cand <- next_cand / cand *) div_nat next_cand 0 rad_len cand 0 cand_len; - (* next_cand (poids fort) <- next_cand (poids fort) + cand, + (* next_cand (strong weight) <- next_cand (strong weight) + cand, i.e. next_cand <- cand + rad / cand *) ignore (add_nat next_cand cand_len cand_rest cand 0 cand_len 0); (* next_cand <- next_cand / 2 *) @@ -296,7 +315,13 @@ let raw_string_of_digit nat off = (* XL: suppression de string_of_digit et de sys_string_of_digit. La copie est de toute facon faite dans string_of_nat, qui est le - seul point d entree public dans ce code. *) + seul point d entree public dans ce code. + + | Deletion of string_of_digit and sys_string_of_digit. + The copy is already done in string_of_nat which is the only + public entry point in this code + +*) (****** let sys_string_of_digit nat off = @@ -339,9 +364,9 @@ let make_power_base base power_base = (!i - 2, !j) (* - int_to_string place la representation de l entier int en base base - dans la chaine s en le rangeant de la fin indiquee par pos vers le - debut, sur times places et affecte a pos sa nouvelle valeur. + int_to_string places the representation of the integer int in base 'base' + in the string s by starting from the end position pos and going towards + the start, for 'times' places and updates the value of pos. *) let int_to_string int s pos_ref base times = let i = ref int @@ -353,8 +378,6 @@ let int_to_string int s pos_ref base times = i := !i / base done -(* XL: suppression de adjust_string *) - let power_base_int base i = if i = 0 || base = 1 then nat_of_int 1 @@ -406,8 +429,9 @@ let power_base_int base i = -- -- *) -(* XL: ai specialise le code d origine a length_of_digit = 32. *) -(* Puis suppression (inutile?) *) +(* XL: ai specialise le code d origine a length_of_digit = 32. + | the original code have been specialized to a length_of_digit = 32. *) +(* Now deleted (useless?) *) (****** let num_digits_max_vector = @@ -455,8 +479,6 @@ let num_digits_max_vector = | n -> failwith "num_digits_max_vector" ******) -(* XL: suppression de string_list_of_nat *) - let unadjusted_string_of_nat nat off len_nat = let len = num_digits_nat nat off len_nat in if len = 1 then @@ -483,9 +505,6 @@ let unadjusted_string_of_nat nat off len_nat = String.blit str 0 s (!pos_ref - String.length str) (String.length str); - (* XL: il y avait pmax a la place de String.length str - mais ca ne marche pas avec le blit de Caml Light, - qui ne verifie pas les debordements *) pos_ref := !pos_ref - pmax; len_copy := num_digits_nat copy2 0 !len_copy; blit_nat copy1 0 copy2 0 !len_copy; @@ -504,10 +523,6 @@ let string_of_nat nat = end; String.sub s !index (String.length s - !index) -(* XL: suppression de sys_string_of_nat *) - -(* XL: suppression de debug_string_nat *) - let base_digit_of_char c base = let n = Char.code c in if n >= 48 && n <= 47 + min base 10 then n - 48 @@ -516,8 +531,8 @@ let base_digit_of_char c base = else failwith "invalid digit" (* - La sous-chaine (s, off, len) represente un nat en base base que - on determine ici + The substring (s, off, len) represents a nat in base 'base' which is +determined here *) let sys_nat_of_string base s off len = let power_base = make_nat (succ length_of_digit) in @@ -535,8 +550,8 @@ let sys_nat_of_string base s off len = for i = off to bound do (* - on lit pint (au maximum) chiffres, on en fait un int - et on l integre au nombre + we read (at most) pint digits, we transform them in a int + and integrate it to the number *) let c = String.get s i in begin match c with @@ -564,7 +579,7 @@ let sys_nat_of_string base s off len = end done; (* - On recadre le nat + We reframe nat *) let nat = create_nat !current_len in blit_nat nat 0 nat1 0 !current_len; diff --git a/otherlibs/num/nat.mli b/otherlibs/num/nat.mli index f9e279b6..803a6537 100644 --- a/otherlibs/num/nat.mli +++ b/otherlibs/num/nat.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Module [Nat]: operations on natural numbers *) @@ -25,11 +27,13 @@ external blit_nat: nat -> int -> nat -> int -> int -> unit = "blit_nat" val copy_nat: nat -> int -> int -> nat external set_digit_nat: nat -> int -> int -> unit = "set_digit_nat" external nth_digit_nat: nat -> int -> int = "nth_digit_nat" -external set_digit_nat_native: nat -> int -> nativeint -> unit = "set_digit_nat_native" +external set_digit_nat_native: nat -> int -> nativeint -> unit + = "set_digit_nat_native" external nth_digit_nat_native: nat -> int -> nativeint = "nth_digit_nat_native" val length_nat : nat -> int external num_digits_nat: nat -> int -> int -> int = "num_digits_nat" -external num_leading_zero_bits_in_digit: nat -> int -> int = "num_leading_zero_bits_in_digit" +external num_leading_zero_bits_in_digit: nat -> int -> int + = "num_leading_zero_bits_in_digit" external is_digit_int: nat -> int -> bool = "is_digit_int" external is_digit_zero: nat -> int -> bool = "is_digit_zero" external is_digit_normalized: nat -> int -> bool = "is_digit_normalized" @@ -39,19 +43,33 @@ val is_nat_int: nat -> int -> int -> bool val int_of_nat: nat -> int val nat_of_int: int -> nat external incr_nat: nat -> int -> int -> int -> int = "incr_nat" -external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "add_nat" "add_nat_native" +external add_nat: nat -> int -> int -> nat -> int -> int -> int -> int + = "add_nat" "add_nat_native" external complement_nat: nat -> int -> int -> unit = "complement_nat" external decr_nat: nat -> int -> int -> int -> int = "decr_nat" -external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int = "sub_nat" "sub_nat_native" -external mult_digit_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int = "mult_digit_nat" "mult_digit_nat_native" -external mult_nat: nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int = "mult_nat" "mult_nat_native" -external square_nat: nat -> int -> int -> nat -> int -> int -> int = "square_nat" "square_nat_native" -external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_left_nat" "shift_left_nat_native" -external div_digit_nat: nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit = "div_digit_nat" "div_digit_nat_native" -external div_nat: nat -> int -> int -> nat -> int -> int -> unit = "div_nat" "div_nat_native" -external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit = "shift_right_nat" "shift_right_nat_native" -external compare_digits_nat: nat -> int -> nat -> int -> int = "compare_digits_nat" -external compare_nat: nat -> int -> int -> nat -> int -> int -> int = "compare_nat" "compare_nat_native" +external sub_nat: nat -> int -> int -> nat -> int -> int -> int -> int + = "sub_nat" "sub_nat_native" +external mult_digit_nat: + nat -> int -> int -> nat -> int -> int -> nat -> int -> int + = "mult_digit_nat" "mult_digit_nat_native" +external mult_nat: + nat -> int -> int -> nat -> int -> int -> nat -> int -> int -> int + = "mult_nat" "mult_nat_native" +external square_nat: nat -> int -> int -> nat -> int -> int -> int + = "square_nat" "square_nat_native" +external shift_left_nat: nat -> int -> int -> nat -> int -> int -> unit + = "shift_left_nat" "shift_left_nat_native" +external div_digit_nat: + nat -> int -> nat -> int -> nat -> int -> int -> nat -> int -> unit + = "div_digit_nat" "div_digit_nat_native" +external div_nat: nat -> int -> int -> nat -> int -> int -> unit + = "div_nat" "div_nat_native" +external shift_right_nat: nat -> int -> int -> nat -> int -> int -> unit + = "shift_right_nat" "shift_right_nat_native" +external compare_digits_nat: nat -> int -> nat -> int -> int + = "compare_digits_nat" +external compare_nat: nat -> int -> int -> nat -> int -> int -> int + = "compare_nat" "compare_nat_native" val eq_nat : nat -> int -> int -> nat -> int -> int -> bool val le_nat : nat -> int -> int -> nat -> int -> int -> bool val lt_nat : nat -> int -> int -> nat -> int -> int -> bool diff --git a/otherlibs/num/nat_stubs.c b/otherlibs/num/nat_stubs.c index ae109ac9..005aaffe 100644 --- a/otherlibs/num/nat_stubs.c +++ b/otherlibs/num/nat_stubs.c @@ -1,17 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - -/* $Id$ */ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 "caml/alloc.h" #include "caml/config.h" @@ -123,7 +123,8 @@ CAMLprim value is_digit_zero(value nat, value ofs) CAMLprim value is_digit_normalized(value nat, value ofs) { return - Val_bool(Digit_val(nat, Long_val(ofs)) & ((bngdigit)1 << (BNG_BITS_PER_DIGIT-1))); + Val_bool(Digit_val(nat, Long_val(ofs)) + & ((bngdigit)1 << (BNG_BITS_PER_DIGIT-1))); } CAMLprim value is_digit_odd(value nat, value ofs) @@ -347,9 +348,9 @@ static void serialize_nat(value nat, if (len >= ((mlsize_t)1 << 32)) failwith("output_value: nat too big"); #endif - serialize_int_4((int32) len); + serialize_int_4((int32_t) len); #if defined(ARCH_SIXTYFOUR) && defined(ARCH_BIG_ENDIAN) - { int32 * p; + { 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 */ @@ -369,7 +370,7 @@ static uintnat deserialize_nat(void * dst) len = deserialize_uint_4(); #if defined(ARCH_SIXTYFOUR) && defined(ARCH_BIG_ENDIAN) - { uint32 * p; + { 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 */ @@ -385,7 +386,7 @@ static uintnat deserialize_nat(void * dst) deserialize_block_4(dst, len); #if defined(ARCH_SIXTYFOUR) if (len & 1){ - ((uint32 *) dst)[len] = 0; + ((uint32_t *) dst)[len] = 0; ++ len; } #endif @@ -396,7 +397,7 @@ static uintnat deserialize_nat(void * dst) static intnat hash_nat(value v) { bngsize len, i; - uint32 h; + uint32_t h; len = bng_num_digits(&Digit_val(v,0), Wosize_val(v) - 1); h = 0; @@ -406,10 +407,10 @@ static intnat hash_nat(value v) /* Mix the two 32-bit halves as if we were on a 32-bit platform, namely low 32 bits first, then high 32 bits. Also, ignore final 32 bits if they are zero. */ - h = caml_hash_mix_uint32(h, (uint32) d); + h = caml_hash_mix_uint32(h, (uint32_t) d); d = d >> 32; if (d == 0 && i + 1 == len) break; - h = caml_hash_mix_uint32(h, (uint32) d); + h = caml_hash_mix_uint32(h, (uint32_t) d); #else h = caml_hash_mix_uint32(h, d); #endif diff --git a/otherlibs/num/num.ml b/otherlibs/num/num.ml index 924e9eab..0a85951c 100644 --- a/otherlibs/num/num.ml +++ b/otherlibs/num/num.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Int_misc open Nat @@ -179,7 +181,7 @@ A correct but slow implementation is: if b >= 0 then floor_num (div_num a b) else minus_num (floor_num (div_num a (minus_num b))) - mod_num a b = + mod_num a b = sub_num a (mult_num b (quo_num a b)) However, this definition is vastly inefficient (cf PR #3473): @@ -197,7 +199,7 @@ let quo_num n1 n2 = Int (if r >= 0 then q else if i2 > 0 then q - 1 else q + 1) | Int i1, Big_int bi2 -> num_of_big_int (div_big_int (big_int_of_int i1) bi2) - | Int i1, Ratio r2 -> + | Int i1, Ratio r2 -> num_of_big_int (report_sign_ratio r2 (floor_ratio (div_int_ratio i1 (abs_ratio r2)))) | Big_int bi1, Int i2 -> @@ -389,8 +391,6 @@ let string_of_big_int_for_num bi = (* Coercion with string type *) -(* XL: suppression de sys_string_of_num *) - let string_of_normalized_num = function Int i -> string_of_int i | Big_int bi -> string_of_big_int_for_num bi @@ -415,8 +415,6 @@ let float_of_num = function | Big_int bi -> float_of_big_int bi | Ratio r -> float_of_ratio r -(* XL: suppression de num_of_float, float_num *) - let succ_num = function Int i -> if i = biggest_int then Big_int (succ_big_int (big_int_of_int i)) diff --git a/otherlibs/num/num.mli b/otherlibs/num/num.mli index 6425085e..3b414a3d 100644 --- a/otherlibs/num/num.mli +++ b/otherlibs/num/num.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Operation on arbitrary-precision numbers. diff --git a/otherlibs/num/nums.mllib b/otherlibs/num/nums.mllib deleted file mode 100644 index 8db16838..00000000 --- a/otherlibs/num/nums.mllib +++ /dev/null @@ -1 +0,0 @@ -Int_misc Nat Big_int Arith_flags Ratio Num Arith_status diff --git a/otherlibs/num/ratio.ml b/otherlibs/num/ratio.ml index 5bb04b64..04f9c5e8 100644 --- a/otherlibs/num/ratio.ml +++ b/otherlibs/num/ratio.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Int_misc open Nat @@ -546,7 +548,9 @@ let string_of_ratio r = else string_of_big_int r.numerator ^ "/" ^ string_of_big_int r.denominator (* XL: j'ai puissamment simplifie "ratio_of_string" en virant la notation - scientifique. *) + scientifique. + | I have strongly simplified "ratio_of_string" by deleting scientific notation +*) let ratio_of_string s = try @@ -561,9 +565,50 @@ let ratio_of_string s = (* Coercion with type float *) let float_of_ratio r = - float_of_string (float_of_rational_string r) + let p = r.numerator and q = r.denominator in + (* Special cases 0/0, 0/q and p/0 *) + if sign_big_int q = 0 then begin + match sign_big_int p with + | 0 -> nan + | 1 -> infinity + | -1 -> neg_infinity + | _ -> assert false + end + else if sign_big_int p = 0 then 0.0 + else begin + let np = num_bits_big_int p and nq = num_bits_big_int q in + if np <= 53 && nq <= 53 then + (* p and q convert to floats exactly; use FP division to get the + correctly-rounded result. *) + Int64.to_float (int64_of_big_int p) + /. Int64.to_float (int64_of_big_int q) + else begin + let ap = abs_big_int p in + (* |p| is in [2^(np-1), 2^np) + q is in [2^(nq-1), 2^nq) + hence |p|/q is in (2^(np-nq-1), 2^(np-nq+1)). + We define n such that |p|/q*2^n is in [2^54, 2^56). + >= 2^54 so that the round to odd technique applies. + < 2^56 so that the integral part is representable as an int64. *) + let n = 55 - (np - nq) in + (* Scaling |p|/q by 2^n *) + let (p', q') = + if n >= 0 + then (shift_left_big_int ap n, q) + else (ap, shift_left_big_int q (-n)) in + (* Euclidean division of p' by q' *) + let (quo, rem) = quomod_big_int p' q' in + (* quo is the integral part of |p|/q*2^n + rem/q' is the fractional part. *) + (* Round quo to float *) + let f = round_big_int_to_float quo (sign_big_int rem = 0) in + (* Apply exponent *) + let f = ldexp f (-n) in + (* Apply sign *) + if sign_big_int p < 0 then -. f else f + end + end -(* XL: suppression de ratio_of_float *) let power_ratio_positive_int r n = create_ratio (power_big_int_positive_int (r.numerator) n) diff --git a/otherlibs/num/ratio.mli b/otherlibs/num/ratio.mli index 7c9809f1..4a765051 100644 --- a/otherlibs/num/ratio.mli +++ b/otherlibs/num/ratio.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Valerie Menissier-Morain, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Operation on rational numbers. diff --git a/otherlibs/str/.depend b/otherlibs/str/.depend index 148cb312..53483c9c 100644 --- a/otherlibs/str/.depend +++ b/otherlibs/str/.depend @@ -1,8 +1,7 @@ strstubs.o: strstubs.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/memory.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/gc.h ../../byterun/caml/major_gc.h \ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ ../../byterun/caml/address_class.h ../../byterun/caml/fail.h diff --git a/otherlibs/str/Makefile b/otherlibs/str/Makefile index 93b2bf95..82685f10 100644 --- a/otherlibs/str/Makefile +++ b/otherlibs/str/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the str library diff --git a/otherlibs/str/Makefile.nt b/otherlibs/str/Makefile.nt index 3b3f51c9..908a3f1e 100644 --- a/otherlibs/str/Makefile.nt +++ b/otherlibs/str/Makefile.nt @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the str library diff --git a/otherlibs/str/libstr.clib b/otherlibs/str/libstr.clib deleted file mode 100644 index 319e7601..00000000 --- a/otherlibs/str/libstr.clib +++ /dev/null @@ -1 +0,0 @@ -strstubs.o diff --git a/otherlibs/str/str.ml b/otherlibs/str/str.ml index ffaea89b..b74cee0c 100644 --- a/otherlibs/str/str.ml +++ b/otherlibs/str/str.ml @@ -1,15 +1,21 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* In this module, [@ocaml.warnerror "-3"] is used in several places + that use deprecated functions to preserve legacy behavior. + It overrides -w @3 given on the command line. *) (** String utilities *) @@ -88,9 +94,9 @@ module Charset = r let fold_case s = - let r = make_empty() in - iter (fun c -> add r (Char.lowercase c); add r (Char.uppercase c)) s; - r + (let r = make_empty() in + iter (fun c -> add r (Char.lowercase c); add r (Char.uppercase c)) s; + r)[@ocaml.warnerror "-3"] end @@ -211,9 +217,9 @@ let charclass_of_regexp fold_case re = (* The case fold table: maps characters to their lowercase equivalent *) 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 + (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"] module StringMap = Map.Make(struct type t = string let compare (x:t) y = compare x y end) @@ -270,6 +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"] else emit_instr op_CHAR (Char.code c) | String s -> @@ -278,6 +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"] else emit_instr op_CHAR (Char.code s.[0]) | _ -> @@ -291,6 +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"] else emit_instr op_STRING (cpool_index s) end @@ -372,13 +381,13 @@ let compile fold_case re = let lbl = !progpos in patch_instr pos_pushback op_PUSHBACK lbl | Group(n, r) -> - if n >= 32 then failwith "too many \\(...\\) groups"; emit_instr op_BEGGROUP n; emit_code r; emit_instr op_ENDGROUP n; numgroups := max !numgroups (n+1) | Refgroup n -> - emit_instr op_REFGROUP n + emit_instr op_REFGROUP n; + numgroups := max !numgroups (n+1) | Bol -> emit_instr op_BOL 0 | Eol -> @@ -511,12 +520,10 @@ let parse s = assert false | '(' -> let group_no = !group_counter in - if group_no < 32 then incr group_counter; + incr group_counter; let (r, j) = regexp0 (i+1) in if j + 1 < len && s.[j] = '\\' && s.[j+1] = ')' then - if group_no < 32 - then (Group(group_no, r), j + 2) - else (r, j + 2) + (Group(group_no, r), j + 2) else failwith "\\( group not closed by \\)" | '1' .. '9' as c -> diff --git a/otherlibs/str/str.mli b/otherlibs/str/str.mli index 448cbd5a..256289c8 100644 --- a/otherlibs/str/str.mli +++ b/otherlibs/str/str.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Regular expressions and high-level string processing *) @@ -36,10 +38,10 @@ val regexp : string -> regexp To include a [\]] character in a set, make it the first character of the set. To include a [-] character in a set, make it the first or the last character of the set. - - [^ ] Matches at beginning of line (either at the beginning of - the matched string, or just after a newline character). - - [$ ] Matches at end of line (either at the end of the matched - string, or just before a newline character). + - [^ ] Matches at beginning of line: either at the beginning of + the matched string, or just after a '\n' character. + - [$ ] Matches at end of line: either at the end of the matched + string, or just before a '\n' character. - [\| ] (infix) Alternative between two expressions. - [\(..\)] Grouping and naming of the enclosed expression. - [\1 ] The text matched by the first [\(...\)] expression diff --git a/otherlibs/str/strstubs.c b/otherlibs/str/strstubs.c index 6c928704..4efa1ed6 100644 --- a/otherlibs/str/strstubs.c +++ b/otherlibs/str/strstubs.c @@ -1,16 +1,19 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ - +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ + +#define CAML_NAME_SPACE #include #include #include @@ -78,12 +81,11 @@ enum { #define Startchars(re) Int_val(Field(re, 5)) /* Record positions of matched groups */ -#define NUM_GROUPS 32 +#define DEFAULT_NUM_GROUPS 10 struct re_group { unsigned char * start; unsigned char * end; }; -static struct re_group re_group[NUM_GROUPS]; /* Record positions reached during matching; used to check progress in repeated matching of a regexp. */ @@ -98,7 +100,7 @@ static void free_backtrack_stack(struct backtrack_stack * stack) { struct backtrack_stack * prevstack; while ((prevstack = stack->previous) != NULL) { - stat_free(stack); + caml_stat_free(stack); stack = prevstack; } } @@ -122,12 +124,40 @@ static unsigned char re_word_letters[32] = { #define Is_word_letter(c) ((re_word_letters[(c) >> 3] >> ((c) & 7)) & 1) -/* The bytecode interpreter for the NFA */ -static int re_match(value re, - unsigned char * starttxt, - register unsigned char * txt, - register unsigned char * endtxt, - int accept_partial_match) +/* Allocate an integer array containing the positions of the matched groups. + Beginning of group #N is at 2N, end is at 2N+1. + Take position = -1 when group wasn't matched. */ + +static value re_alloc_groups(value re, unsigned char * starttxt, + struct re_group * groups) +{ + value res; + int n = Numgroups(re); + int i; + struct re_group * group; + + res = caml_alloc(n * 2, 0); + for (i = 0; i < n; i++) { + group = &(groups[i]); + if (group->start == NULL || group->end == NULL) { + Field(res, i * 2) = Val_int(-1); + Field(res, i * 2 + 1) = Val_int(-1); + } else { + Field(res, i * 2) = Val_long(group->start - starttxt); + Field(res, i * 2 + 1) = Val_long(group->end - starttxt); + } + } + return res; +} + +/* The bytecode interpreter for the NFA. + Return Caml array of matched groups on success, 0 on failure. */ + +static value re_match(value re, + unsigned char * starttxt, + register unsigned char * txt, + register unsigned char * endtxt, + int accept_partial_match) { register value * pc; intnat instr; @@ -137,11 +167,20 @@ static int re_match(value re, value normtable; unsigned char c; union backtrack_point back; + struct re_group default_groups[DEFAULT_NUM_GROUPS]; + struct re_group * groups; + int numgroups = Numgroups(re); + value result; + + if (numgroups <= DEFAULT_NUM_GROUPS) + groups = default_groups; + else + groups = caml_stat_alloc(sizeof(struct re_group) * numgroups); { int i; struct re_group * p; unsigned char ** q; - for (p = &re_group[1], i = Numgroups(re); i > 1; i--, p++) + for (p = &groups[1], i = numgroups; i > 1; i--, p++) p->start = p->end = NULL; for (q = &re_register[0], i = Numregisters(re); i > 0; i--, q++) *q = NULL; @@ -152,7 +191,7 @@ static int re_match(value re, sp = stack->point; cpool = Cpool(re); normtable = Normtable(re); - re_group[0].start = txt; + groups[0].start = txt; while (1) { instr = Long_val(*pc++); @@ -219,7 +258,7 @@ static int re_match(value re, } case BEGGROUP: { int group_no = Arg(instr); - struct re_group * group = &(re_group[group_no]); + struct re_group * group = &(groups[group_no]); back.undo.loc = &(group->start); back.undo.val = group->start; group->start = txt; @@ -227,7 +266,7 @@ static int re_match(value re, } case ENDGROUP: { int group_no = Arg(instr); - struct re_group * group = &(re_group[group_no]); + struct re_group * group = &(groups[group_no]); back.undo.loc = &(group->end); back.undo.val = group->end; group->end = txt; @@ -235,7 +274,7 @@ static int re_match(value re, } case REFGROUP: { int group_no = Arg(instr); - struct re_group * group = &(re_group[group_no]); + struct re_group * group = &(groups[group_no]); unsigned char * s; if (group->start == NULL || group->end == NULL) goto backtrack; for (s = group->start; s < group->end; s++) { @@ -318,8 +357,8 @@ static int re_match(value re, while (1) { if (sp == stack->point) { struct backtrack_stack * prevstack = stack->previous; - if (prevstack == NULL) return 0; - stat_free(stack); + if (prevstack == NULL) goto reject; + caml_stat_free(stack); stack = prevstack; sp = stack->point + BACKTRACK_STACK_BLOCK_SIZE; } @@ -338,35 +377,15 @@ static int re_match(value re, accept: /* We get here when the regexp was successfully matched */ free_backtrack_stack(stack); - re_group[0].end = txt; - return 1; -} - -/* Allocate an integer array containing the positions of the matched groups. - Beginning of group #N is at 2N, end is at 2N+1. - Take position = -1 when group wasn't matched. */ - -static value re_alloc_groups(value re, value str) -{ - CAMLparam1(str); - CAMLlocal1(res); - unsigned char * starttxt = (unsigned char *) String_val(str); - int n = Numgroups(re); - int i; - struct re_group * group; - - res = alloc(n * 2, 0); - for (i = 0; i < n; i++) { - group = &(re_group[i]); - if (group->start == NULL || group->end == NULL) { - Field(res, i * 2) = Val_int(-1); - Field(res, i * 2 + 1) = Val_int(-1); - } else { - Field(res, i * 2) = Val_long(group->start - starttxt); - Field(res, i * 2 + 1) = Val_long(group->end - starttxt); - } - } - CAMLreturn(res); + groups[0].end = txt; + result = re_alloc_groups(re, starttxt, groups); + if (groups != default_groups) caml_stat_free(groups); + return result; + + reject: + /* We get here when the regexp was not matched */ + if (groups != default_groups) caml_stat_free(groups); + return 0; } /* String matching and searching. All functions return the empty array @@ -376,45 +395,42 @@ CAMLprim value re_string_match(value re, value str, value pos) { unsigned char * starttxt = &Byte_u(str, 0); unsigned char * txt = &Byte_u(str, Long_val(pos)); - unsigned char * endtxt = &Byte_u(str, string_length(str)); + unsigned char * endtxt = &Byte_u(str, caml_string_length(str)); + value res; if (txt < starttxt || txt > endtxt) - invalid_argument("Str.string_match"); - if (re_match(re, starttxt, txt, endtxt, 0)) { - return re_alloc_groups(re, str); - } else { - return Atom(0); - } + caml_invalid_argument("Str.string_match"); + res = re_match(re, starttxt, txt, endtxt, 0); + return res == 0 ? Atom(0) : res; } CAMLprim value re_partial_match(value re, value str, value pos) { unsigned char * starttxt = &Byte_u(str, 0); unsigned char * txt = &Byte_u(str, Long_val(pos)); - unsigned char * endtxt = &Byte_u(str, string_length(str)); + unsigned char * endtxt = &Byte_u(str, caml_string_length(str)); + value res; if (txt < starttxt || txt > endtxt) - invalid_argument("Str.string_partial_match"); - if (re_match(re, starttxt, txt, endtxt, 1)) { - return re_alloc_groups(re, str); - } else { - return Atom(0); - } + caml_invalid_argument("Str.string_partial_match"); + res = re_match(re, starttxt, txt, endtxt, 1); + return res == 0 ? Atom(0) : res; } CAMLprim value re_search_forward(value re, value str, value startpos) { unsigned char * starttxt = &Byte_u(str, 0); unsigned char * txt = &Byte_u(str, Long_val(startpos)); - unsigned char * endtxt = &Byte_u(str, string_length(str)); + unsigned char * endtxt = &Byte_u(str, caml_string_length(str)); unsigned char * startchars; + value res; if (txt < starttxt || txt > endtxt) - invalid_argument("Str.search_forward"); + caml_invalid_argument("Str.search_forward"); if (Startchars(re) == -1) { do { - if (re_match(re, starttxt, txt, endtxt, 0)) - return re_alloc_groups(re, str); + res = re_match(re, starttxt, txt, endtxt, 0); + if (res != 0) return res; txt++; } while (txt <= endtxt); return Atom(0); @@ -423,8 +439,8 @@ CAMLprim value re_search_forward(value re, value str, value startpos) (unsigned char *) String_val(Field(Cpool(re), Startchars(re))); do { while (txt < endtxt && startchars[*txt] == 0) txt++; - if (re_match(re, starttxt, txt, endtxt, 0)) - return re_alloc_groups(re, str); + res = re_match(re, starttxt, txt, endtxt, 0); + if (res != 0) return res; txt++; } while (txt <= endtxt); return Atom(0); @@ -435,15 +451,16 @@ CAMLprim value re_search_backward(value re, value str, value startpos) { unsigned char * starttxt = &Byte_u(str, 0); unsigned char * txt = &Byte_u(str, Long_val(startpos)); - unsigned char * endtxt = &Byte_u(str, string_length(str)); + unsigned char * endtxt = &Byte_u(str, caml_string_length(str)); unsigned char * startchars; + value res; if (txt < starttxt || txt > endtxt) - invalid_argument("Str.search_backward"); + caml_invalid_argument("Str.search_backward"); if (Startchars(re) == -1) { do { - if (re_match(re, starttxt, txt, endtxt, 0)) - return re_alloc_groups(re, str); + res = re_match(re, starttxt, txt, endtxt, 0); + if (res != 0) return res; txt--; } while (txt >= starttxt); return Atom(0); @@ -452,8 +469,8 @@ CAMLprim value re_search_backward(value re, value str, value startpos) (unsigned char *) String_val(Field(Cpool(re), Startchars(re))); do { while (txt > starttxt && startchars[*txt] == 0) txt--; - if (re_match(re, starttxt, txt, endtxt, 0)) - return re_alloc_groups(re, str); + res = re_match(re, starttxt, txt, endtxt, 0); + if (res != 0) return res; txt--; } while (txt >= starttxt); return Atom(0); @@ -472,13 +489,13 @@ CAMLprim value re_replacement_text(value repl, value groups, value orig) len = 0; p = String_val(repl); - n = string_length(repl); + n = caml_string_length(repl); while (n > 0) { c = *p++; n--; if(c != '\\') len++; else { - if (n == 0) failwith("Str.replace: illegal backslash sequence"); + if (n == 0) caml_failwith("Str.replace: illegal backslash sequence"); c = *p++; n--; switch (c) { case '\\': @@ -487,11 +504,11 @@ CAMLprim value re_replacement_text(value repl, value groups, value orig) case '5': case '6': case '7': case '8': case '9': c -= '0'; if (c*2 >= Wosize_val(groups)) - failwith("Str.replace: reference to unmatched group"); + caml_failwith("Str.replace: reference to unmatched group"); start = Long_val(Field(groups, c*2)); end = Long_val(Field(groups, c*2 + 1)); if (start == (mlsize_t) -1) - failwith("Str.replace: reference to unmatched group"); + caml_failwith("Str.replace: reference to unmatched group"); len += end - start; break; default: @@ -499,10 +516,10 @@ CAMLprim value re_replacement_text(value repl, value groups, value orig) } } } - res = alloc_string(len); + res = caml_alloc_string(len); p = String_val(repl); q = String_val(res); - n = string_length(repl); + n = caml_string_length(repl); while (n > 0) { c = *p++; n--; if(c != '\\') diff --git a/otherlibs/systhreads/.depend b/otherlibs/systhreads/.depend index abe592e5..03da2d85 100644 --- a/otherlibs/systhreads/.depend +++ b/otherlibs/systhreads/.depend @@ -2,15 +2,15 @@ st_stubs.o: st_stubs.c ../../byterun/caml/alloc.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 \ - ../../byterun/caml/backtrace.h ../../byterun/caml/callback.h \ - ../../byterun/caml/custom.h ../../byterun/caml/fail.h \ - ../../byterun/caml/io.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/printexc.h \ - ../../byterun/caml/roots.h ../../byterun/caml/signals.h \ - ../../byterun/caml/stacks.h ../../byterun/caml/sys.h threads.h \ - st_posix.h + ../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \ + ../../byterun/caml/callback.h ../../byterun/caml/custom.h \ + ../../byterun/caml/fail.h ../../byterun/caml/io.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/printexc.h ../../byterun/caml/roots.h \ + ../../byterun/caml/signals.h ../../byterun/caml/stacks.h \ + ../../byterun/caml/sys.h threads.h st_posix.h condition.cmi : mutex.cmi event.cmi : mutex.cmi : diff --git a/otherlibs/systhreads/.ignore b/otherlibs/systhreads/.ignore deleted file mode 100644 index 71702b88..00000000 --- a/otherlibs/systhreads/.ignore +++ /dev/null @@ -1 +0,0 @@ -thread.ml diff --git a/otherlibs/systhreads/Makefile b/otherlibs/systhreads/Makefile index 942a7b78..1091e232 100644 --- a/otherlibs/systhreads/Makefile +++ b/otherlibs/systhreads/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 @@ -22,6 +24,11 @@ CAMLOPT=$(CAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib \ -I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix MKLIB=$(CAMLRUN) ../../tools/ocamlmklib COMPFLAGS=-w +33..39 -warn-error A -g -bin-annot -safe-string +ifeq "$(FLAMBDA)" "true" +OPTCOMPFLAGS=-O3 +else +OPTCOMPFLAGS= +endif BYTECODE_C_OBJS=st_stubs_b.o NATIVECODE_C_OBJS=st_stubs_n.o @@ -48,7 +55,7 @@ libthreadsnat.a: $(NATIVECODE_C_OBJS) st_stubs_n.o: st_stubs.c st_posix.h $(NATIVECC) -I../../asmrun -I../../byterun $(NATIVECCCOMPOPTS) \ $(SHAREDCCCOMPOPTS) -DNATIVE_CODE -DTARGET_$(ARCH) \ - -DSYS_$(SYSTEM) -c st_stubs.c + -DMODEL_$(MODEL) -DSYS_$(SYSTEM) -c st_stubs.c mv st_stubs.o st_stubs_n.o threads.cma: $(THREAD_OBJS) @@ -93,8 +100,9 @@ install: 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 $(THREAD_OBJS:.cmo=.cmx) threads.cmxa threads.a \ + $(INSTALL_LIBDIR)/threads + cd $(INSTALL_LIBDIR)/threads && $(RANLIB) threads.a .SUFFIXES: .ml .mli .cmo .cmi .cmx @@ -105,7 +113,7 @@ installopt: $(CAMLC) -c $(COMPFLAGS) $< .ml.cmx: - $(CAMLOPT) -c $(COMPFLAGS) $< + $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< depend: $(GENFILES) -$(CC) -MM -I../../byterun *.c > .depend diff --git a/otherlibs/systhreads/Makefile.nt b/otherlibs/systhreads/Makefile.nt index 22fb1c71..48e3bdcd 100644 --- a/otherlibs/systhreads/Makefile.nt +++ b/otherlibs/systhreads/Makefile.nt @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 @@ -19,9 +21,20 @@ CAMLYACC ?= ../../boot/ocamlyacc 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 + CAMLOBJS=thread.cmo mutex.cmo condition.cmo event.cmo threadUnix.cmo CMIFILES=$(CAMLOBJS:.cmo=.cmi) COBJS=st_stubs_b.$(O) @@ -76,17 +89,18 @@ 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 + 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 + 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 @@ -97,7 +111,7 @@ installopt: $(CAMLC) -c -g $(COMPFLAGS) $< .ml.cmx: - $(CAMLOPT) -c $(COMPFLAGS) $< + $(CAMLOPT) -c $(COMPFLAGS) $(OPTCOMPFLAGS) $< depend: diff --git a/otherlibs/systhreads/condition.ml b/otherlibs/systhreads/condition.ml index 4d12378d..9a014528 100644 --- a/otherlibs/systhreads/condition.ml +++ b/otherlibs/systhreads/condition.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1995 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1995 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 t external create: unit -> t = "caml_condition_new" diff --git a/otherlibs/systhreads/condition.mli b/otherlibs/systhreads/condition.mli index 9e005dc6..decf6dce 100644 --- a/otherlibs/systhreads/condition.mli +++ b/otherlibs/systhreads/condition.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Condition variables to synchronize between threads. diff --git a/otherlibs/systhreads/event.ml b/otherlibs/systhreads/event.ml index 68d8a5b4..f5fc9785 100644 --- a/otherlibs/systhreads/event.ml +++ b/otherlibs/systhreads/event.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Events *) type 'a basic_event = @@ -84,7 +86,9 @@ let basic_sync abort_env genev = (* Suspend on all events *) for i = 0 to Array.length bev - 1 do bev.(i).suspend() done; (* Wait until the condition is signalled *) - Condition.wait condition masterlock + Condition.wait condition masterlock; + (* PR#7013: protect against spurious wake-up *) + while !performed < 0 do Condition.wait condition masterlock done end; Mutex.unlock masterlock; (* Extract the result *) diff --git a/otherlibs/systhreads/event.mli b/otherlibs/systhreads/event.mli index 8352ca1f..83dbe9a1 100644 --- a/otherlibs/systhreads/event.mli +++ b/otherlibs/systhreads/event.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** First-class synchronous communication. diff --git a/otherlibs/systhreads/libthreads.clib b/otherlibs/systhreads/libthreads.clib deleted file mode 100644 index a0582d41..00000000 --- a/otherlibs/systhreads/libthreads.clib +++ /dev/null @@ -1 +0,0 @@ -st_stubs_b.o diff --git a/otherlibs/systhreads/mutex.ml b/otherlibs/systhreads/mutex.ml index 5b8be9da..836109e7 100644 --- a/otherlibs/systhreads/mutex.ml +++ b/otherlibs/systhreads/mutex.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Pascal Cuoq, INRIA Rocquencourt *) -(* *) -(* Copyright 1995 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Pascal Cuoq, INRIA Rocquencourt *) +(* *) +(* Copyright 1995 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 t external create: unit -> t = "caml_mutex_new" diff --git a/otherlibs/systhreads/mutex.mli b/otherlibs/systhreads/mutex.mli index 265ae94e..8953a159 100644 --- a/otherlibs/systhreads/mutex.mli +++ b/otherlibs/systhreads/mutex.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Locks for mutual exclusion. diff --git a/otherlibs/systhreads/st_posix.h b/otherlibs/systhreads/st_posix.h index 1d87a229..cfa3f6f3 100644 --- a/otherlibs/systhreads/st_posix.h +++ b/otherlibs/systhreads/st_posix.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 2009 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. */ +/* */ +/**************************************************************************/ /* POSIX thread implementation of the "st" interface */ @@ -78,14 +80,10 @@ static void st_thread_exit(void) pthread_exit(NULL); } -static void st_thread_kill(st_thread_id thr) +static void st_thread_join(st_thread_id thr) { -#if !defined(__ANDROID__) - /* pthread_cancel is unsafe, as it does not allow the thread an opportunity - to free shared resources such as mutexes. Thus, it is not implemented - in Android's libc. */ - pthread_cancel(thr); -#endif + pthread_join(thr, NULL); + /* best effort: ignore errors */ } /* Scheduling hints */ @@ -317,6 +315,9 @@ static void st_check_error(int retcode, char * msg) raise_sys_error(str); } +/* Variable used to stop the "tick" thread */ +static volatile int caml_tick_thread_stop = 0; + /* The tick thread: posts a SIGPREEMPTION signal periodically */ static void * caml_thread_tick(void * arg) @@ -327,11 +328,7 @@ static void * caml_thread_tick(void * arg) /* Block all signals so that we don't try to execute an OCaml signal handler*/ sigfillset(&mask); pthread_sigmask(SIG_BLOCK, &mask, NULL); -#if !defined(__ANDROID__) - /* Allow async cancellation */ - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); -#endif - while(1) { + while(! caml_tick_thread_stop) { /* select() seems to be the most efficient way to suspend the thread for sub-second intervals */ timeout.tv_sec = 0; @@ -342,7 +339,7 @@ static void * caml_thread_tick(void * arg) caml_record_signal(). */ caml_record_signal(SIGPREEMPTION); } - return NULL; /* prevents compiler warning */ + return NULL; } /* "At fork" processing */ @@ -353,7 +350,8 @@ static void * caml_thread_tick(void * arg) The reason for the omission is that Android (GUI) applications are not supposed to fork at all, however this workaround is still included in case OCaml is used for an Android CLI utility. */ -int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)); +int pthread_atfork(void (*prepare)(void), void (*parent)(void), + void (*child)(void)); #endif static int st_atfork(void (*fn)(void)) diff --git a/otherlibs/systhreads/st_stubs.c b/otherlibs/systhreads/st_stubs.c index eab89ab4..dd7f3f5d 100644 --- a/otherlibs/systhreads/st_stubs.c +++ b/otherlibs/systhreads/st_stubs.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1995 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1995 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 "caml/alloc.h" #include "caml/backtrace.h" @@ -80,7 +82,7 @@ struct caml_thread_struct { struct longjmp_buffer * external_raise; /* Saved external_raise */ #endif int backtrace_pos; /* Saved backtrace_pos */ - code_t * backtrace_buffer; /* Saved backtrace_buffer */ + backtrace_slot * backtrace_buffer; /* Saved backtrace_buffer */ value backtrace_last_exn; /* Saved backtrace_last_exn (root) */ }; @@ -95,10 +97,10 @@ static caml_thread_t curr_thread = NULL; /* The master lock protecting the OCaml runtime system */ static st_masterlock caml_master_lock; -/* Whether the ``tick'' thread is already running */ +/* Whether the "tick" thread is already running */ static int caml_tick_thread_running = 0; -/* The thread identifier of the ``tick'' thread */ +/* The thread identifier of the "tick" thread */ static st_thread_id caml_tick_thread_id; /* The key used for storing the thread descriptor in the specific data @@ -150,12 +152,10 @@ static void caml_thread_scan_roots(scanning_action action) if (prev_scan_roots_hook != NULL) (*prev_scan_roots_hook)(action); } -/* Hooks for enter_blocking_section and leave_blocking_section */ +/* Saving and restoring runtime state in curr_thread */ -static void caml_thread_enter_blocking_section(void) +static inline void caml_thread_save_runtime_state(void) { - /* Save the stack-related global variables in the thread descriptor - of the current thread */ #ifdef NATIVE_CODE curr_thread->bottom_of_stack = caml_bottom_of_stack; curr_thread->last_retaddr = caml_last_return_address; @@ -174,18 +174,10 @@ static void caml_thread_enter_blocking_section(void) curr_thread->backtrace_pos = backtrace_pos; curr_thread->backtrace_buffer = backtrace_buffer; curr_thread->backtrace_last_exn = backtrace_last_exn; - /* Tell other threads that the runtime is free */ - st_masterlock_release(&caml_master_lock); } -static void caml_thread_leave_blocking_section(void) +static inline void caml_thread_restore_runtime_state(void) { - /* Wait until the runtime is free */ - st_masterlock_acquire(&caml_master_lock); - /* Update curr_thread to point to the thread descriptor corresponding - to the thread currently executing */ - curr_thread = st_tls_get(thread_descriptor_key); - /* Restore the stack-related global variables */ #ifdef NATIVE_CODE caml_bottom_of_stack= curr_thread->bottom_of_stack; caml_last_return_address = curr_thread->last_retaddr; @@ -206,6 +198,29 @@ static void caml_thread_leave_blocking_section(void) backtrace_last_exn = curr_thread->backtrace_last_exn; } +/* Hooks for enter_blocking_section and leave_blocking_section */ + + +static void caml_thread_enter_blocking_section(void) +{ + /* Save the current runtime state in the thread descriptor + of the current thread */ + caml_thread_save_runtime_state(); + /* Tell other threads that the runtime is free */ + st_masterlock_release(&caml_master_lock); +} + +static void caml_thread_leave_blocking_section(void) +{ + /* Wait until the runtime is free */ + st_masterlock_acquire(&caml_master_lock); + /* Update curr_thread to point to the thread descriptor corresponding + to the thread currently executing */ + curr_thread = st_tls_get(thread_descriptor_key); + /* Restore the runtime state from the curr_thread descriptor */ + caml_thread_restore_runtime_state(); +} + static int caml_thread_try_leave_blocking_section(void) { /* Disable immediate processing of signals (PR#3659). @@ -228,7 +243,7 @@ static void caml_io_mutex_lock(struct channel *chan) st_mutex mutex = chan->mutex; if (mutex == NULL) { - st_mutex_create(&mutex); + st_check_error(st_mutex_create(&mutex), "channel locking"); /*PR#7038*/ chan->mutex = mutex; } /* PR#4351: first try to acquire mutex without releasing the master lock */ @@ -291,7 +306,6 @@ static uintnat caml_thread_stack_usage(void) static caml_thread_t caml_thread_new_info(void) { caml_thread_t th; - th = (caml_thread_t) malloc(sizeof(struct caml_thread_struct)); if (th == NULL) return NULL; th->descr = Val_unit; /* filled later */ @@ -444,7 +458,12 @@ CAMLprim value caml_thread_initialize(value unit) /* ML */ CAMLprim value caml_thread_cleanup(value unit) /* ML */ { - if (caml_tick_thread_running) st_thread_kill(caml_tick_thread_id); + if (caml_tick_thread_running){ + caml_tick_thread_stop = 1; + st_thread_join(caml_tick_thread_id); + caml_tick_thread_stop = 0; + caml_tick_thread_running = 0; + } return Val_unit; } @@ -452,11 +471,11 @@ CAMLprim value caml_thread_cleanup(value unit) /* ML */ static void caml_thread_stop(void) { -#ifndef NATIVE_CODE - /* PR#5188: update curr_thread->stack_low because the stack may have - been reallocated since the last time we entered a blocking section */ - curr_thread->stack_low = stack_low; -#endif + /* PR#5188, PR#7220: some of the global runtime state may have + changed as the thread was running, so we save it in the + curr_thread data to make sure that the cleanup logic + below uses accurate information. */ + caml_thread_save_runtime_state(); /* Signal that the thread has terminated */ caml_threadstatus_terminate(Terminated(curr_thread->descr)); /* Remove th from the doubly-linked list of threads and free its info block */ diff --git a/otherlibs/systhreads/st_win32.h b/otherlibs/systhreads/st_win32.h index cd04b319..37f88df5 100644 --- a/otherlibs/systhreads/st_win32.h +++ b/otherlibs/systhreads/st_win32.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 2009 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. */ +/* */ +/**************************************************************************/ /* Win32 implementation of the "st" interface */ @@ -84,11 +86,10 @@ static void st_thread_exit(void) ExitThread(0); } -static void st_thread_kill(st_thread_id thr) +static void st_thread_join(st_thread_id thr) { - TRACE1("st_thread_kill", thr); - TerminateThread(thr, 0); - CloseHandle(thr); + TRACE1("st_thread_join", h); + WaitForSingleObject(thr, INFINITE); } /* Scheduling hints */ @@ -383,18 +384,21 @@ static void st_check_error(DWORD retcode, char * msg) raise_sys_error(str); } +/* Variable used to stop the "tick" thread */ +static volatile int caml_tick_thread_stop = 0; + /* The tick thread: posts a SIGPREEMPTION signal periodically */ static DWORD WINAPI caml_thread_tick(void * arg) { - while(1) { + while(! caml_tick_thread_stop) { Sleep(Thread_timeout); /* The preemption signal should never cause a callback, so don't go through caml_handle_signal(), just record signal delivery via caml_record_signal(). */ caml_record_signal(SIGPREEMPTION); } - return 0; /* prevents compiler warning */ + return 0; } /* "At fork" processing -- none under Win32 */ diff --git a/otherlibs/systhreads/thread.ml b/otherlibs/systhreads/thread.ml index c7988b56..c55ff3fe 100644 --- a/otherlibs/systhreads/thread.ml +++ b/otherlibs/systhreads/thread.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* User-level threads *) @@ -22,8 +24,8 @@ external thread_uncaught_exception : exn -> unit = "caml_thread_uncaught_exception" external yield : unit -> unit = "caml_thread_yield" -external self : unit -> t = "caml_thread_self" -external id : t -> int = "caml_thread_id" +external self : unit -> t = "caml_thread_self" [@@noalloc] +external id : t -> int = "caml_thread_id" [@@noalloc] external join : t -> unit = "caml_thread_join" external exit : unit -> unit = "caml_thread_exit" diff --git a/otherlibs/systhreads/thread.mli b/otherlibs/systhreads/thread.mli index 93e52be2..e5581a2f 100644 --- a/otherlibs/systhreads/thread.mli +++ b/otherlibs/systhreads/thread.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1995 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1995 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. *) +(* *) +(**************************************************************************) (** Lightweight threads for Posix [1003.1c] and Win32. *) diff --git a/otherlibs/systhreads/threadUnix.ml b/otherlibs/systhreads/threadUnix.ml index c18f75bb..acaafb01 100644 --- a/otherlibs/systhreads/threadUnix.ml +++ b/otherlibs/systhreads/threadUnix.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Module [ThreadUnix]: thread-compatible system calls *) diff --git a/otherlibs/systhreads/threadUnix.mli b/otherlibs/systhreads/threadUnix.mli index cac796b9..7829884e 100644 --- a/otherlibs/systhreads/threadUnix.mli +++ b/otherlibs/systhreads/threadUnix.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Thread-compatible system calls. diff --git a/otherlibs/systhreads/threads.h b/otherlibs/systhreads/threads.h index 616138da..97fd1b27 100644 --- a/otherlibs/systhreads/threads.h +++ b/otherlibs/systhreads/threads.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1995 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1995 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_THREADS_H #define CAML_THREADS_H diff --git a/otherlibs/systhreads/threads.mllib b/otherlibs/systhreads/threads.mllib deleted file mode 100644 index 3ff8841b..00000000 --- a/otherlibs/systhreads/threads.mllib +++ /dev/null @@ -1 +0,0 @@ -Thread Mutex Condition Event ThreadUnix diff --git a/otherlibs/threads/.depend b/otherlibs/threads/.depend index aa869a60..b425264d 100644 --- a/otherlibs/threads/.depend +++ b/otherlibs/threads/.depend @@ -2,16 +2,14 @@ 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/../../config/s.h ../../byterun/caml/mlvalues.h \ - ../../byterun/caml/backtrace.h ../../byterun/caml/callback.h \ - ../../byterun/caml/config.h ../../byterun/caml/fail.h \ + ../../byterun/caml/backtrace.h ../../byterun/caml/exec.h \ + ../../byterun/caml/callback.h ../../byterun/caml/fail.h \ ../../byterun/caml/io.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/misc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/printexc.h \ - ../../byterun/caml/roots.h ../../byterun/caml/memory.h \ - ../../byterun/caml/signals.h ../../byterun/caml/stacks.h \ - ../../byterun/caml/sys.h + ../../byterun/caml/address_class.h ../../byterun/caml/printexc.h \ + ../../byterun/caml/roots.h ../../byterun/caml/signals.h \ + ../../byterun/caml/stacks.h ../../byterun/caml/sys.h condition.cmi : mutex.cmi event.cmi : mutex.cmi : diff --git a/otherlibs/threads/.ignore b/otherlibs/threads/.ignore deleted file mode 100644 index fb2df562..00000000 --- a/otherlibs/threads/.ignore +++ /dev/null @@ -1,3 +0,0 @@ -marshal.mli -pervasives.mli -unix.mli diff --git a/otherlibs/threads/Makefile b/otherlibs/threads/Makefile index de789afd..729c444e 100644 --- a/otherlibs/threads/Makefile +++ b/otherlibs/threads/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # FIXME reduce redundancy by including ../Makefile @@ -33,7 +35,7 @@ LIB=../../stdlib LIB_OBJS=$(LIB)/camlinternalFormatBasics.cmo pervasives.cmo \ $(LIB)/array.cmo $(LIB)/list.cmo $(LIB)/char.cmo $(LIB)/bytes.cmo \ - $(LIB)/string.cmo $(LIB)/sys.cmo $(LIB)/sort.cmo $(LIB)/marshal.cmo \ + $(LIB)/string.cmo $(LIB)/sys.cmo $(LIB)/sort.cmo marshal.cmo \ $(LIB)/obj.cmo $(LIB)/int32.cmo $(LIB)/int64.cmo \ $(LIB)/nativeint.cmo $(LIB)/lexing.cmo $(LIB)/parsing.cmo \ $(LIB)/set.cmo $(LIB)/map.cmo $(LIB)/stack.cmo $(LIB)/queue.cmo \ @@ -43,9 +45,10 @@ LIB_OBJS=$(LIB)/camlinternalFormatBasics.cmo pervasives.cmo \ $(LIB)/random.cmo $(LIB)/hashtbl.cmo $(LIB)/format.cmo \ $(LIB)/scanf.cmo $(LIB)/callback.cmo $(LIB)/camlinternalOO.cmo \ $(LIB)/oo.cmo $(LIB)/camlinternalMod.cmo $(LIB)/genlex.cmo \ - $(LIB)/weak.cmo $(LIB)/filename.cmo $(LIB)/complex.cmo \ - $(LIB)/arrayLabels.cmo $(LIB)/listLabels.cmo $(LIB)/bytesLabels.cmo \ - $(LIB)/stringLabels.cmo $(LIB)/moreLabels.cmo $(LIB)/stdLabels.cmo + $(LIB)/weak.cmo $(LIB)/ephemeron.cmo $(LIB)/filename.cmo \ + $(LIB)/complex.cmo $(LIB)/arrayLabels.cmo $(LIB)/listLabels.cmo \ + $(LIB)/bytesLabels.cmo $(LIB)/stringLabels.cmo \ + $(LIB)/moreLabels.cmo $(LIB)/stdLabels.cmo UNIXLIB=../unix @@ -105,7 +108,9 @@ INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) INSTALL_STUBLIBDIR=$(DESTDIR)$(STUBLIBDIR) install: - if test -f dllvmthreads.so; then cp dllvmthreads.so $(INSTALL_STUBLIBDIR)/.; fi + if test -f dllvmthreads.so; then \ + cp dllvmthreads.so $(INSTALL_STUBLIBDIR)/.; \ + fi mkdir -p $(INSTALL_LIBDIR)/vmthreads cp libvmthreads.a $(INSTALL_LIBDIR)/vmthreads/libvmthreads.a cd $(INSTALL_LIBDIR)/vmthreads; $(RANLIB) libvmthreads.a diff --git a/otherlibs/threads/condition.ml b/otherlibs/threads/condition.ml index 7912cd60..c685d813 100644 --- a/otherlibs/threads/condition.ml +++ b/otherlibs/threads/condition.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 t = { mutable waiting: Thread.t list } diff --git a/otherlibs/threads/condition.mli b/otherlibs/threads/condition.mli index 2d5bcde1..2e1ee777 100644 --- a/otherlibs/threads/condition.mli +++ b/otherlibs/threads/condition.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Condition variables to synchronize between threads. diff --git a/otherlibs/threads/event.ml b/otherlibs/threads/event.ml index 68d8a5b4..b00a6fc3 100644 --- a/otherlibs/threads/event.ml +++ b/otherlibs/threads/event.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Events *) type 'a basic_event = diff --git a/otherlibs/threads/event.mli b/otherlibs/threads/event.mli index e38235f1..a1921234 100644 --- a/otherlibs/threads/event.mli +++ b/otherlibs/threads/event.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* David Nowak and Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** First-class synchronous communication. diff --git a/otherlibs/threads/libvmthreads.clib b/otherlibs/threads/libvmthreads.clib deleted file mode 100644 index 0b4f31e5..00000000 --- a/otherlibs/threads/libvmthreads.clib +++ /dev/null @@ -1 +0,0 @@ -scheduler.o diff --git a/otherlibs/threads/marshal.ml b/otherlibs/threads/marshal.ml index 005e9643..88660680 100644 --- a/otherlibs/threads/marshal.ml +++ b/otherlibs/threads/marshal.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1997 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1997 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 extern_flags = No_sharing diff --git a/otherlibs/threads/mutex.ml b/otherlibs/threads/mutex.ml index 976527ce..8209d7d2 100644 --- a/otherlibs/threads/mutex.ml +++ b/otherlibs/threads/mutex.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 t = { mutable locked: bool; mutable waiting: Thread.t list } diff --git a/otherlibs/threads/mutex.mli b/otherlibs/threads/mutex.mli index 265ae94e..8953a159 100644 --- a/otherlibs/threads/mutex.mli +++ b/otherlibs/threads/mutex.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Damien Doligez, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Locks for mutual exclusion. diff --git a/otherlibs/threads/pervasives.ml b/otherlibs/threads/pervasives.ml index e6f1cc16..a497350a 100644 --- a/otherlibs/threads/pervasives.ml +++ b/otherlibs/threads/pervasives.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Same as ../../stdlib/pervasives.ml, except that I/O functions have been redefined to not block the whole process, but only the calling @@ -112,33 +114,50 @@ external ( +. ) : float -> float -> float = "%addfloat" external ( -. ) : float -> float -> float = "%subfloat" external ( *. ) : float -> float -> float = "%mulfloat" external ( /. ) : float -> float -> float = "%divfloat" -external ( ** ) : float -> float -> float = "caml_power_float" "pow" "float" -external exp : float -> float = "caml_exp_float" "exp" "float" -external expm1 : float -> float = "caml_expm1_float" "caml_expm1" "float" -external acos : float -> float = "caml_acos_float" "acos" "float" -external asin : float -> float = "caml_asin_float" "asin" "float" -external atan : float -> float = "caml_atan_float" "atan" "float" -external atan2 : float -> float -> float = "caml_atan2_float" "atan2" "float" +external ( ** ) : float -> float -> float = "caml_power_float" "pow" + [@@unboxed] [@@noalloc] +external exp : float -> float = "caml_exp_float" "exp" [@@unboxed] [@@noalloc] +external expm1 : float -> float = "caml_expm1_float" "caml_expm1" + [@@unboxed] [@@noalloc] +external acos : float -> float = "caml_acos_float" "acos" + [@@unboxed] [@@noalloc] +external asin : float -> float = "caml_asin_float" "asin" + [@@unboxed] [@@noalloc] +external atan : float -> float = "caml_atan_float" "atan" + [@@unboxed] [@@noalloc] +external atan2 : float -> float -> float = "caml_atan2_float" "atan2" + [@@unboxed] [@@noalloc] external hypot : float -> float -> float - = "caml_hypot_float" "caml_hypot" "float" -external cos : float -> float = "caml_cos_float" "cos" "float" -external cosh : float -> float = "caml_cosh_float" "cosh" "float" -external log : float -> float = "caml_log_float" "log" "float" -external log10 : float -> float = "caml_log10_float" "log10" "float" -external log1p : float -> float = "caml_log1p_float" "caml_log1p" "float" -external sin : float -> float = "caml_sin_float" "sin" "float" -external sinh : float -> float = "caml_sinh_float" "sinh" "float" -external sqrt : float -> float = "caml_sqrt_float" "sqrt" "float" -external tan : float -> float = "caml_tan_float" "tan" "float" -external tanh : float -> float = "caml_tanh_float" "tanh" "float" -external ceil : float -> float = "caml_ceil_float" "ceil" "float" -external floor : float -> float = "caml_floor_float" "floor" "float" + = "caml_hypot_float" "caml_hypot" [@@unboxed] [@@noalloc] +external cos : float -> float = "caml_cos_float" "cos" [@@unboxed] [@@noalloc] +external cosh : float -> float = "caml_cosh_float" "cosh" + [@@unboxed] [@@noalloc] +external log : float -> float = "caml_log_float" "log" [@@unboxed] [@@noalloc] +external log10 : float -> float = "caml_log10_float" "log10" + [@@unboxed] [@@noalloc] +external log1p : float -> float = "caml_log1p_float" "caml_log1p" + [@@unboxed] [@@noalloc] +external sin : float -> float = "caml_sin_float" "sin" [@@unboxed] [@@noalloc] +external sinh : float -> float = "caml_sinh_float" "sinh" + [@@unboxed] [@@noalloc] +external sqrt : float -> float = "caml_sqrt_float" "sqrt" + [@@unboxed] [@@noalloc] +external tan : float -> float = "caml_tan_float" "tan" [@@unboxed] [@@noalloc] +external tanh : float -> float = "caml_tanh_float" "tanh" + [@@unboxed] [@@noalloc] +external ceil : float -> float = "caml_ceil_float" "ceil" + [@@unboxed] [@@noalloc] +external floor : float -> float = "caml_floor_float" "floor" + [@@unboxed] [@@noalloc] external abs_float : float -> float = "%absfloat" external copysign : float -> float -> float - = "caml_copysign_float" "caml_copysign" "float" -external mod_float : float -> float -> float = "caml_fmod_float" "fmod" "float" + = "caml_copysign_float" "caml_copysign" + [@@unboxed] [@@noalloc] +external mod_float : float -> float -> float = "caml_fmod_float" "fmod" + [@@unboxed] [@@noalloc] external frexp : float -> float * int = "caml_frexp_float" -external ldexp : float -> int -> float = "caml_ldexp_float" +external ldexp : (float [@unboxed]) -> (int [@untagged]) -> (float [@unboxed]) = + "caml_ldexp_float" "caml_ldexp_float_unboxed" [@@noalloc] external modf : float -> float * float = "caml_modf_float" external float : int -> float = "%floatofint" external float_of_int : int -> float = "%floatofint" @@ -164,7 +183,8 @@ type fpclass = | FP_zero | FP_infinite | FP_nan -external classify_float : float -> fpclass = "caml_classify_float" +external classify_float : (float [@unboxed]) -> fpclass = + "caml_classify_float" "caml_classify_float_unboxed" [@@noalloc] (* String and byte sequence operations -- more in modules String and Bytes *) @@ -172,9 +192,9 @@ external string_length : string -> int = "%string_length" external bytes_length : bytes -> int = "%string_length" external bytes_create : int -> bytes = "caml_create_string" external string_blit : string -> int -> bytes -> int -> int -> unit - = "caml_blit_string" "noalloc" + = "caml_blit_string" [@@noalloc] external bytes_blit : bytes -> int -> bytes -> int -> int -> unit - = "caml_blit_string" "noalloc" + = "caml_blit_string" [@@noalloc] external bytes_unsafe_to_string : bytes -> string = "%identity" external bytes_unsafe_of_string : string -> bytes = "%identity" @@ -210,6 +230,10 @@ external ( := ) : 'a ref -> 'a -> unit = "%setfield0" external incr : int ref -> unit = "%incr" external decr : int ref -> unit = "%decr" +(* Result type *) + +type ('a,'b) result = Ok of 'a | Error of 'b + (* String conversion functions *) external format_int : string -> int -> string = "caml_format_int" @@ -289,8 +313,13 @@ type open_flag = external open_desc : string -> open_flag list -> int -> int = "caml_sys_open" +external set_out_channel_name: out_channel -> string -> unit = + "caml_ml_set_channel_name" + let open_out_gen mode perm name = - open_descriptor_out(open_desc name mode perm) + let c = open_descriptor_out(open_desc name mode perm) in + set_out_channel_name c name; + c let open_out name = open_out_gen [Open_wronly; Open_creat; Open_trunc; Open_text] 0o666 name @@ -395,8 +424,13 @@ external set_binary_mode_out : out_channel -> bool -> unit (* General input functions *) +external set_in_channel_name: in_channel -> string -> unit = + "caml_ml_set_channel_name" + let open_in_gen mode perm name = - open_descriptor_in(open_desc name mode perm) + let c = open_descriptor_in(open_desc name mode perm) in + set_in_channel_name c name; + c let open_in name = open_in_gen [Open_rdonly; Open_text] 0 name diff --git a/otherlibs/threads/scheduler.c b/otherlibs/threads/scheduler.c index 585a8903..4fb9b1c3 100644 --- a/otherlibs/threads/scheduler.c +++ b/otherlibs/threads/scheduler.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The thread scheduler */ @@ -80,7 +82,7 @@ struct caml_thread_struct { value * sp; value * trapsp; value backtrace_pos; /* The backtrace info for this thread */ - code_t * backtrace_buffer; + backtrace_slot * backtrace_buffer; value backtrace_last_exn; value status; /* RUNNABLE, KILLED. etc (see below) */ value fd; /* File descriptor on which we're doing read or write */ diff --git a/otherlibs/threads/thread.ml b/otherlibs/threads/thread.ml index 6ef9997d..c4561e18 100644 --- a/otherlibs/threads/thread.ml +++ b/otherlibs/threads/thread.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* User-level threads *) @@ -64,11 +66,10 @@ external thread_join : t -> unit = "thread_join" external thread_delay : float -> unit = "thread_delay" external thread_wait_pid : int -> resumption_status = "thread_wait_pid" external thread_wakeup : t -> unit = "thread_wakeup" -external thread_self : unit -> t = "thread_self" +external thread_self : unit -> t = "thread_self" [@@noalloc] external thread_kill : t -> unit = "thread_kill" external thread_uncaught_exception : exn -> unit = "thread_uncaught_exception" - -external id : t -> int = "thread_id" +external thread_id : t -> int = "thread_id" [@@noalloc] (* In sleep() below, we rely on the fact that signals are detected only at function applications and beginning of loops, @@ -82,6 +83,7 @@ let wakeup pid = thread_wakeup pid let self () = thread_self() let kill pid = thread_kill pid let exit () = thread_kill(thread_self()) +let id t = thread_id t let select_aux arg = thread_select arg diff --git a/otherlibs/threads/thread.mli b/otherlibs/threads/thread.mli index e026a214..8369bbae 100644 --- a/otherlibs/threads/thread.mli +++ b/otherlibs/threads/thread.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Lightweight threads. *) @@ -35,7 +37,7 @@ val create : ('a -> 'b) -> 'a -> t val self : unit -> t (** Return the thread currently executing. *) -external id : t -> int = "thread_id" +val id : t -> int (** Return the identifier of the given thread. A thread identifier is an integer that identifies uniquely the thread. It can be used to build data structures indexed by threads. *) diff --git a/otherlibs/threads/threadUnix.ml b/otherlibs/threads/threadUnix.ml index c086c1f5..95b5857a 100644 --- a/otherlibs/threads/threadUnix.ml +++ b/otherlibs/threads/threadUnix.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Module [ThreadUnix]: thread-compatible system calls *) diff --git a/otherlibs/threads/threadUnix.mli b/otherlibs/threads/threadUnix.mli index 52862f98..1bc9dea1 100644 --- a/otherlibs/threads/threadUnix.mli +++ b/otherlibs/threads/threadUnix.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Thread-compatible system calls. diff --git a/otherlibs/threads/threads.mllib b/otherlibs/threads/threads.mllib deleted file mode 100644 index 3ff8841b..00000000 --- a/otherlibs/threads/threads.mllib +++ /dev/null @@ -1 +0,0 @@ -Thread Mutex Condition Event ThreadUnix diff --git a/otherlibs/threads/unix.ml b/otherlibs/threads/unix.ml index a397ec40..491aeda1 100644 --- a/otherlibs/threads/unix.ml +++ b/otherlibs/threads/unix.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* An alternate implementation of the Unix module from ../unix which is safe in conjunction with bytecode threads. *) @@ -356,7 +358,8 @@ let pipe() = set_nonblock out_fd; fd_pair -external symlink : string -> string -> unit = "unix_symlink" +external symlink : ?to_dir:bool -> string -> string -> unit = "unix_symlink" +external has_symlink : unit -> bool = "unix_has_symlink" external readlink : string -> string = "unix_readlink" external mkfifo : string -> file_perm -> unit = "unix_mkfifo" @@ -472,6 +475,7 @@ external localtime : float -> tm = "unix_localtime" external mktime : tm -> float * tm = "unix_mktime" external alarm : int -> int = "unix_alarm" +let sleepf = delay let sleep secs = delay (float secs) external times : unit -> process_times = "unix_times" diff --git a/otherlibs/threads/unix.mllib b/otherlibs/threads/unix.mllib deleted file mode 100644 index 8d569c56..00000000 --- a/otherlibs/threads/unix.mllib +++ /dev/null @@ -1 +0,0 @@ -Unix UnixLabels diff --git a/otherlibs/unix/.depend b/otherlibs/unix/.depend index f03f792a..7e794880 100644 --- a/otherlibs/unix/.depend +++ b/otherlibs/unix/.depend @@ -1,83 +1,81 @@ accept.o: accept.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + ../../byterun/caml/signals.h unixsupport.h socketaddr.h access.o: access.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/memory.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/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 \ unixsupport.h addrofstr.o: addrofstr.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/fail.h unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + ../../byterun/caml/fail.h unixsupport.h socketaddr.h alarm.o: alarm.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h bind.o: bind.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + unixsupport.h socketaddr.h chdir.o: chdir.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h chmod.o: chmod.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h chown.o: chown.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h chroot.o: chroot.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h close.o: close.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/signals.h \ - ../../byterun/caml/mlvalues.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/signals.h unixsupport.h closedir.o: closedir.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h @@ -85,203 +83,203 @@ connect.o: connect.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/signals.h \ - unixsupport.h socketaddr.h ../../byterun/caml/misc.h + ../../byterun/caml/signals.h unixsupport.h socketaddr.h cst2constr.o: cst2constr.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/fail.h \ - ../../byterun/caml/mlvalues.h cst2constr.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/fail.h cst2constr.h cstringv.o: cstringv.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 \ unixsupport.h dup.o: dup.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h dup2.o: dup2.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h envir.o: envir.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/alloc.h \ - ../../byterun/caml/mlvalues.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h errmsg.o: errmsg.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/alloc.h \ - ../../byterun/caml/mlvalues.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h execv.o: execv.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 \ unixsupport.h execve.o: execve.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 \ unixsupport.h 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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 \ unixsupport.h exit.o: exit.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h fchmod.o: fchmod.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/signals.h \ - unixsupport.h + ../../byterun/caml/signals.h unixsupport.h fchown.o: fchown.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/signals.h \ - unixsupport.h + ../../byterun/caml/signals.h unixsupport.h fcntl.o: fcntl.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h + unixsupport.h fork.o: fork.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/debugger.h \ - ../../byterun/caml/mlvalues.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/debugger.h unixsupport.h ftruncate.o: ftruncate.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/io.h \ - ../../byterun/caml/signals.h unixsupport.h + ../../byterun/caml/io.h ../../byterun/caml/signals.h unixsupport.h getaddrinfo.o: getaddrinfo.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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/misc.h ../../byterun/caml/signals.h unixsupport.h \ - cst2constr.h socketaddr.h + ../../byterun/caml/signals.h unixsupport.h cst2constr.h socketaddr.h getcwd.o: getcwd.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h getegid.o: getegid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h geteuid.o: geteuid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h getgid.o: getgid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h getgr.o: getgr.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/fail.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/alloc.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/fail.h ../../byterun/caml/alloc.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 \ unixsupport.h getgroups.o: getgroups.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h gethost.o: gethost.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + ../../byterun/caml/signals.h unixsupport.h socketaddr.h gethostname.o: gethostname.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h getlogin.o: getlogin.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/alloc.h \ - ../../byterun/caml/mlvalues.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h unixsupport.h getnameinfo.o: getnameinfo.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + ../../byterun/caml/signals.h unixsupport.h socketaddr.h getpeername.o: getpeername.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + unixsupport.h socketaddr.h getpid.o: getpid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h getppid.o: getppid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h getproto.o: getproto.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 \ unixsupport.h getpw.o: getpw.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/memory.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/gc.h ../../byterun/caml/major_gc.h \ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ ../../byterun/caml/address_class.h ../../byterun/caml/fail.h \ unixsupport.h getserv.o: getserv.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 \ @@ -290,55 +288,55 @@ getsockname.o: getsockname.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + unixsupport.h socketaddr.h gettimeofday.o: gettimeofday.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h getuid.o: getuid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h gmtime.o: gmtime.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 \ unixsupport.h initgroups.o: initgroups.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h isatty.o: isatty.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h itimer.o: itimer.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 \ unixsupport.h kill.o: kill.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/fail.h \ - ../../byterun/caml/mlvalues.h unixsupport.h \ - ../../byterun/caml/signals.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/fail.h unixsupport.h ../../byterun/caml/signals.h link.o: link.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h @@ -346,24 +344,23 @@ listen.o: listen.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h + unixsupport.h lockf.o: lockf.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/signals.h \ - unixsupport.h + ../../byterun/caml/signals.h unixsupport.h lseek.o: lseek.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/io.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/io.h \ ../../byterun/caml/signals.h unixsupport.h mkdir.o: mkdir.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h @@ -371,37 +368,37 @@ mkfifo.o: mkfifo.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.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 \ - unixsupport.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 unixsupport.h nice.o: nice.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h open.o: open.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/memory.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/gc.h ../../byterun/caml/major_gc.h \ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h ../../byterun/caml/misc.h \ - ../../byterun/caml/signals.h unixsupport.h + ../../byterun/caml/address_class.h ../../byterun/caml/signals.h \ + unixsupport.h opendir.o: opendir.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/alloc.h ../../byterun/caml/signals.h unixsupport.h pipe.o: pipe.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/alloc.h \ - ../../byterun/caml/mlvalues.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h unixsupport.h putenv.o: putenv.c ../../byterun/caml/fail.h \ ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \ ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ @@ -409,35 +406,35 @@ putenv.o: putenv.c ../../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/mlvalues.h unixsupport.h + unixsupport.h read.o: read.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h readdir.o: readdir.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/fail.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/alloc.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/fail.h ../../byterun/caml/alloc.h \ ../../byterun/caml/signals.h unixsupport.h readlink.o: readlink.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/alloc.h ../../byterun/caml/fail.h \ ../../byterun/caml/signals.h unixsupport.h rename.o: rename.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h @@ -445,43 +442,43 @@ rewinddir.o: rewinddir.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h + unixsupport.h rmdir.o: rmdir.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h select.o: select.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 unixsupport.h sendrecv.o: sendrecv.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + ../../byterun/caml/signals.h unixsupport.h socketaddr.h setgid.o: setgid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h setgroups.o: setgroups.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 \ @@ -490,16 +487,17 @@ setsid.o: setsid.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h + unixsupport.h setuid.o: setuid.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h shutdown.o: shutdown.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h + unixsupport.h signals.o: signals.c ../../byterun/caml/alloc.h \ ../../byterun/caml/compatibility.h ../../byterun/caml/misc.h \ ../../byterun/caml/config.h ../../byterun/caml/../../config/m.h \ @@ -507,110 +505,109 @@ signals.o: signals.c ../../byterun/caml/alloc.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/mlvalues.h \ - ../../byterun/caml/signals.h unixsupport.h + ../../byterun/caml/address_class.h ../../byterun/caml/signals.h \ + unixsupport.h sleep.o: sleep.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/signals.h \ - ../../byterun/caml/mlvalues.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/signals.h unixsupport.h socket.o: socket.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.h unixsupport.h + unixsupport.h socketaddr.o: socketaddr.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/memory.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/gc.h ../../byterun/caml/major_gc.h \ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ - ../../byterun/caml/address_class.h unixsupport.h socketaddr.h \ - ../../byterun/caml/misc.h + ../../byterun/caml/address_class.h unixsupport.h socketaddr.h socketpair.o: socketpair.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h sockopt.o: sockopt.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/alloc.h ../../byterun/caml/fail.h unixsupport.h \ - socketaddr.h ../../byterun/caml/misc.h + socketaddr.h stat.o: stat.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/alloc.h ../../byterun/caml/signals.h \ ../../byterun/caml/io.h unixsupport.h cst2constr.h nanosecond_stat.h strofaddr.o: strofaddr.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h \ - socketaddr.h ../../byterun/caml/misc.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h \ + socketaddr.h symlink.o: symlink.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.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 \ - unixsupport.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 unixsupport.h termios.o: termios.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/fail.h unixsupport.h time.o: time.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/alloc.h \ - ../../byterun/caml/mlvalues.h unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h unixsupport.h times.o: times.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/memory.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/gc.h ../../byterun/caml/major_gc.h \ ../../byterun/caml/freelist.h ../../byterun/caml/minor_gc.h \ ../../byterun/caml/address_class.h unixsupport.h truncate.o: truncate.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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/fail.h ../../byterun/caml/signals.h \ ../../byterun/caml/io.h unixsupport.h umask.o: umask.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 unixsupport.h + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + unixsupport.h unixsupport.o: unixsupport.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/callback.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.h ../../byterun/caml/callback.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/fail.h unixsupport.h cst2constr.h unlink.o: unlink.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h @@ -618,25 +615,24 @@ utimes.o: utimes.c ../../byterun/caml/fail.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 \ - ../../byterun/caml/mlvalues.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 \ - unixsupport.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 unixsupport.h wait.o: wait.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/alloc.h \ - ../../byterun/caml/mlvalues.h ../../byterun/caml/fail.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.h \ + ../../byterun/caml/alloc.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 unixsupport.h write.o: write.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 \ - ../../byterun/caml/gc.h ../../byterun/caml/mlvalues.h \ + ../../byterun/caml/../../config/m.h \ + ../../byterun/caml/../../config/s.h ../../byterun/caml/misc.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 unixsupport.h diff --git a/otherlibs/unix/Makefile b/otherlibs/unix/Makefile index faebd3f5..e93696ea 100644 --- a/otherlibs/unix/Makefile +++ b/otherlibs/unix/Makefile @@ -1,15 +1,17 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** # Makefile for the Unix interface library diff --git a/otherlibs/unix/accept.c b/otherlibs/unix/accept.c index 3fd01918..d2217496 100644 --- a/otherlibs/unix/accept.c +++ b/otherlibs/unix/accept.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/access.c b/otherlibs/unix/access.c index 28c26b82..25401c5c 100644 --- a/otherlibs/unix/access.c +++ b/otherlibs/unix/access.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -46,6 +48,7 @@ CAMLprim value unix_access(value path, value perms) char * p; int ret, cv_flags; + caml_unix_check_path(path, "access"); cv_flags = convert_flag_list(perms, access_permission_table); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); diff --git a/otherlibs/unix/addrofstr.c b/otherlibs/unix/addrofstr.c index c4bd2e72..72f0ebd3 100644 --- a/otherlibs/unix/addrofstr.c +++ b/otherlibs/unix/addrofstr.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -22,8 +24,10 @@ CAMLprim value unix_inet_addr_of_string(value s) { + if (! caml_string_is_c_safe(s)) failwith("inet_addr_of_string"); #if defined(HAS_IPV6) #ifdef _WIN32 + { CAMLparam1(s); CAMLlocal1(vres); struct addrinfo hints; @@ -55,7 +59,9 @@ CAMLprim value unix_inet_addr_of_string(value s) } freeaddrinfo(res); CAMLreturn (vres); + } #else + { struct in_addr address; struct in6_addr address6; if (inet_pton(AF_INET, String_val(s), &address) > 0) @@ -64,17 +70,22 @@ CAMLprim value unix_inet_addr_of_string(value s) return alloc_inet6_addr(&address6); else 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"); return alloc_inet_addr(&address); + } #else + { struct in_addr address; address.s_addr = inet_addr(String_val(s)); - if (address.s_addr == (uint32) -1) failwith("inet_addr_of_string"); + if (address.s_addr == (uint32_t) -1) failwith("inet_addr_of_string"); return alloc_inet_addr(&address); + } #endif } diff --git a/otherlibs/unix/alarm.c b/otherlibs/unix/alarm.c index eb92a682..05542524 100644 --- a/otherlibs/unix/alarm.c +++ b/otherlibs/unix/alarm.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/bind.c b/otherlibs/unix/bind.c index 4ea75c21..8849e6a9 100644 --- a/otherlibs/unix/bind.c +++ b/otherlibs/unix/bind.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/chdir.c b/otherlibs/unix/chdir.c index 24732111..244ad5d3 100644 --- a/otherlibs/unix/chdir.c +++ b/otherlibs/unix/chdir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -21,6 +23,7 @@ CAMLprim value unix_chdir(value path) CAMLparam1(path); char * p; int ret; + caml_unix_check_path(path, "chdir"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = chdir(p); diff --git a/otherlibs/unix/chmod.c b/otherlibs/unix/chmod.c index 2d3f30fe..cfdc1a33 100644 --- a/otherlibs/unix/chmod.c +++ b/otherlibs/unix/chmod.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -23,6 +25,7 @@ CAMLprim value unix_chmod(value path, value perm) CAMLparam2(path, perm); char * p; int ret; + caml_unix_check_path(path, "chmod"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = chmod(p, Int_val(perm)); diff --git a/otherlibs/unix/chown.c b/otherlibs/unix/chown.c index 6c9e896a..f018e9e0 100644 --- a/otherlibs/unix/chown.c +++ b/otherlibs/unix/chown.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -21,6 +23,7 @@ CAMLprim value unix_chown(value path, value uid, value gid) CAMLparam1(path); char * p; int ret; + caml_unix_check_path(path, "chown"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = chown(p, Int_val(uid), Int_val(gid)); diff --git a/otherlibs/unix/chroot.c b/otherlibs/unix/chroot.c index c30a0da9..7b87de72 100644 --- a/otherlibs/unix/chroot.c +++ b/otherlibs/unix/chroot.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -21,6 +23,7 @@ CAMLprim value unix_chroot(value path) CAMLparam1(path); char * p; int ret; + caml_unix_check_path(path, "chroot"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = chroot(p); diff --git a/otherlibs/unix/close.c b/otherlibs/unix/close.c index aff8911f..961b8cbf 100644 --- a/otherlibs/unix/close.c +++ b/otherlibs/unix/close.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/closedir.c b/otherlibs/unix/closedir.c index 5e8008d5..97bebb49 100644 --- a/otherlibs/unix/closedir.c +++ b/otherlibs/unix/closedir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/connect.c b/otherlibs/unix/connect.c index b4b3e19c..4e79efa0 100644 --- a/otherlibs/unix/connect.c +++ b/otherlibs/unix/connect.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/cst2constr.c b/otherlibs/unix/cst2constr.c index 87721ce3..aab492b9 100644 --- a/otherlibs/unix/cst2constr.c +++ b/otherlibs/unix/cst2constr.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/cst2constr.h b/otherlibs/unix/cst2constr.h index 88985e52..44c9299e 100644 --- a/otherlibs/unix/cst2constr.h +++ b/otherlibs/unix/cst2constr.h @@ -1,14 +1,16 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ extern value cst_to_constr(int n, int * tbl, int size, int deflt); diff --git a/otherlibs/unix/cstringv.c b/otherlibs/unix/cstringv.c index 0e614918..68441cfa 100644 --- a/otherlibs/unix/cstringv.c +++ b/otherlibs/unix/cstringv.c @@ -1,26 +1,32 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include #include "unixsupport.h" -char ** cstringvect(value arg) +char ** cstringvect(value arg, char * cmdname) { char ** res; mlsize_t size, i; size = Wosize_val(arg); + for (i = 0; i < size; i++) + if (! caml_string_is_c_safe(Field(arg, i))) + unix_error(EINVAL, cmdname, Field(arg, i)); res = (char **) caml_stat_alloc((size + 1) * sizeof(char *)); for (i = 0; i < size; i++) res[i] = String_val(Field(arg, i)); res[size] = NULL; diff --git a/otherlibs/unix/dup.c b/otherlibs/unix/dup.c index c6e9dcf2..018eafa8 100644 --- a/otherlibs/unix/dup.c +++ b/otherlibs/unix/dup.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/dup2.c b/otherlibs/unix/dup2.c index fd9ea3d2..c824cc58 100644 --- a/otherlibs/unix/dup2.c +++ b/otherlibs/unix/dup2.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/envir.c b/otherlibs/unix/envir.c index 366608b6..b9d451ea 100644 --- a/otherlibs/unix/envir.c +++ b/otherlibs/unix/envir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/errmsg.c b/otherlibs/unix/errmsg.c index 0f610e9d..927e2cfa 100644 --- a/otherlibs/unix/errmsg.c +++ b/otherlibs/unix/errmsg.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/execv.c b/otherlibs/unix/execv.c index 9a775489..2a77224d 100644 --- a/otherlibs/unix/execv.c +++ b/otherlibs/unix/execv.c @@ -1,26 +1,27 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include "unixsupport.h" -extern char ** cstringvect(); - CAMLprim value unix_execv(value path, value args) { char ** argv; - argv = cstringvect(args); + caml_unix_check_path(path, "execv"); + argv = cstringvect(args, "execv"); (void) execv(String_val(path), argv); stat_free((char *) argv); uerror("execv", path); diff --git a/otherlibs/unix/execve.c b/otherlibs/unix/execve.c index 92171c2d..65f6a349 100644 --- a/otherlibs/unix/execve.c +++ b/otherlibs/unix/execve.c @@ -1,28 +1,29 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include "unixsupport.h" -extern char ** cstringvect(); - CAMLprim value unix_execve(value path, value args, value env) { char ** argv; char ** envp; - argv = cstringvect(args); - envp = cstringvect(env); + caml_unix_check_path(path, "execve"); + argv = cstringvect(args, "execve"); + envp = cstringvect(env, "execve"); (void) execve(String_val(path), argv, envp); stat_free((char *) argv); stat_free((char *) envp); diff --git a/otherlibs/unix/execvp.c b/otherlibs/unix/execvp.c index ce6900ab..72a986e1 100644 --- a/otherlibs/unix/execvp.c +++ b/otherlibs/unix/execvp.c @@ -1,21 +1,22 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include "unixsupport.h" -extern char ** cstringvect(); #ifndef _WIN32 extern char ** environ; #endif @@ -23,7 +24,8 @@ extern char ** environ; CAMLprim value unix_execvp(value path, value args) { char ** argv; - argv = cstringvect(args); + caml_unix_check_path(path, "execvp"); + argv = cstringvect(args, "execvp"); (void) execvp(String_val(path), argv); stat_free((char *) argv); uerror("execvp", path); @@ -35,9 +37,10 @@ CAMLprim value unix_execvpe(value path, value args, value env) { char ** argv; char ** saved_environ; - argv = cstringvect(args); + caml_unix_check_path(path, "execvpe"); + argv = cstringvect(args, "execvpe"); saved_environ = environ; - environ = cstringvect(env); + environ = cstringvect(env, "execvpe"); (void) execvp(String_val(path), argv); stat_free((char *) argv); stat_free((char *) environ); diff --git a/otherlibs/unix/exit.c b/otherlibs/unix/exit.c index cfc4e16c..8da00dac 100644 --- a/otherlibs/unix/exit.c +++ b/otherlibs/unix/exit.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/fchmod.c b/otherlibs/unix/fchmod.c index 11578ff2..5fe50c46 100644 --- a/otherlibs/unix/fchmod.c +++ b/otherlibs/unix/fchmod.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/fchown.c b/otherlibs/unix/fchown.c index 24872ec8..c1d86d62 100644 --- a/otherlibs/unix/fchown.c +++ b/otherlibs/unix/fchown.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/fcntl.c b/otherlibs/unix/fcntl.c index c89e9a6f..869534db 100644 --- a/otherlibs/unix/fcntl.c +++ b/otherlibs/unix/fcntl.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/fork.c b/otherlibs/unix/fork.c index ac0d6772..bd174de5 100644 --- a/otherlibs/unix/fork.c +++ b/otherlibs/unix/fork.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/ftruncate.c b/otherlibs/unix/ftruncate.c index 08a4a775..8542786a 100644 --- a/otherlibs/unix/ftruncate.c +++ b/otherlibs/unix/ftruncate.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/getaddrinfo.c b/otherlibs/unix/getaddrinfo.c index 28179343..837794ed 100644 --- a/otherlibs/unix/getaddrinfo.c +++ b/otherlibs/unix/getaddrinfo.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2004 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2004 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 #include @@ -62,6 +64,9 @@ CAMLprim value unix_getaddrinfo(value vnode, value vserv, value vopts) struct addrinfo * res, * r; int retcode; + if (! (caml_string_is_c_safe(vnode) && caml_string_is_c_safe(vserv))) + return Val_int(0); + /* Extract "node" parameter */ if (caml_string_length(vnode) == 0) { node = NULL; diff --git a/otherlibs/unix/getcwd.c b/otherlibs/unix/getcwd.c index 043c96b6..9dac1477 100644 --- a/otherlibs/unix/getcwd.c +++ b/otherlibs/unix/getcwd.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/getegid.c b/otherlibs/unix/getegid.c index c0ab2b39..ddda2f63 100644 --- a/otherlibs/unix/getegid.c +++ b/otherlibs/unix/getegid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/geteuid.c b/otherlibs/unix/geteuid.c index 095d3fe1..3243ba76 100644 --- a/otherlibs/unix/geteuid.c +++ b/otherlibs/unix/geteuid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/getgid.c b/otherlibs/unix/getgid.c index 8a4991a5..f18b4c09 100644 --- a/otherlibs/unix/getgid.c +++ b/otherlibs/unix/getgid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/getgr.c b/otherlibs/unix/getgr.c index 14338ccf..ee194fa7 100644 --- a/otherlibs/unix/getgr.c +++ b/otherlibs/unix/getgr.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -40,6 +42,7 @@ 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(); entry = getgrnam(String_val(name)); if (entry == NULL) raise_not_found(); return alloc_group_entry(entry); diff --git a/otherlibs/unix/getgroups.c b/otherlibs/unix/getgroups.c index 84cd4540..bc65e3a8 100644 --- a/otherlibs/unix/getgroups.c +++ b/otherlibs/unix/getgroups.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/gethost.c b/otherlibs/unix/gethost.c index d5220415..8d211dd5 100644 --- a/otherlibs/unix/gethost.c +++ b/otherlibs/unix/gethost.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -125,6 +127,13 @@ CAMLprim value unix_gethostbyname(value name) { struct hostent * hp; char * hostname; +#if HAS_GETHOSTBYNAME_R + struct hostent h; + char buffer[NETDB_BUFFER_SIZE]; + int err; +#endif + + if (! caml_string_is_c_safe(name)) raise_not_found(); #if HAS_GETHOSTBYNAME_R || GETHOSTBYNAME_IS_REENTRANT hostname = caml_strdup(String_val(name)); @@ -134,20 +143,15 @@ CAMLprim value unix_gethostbyname(value name) #if HAS_GETHOSTBYNAME_R == 5 { - struct hostent h; - char buffer[NETDB_BUFFER_SIZE]; - int h_errno; enter_blocking_section(); - hp = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &h_errno); + hp = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &err); leave_blocking_section(); } #elif HAS_GETHOSTBYNAME_R == 6 { - struct hostent h; - char buffer[NETDB_BUFFER_SIZE]; - int h_errno, rc; + int rc; enter_blocking_section(); - rc = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &hp, &h_errno); + rc = gethostbyname_r(hostname, &h, buffer, sizeof(buffer), &hp, &err); leave_blocking_section(); if (rc != 0) hp = NULL; } diff --git a/otherlibs/unix/gethostname.c b/otherlibs/unix/gethostname.c index a3aba574..b7f88b84 100644 --- a/otherlibs/unix/gethostname.c +++ b/otherlibs/unix/gethostname.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/getlogin.c b/otherlibs/unix/getlogin.c index 7f40e442..9ed4936b 100644 --- a/otherlibs/unix/getlogin.c +++ b/otherlibs/unix/getlogin.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/getnameinfo.c b/otherlibs/unix/getnameinfo.c index d4663957..0e6e6c3b 100644 --- a/otherlibs/unix/getnameinfo.c +++ b/otherlibs/unix/getnameinfo.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2004 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2004 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 #include diff --git a/otherlibs/unix/getpeername.c b/otherlibs/unix/getpeername.c index 183b210d..86108c33 100644 --- a/otherlibs/unix/getpeername.c +++ b/otherlibs/unix/getpeername.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/getpid.c b/otherlibs/unix/getpid.c index 4cf46e4c..1c7600d6 100644 --- a/otherlibs/unix/getpid.c +++ b/otherlibs/unix/getpid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/getppid.c b/otherlibs/unix/getppid.c index 8c30a77a..ba961f32 100644 --- a/otherlibs/unix/getppid.c +++ b/otherlibs/unix/getppid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/getproto.c b/otherlibs/unix/getproto.c index b89cbba4..c4edcdcc 100644 --- a/otherlibs/unix/getproto.c +++ b/otherlibs/unix/getproto.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -42,6 +44,7 @@ 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(); entry = getprotobyname(String_val(name)); if (entry == (struct protoent *) NULL) raise_not_found(); return alloc_proto_entry(entry); diff --git a/otherlibs/unix/getpw.c b/otherlibs/unix/getpw.c index 82fb4d8f..07dc36b5 100644 --- a/otherlibs/unix/getpw.c +++ b/otherlibs/unix/getpw.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -49,6 +51,7 @@ 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(); entry = getpwnam(String_val(name)); if (entry == (struct passwd *) NULL) raise_not_found(); return alloc_passwd_entry(entry); diff --git a/otherlibs/unix/getserv.c b/otherlibs/unix/getserv.c index deb5f147..1ece7900 100644 --- a/otherlibs/unix/getserv.c +++ b/otherlibs/unix/getserv.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -48,6 +50,8 @@ static value alloc_service_entry(struct servent *entry) 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(); entry = getservbyname(String_val(name), String_val(proto)); if (entry == (struct servent *) NULL) raise_not_found(); return alloc_service_entry(entry); @@ -56,6 +60,7 @@ CAMLprim value unix_getservbyname(value name, value proto) CAMLprim value unix_getservbyport(value port, value proto) { struct servent * entry; + if (! caml_string_is_c_safe(proto)) raise_not_found(); entry = getservbyport(htons(Int_val(port)), String_val(proto)); if (entry == (struct servent *) NULL) raise_not_found(); return alloc_service_entry(entry); diff --git a/otherlibs/unix/getsockname.c b/otherlibs/unix/getsockname.c index b28cfd14..008da873 100644 --- a/otherlibs/unix/getsockname.c +++ b/otherlibs/unix/getsockname.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/gettimeofday.c b/otherlibs/unix/gettimeofday.c index 9cbfbeaa..3b8250ad 100644 --- a/otherlibs/unix/gettimeofday.c +++ b/otherlibs/unix/gettimeofday.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/getuid.c b/otherlibs/unix/getuid.c index 7d0ce399..781c4b8d 100644 --- a/otherlibs/unix/getuid.c +++ b/otherlibs/unix/getuid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/gmtime.c b/otherlibs/unix/gmtime.c index 566f174f..9ffbbc65 100644 --- a/otherlibs/unix/gmtime.c +++ b/otherlibs/unix/gmtime.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/initgroups.c b/otherlibs/unix/initgroups.c index ca3ed4c9..48fb532f 100644 --- a/otherlibs/unix/initgroups.c +++ b/otherlibs/unix/initgroups.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Stephane Glondu */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Stephane Glondu */ +/* */ +/* Copyright 2009 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 #include @@ -21,12 +23,15 @@ #ifdef HAS_UNISTD #include #endif +#include #include #include #include "unixsupport.h" CAMLprim value unix_initgroups(value user, value group) { + if (! caml_string_is_c_safe(user)) + unix_error(EINVAL, "initgroups", user); if (initgroups(String_val(user), Int_val(group)) == -1) { uerror("initgroups", Nothing); } diff --git a/otherlibs/unix/isatty.c b/otherlibs/unix/isatty.c index 935c39d4..fb537dd1 100644 --- a/otherlibs/unix/isatty.c +++ b/otherlibs/unix/isatty.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ -/* */ -/* Copyright 2006 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Gallium, INRIA Rocquencourt */ +/* */ +/* Copyright 2006 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 #include "unixsupport.h" diff --git a/otherlibs/unix/itimer.c b/otherlibs/unix/itimer.c index f1950264..713a4f34 100644 --- a/otherlibs/unix/itimer.c +++ b/otherlibs/unix/itimer.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/kill.c b/otherlibs/unix/kill.c index c0f74d48..3593369b 100644 --- a/otherlibs/unix/kill.c +++ b/otherlibs/unix/kill.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/libunix.clib b/otherlibs/unix/libunix.clib deleted file mode 100644 index b866ea06..00000000 --- a/otherlibs/unix/libunix.clib +++ /dev/null @@ -1,16 +0,0 @@ -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 -fchmod.o fchown.o fcntl.o fork.o ftruncate.o -getaddrinfo.o getcwd.o getegid.o geteuid.o getgid.o -getgr.o getgroups.o gethost.o gethostname.o getlogin.o -getnameinfo.o getpeername.o getpid.o getppid.o getproto.o getpw.o -gettimeofday.o getserv.o getsockname.o getuid.o gmtime.o -initgroups.o isatty.o itimer.o kill.o link.o listen.o lockf.o lseek.o -mkdir.o mkfifo.o nice.o open.o opendir.o pipe.o putenv.o read.o -readdir.o readlink.o rename.o rewinddir.o rmdir.o select.o sendrecv.o -setgid.o setgroups.o setsid.o setuid.o shutdown.o signals.o -sleep.o socket.o socketaddr.o -socketpair.o sockopt.o stat.o strofaddr.o symlink.o termios.o -time.o times.o truncate.o umask.o unixsupport.o unlink.o -utimes.o wait.o write.o diff --git a/otherlibs/unix/link.c b/otherlibs/unix/link.c index 0ec42f5f..3179c060 100644 --- a/otherlibs/unix/link.c +++ b/otherlibs/unix/link.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -22,6 +24,8 @@ CAMLprim value unix_link(value path1, value path2) char * p1; char * p2; int ret; + caml_unix_check_path(path1, "link"); + caml_unix_check_path(path2, "link"); p1 = caml_strdup(String_val(path1)); p2 = caml_strdup(String_val(path2)); caml_enter_blocking_section(); diff --git a/otherlibs/unix/listen.c b/otherlibs/unix/listen.c index 38efc9fd..40b511b1 100644 --- a/otherlibs/unix/listen.c +++ b/otherlibs/unix/listen.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/lockf.c b/otherlibs/unix/lockf.c index aeaf4513..130b107a 100644 --- a/otherlibs/unix/lockf.c +++ b/otherlibs/unix/lockf.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/lseek.c b/otherlibs/unix/lseek.c index 5a7b7770..d8978555 100644 --- a/otherlibs/unix/lseek.c +++ b/otherlibs/unix/lseek.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/mkdir.c b/otherlibs/unix/mkdir.c index 6b9c76e6..93cb61cc 100644 --- a/otherlibs/unix/mkdir.c +++ b/otherlibs/unix/mkdir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -23,6 +25,7 @@ CAMLprim value unix_mkdir(value path, value perm) CAMLparam2(path, perm); char * p; int ret; + caml_unix_check_path(path, "mkdir"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = mkdir(p, Int_val(perm)); diff --git a/otherlibs/unix/mkfifo.c b/otherlibs/unix/mkfifo.c index 07481385..eb726ca5 100644 --- a/otherlibs/unix/mkfifo.c +++ b/otherlibs/unix/mkfifo.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -26,6 +28,7 @@ CAMLprim value unix_mkfifo(value path, value mode) CAMLparam2(path, mode); char * p; int ret; + caml_unix_check_path(path, "mkfifo"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = mkfifo(p, Int_val(mode)); @@ -48,6 +51,7 @@ CAMLprim value unix_mkfifo(value path, value mode) CAMLparam2(path, mode); char * p; int ret; + caml_unix_check_path(path, "mkfifo"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = mknod(p, (Int_val(mode) & 07777) | S_IFIFO, 0); diff --git a/otherlibs/unix/nanosecond_stat.h b/otherlibs/unix/nanosecond_stat.h index c1a648ef..6abeb57e 100644 --- a/otherlibs/unix/nanosecond_stat.h +++ b/otherlibs/unix/nanosecond_stat.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Jeremie Dimino, Jane Street Group, LLC */ -/* */ -/* Copyright 2015 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jeremie Dimino, Jane Street Group, LLC */ +/* */ +/* Copyright 2015 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. */ +/* */ +/**************************************************************************/ /* This file is used by the configure test program nanosecond_stat.c and stat.c in this directory */ diff --git a/otherlibs/unix/nice.c b/otherlibs/unix/nice.c index e8f4f2b0..50d46413 100644 --- a/otherlibs/unix/nice.c +++ b/otherlibs/unix/nice.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/open.c b/otherlibs/unix/open.c index 1bad2c5b..d1feb6a1 100644 --- a/otherlibs/unix/open.c +++ b/otherlibs/unix/open.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -62,6 +64,7 @@ CAMLprim value unix_open(value path, value flags, value perm) int fd, cv_flags; char * p; + caml_unix_check_path(path, "open"); cv_flags = convert_flag_list(flags, open_flag_table); p = caml_strdup(String_val(path)); /* open on a named FIFO can block (PR#1533) */ diff --git a/otherlibs/unix/opendir.c b/otherlibs/unix/opendir.c index bdf031b3..387d108a 100644 --- a/otherlibs/unix/opendir.c +++ b/otherlibs/unix/opendir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -30,6 +32,7 @@ CAMLprim value unix_opendir(value path) value res; char * p; + caml_unix_check_path(path, "opendir"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); d = opendir(p); diff --git a/otherlibs/unix/pipe.c b/otherlibs/unix/pipe.c index 5f8f23da..315d9042 100644 --- a/otherlibs/unix/pipe.c +++ b/otherlibs/unix/pipe.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/putenv.c b/otherlibs/unix/putenv.c index ccb8f1ab..5e1ff1fe 100644 --- a/otherlibs/unix/putenv.c +++ b/otherlibs/unix/putenv.c @@ -1,18 +1,21 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1998 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1998 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 #include +#include #include #include @@ -26,8 +29,11 @@ CAMLprim value unix_putenv(value name, value val) { mlsize_t namelen = string_length(name); mlsize_t vallen = string_length(val); - char * s = (char *) caml_stat_alloc(namelen + 1 + vallen + 1); + char * s; + if (! (caml_string_is_c_safe(name) && caml_string_is_c_safe(val))) + unix_error(EINVAL, "putenv", name); + s = (char *) caml_stat_alloc(namelen + 1 + vallen + 1); memmove (s, String_val(name), namelen); s[namelen] = '='; memmove (s + namelen + 1, String_val(val), vallen); diff --git a/otherlibs/unix/read.c b/otherlibs/unix/read.c index 14305d37..feaa7691 100644 --- a/otherlibs/unix/read.c +++ b/otherlibs/unix/read.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/readdir.c b/otherlibs/unix/readdir.c index 4c309268..6c891de0 100644 --- a/otherlibs/unix/readdir.c +++ b/otherlibs/unix/readdir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/readlink.c b/otherlibs/unix/readlink.c index 836718d1..94a2eb9a 100644 --- a/otherlibs/unix/readlink.c +++ b/otherlibs/unix/readlink.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -36,6 +38,7 @@ CAMLprim value unix_readlink(value path) char buffer[PATH_MAX]; int len; char * p; + caml_unix_check_path(path, "readlink"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); len = readlink(p, buffer, sizeof(buffer) - 1); diff --git a/otherlibs/unix/rename.c b/otherlibs/unix/rename.c index 78e0846c..bf13eab6 100644 --- a/otherlibs/unix/rename.c +++ b/otherlibs/unix/rename.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -23,6 +25,8 @@ CAMLprim value unix_rename(value path1, value path2) char * p1; char * p2; int ret; + caml_unix_check_path(path1, "rename"); + caml_unix_check_path(path2, "rename"); p1 = caml_strdup(String_val(path1)); p2 = caml_strdup(String_val(path2)); caml_enter_blocking_section(); diff --git a/otherlibs/unix/rewinddir.c b/otherlibs/unix/rewinddir.c index c3771323..2ebc1664 100644 --- a/otherlibs/unix/rewinddir.c +++ b/otherlibs/unix/rewinddir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/rmdir.c b/otherlibs/unix/rmdir.c index 20359ce6..9f9b4589 100644 --- a/otherlibs/unix/rmdir.c +++ b/otherlibs/unix/rmdir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -21,6 +23,7 @@ CAMLprim value unix_rmdir(value path) CAMLparam1(path); char * p; int ret; + caml_unix_check_path(path, "rmdir"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = rmdir(p); diff --git a/otherlibs/unix/select.c b/otherlibs/unix/select.c index 23c48024..1fab0996 100644 --- a/otherlibs/unix/select.c +++ b/otherlibs/unix/select.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/sendrecv.c b/otherlibs/unix/sendrecv.c index 7d251a43..c4af2b45 100644 --- a/otherlibs/unix/sendrecv.c +++ b/otherlibs/unix/sendrecv.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/setgid.c b/otherlibs/unix/setgid.c index b7204745..91d22557 100644 --- a/otherlibs/unix/setgid.c +++ b/otherlibs/unix/setgid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/setgroups.c b/otherlibs/unix/setgroups.c index 7284b735..91b6bffb 100644 --- a/otherlibs/unix/setgroups.c +++ b/otherlibs/unix/setgroups.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Stephane Glondu */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Stephane Glondu */ +/* */ +/* Copyright 2009 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 #include diff --git a/otherlibs/unix/setsid.c b/otherlibs/unix/setsid.c index 92814eba..5caa4359 100644 --- a/otherlibs/unix/setsid.c +++ b/otherlibs/unix/setsid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 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 #include diff --git a/otherlibs/unix/setuid.c b/otherlibs/unix/setuid.c index c8a9c622..978dd9eb 100644 --- a/otherlibs/unix/setuid.c +++ b/otherlibs/unix/setuid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/unix/shutdown.c b/otherlibs/unix/shutdown.c index 1ceafd6e..db7d7ad6 100644 --- a/otherlibs/unix/shutdown.c +++ b/otherlibs/unix/shutdown.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/signals.c b/otherlibs/unix/signals.c index d30a70db..d1fb3a08 100644 --- a/otherlibs/unix/signals.c +++ b/otherlibs/unix/signals.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1998 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1998 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 #include diff --git a/otherlibs/unix/sleep.c b/otherlibs/unix/sleep.c index a39c5f82..1357d44c 100644 --- a/otherlibs/unix/sleep.c +++ b/otherlibs/unix/sleep.c @@ -1,24 +1,71 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include "unixsupport.h" -CAMLprim value unix_sleep(value t) +#include +#include +#ifdef HAS_SELECT +#include +#include +#ifdef HAS_SYS_SELECT_H +#include +#endif +#endif + +CAMLprim value unix_sleep(value duration) { - enter_blocking_section(); - sleep(Int_val(t)); - leave_blocking_section(); + double d = Double_val(duration); + if (d <= 0.0) return Val_unit; +#if _POSIX_C_SOURCE >= 199309L + { + struct timespec t; + int ret; + 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(); + if (ret == -1) uerror("sleep", Nothing); + } +#elif defined(HAS_SELECT) + { + struct timeval t; + int ret; + 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(); + if (ret == -1) uerror("sleep", Nothing); + } +#else + /* Fallback implementation, resolution 1 second only. + We cannot reliably iterate until sleep() returns 0, because the + remaining time returned by sleep() is generally rounded up. */ + { + enter_blocking_section(); + sleep ((unsigned int) d); + leave_blocking_section(); + } +#endif return Val_unit; } diff --git a/otherlibs/unix/socket.c b/otherlibs/unix/socket.c index 9cf3ed3a..667381ed 100644 --- a/otherlibs/unix/socket.c +++ b/otherlibs/unix/socket.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/socketaddr.c b/otherlibs/unix/socketaddr.c index 2f4bdadf..cbdfa37f 100644 --- a/otherlibs/unix/socketaddr.c +++ b/otherlibs/unix/socketaddr.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -23,6 +25,7 @@ #include "socketaddr.h" #ifdef _WIN32 +#undef EAFNOSUPPORT #define EAFNOSUPPORT WSAEAFNOSUPPORT #endif @@ -64,6 +67,10 @@ void get_sockaddr(value mladr, if (len >= sizeof(adr->s_unix.sun_path)) { unix_error(ENAMETOOLONG, "", path); } + /* "Abstract" sockets in Linux have names starting with '\0' */ + if (Byte(path, 0) != 0 && ! caml_string_is_c_safe(path)) { + unix_error(ENOENT, "", path); + } memmove (adr->s_unix.sun_path, String_val(path), len + 1); *adr_len = ((char *)&(adr->s_unix.sun_path) - (char *)&(adr->s_unix)) @@ -104,7 +111,14 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, switch(adr->s_gen.sa_family) { #ifndef _WIN32 case AF_UNIX: - { value n = copy_string(adr->s_unix.sun_path); + { 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); Begin_root (n); res = alloc_small(1, 0); Field(res,0) = n; diff --git a/otherlibs/unix/socketaddr.h b/otherlibs/unix/socketaddr.h index 0077daea..4c80d25d 100644 --- a/otherlibs/unix/socketaddr.h +++ b/otherlibs/unix/socketaddr.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_SOCKETADDR_H #define CAML_SOCKETADDR_H diff --git a/otherlibs/unix/socketpair.c b/otherlibs/unix/socketpair.c index 4f85f9a6..4c7b0543 100644 --- a/otherlibs/unix/socketpair.c +++ b/otherlibs/unix/socketpair.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/sockopt.c b/otherlibs/unix/sockopt.c index 8137e42c..e254987a 100644 --- a/otherlibs/unix/sockopt.c +++ b/otherlibs/unix/sockopt.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/stat.c b/otherlibs/unix/stat.c index f938645a..e2a8f6a9 100644 --- a/otherlibs/unix/stat.c +++ b/otherlibs/unix/stat.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -49,9 +51,12 @@ static value stat_aux(int use_64, struct stat *buf) CAMLlocal5(atime, mtime, ctime, offset, v); #include "nanosecond_stat.h" - atime = caml_copy_double((double) buf->st_atime + (NSEC(buf, a) / 1000000000.0)); - mtime = caml_copy_double((double) buf->st_mtime + (NSEC(buf, m) / 1000000000.0)); - ctime = caml_copy_double((double) buf->st_ctime + (NSEC(buf, c) / 1000000000.0)); + atime = caml_copy_double((double) buf->st_atime + + (NSEC(buf, a) / 1000000000.0)); + mtime = caml_copy_double((double) buf->st_mtime + + (NSEC(buf, m) / 1000000000.0)); + ctime = caml_copy_double((double) buf->st_ctime + + (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); @@ -77,6 +82,7 @@ CAMLprim value unix_stat(value path) int ret; struct stat buf; char * p; + caml_unix_check_path(path, "stat"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = stat(p, &buf); @@ -94,6 +100,7 @@ CAMLprim value unix_lstat(value path) int ret; struct stat buf; char * p; + caml_unix_check_path(path, "lstat"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); #ifdef HAS_SYMLINK @@ -128,6 +135,7 @@ CAMLprim value unix_stat_64(value path) int ret; struct stat buf; char * p; + caml_unix_check_path(path, "stat"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = stat(p, &buf); @@ -143,6 +151,7 @@ CAMLprim value unix_lstat_64(value path) int ret; struct stat buf; char * p; + caml_unix_check_path(path, "lstat"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); #ifdef HAS_SYMLINK diff --git a/otherlibs/unix/strofaddr.c b/otherlibs/unix/strofaddr.c index c4ea6bad..7e2b2309 100644 --- a/otherlibs/unix/strofaddr.c +++ b/otherlibs/unix/strofaddr.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/symlink.c b/otherlibs/unix/symlink.c index dbbd2665..72f9c21c 100644 --- a/otherlibs/unix/symlink.c +++ b/otherlibs/unix/symlink.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -19,12 +21,14 @@ #ifdef HAS_SYMLINK -CAMLprim value unix_symlink(value path1, value path2) +CAMLprim value unix_symlink(value to_dir, value path1, value path2) { - CAMLparam2(path1, path2); + CAMLparam3(to_dir, path1, path2); char * p1; char * p2; int ret; + caml_unix_check_path(path1, "symlink"); + caml_unix_check_path(path2, "symlink"); p1 = caml_strdup(String_val(path1)); p2 = caml_strdup(String_val(path2)); caml_enter_blocking_section(); @@ -37,9 +41,21 @@ CAMLprim value unix_symlink(value path1, value path2) CAMLreturn(Val_unit); } +CAMLprim value unix_has_symlink(value unit) +{ + CAMLparam0(); + CAMLreturn(Val_true); +} + #else -CAMLprim value unix_symlink(value path1, value path2) +CAMLprim value unix_symlink(value to_dir, value path1, value path2) { invalid_argument("symlink not implemented"); } +CAMLprim value unix_has_symlink(value unit) +{ + CAMLparam0(); + CAMLreturn(Val_false); +} + #endif diff --git a/otherlibs/unix/termios.c b/otherlibs/unix/termios.c index 40173737..ff3592af 100644 --- a/otherlibs/unix/termios.c +++ b/otherlibs/unix/termios.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/time.c b/otherlibs/unix/time.c index 495adb66..f14fc86a 100644 --- a/otherlibs/unix/time.c +++ b/otherlibs/unix/time.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/times.c b/otherlibs/unix/times.c index 8760ad2a..91ce67d7 100644 --- a/otherlibs/unix/times.c +++ b/otherlibs/unix/times.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/truncate.c b/otherlibs/unix/truncate.c index 62683fcf..4daba78a 100644 --- a/otherlibs/unix/truncate.c +++ b/otherlibs/unix/truncate.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -29,6 +31,7 @@ CAMLprim value unix_truncate(value path, value len) CAMLparam2(path, len); char * p; int ret; + caml_unix_check_path(path, "truncate"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = truncate(p, Long_val(len)); @@ -45,6 +48,7 @@ CAMLprim value unix_truncate_64(value path, value vlen) char * p; int ret; file_offset len = File_offset_val(vlen); + caml_unix_check_path(path, "truncate"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = truncate(p, len); diff --git a/otherlibs/unix/umask.c b/otherlibs/unix/umask.c index 9b88f105..90fd970d 100644 --- a/otherlibs/unix/umask.c +++ b/otherlibs/unix/umask.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/unix.ml b/otherlibs/unix/unix.ml index d18b338a..e345e9bb 100644 --- a/otherlibs/unix/unix.ml +++ b/otherlibs/unix/unix.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 error = E2BIG @@ -378,7 +380,8 @@ external rewinddir : dir_handle -> unit = "unix_rewinddir" external closedir : dir_handle -> unit = "unix_closedir" external pipe : unit -> file_descr * file_descr = "unix_pipe" -external symlink : string -> string -> unit = "unix_symlink" +external symlink : ?to_dir:bool -> string -> string -> unit = "unix_symlink" +external has_symlink : unit -> bool = "unix_has_symlink" external readlink : string -> string = "unix_readlink" external mkfifo : string -> file_perm -> unit = "unix_mkfifo" external select : @@ -427,7 +430,8 @@ external gmtime : float -> tm = "unix_gmtime" external localtime : float -> tm = "unix_localtime" external mktime : tm -> float * tm = "unix_mktime" external alarm : int -> int = "unix_alarm" -external sleep : int -> unit = "unix_sleep" +external sleepf : float -> unit = "unix_sleep" +let sleep duration = sleepf (float duration) external times : unit -> process_times = "unix_times" external utimes : string -> float -> float -> unit = "unix_utimes" @@ -858,12 +862,14 @@ let rec waitpid_non_intr pid = try waitpid [] pid with Unix_error (EINTR, _, _) -> waitpid_non_intr pid +external sys_exit : int -> 'a = "caml_sys_exit" + let system cmd = match fork() with 0 -> begin try execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |] with _ -> - exit 127 + sys_exit 127 end | id -> snd(waitpid_non_intr id) @@ -898,7 +904,7 @@ let create_process cmd args new_stdin new_stdout new_stderr = perform_redirections new_stdin new_stdout new_stderr; execvp cmd args with _ -> - exit 127 + sys_exit 127 end | id -> id @@ -909,7 +915,7 @@ let create_process_env cmd args env new_stdin new_stdout new_stderr = perform_redirections new_stdin new_stdout new_stderr; execvpe cmd args env with _ -> - exit 127 + sys_exit 127 end | id -> id @@ -924,11 +930,12 @@ 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 -> 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; - begin try execv "/bin/sh" [| "/bin/sh"; "-c"; cmd |] - with _ -> exit 127 + 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 end | id -> Hashtbl.add popen_processes proc id @@ -980,12 +987,13 @@ let open_process cmd = 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 -> dup2 input stdin; close input; - dup2 output stdout; close output; - dup2 error stderr; close error; - if not cloexec then List.iter close toclose; - begin try execve "/bin/sh" [| "/bin/sh"; "-c"; cmd |] env - with _ -> exit 127 + 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 @@ -1073,7 +1081,8 @@ let establish_server server_fun sockaddr = (* 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 *) + 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 diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli index bd68f8c7..cfec2cb6 100644 --- a/otherlibs/unix/unix.mli +++ b/otherlibs/unix/unix.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Interface to the Unix system. @@ -123,7 +125,9 @@ val environment : unit -> string array val getenv : string -> string (** Return the value associated to a variable in the process - environment. Raise [Not_found] if the variable is unbound. + environment. + @raise Not_found if the variable is unbound. + (This function is identical to {!Sys.getenv}.) *) val putenv : string -> string -> unit @@ -152,17 +156,17 @@ type process_status = type wait_flag = - WNOHANG (** do not block if no child has + WNOHANG (** Do not block if no child has died yet, but immediately return with a pid equal to 0.*) - | WUNTRACED (** report also the children that receive stop signals. *) + | WUNTRACED (** Report also the children that receive stop signals. *) (** Flags for {!Unix.waitpid}. *) val execv : string -> string array -> 'a (** [execv prog args] execute the program in file [prog], with the arguments [args], and the current process environment. These [execv*] functions never return: on success, the current - program is replaced by the new one; - on failure, a {!Unix.Unix_error} exception is raised. *) + program is replaced by the new one. + @raise Unix.Unix_error on failure. *) val execve : string -> string array -> string array -> 'a (** Same as {!Unix.execv}, except that the third argument provides the @@ -178,11 +182,15 @@ val execvpe : string -> string array -> string array -> 'a val fork : unit -> int (** Fork a new process. The returned integer is 0 for the child - process, the pid of the child process for the parent process. *) + process, the pid of the child process for the parent process. + + On Windows: not implemented, use {!create_process} or threads. *) val wait : unit -> int * process_status (** Wait until one of the children processes die, and return its pid - and termination status. *) + and termination status. + + On Windows: Not implemented, use {!waitpid}. *) val waitpid : wait_flag list -> int -> int * process_status (** Same as {!Unix.wait}, but waits for the child process whose pid is given. @@ -192,25 +200,32 @@ val waitpid : wait_flag list -> int -> int * process_status Negative pid arguments represent process groups. The list of options indicates whether [waitpid] should return immediately without waiting, and whether it should report stopped - children. *) + children. + + On Windows, this function can only wait for a given PID, not any + child process. *) val system : string -> process_status (** Execute the given command, wait until it terminates, and return its termination status. The string is interpreted by the shell - [/bin/sh] and therefore can contain redirections, quotes, variables, - etc. The result [WEXITED 127] indicates that the shell couldn't - be executed. *) + [/bin/sh] (or the command interpreter [cmd.exe] on Windows) and + therefore can contain redirections, quotes, variables, etc. The + result [WEXITED 127] indicates that the shell couldn't be + executed. *) val getpid : unit -> int (** Return the pid of the process. *) val getppid : unit -> int -(** Return the pid of the parent process. *) +(** Return the pid of the parent process. + On Windows: not implemented (because it is meaningless). *) val nice : int -> int (** Change the process priority. The integer argument is added to the ``nice'' value. (Higher values of the ``nice'' value mean - lower priorities.) Return the new nice value. *) + lower priorities.) Return the new nice value. + + On Windows: not implemented. *) (** {6 Basic file input/output} *) @@ -295,12 +310,37 @@ val single_write_substring : file_descr -> string -> int -> int -> int val in_channel_of_descr : file_descr -> in_channel (** Create an input channel reading from the given descriptor. The channel is initially in binary mode; use - [set_binary_mode_in ic false] if text mode is desired. *) + [set_binary_mode_in ic false] if text mode is desired. + Text mode is supported only if the descriptor refers to a file + or pipe, but is not supported if it refers to a socket. + On Windows, [set_binary_mode_in] always fails on channels created + with this function. + + Beware that channels are buffered so more characters may have been + read from the file descriptor than those accessed using channel functions. + Channels also keep a copy of the current position in the file. + + You need to explicitly close all channels created with this function. + Closing the channel also closes the underlying file descriptor (unless + it was already closed). *) val out_channel_of_descr : file_descr -> out_channel (** Create an output channel writing on the given descriptor. The channel is initially in binary mode; use - [set_binary_mode_out oc false] if text mode is desired. *) + [set_binary_mode_out oc false] if text mode is desired. + Text mode is supported only if the descriptor refers to a file + or pipe, but is not supported if it refers to a socket. + On Windows, [set_binary_mode_out] always fails on channels created + with this function. + + Beware that channels are buffered so you may have to [flush] them + to ensure that all data has been sent to the file descriptor. + Channels also keep a copy of the current position in the file. + + You need to explicitly close all channels created with this function. + Closing the channel flushes the data and closes the underlying file + descriptor (unless it has already been closed, in which case the + buffered data is lost).*) val descr_of_in_channel : in_channel -> file_descr (** Return the descriptor corresponding to an input channel. *) @@ -324,11 +364,15 @@ val lseek : file_descr -> int -> seek_command -> int offset (from the beginning of the file). *) val truncate : string -> int -> unit -(** Truncates the named file to the given size. *) +(** Truncates the named file to the given size. + + On Windows: not implemented. *) val ftruncate : file_descr -> int -> unit (** Truncates the file corresponding to the given descriptor - to the given size. *) + to the given size. + + On Windows: not implemented. *) (** {6 File status} *) @@ -379,8 +423,14 @@ val isatty : file_descr -> bool module LargeFile : sig val lseek : file_descr -> int64 -> seek_command -> int64 + (** See {!Unix.lseek}. *) + val truncate : string -> int64 -> unit + (** See {!Unix.truncate}. *) + val ftruncate : file_descr -> int64 -> unit + (** See {!Unix.ftruncate}. *) + type stats = { st_dev : int; (** Device number *) st_ino : int; (** Inode number *) @@ -414,7 +464,7 @@ module LargeFile : val unlink : string -> unit -(** Removes the named file *) +(** Removes the named file. *) val rename : string -> string -> unit (** [rename old new] changes the name of a file from [old] to [new]. *) @@ -439,21 +489,28 @@ val chmod : string -> file_perm -> unit (** Change the permissions of the named file. *) val fchmod : file_descr -> file_perm -> unit -(** Change the permissions of an opened file. *) +(** Change the permissions of an opened file. + On Windows: not implemented. *) val chown : string -> int -> int -> unit -(** Change the owner uid and owner gid of the named file. *) +(** Change the owner uid and owner gid of the named file. + On Windows: not implemented (make no sense on a DOS file system). *) val fchown : file_descr -> int -> int -> unit -(** Change the owner uid and owner gid of an opened file. *) +(** Change the owner uid and owner gid of an opened file. + On Windows: not implemented (make no sense on a DOS file system). *) val umask : int -> int (** Set the process's file mode creation mask, and return the previous - mask. *) + mask. + On Windows: not implemented. *) val access : string -> access_permission list -> unit -(** Check that the process has the given permissions over the named - file. Raise [Unix_error] otherwise. *) +(** Check that the process has the given permissions over the named file. + @raise Unix_error otherwise. + + On Windows, execute permission [X_OK], cannot be tested, it just + tests for read permission instead. *) (** {6 Operations on file descriptors} *) @@ -506,7 +563,8 @@ val getcwd : unit -> string (** Return the name of the current working directory. *) val chroot : string -> unit -(** Change the process root directory. *) +(** Change the process root directory. + On Windows: not implemented. *) type dir_handle (** The type of descriptors over opened directories. *) @@ -535,7 +593,8 @@ val pipe : unit -> file_descr * file_descr opened for writing, that's the entrance to the pipe. *) val mkfifo : string -> file_perm -> unit -(** Create a named pipe with the given permissions (see {!umask}). *) +(** Create a named pipe with the given permissions (see {!umask}). + On Windows: not implemented. *) (** {6 High-level process and redirection management} *) @@ -569,7 +628,8 @@ val open_process_in : string -> in_channel runs the given command in parallel with the program. The standard output of the command is redirected to a pipe, which can be read via the returned input channel. - The command is interpreted by the shell [/bin/sh] (cf. [system]). *) + The command is interpreted by the shell [/bin/sh] + (or [cmd.exe] on Windows), cf. [system]. *) val open_process_out : string -> out_channel (** Same as {!Unix.open_process_in}, but redirect the standard input of @@ -617,12 +677,48 @@ val close_process_full : (** {6 Symbolic links} *) -val symlink : string -> string -> unit -(** [symlink source dest] creates the file [dest] as a symbolic link - to the file [source]. *) +val symlink : ?to_dir:bool -> string -> string -> unit +(** [symlink ?to_dir source dest] creates the file [dest] as a symbolic link + to the file [source]. On Windows, [~to_dir] indicates if the symbolic link + 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. + + Windows symbolic links are available in Windows Vista onwards. There are some + important differences between Windows symlinks and their POSIX counterparts. + + Windows symbolic links come in two flavours: directory and regular, which + designate whether the symbolic link points to a directory or a file. The type + must be correct - a directory symlink which actually points to a file cannot + be selected with chdir and a file symlink which actually points to a + directory cannot be read or written (note that Cygwin's emulation layer + ignores this distinction). + + When symbolic links are created to existing targets, this distinction doesn't + matter and [symlink] will automatically create the correct kind of symbolic + link. The distinction matters when a symbolic link is created to a + non-existent target. + + The other caveat is that by default symbolic links are a privileged + operation. Administrators will always need to be running elevated (or with + UAC disabled) and by default normal user accounts need to be granted the + SeCreateSymbolicLinkPrivilege via Local Security Policy (secpol.msc) or via + Active Directory. + + {!has_symlink} can be used to check that a process is able to create symbolic + links. *) + +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. *) val readlink : string -> string -(** Read the contents of a link. *) +(** Read the contents of a link. + + On Windows: not implemented. *) (** {6 Polling} *) @@ -642,8 +738,8 @@ val select : and over which an exceptional condition is pending (third component). *) -(** {6 Locking} *) +(** {6 Locking} *) type lock_command = F_ULOCK (** Unlock a region *) @@ -688,7 +784,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]. Under Windows, only the [Sys.sigkill] signal + with id [pid]. On Windows, only the [Sys.sigkill] signal is emulated. *) type sigprocmask_command = @@ -704,18 +800,26 @@ val sigprocmask : sigprocmask_command -> int list -> int list the set of blocked signals. If [cmd] is [SIG_UNBLOCK], the signals in [sigs] are removed from the set of blocked signals. - [sigprocmask] returns the set of previously blocked signals. *) + [sigprocmask] returns the set of previously blocked signals. + + On Windows: not implemented (no inter-process signals on Windows). *) val sigpending : unit -> int list -(** Return the set of blocked signals that are currently pending. *) +(** Return the set of blocked signals that are currently pending. + + On Windows: not implemented (no inter-process signals on Windows). *) val sigsuspend : int list -> unit (** [sigsuspend sigs] atomically sets the blocked signals to [sigs] and waits for a non-ignored, non-blocked signal to be delivered. - On return, the blocked signals are reset to their initial value. *) + On return, the blocked signals are reset to their initial value. + + On Windows: not implemented (no inter-process signals on Windows). *) val pause : unit -> unit -(** Wait until a non-ignored, non-blocked signal is delivered. *) +(** Wait until a non-ignored, non-blocked signal is delivered. + + On Windows: not implemented (no inter-process signals on Windows). *) (** {6 Time functions} *) @@ -769,19 +873,27 @@ val mktime : tm -> float * tm local time zone. *) val alarm : int -> int -(** Schedule a [SIGALRM] signal after the given number of seconds. *) +(** Schedule a [SIGALRM] signal after the given number of seconds. + + On Windows: not implemented. *) val sleep : int -> unit (** Stop execution for the given number of seconds. *) +val sleepf : float -> unit +(** Stop execution for the given number of seconds. Like [sleep], + but fractions of seconds are supported. *) + val times : unit -> process_times -(** Return the execution times of the process. *) +(** Return the execution times of the process. + On Windows, it is partially implemented, will not report timings + for child processes. *) val utimes : string -> float -> float -> unit (** Set the last access time (second arg) and last modification time (third arg) for a file. Times are expressed in seconds from - 00:00:00 GMT, Jan. 1, 1970. A time of [0.0] is interpreted as the - current time. *) + 00:00:00 GMT, Jan. 1, 1970. If both times are [0.0], the access + and last modification times are both set to the current time. *) type interval_timer = ITIMER_REAL @@ -803,7 +915,9 @@ type interval_timer_status = (** The type describing the status of an interval timer *) val getitimer : interval_timer -> interval_timer_status -(** Return the current status of the given interval timer. *) +(** Return the current status of the given interval timer. + + On Windows: not implemented. *) val setitimer : interval_timer -> interval_timer_status -> interval_timer_status @@ -814,43 +928,54 @@ val setitimer : be used in reloading [it_value] when the timer expires. Setting [s.it_value] to zero disables the timer. Setting [s.it_interval] to zero causes the timer to be disabled - after its next expiration. *) + after its next expiration. + + On Windows: not implemented. *) (** {6 User id, group id} *) val getuid : unit -> int -(** Return the user id of the user executing the process. *) +(** Return the user id of the user executing the process. + On Windows, always return [1]. *) val geteuid : unit -> int -(** Return the effective user id under which the process runs. *) +(** Return the effective user id under which the process runs. + On Windows, always return [1]. *) val setuid : int -> unit -(** Set the real user id and effective user id for the process. *) +(** Set the real user id and effective user id for the process. + On Windows: not implemented. *) val getgid : unit -> int -(** Return the group id of the user executing the process. *) +(** Return the group id of the user executing the process. + On Windows, always return [1]. *) val getegid : unit -> int -(** Return the effective group id under which the process runs. *) +(** Return the effective group id under which the process runs. + On Windows, always return [1]. *) val setgid : int -> unit -(** Set the real group id and effective group id for the process. *) +(** Set the real group id and effective group id for the process. + On Windows: not implemented. *) val getgroups : unit -> int array (** Return the list of groups to which the user executing the process - belongs. *) + belongs. + On Windows, always return [[|1|]]. *) val setgroups : int array -> unit - (** [setgroups groups] sets the supplementary group IDs for the - calling process. Appropriate privileges are required. *) +(** [setgroups groups] sets the supplementary group IDs for the + calling process. Appropriate privileges are required. + On Windows: not implemented. *) val initgroups : string -> int -> unit - (** [initgroups user group] initializes the group access list by - reading the group database /etc/group and using all groups of - which [user] is a member. The additional group [group] is also - added to the list. *) +(** [initgroups user group] initializes the group access list by + reading the group database /etc/group and using all groups of + which [user] is a member. The additional group [group] is also + added to the list. + On Windows: not implemented. *) type passwd_entry = { pw_name : string; @@ -875,20 +1000,28 @@ val getlogin : unit -> string (** Return the login name of the user executing the process. *) val getpwnam : string -> passwd_entry -(** Find an entry in [passwd] with the given name, or raise - [Not_found]. *) +(** Find an entry in [passwd] with the given name. + @raise Not_found if no such entry exist. + + On Windows, always raise [Not_found]. *) val getgrnam : string -> group_entry -(** Find an entry in [group] with the given name, or raise - [Not_found]. *) +(** Find an entry in [group] with the given name. + @raise Not_found if no such entry exist. + + On Windows, always raise [Not_found]. *) val getpwuid : int -> passwd_entry -(** Find an entry in [passwd] with the given user id, or raise - [Not_found]. *) +(** Find an entry in [passwd] with the given user id. + @raise Not_found if no such entry exist. + + On Windows, always raise [Not_found]. *) val getgrgid : int -> group_entry -(** Find an entry in [group] with the given group id, or raise - [Not_found]. *) +(** Find an entry in [group] with the given group id. + @raise Not_found if no such entry exist. + + On Windows, always raise [Not_found]. *) (** {6 Internet addresses} *) @@ -902,8 +1035,8 @@ val inet_addr_of_string : string -> inet_addr address to its internal representation. The argument string consists of 4 numbers separated by periods ([XXX.YYY.ZZZ.TTT]) for IPv4 addresses, and up to 8 numbers separated by colons - for IPv6 addresses. Raise [Failure] when given a string that - does not match these formats. *) + for IPv6 addresses. + @raise Failure when given a string that does not match these formats. *) val string_of_inet_addr : inet_addr -> string (** Return the printable representation of the given Internet address. @@ -933,7 +1066,9 @@ type socket_domain = | PF_INET (** Internet domain (IPv4) *) | PF_INET6 (** Internet domain (IPv6) *) (** The type of socket domains. Not all platforms support - IPv6 sockets (type [PF_INET6]). *) + IPv6 sockets (type [PF_INET6]). + On Windows, the domains [PF_UNIX] and [PF_INET6] are not + supported; [PF_INET] is fully supported. *) type socket_type = SOCK_STREAM (** Stream socket *) @@ -1109,6 +1244,7 @@ val getsockopt_error : file_descr -> error option (** Return the error condition associated with the given socket, and clear it. *) + (** {6 High-level network connection functions} *) @@ -1130,7 +1266,9 @@ val establish_server : (in_channel -> out_channel -> unit) -> sockaddr -> unit The function given as first argument is called for each connection with two buffered channels connected to the client. A new process is created for each connection. The function {!Unix.establish_server} - never returns normally. *) + never returns normally. + + On Windows, it is not implemented. Use threads. *) (** {6 Host and protocol databases} *) @@ -1163,28 +1301,28 @@ val gethostname : unit -> string (** Return the name of the local host. *) val gethostbyname : string -> host_entry -(** Find an entry in [hosts] with the given name, or raise - [Not_found]. *) +(** Find an entry in [hosts] with the given name. + @raise Not_found if no such entry exist. *) val gethostbyaddr : inet_addr -> host_entry -(** Find an entry in [hosts] with the given address, or raise - [Not_found]. *) +(** Find an entry in [hosts] with the given address. + @raise Not_found if no such entry exist. *) val getprotobyname : string -> protocol_entry -(** Find an entry in [protocols] with the given name, or raise - [Not_found]. *) +(** Find an entry in [protocols] with the given name. + @raise Not_found if no such entry exist. *) val getprotobynumber : int -> protocol_entry -(** Find an entry in [protocols] with the given protocol number, - or raise [Not_found]. *) +(** Find an entry in [protocols] with the given protocol number. + @raise Not_found if no such entry exist. *) val getservbyname : string -> string -> service_entry -(** Find an entry in [services] with the given name, or raise - [Not_found]. *) +(** Find an entry in [services] with the given name. + @raise Not_found if no such entry exist. *) val getservbyport : int -> string -> service_entry -(** Find an entry in [services] with the given service number, - or raise [Not_found]. *) +(** Find an entry in [services] with the given service number. + @raise Not_found if no such entry exist. *) type addr_info = { ai_family : socket_domain; (** Socket domain *) @@ -1228,7 +1366,8 @@ val getaddrinfo: type name_info = { ni_hostname : string; (** Name or IP address of host *) - ni_service : string } (** Name of service or port number *) + ni_service : string (** Name of service or port number *) + } (** Host and service information returned by {!Unix.getnameinfo}. *) type getnameinfo_option = @@ -1244,7 +1383,7 @@ val getnameinfo : sockaddr -> getnameinfo_option list -> name_info (** [getnameinfo addr opts] returns the host name and service name corresponding to the socket address [addr]. [opts] is a possibly empty list of options that governs how these names are obtained. - Raise [Not_found] if an error occurs. *) + @raise Not_found if an error occurs. *) (** {6 Terminal interface} *) @@ -1306,7 +1445,8 @@ type terminal_io = val tcgetattr : file_descr -> terminal_io (** Return the status of the terminal referred to by the given - file descriptor. *) + file descriptor. + On Windows, not implemented. *) type setattr_when = TCSANOW @@ -1321,16 +1461,22 @@ val tcsetattr : file_descr -> setattr_when -> terminal_io -> unit or after flushing all input that has been received but not read ([TCSAFLUSH]). [TCSADRAIN] is recommended when changing the output parameters; [TCSAFLUSH], when changing the input - parameters. *) + parameters. + + On Windows, not implemented. *) val tcsendbreak : file_descr -> int -> unit (** Send a break condition on the given file descriptor. The second argument is the duration of the break, in 0.1s units; - 0 means standard duration (0.25s). *) + 0 means standard duration (0.25s). + + On Windows, not implemented. *) val tcdrain : file_descr -> unit (** Waits until all output written on the given file descriptor - has been transmitted. *) + has been transmitted. + + On Windows, not implemented. *) type flush_queue = TCIFLUSH @@ -1342,7 +1488,9 @@ val tcflush : file_descr -> flush_queue -> unit transmitted, or data received but not yet read, depending on the second argument: [TCIFLUSH] flushes data received but not read, [TCOFLUSH] flushes data written but not transmitted, and - [TCIOFLUSH] flushes both. *) + [TCIOFLUSH] flushes both. + + On Windows, not implemented. *) type flow_action = TCOOFF @@ -1355,8 +1503,12 @@ val tcflow : file_descr -> flow_action -> unit the given file descriptor, depending on the second argument: [TCOOFF] suspends output, [TCOON] restarts output, [TCIOFF] transmits a STOP character to suspend input, - and [TCION] transmits a START character to restart input. *) + and [TCION] transmits a START character to restart input. + + On Windows, not implemented. *) val setsid : unit -> int (** Put the calling process in a new session and detach it from - its controlling terminal. *) + its controlling terminal. + + On Windows, not implemented. *) diff --git a/otherlibs/unix/unix.mllib b/otherlibs/unix/unix.mllib deleted file mode 100644 index 8d569c56..00000000 --- a/otherlibs/unix/unix.mllib +++ /dev/null @@ -1 +0,0 @@ -Unix UnixLabels diff --git a/otherlibs/unix/unixLabels.ml b/otherlibs/unix/unixLabels.ml index 1bd410bd..3da36995 100644 --- a/otherlibs/unix/unixLabels.ml +++ b/otherlibs/unix/unixLabels.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jacques Garrigue, Kyoto University RIMS *) -(* *) -(* Copyright 2001 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jacques Garrigue, Kyoto University RIMS *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (* Module [UnixLabels]: labelled Unix module *) diff --git a/otherlibs/unix/unixLabels.mli b/otherlibs/unix/unixLabels.mli index 76ff890b..fdf29a1c 100644 --- a/otherlibs/unix/unixLabels.mli +++ b/otherlibs/unix/unixLabels.mli @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Interface to the Unix system. To use as replacement to default {!Unix} module, @@ -618,9 +620,15 @@ val close_process_full : (** {6 Symbolic links} *) -val symlink : src:string -> dst:string -> unit +val symlink : ?to_dir:bool -> src:string -> dst:string -> unit (** [symlink source dest] creates the file [dest] as a symbolic link - to the file [source]. *) + to the file [source]. See {!Unix.symlink} for details of [~to_dir] *) + +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. *) val readlink : string -> string (** Read the contents of a link. *) @@ -1235,7 +1243,8 @@ val getaddrinfo: type name_info = { ni_hostname : string; (** Name or IP address of host *) - ni_service : string } (** Name of service or port number *) + ni_service : string (** Name of service or port number *) + } (** Host and service information returned by {!Unix.getnameinfo}. *) type getnameinfo_option = diff --git a/otherlibs/unix/unixsupport.c b/otherlibs/unix/unixsupport.c index 6c7171fd..6280c100 100644 --- a/otherlibs/unix/unixsupport.c +++ b/otherlibs/unix/unixsupport.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -307,3 +309,8 @@ void uerror(char *cmdname, value cmdarg) { unix_error(errno, cmdname, cmdarg); } + +void caml_unix_check_path(value path, char * cmdname) +{ + if (! caml_string_is_c_safe(path)) unix_error(ENOENT, cmdname, path); +} diff --git a/otherlibs/unix/unixsupport.h b/otherlibs/unix/unixsupport.h index d4312ab4..a615f7ae 100644 --- a/otherlibs/unix/unixsupport.h +++ b/otherlibs/unix/unixsupport.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_UNIXSUPPORT_H #define CAML_UNIXSUPPORT_H @@ -26,13 +28,23 @@ extern "C" { extern value unix_error_of_code (int errcode); extern int code_of_unix_error (value error); -extern void unix_error (int errcode, char * cmdname, value arg) Noreturn; -extern void uerror (char * cmdname, value arg) Noreturn; + +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); #define UNIX_BUFFER_SIZE 65536 #define DIR_Val(v) *((DIR **) &Field(v, 0)) +extern char ** cstringvect(value arg, char * cmdname); + #ifdef __cplusplus } #endif diff --git a/otherlibs/unix/unlink.c b/otherlibs/unix/unlink.c index 687c69c2..c06dd363 100644 --- a/otherlibs/unix/unlink.c +++ b/otherlibs/unix/unlink.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -21,6 +23,7 @@ CAMLprim value unix_unlink(value path) CAMLparam1(path); char * p; int ret; + caml_unix_check_path(path, "unlink"); p = caml_strdup(String_val(path)); caml_enter_blocking_section(); ret = unlink(p); diff --git a/otherlibs/unix/utimes.c b/otherlibs/unix/utimes.c index bf2ae2fb..f5efd7d1 100644 --- a/otherlibs/unix/utimes.c +++ b/otherlibs/unix/utimes.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -17,62 +19,68 @@ #include #include "unixsupport.h" -#ifdef HAS_UTIME +#if defined(HAS_UTIMES) #include -#ifndef _WIN32 -#include -#else -#include -#endif +#include CAMLprim value unix_utimes(value path, value atime, value mtime) { CAMLparam3(path, atime, mtime); - struct utimbuf times, * t; + struct timeval tv[2], * t; char * p; int ret; - times.actime = Double_val(atime); - times.modtime = Double_val(mtime); - if (times.actime || times.modtime) - t = × - else - t = (struct utimbuf *) NULL; + double at, mt; + caml_unix_check_path(path, "utimes"); + at = Double_val(atime); + mt = Double_val(mtime); + if (at == 0.0 && mt == 0.0) { + t = (struct timeval *) NULL; + } else { + tv[0].tv_sec = at; + tv[0].tv_usec = (at - tv[0].tv_sec) * 1000000; + tv[1].tv_sec = mt; + tv[1].tv_usec = (mt - tv[1].tv_sec) * 1000000; + t = tv; + } p = caml_strdup(String_val(path)); caml_enter_blocking_section(); - ret = utime(p, t); + ret = utimes(p, t); caml_leave_blocking_section(); caml_stat_free(p); if (ret == -1) uerror("utimes", path); CAMLreturn(Val_unit); } -#else - -#ifdef HAS_UTIMES +#elif defined(HAS_UTIME) #include -#include +#ifndef _WIN32 +#include +#else +#include +#endif CAMLprim value unix_utimes(value path, value atime, value mtime) { CAMLparam3(path, atime, mtime); - struct timeval tv[2], * t; + struct utimbuf times, * t; char * p; int ret; - double at = Double_val(atime); - double mt = Double_val(mtime); - tv[0].tv_sec = at; - tv[0].tv_usec = (at - tv[0].tv_sec) * 1000000; - tv[1].tv_sec = mt; - tv[1].tv_usec = (mt - tv[1].tv_sec) * 1000000; - if (tv[0].tv_sec || tv[1].tv_sec) - t = tv; - else - t = (struct timeval *) NULL; + double at, mt; + caml_unix_check_path(path, "utimes"); + at = Double_val(atime); + mt = Double_val(mtime); + if (at == 0.0 && mt == 0.0) { + t = (struct utimbuf *) NULL; + } else { + times.actime = at; + times.modtime = mt; + t = × + } p = caml_strdup(String_val(path)); caml_enter_blocking_section(); - ret = utimes(p, t); + ret = utime(p, t); caml_leave_blocking_section(); caml_stat_free(p); if (ret == -1) uerror("utimes", path); @@ -85,4 +93,3 @@ CAMLprim value unix_utimes(value path, value atime, value mtime) { invalid_argument("utimes not implemented"); } #endif -#endif diff --git a/otherlibs/unix/wait.c b/otherlibs/unix/wait.c index a8eb42b7..1d261295 100644 --- a/otherlibs/unix/wait.c +++ b/otherlibs/unix/wait.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/unix/write.c b/otherlibs/unix/write.c index d6842d9f..0d12d48a 100644 --- a/otherlibs/unix/write.c +++ b/otherlibs/unix/write.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32graph/.ignore b/otherlibs/win32graph/.ignore deleted file mode 100644 index 090a9a25..00000000 --- a/otherlibs/win32graph/.ignore +++ /dev/null @@ -1,2 +0,0 @@ -graphics.ml -graphics.mli diff --git a/otherlibs/win32graph/Makefile.nt b/otherlibs/win32graph/Makefile.nt index f09392ed..26d9c5a6 100644 --- a/otherlibs/win32graph/Makefile.nt +++ b/otherlibs/win32graph/Makefile.nt @@ -1,15 +1,17 @@ -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2001 Institut National de Recherche en Informatique et # -# en Automatique. All rights reserved. This file is distributed # -# under the terms of the GNU Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* 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. * +#* * +#************************************************************************** LIBNAME=graphics COBJS=open.$(O) draw.$(O) events.$(O) dib.$(O) @@ -31,3 +33,6 @@ 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/dib.c b/otherlibs/win32graph/dib.c index 26fccf7f..f980869f 100644 --- a/otherlibs/win32graph/dib.c +++ b/otherlibs/win32graph/dib.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* 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 Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* 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 @@ -77,7 +79,7 @@ enum PAL_SIZE PALSIZE_MEDIUM, PALSIZE_LARGE }; -#define CopyPalette(hPal) CopyPaletteChangingFlags (hPal, DONT_CHANGE_FLAGS) +#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. @@ -296,8 +298,9 @@ static HANDLE ReadDIBFile (int hFile,int dwBitsSize) // 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)) + if ((_lread (hFile, (LPSTR) &bmfHeader, sizeof (bmfHeader)) + != sizeof (bmfHeader)) + || (bmfHeader.bfType != DIB_HEADER_MARKER)) { // ShowDbgMsg("Not a DIB file!"); return NULL; @@ -305,7 +308,8 @@ static HANDLE ReadDIBFile (int hFile,int dwBitsSize) // Allocate memory for DIB - hDIB = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER)); + hDIB = GlobalAlloc (GMEM_SHARE|GMEM_MOVEABLE | GMEM_ZEROINIT, + dwBitsSize - sizeof(BITMAPFILEHEADER)); if (hDIB == 0) { @@ -402,18 +406,18 @@ static void DIBPaint (HDC hDC,LPRECT lpDCRect,HANDLE hDIB) // 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, + 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 + 0, // nStartScan + (WORD) DIBHeight (lpDIBHdr), // nNumScans + lpDIBBits, // lpBits + (LPBITMAPINFO) lpDIBHdr, // lpBitsInfo + DIB_RGB_COLORS); // wUsage GlobalUnlock (hDIB); } @@ -442,7 +446,8 @@ HANDLE ChargerBitmap(char *FileName,POINT *lppt) unsigned int size; size = Getfilesize(FileName); - hFile=OpenFile((LPSTR) FileName, &ofstruct, OF_READ | OF_SHARE_DENY_WRITE); + hFile=OpenFile((LPSTR) FileName, &ofstruct, + OF_READ | OF_SHARE_DENY_WRITE); result = ReadDIBFile(hFile,size); if (hFile) _lclose(hFile); if (result) { diff --git a/otherlibs/win32graph/draw.c b/otherlibs/win32graph/draw.c index 99e1c5c7..482299b3 100644 --- a/otherlibs/win32graph/draw.c +++ b/otherlibs/win32graph/draw.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Developed by Jacob Navia, based on code by J-M Geffroy and X Leroy */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Developed by Jacob Navia, based on code by J-M Geffroy and X Leroy */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #include #include "caml/mlvalues.h" @@ -500,7 +502,8 @@ CAMLprim value caml_gr_draw_image(value i, value x, value y) if (Mask(i) == NULL) { if (grremember_mode) { oldBmp = SelectObject(grwindow.tempDC,Data(i)); - BitBlt(grwindow.gcBitmap,xdst, ydst, Width(i), Height(i), + BitBlt(grwindow.gcBitmap,xdst, ydst, Width(i), + Height(i), grwindow.tempDC, 0, 0, SRCCOPY); SelectObject(grwindow.tempDC,oldBmp); } @@ -514,11 +517,13 @@ CAMLprim value caml_gr_draw_image(value i, value x, value y) else { if (grremember_mode) { oldBmp = SelectObject(grwindow.tempDC,Mask(i)); - BitBlt(grwindow.gcBitmap,xdst, ydst, Width(i), Height(i), - grwindow.tempDC, 0, 0, SRCAND); + BitBlt(grwindow.gcBitmap,xdst, ydst, Width(i), + Height(i), + grwindow.tempDC, 0, 0, SRCAND); SelectObject(grwindow.tempDC,Data(i)); - BitBlt(grwindow.gcBitmap,xdst, ydst, Width(i), Height(i), - grwindow.tempDC, 0, 0, SRCPAINT); + BitBlt(grwindow.gcBitmap,xdst, ydst, Width(i), + Height(i), + grwindow.tempDC, 0, 0, SRCPAINT); SelectObject(grwindow.tempDC,oldBmp); } if (grdisplay_mode) { @@ -567,7 +572,8 @@ CAMLprim value caml_gr_make_image(value matrix) int red = (col >> 16) & 0xFF; int green = (col >> 8) & 0xFF; int blue = col & 0xFF; - SetPixel(grwindow.tempDC,j, i, RGB(red, green, blue)); + SetPixel(grwindow.tempDC,j, i, + RGB(red, green, blue)); } } } @@ -579,8 +585,9 @@ CAMLprim value caml_gr_make_image(value matrix) oldBmp = SelectObject(grwindow.tempDC,Mask(img)); for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { - int col = Long_val (Field (Field (matrix, i), j)); - SetPixel(grwindow.tempDC,j, i, col == -1 ? 0xFFFFFF : 0); + int col = Long_val (Field (Field (matrix,i),j)); + SetPixel(grwindow.tempDC,j, i, + col == -1 ? 0xFFFFFF : 0); } } SelectObject(grwindow.tempDC,oldBmp); diff --git a/otherlibs/win32graph/events.c b/otherlibs/win32graph/events.c index 837e53ac..65642838 100755 --- a/otherlibs/win32graph/events.c +++ b/otherlibs/win32graph/events.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2004 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2004 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 "caml/mlvalues.h" #include "caml/alloc.h" diff --git a/otherlibs/win32graph/libgraph.h b/otherlibs/win32graph/libgraph.h index 99ede995..674f92f5 100644 --- a/otherlibs/win32graph/libgraph.h +++ b/otherlibs/win32graph/libgraph.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Jacob Navia, after Xavier Leroy */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jacob Navia, after Xavier Leroy */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #include #include diff --git a/otherlibs/win32graph/libgraphics.clib b/otherlibs/win32graph/libgraphics.clib deleted file mode 100644 index 5084c973..00000000 --- a/otherlibs/win32graph/libgraphics.clib +++ /dev/null @@ -1 +0,0 @@ -open.o draw.o events.o dib.o diff --git a/otherlibs/win32graph/open.c b/otherlibs/win32graph/open.c index e9d10cad..016e52eb 100644 --- a/otherlibs/win32graph/open.c +++ b/otherlibs/win32graph/open.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Developed by Jacob Navia, based on code by J-M Geffroy and X Leroy */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Developed by Jacob Navia, based on code by J-M Geffroy and X Leroy */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #include #include @@ -74,7 +76,8 @@ void ResetForClose(HWND hwnd) -static LRESULT CALLBACK GraphicsWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) +static LRESULT CALLBACK GraphicsWndProc(HWND hwnd,UINT msg,WPARAM wParam, + LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; @@ -91,7 +94,8 @@ static LRESULT CALLBACK GraphicsWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM break; // Move the child windows case WM_SIZE: - // Position the MDI client window between the tool and status bars + // Position the MDI client window between the tool and + // status bars if (wParam != SIZE_MINIMIZED) { SetCoordinates(hwnd); } @@ -135,7 +139,8 @@ static value gr_reset(void) grwindow.width = rc.right; grwindow.height = rc.bottom; if (grwindow.gcBitmap == (HDC)0) { - grwindow.hBitmap = CreateCompatibleBitmap(grwindow.gc,screenx,screeny); + grwindow.hBitmap = CreateCompatibleBitmap(grwindow.gc,screenx, + screeny); grwindow.gcBitmap = CreateCompatibleDC(grwindow.gc); grwindow.tempDC = CreateCompatibleDC(grwindow.gc); SelectObject(grwindow.gcBitmap,grwindow.hBitmap); @@ -149,10 +154,12 @@ static value gr_reset(void) grwindow.CurrentColor = GetSysColor(COLOR_WINDOWTEXT); grwindow.grx = 0; grwindow.gry = 0; - grwindow.CurrentPen = SelectObject(grwindow.gc,GetStockObject(WHITE_PEN)); + grwindow.CurrentPen = SelectObject(grwindow.gc, + GetStockObject(WHITE_PEN)); SelectObject(grwindow.gc,grwindow.CurrentPen); SelectObject(grwindow.gcBitmap,grwindow.CurrentPen); - grwindow.CurrentBrush = SelectObject(grwindow.gc,GetStockObject(WHITE_BRUSH)); + grwindow.CurrentBrush = SelectObject(grwindow.gc, + GetStockObject(WHITE_BRUSH)); SelectObject(grwindow.gc,grwindow.CurrentBrush); SelectObject(grwindow.gcBitmap,grwindow.CurrentBrush); caml_gr_set_color(Val_long(0)); @@ -353,7 +360,8 @@ 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, must link graphics.cma"); + invalid_argument("Exception Graphics.Graphic_failure not initialized, " + "must link graphics.cma"); } sprintf(buffer, fmt, arg); raise_with_string(*graphic_failure_exn, buffer); diff --git a/otherlibs/win32unix/.ignore b/otherlibs/win32unix/.ignore deleted file mode 100644 index 1eac7a1f..00000000 --- a/otherlibs/win32unix/.ignore +++ /dev/null @@ -1,29 +0,0 @@ -unixLabels.ml* -unix.mli -unix.lib -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 diff --git a/otherlibs/win32unix/Makefile b/otherlibs/win32unix/Makefile index 72248e53..58208a3b 100644 --- a/otherlibs/win32unix/Makefile +++ b/otherlibs/win32unix/Makefile @@ -1,60 +1,18 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### - -# 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 rename.c \ - select.c sendrecv.c \ - shutdown.c sleep.c socket.c sockopt.c startup.c stat.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) - -LIBNAME=unix -COBJS=$(ALL_FILES:.c=.$(O)) -CAMLOBJS=unix.cmo unixLabels.cmo -LINKOPTS=-cclib $(WSOCKLIB) -LDOPTS=-ldopt $(WSOCKLIB) -EXTRACAMLFLAGS=-nolabels -EXTRACFLAGS=-I../unix -HEADERS=unixsupport.h socketaddr.h - +#************************************************************************** +#* * +#* 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 Makefile.common 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.common b/otherlibs/win32unix/Makefile.common new file mode 100644 index 00000000..9487db0d --- /dev/null +++ b/otherlibs/win32unix/Makefile.common @@ -0,0 +1,63 @@ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +# 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.nt + +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 77555b2c..bb59270d 100644 --- a/otherlibs/win32unix/Makefile.nt +++ b/otherlibs/win32unix/Makefile.nt @@ -1,60 +1,18 @@ -######################################################################### -# # -# 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 Library General Public License, with # -# the special exception on linking described in file ../../LICENSE. # -# # -######################################################################### - -# 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 rename.c \ - select.c sendrecv.c \ - shutdown.c sleep.c socket.c sockopt.c startup.c stat.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) - -LIBNAME=unix -COBJS=$(ALL_FILES:.c=.$(O)) -CAMLOBJS=unix.cmo unixLabels.cmo -LINKOPTS=-cclib $(WSOCKLIB) -LDOPTS=-ldopt $(WSOCKLIB) -EXTRACAMLFLAGS=-nolabels -EXTRACFLAGS=-I../unix -HEADERS=unixsupport.h socketaddr.h - +#************************************************************************** +#* * +#* 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 Makefile.common include ../Makefile.nt - -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/accept.c b/otherlibs/win32unix/accept.c index f705f0f0..ec7053c7 100644 --- a/otherlibs/win32unix/accept.c +++ b/otherlibs/win32unix/accept.c @@ -1,22 +1,23 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include #include #include #include "unixsupport.h" -#include // for SO_OPENTYPE and SO_SYNCHRONOUS_NONALERT #include "socketaddr.h" CAMLprim value unix_accept(sock) @@ -25,30 +26,15 @@ CAMLprim value unix_accept(sock) SOCKET sconn = Socket_val(sock); SOCKET snew; value fd = Val_unit, adr = Val_unit, res; - int oldvalue, oldvaluelen, newvalue, retcode; union sock_addr_union addr; socklen_param_type addr_len; DWORD err = 0; - oldvaluelen = sizeof(oldvalue); - retcode = getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &oldvalue, &oldvaluelen); - if (retcode == 0) { - /* Set sockets to synchronous mode */ - newvalue = SO_SYNCHRONOUS_NONALERT; - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &newvalue, sizeof(newvalue)); - } addr_len = sizeof(sock_addr); enter_blocking_section(); snew = accept(sconn, &addr.s_gen, &addr_len); if (snew == INVALID_SOCKET) err = WSAGetLastError (); leave_blocking_section(); - if (retcode == 0) { - /* Restore initial mode */ - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &oldvalue, oldvaluelen); - } if (snew == INVALID_SOCKET) { win32_maperr(err); uerror("accept", Nothing); diff --git a/otherlibs/win32unix/bind.c b/otherlibs/win32unix/bind.c index 4b1d3def..b852f93f 100644 --- a/otherlibs/win32unix/bind.c +++ b/otherlibs/win32unix/bind.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/channels.c b/otherlibs/win32unix/channels.c index b6350e17..edd83813 100644 --- a/otherlibs/win32unix/channels.c +++ b/otherlibs/win32unix/channels.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/close.c b/otherlibs/win32unix/close.c index 7f8da29d..a4adee3f 100644 --- a/otherlibs/win32unix/close.c +++ b/otherlibs/win32unix/close.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/close_on.c b/otherlibs/win32unix/close_on.c index 7a316abc..79dd56a8 100644 --- a/otherlibs/win32unix/close_on.c +++ b/otherlibs/win32unix/close_on.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/connect.c b/otherlibs/win32unix/connect.c index 37cdbdaa..e30243c1 100644 --- a/otherlibs/win32unix/connect.c +++ b/otherlibs/win32unix/connect.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/createprocess.c b/otherlibs/win32unix/createprocess.c index 9766df5c..96dbfe4a 100644 --- a/otherlibs/win32unix/createprocess.c +++ b/otherlibs/win32unix/createprocess.c @@ -1,20 +1,23 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" #include #include +#include static int win_has_console(void); @@ -26,6 +29,11 @@ value win_create_process_native(value cmd, value cmdline, value env, char * exefile, * envp; int flags; + 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)); if (env != Val_int(0)) { envp = String_val(Field(env, 0)); @@ -53,9 +61,11 @@ 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); } + caml_stat_free(exefile); CloseHandle(pi.hThread); /* Return the process handle as pseudo-PID (this is consistent with the wait() emulation in the MSVC C library */ diff --git a/otherlibs/win32unix/dup.c b/otherlibs/win32unix/dup.c index 5db19e30..d43f66d3 100644 --- a/otherlibs/win32unix/dup.c +++ b/otherlibs/win32unix/dup.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/dup2.c b/otherlibs/win32unix/dup2.c index 51842077..c6c258f9 100644 --- a/otherlibs/win32unix/dup2.c +++ b/otherlibs/win32unix/dup2.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/errmsg.c b/otherlibs/win32unix/errmsg.c index 6107abc3..cdefa601 100644 --- a/otherlibs/win32unix/errmsg.c +++ b/otherlibs/win32unix/errmsg.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #include #include diff --git a/otherlibs/win32unix/getpeername.c b/otherlibs/win32unix/getpeername.c index 3467e03f..d022a847 100644 --- a/otherlibs/win32unix/getpeername.c +++ b/otherlibs/win32unix/getpeername.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/getpid.c b/otherlibs/win32unix/getpid.c index 06d95356..71e9c141 100644 --- a/otherlibs/win32unix/getpid.c +++ b/otherlibs/win32unix/getpid.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/getsockname.c b/otherlibs/win32unix/getsockname.c index 21e9d063..6df6adfb 100644 --- a/otherlibs/win32unix/getsockname.c +++ b/otherlibs/win32unix/getsockname.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/gettimeofday.c b/otherlibs/win32unix/gettimeofday.c index f4e25b5f..936cb89e 100644 --- a/otherlibs/win32unix/gettimeofday.c +++ b/otherlibs/win32unix/gettimeofday.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -25,6 +27,6 @@ CAMLprim value unix_gettimeofday(value unit) FILETIME ft; double tm; GetSystemTimeAsFileTime(&ft); - tm = *(uint64 *)&ft - epoch_ft; /* shift to Epoch-relative time */ + tm = *(uint64_t *)&ft - epoch_ft; /* shift to Epoch-relative time */ return copy_double(tm * 1e-7); /* tm is in 100ns */ } diff --git a/otherlibs/win32unix/libunix.clib b/otherlibs/win32unix/libunix.clib deleted file mode 100644 index 043dcf76..00000000 --- a/otherlibs/win32unix/libunix.clib +++ /dev/null @@ -1,17 +0,0 @@ -# Files in this directory -accept.o bind.o channels.o close.o -close_on.o connect.o createprocess.o dup.o dup2.o errmsg.o -getpeername.o getpid.o getsockname.o gettimeofday.o -link.o listen.o lockf.o lseek.o nonblock.o -mkdir.o open.o pipe.o read.o rename.o -select.o sendrecv.o -shutdown.o sleep.o socket.o sockopt.o startup.o stat.o -system.o unixsupport.o windir.o winwait.o write.o -winlist.o winworker.o windbug.o - -# Files from the ../unix directory -access.o addrofstr.o chdir.o chmod.o cst2constr.o -cstringv.o envir.o execv.o execve.o execvp.o -exit.o getcwd.o gethost.o gethostname.o getproto.o -getserv.o gmtime.o putenv.o rmdir.o -socketaddr.o strofaddr.o time.o unlink.o utimes.o diff --git a/otherlibs/win32unix/link.c b/otherlibs/win32unix/link.c index 93d21508..5116fe02 100644 --- a/otherlibs/win32unix/link.c +++ b/otherlibs/win32unix/link.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* File contributed by Lionel Fourquaux */ -/* */ -/* Copyright 2001 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* File contributed by Lionel Fourquaux */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ #include #include @@ -32,6 +34,8 @@ CAMLprim value unix_link(value path1, value path2) (tCreateHardLink) GetProcAddress(hModKernel32, "CreateHardLinkA"); if (pCreateHardLink == NULL) 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)) { win32_maperr(GetLastError()); uerror("link", path2); diff --git a/otherlibs/win32unix/listen.c b/otherlibs/win32unix/listen.c index 767db61d..364b4be4 100644 --- a/otherlibs/win32unix/listen.c +++ b/otherlibs/win32unix/listen.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/lockf.c b/otherlibs/win32unix/lockf.c index 9c705a67..bd732076 100644 --- a/otherlibs/win32unix/lockf.c +++ b/otherlibs/win32unix/lockf.c @@ -1,17 +1,18 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Tracy Camp, PolyServe Inc., */ -/* Further improvements by Reed Wilson */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* under the terms of the GNU Library General Public License. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Tracy Camp, PolyServe Inc., */ +/* Further improvements by Reed Wilson */ +/* */ +/* Copyright 2002 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 #include diff --git a/otherlibs/win32unix/lseek.c b/otherlibs/win32unix/lseek.c index 6c30a62a..bf5b80f8 100644 --- a/otherlibs/win32unix/lseek.c +++ b/otherlibs/win32unix/lseek.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/mkdir.c b/otherlibs/win32unix/mkdir.c index 21bca10c..7aaf040a 100644 --- a/otherlibs/win32unix/mkdir.c +++ b/otherlibs/win32unix/mkdir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" @@ -17,6 +19,7 @@ CAMLprim value unix_mkdir(path, perm) value path, perm; { + caml_unix_check_path(path, "mkdir"); if (_mkdir(String_val(path)) == -1) uerror("mkdir", path); return Val_unit; } diff --git a/otherlibs/win32unix/nonblock.c b/otherlibs/win32unix/nonblock.c index 4001beca..599445e6 100755 --- a/otherlibs/win32unix/nonblock.c +++ b/otherlibs/win32unix/nonblock.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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 #include diff --git a/otherlibs/win32unix/open.c b/otherlibs/win32unix/open.c index f9e9df21..65568b64 100644 --- a/otherlibs/win32unix/open.c +++ b/otherlibs/win32unix/open.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -39,6 +41,7 @@ CAMLprim value unix_open(value path, value flags, value perm) SECURITY_ATTRIBUTES attr; HANDLE h; + caml_unix_check_path(path, "open"); fileaccess = convert_flag_list(flags, open_access_flags); sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE | convert_flag_list(flags, open_share_flags); diff --git a/otherlibs/win32unix/pipe.c b/otherlibs/win32unix/pipe.c index 88debb02..64a63c60 100644 --- a/otherlibs/win32unix/pipe.c +++ b/otherlibs/win32unix/pipe.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/read.c b/otherlibs/win32unix/read.c index d65683cc..532a0bfb 100644 --- a/otherlibs/win32unix/read.c +++ b/otherlibs/win32unix/read.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/readlink.c b/otherlibs/win32unix/readlink.c new file mode 100644 index 00000000..696d435f --- /dev/null +++ b/otherlibs/win32unix/readlink.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* David Allsopp, MetaStack Solutions Ltd. */ +/* */ +/* Copyright 2015 MetaStack Solutions Ltd. */ +/* */ +/* 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 +#include +#include +#include +#include +#include "unixsupport.h" +#include +#include + +CAMLprim value unix_readlink(value opath) +{ + CAMLparam1(opath); + CAMLlocal1(result); + HANDLE h; + char* path = String_val(opath); + DWORD attributes; + + caml_enter_blocking_section(); + attributes = GetFileAttributes(path); + caml_leave_blocking_section(); + + if (attributes == INVALID_FILE_ATTRIBUTES) { + win32_maperr(GetLastError()); + uerror("readlink", opath); + } + else if (!(attributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + errno = EINVAL; + uerror("readlink", opath); + } + else { + caml_enter_blocking_section(); + if ((h = CreateFile(path, + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + NULL)) == INVALID_HANDLE_VALUE) { + caml_leave_blocking_section(); + errno = ENOENT; + uerror("readlink", opath); + } + else { + char buffer[16384]; + DWORD read; + REPARSE_DATA_BUFFER* point; + + if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, 16384, &read, NULL)) { + caml_leave_blocking_section(); + point = (REPARSE_DATA_BUFFER*)buffer; + if (point->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + int cbLen = point->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); + int len; + len = WideCharToMultiByte( + CP_THREAD_ACP, + 0, + point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / 2, + cbLen, + NULL, + 0, + NULL, + NULL); + result = caml_alloc_string(len); + WideCharToMultiByte( + CP_THREAD_ACP, + 0, + point->SymbolicLinkReparseBuffer.PathBuffer + point->SymbolicLinkReparseBuffer.SubstituteNameOffset / 2, + cbLen, + String_val(result), + len, + NULL, + NULL); + CloseHandle(h); + } + else { + errno = EINVAL; + CloseHandle(h); + uerror("readline", opath); + } + } + else { + caml_leave_blocking_section(); + win32_maperr(GetLastError()); + CloseHandle(h); + uerror("readlink", opath); + } + } + } + + CAMLreturn(result); +} diff --git a/otherlibs/win32unix/rename.c b/otherlibs/win32unix/rename.c index ad46ead2..155a73fb 100644 --- a/otherlibs/win32unix/rename.c +++ b/otherlibs/win32unix/rename.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Tracy Camp, PolyServe Inc., */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Tracy Camp, PolyServe Inc., */ +/* */ +/* Copyright 2002 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 #include @@ -20,6 +22,8 @@ CAMLprim value unix_rename(value path1, value path2) static int supports_MoveFileEx = -1; /* don't know yet */ BOOL ok; + caml_unix_check_path(path1, "rename"); + caml_unix_check_path(path2, "rename"); if (supports_MoveFileEx < 0) { OSVERSIONINFO VersionInfo; VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); diff --git a/otherlibs/win32unix/select.c b/otherlibs/win32unix/select.c index 0e21db89..ad77bf96 100644 --- a/otherlibs/win32unix/select.c +++ b/otherlibs/win32unix/select.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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 #include @@ -152,7 +154,8 @@ typedef SELECTQUERY *LPSELECTQUERY; typedef struct _SELECTDATA { LIST lst; SELECTTYPE EType; - /* Sockets may generate a result for all three lists from one single query object + /* Sockets may generate a result for all three lists from one single + query object */ SELECTRESULT aResults[MAXIMUM_SELECT_OBJECTS * 3]; DWORD nResultsCount; @@ -231,7 +234,8 @@ void select_data_free (LPSELECTDATA lpSelectData) } /* Add a result to select data, return zero if something goes wrong. */ -DWORD select_data_result_add (LPSELECTDATA lpSelectData, SELECTMODE EMode, int lpOrigIdx) +DWORD select_data_result_add (LPSELECTDATA lpSelectData, SELECTMODE EMode, + int lpOrigIdx) { DWORD res; DWORD i; @@ -278,7 +282,8 @@ DWORD select_data_query_add (LPSELECTDATA lpSelectData, * If none is found, create a new one. Return the corresponding SELECTDATA, and * update provided SELECTDATA head, if required. */ -LPSELECTDATA select_data_job_search (LPSELECTDATA *lppSelectData, SELECTTYPE EType) +LPSELECTDATA select_data_job_search (LPSELECTDATA *lppSelectData, + SELECTTYPE EType) { LPSELECTDATA res; @@ -335,13 +340,16 @@ void read_console_poll(HANDLE hStop, void *_data) while (lpSelectData->EState == SELECT_STATE_NONE) { waitRes = WaitForMultipleObjects(2, events, FALSE, INFINITE); - if (waitRes == WAIT_OBJECT_0 || check_error(lpSelectData, waitRes == WAIT_FAILED)) + if (waitRes == WAIT_OBJECT_0 + || check_error(lpSelectData, waitRes == WAIT_FAILED)) { /* stop worker event or error */ break; } /* console event */ - if (check_error(lpSelectData, PeekConsoleInput(lpQuery->hFileDescr, &record, 1, &n) == 0)) + if (check_error(lpSelectData, PeekConsoleInput(lpQuery->hFileDescr, + &record, 1, &n) + == 0)) { break; } @@ -357,7 +365,9 @@ void read_console_poll(HANDLE hStop, void *_data) else { /* discard everything else and try again */ - if (check_error(lpSelectData, ReadConsoleInput(lpQuery->hFileDescr, &record, 1, &n) == 0)) + if (check_error(lpSelectData, ReadConsoleInput(lpQuery->hFileDescr, + &record, 1, &n) + == 0)) { break; } @@ -425,7 +435,8 @@ void read_pipe_poll (HANDLE hStop, void *_data) if ((n > 0) || (res == 0)) { lpSelectData->EState = SELECT_STATE_SIGNALED; - select_data_result_add(lpSelectData, iterQuery->EMode, iterQuery->lpOrigIdx); + select_data_result_add(lpSelectData, iterQuery->EMode, + iterQuery->lpOrigIdx); }; }; @@ -445,7 +456,8 @@ void read_pipe_poll (HANDLE hStop, void *_data) { wait = 10; }; - if (event == WAIT_OBJECT_0 || check_error(lpSelectData, event == WAIT_FAILED)) + if (event == WAIT_OBJECT_0 + || check_error(lpSelectData, event == WAIT_FAILED)) { break; } @@ -554,19 +566,28 @@ void socket_poll (HANDLE hStop, void *_data) { /* Find out what kind of events were raised */ - if (WSAEnumNetworkEvents((SOCKET)(iterQuery->hFileDescr), aEvents[i], &events) == 0) + if (WSAEnumNetworkEvents((SOCKET)(iterQuery->hFileDescr), + aEvents[i], &events) == 0) { - if ((iterQuery->EMode & SELECT_MODE_READ) != 0 && (events.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) != 0) + if ((iterQuery->EMode & SELECT_MODE_READ) != 0 + && (events.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) + != 0) { - select_data_result_add(lpSelectData, SELECT_MODE_READ, iterQuery->lpOrigIdx); + select_data_result_add(lpSelectData, SELECT_MODE_READ, + iterQuery->lpOrigIdx); } - if ((iterQuery->EMode & SELECT_MODE_WRITE) != 0 && (events.lNetworkEvents & (FD_WRITE | FD_CONNECT | FD_CLOSE)) != 0) + if ((iterQuery->EMode & SELECT_MODE_WRITE) != 0 + && (events.lNetworkEvents & (FD_WRITE | FD_CONNECT | FD_CLOSE)) + != 0) { - select_data_result_add(lpSelectData, SELECT_MODE_WRITE, iterQuery->lpOrigIdx); + select_data_result_add(lpSelectData, SELECT_MODE_WRITE, + iterQuery->lpOrigIdx); } - if ((iterQuery->EMode & SELECT_MODE_EXCEPT) != 0 && (events.lNetworkEvents & FD_OOB) != 0) + if ((iterQuery->EMode & SELECT_MODE_EXCEPT) != 0 + && (events.lNetworkEvents & FD_OOB) != 0) { - select_data_result_add(lpSelectData, SELECT_MODE_EXCEPT, iterQuery->lpOrigIdx); + select_data_result_add(lpSelectData, SELECT_MODE_EXCEPT, + iterQuery->lpOrigIdx); } } } @@ -612,13 +633,15 @@ LPSELECTDATA socket_poll_add (LPSELECTDATA lpSelectData, /* Polling socket can be done mulitple handle at the same time. You just need one worker to use it. Try to find if there is already a worker handling this kind of request. - Only one event can be associated with a given socket which means that if a socket - is in more than one of the fd_sets then we have to find that particular query and update - EMode with the additional flag. + Only one event can be associated with a given socket which means + that if a socket is in more than one of the fd_sets then we have + to find that particular query and update EMode with the + additional flag. */ DEBUG_PRINT("Scanning list of worker to find one that already handle socket"); /* Search for job */ - DEBUG_PRINT("Searching for an available job for type %d for descriptor %d", SELECT_TYPE_SOCKET, hFileDescr); + DEBUG_PRINT("Searching for an available job for type %d for descriptor %d", + SELECT_TYPE_SOCKET, hFileDescr); while (res != NULL) { if (res->EType == SELECT_TYPE_SOCKET) @@ -629,7 +652,8 @@ LPSELECTDATA socket_poll_add (LPSELECTDATA lpSelectData, { i--; } - /* If we didn't find the socket but this worker has available slots, store it + /* If we didn't find the socket but this worker has available + slots, store it */ if (i < 0) { @@ -748,7 +772,8 @@ static SELECTHANDLETYPE get_handle_type(value fd) }; break; - case FILE_TYPE_PIPE: /* a named or an anonymous pipe (socket already handled) */ + case FILE_TYPE_PIPE: /* a named or an anonymous pipe (socket + already handled) */ res = SELECT_HANDLE_PIPE; break; }; @@ -758,7 +783,8 @@ static SELECTHANDLETYPE get_handle_type(value fd) } /* Choose what to do with given data */ -LPSELECTDATA select_data_dispatch (LPSELECTDATA lpSelectData, SELECTMODE EMode, value fd, int lpOrigIdx) +LPSELECTDATA select_data_dispatch (LPSELECTDATA lpSelectData, SELECTMODE EMode, + value fd, int lpOrigIdx) { LPSELECTDATA res; HANDLE hFileDescr; @@ -799,7 +825,8 @@ LPSELECTDATA select_data_dispatch (LPSELECTDATA lpSelectData, SELECTMODE EMode, /* Console is always ready in write operation, need to check for read. */ if (EMode == SELECT_MODE_READ) { - res = read_console_poll_add(res, EMode, hFileDescr, lpOrigIdx, uFlagsFd); + res = read_console_poll_add(res, EMode, hFileDescr, lpOrigIdx, + uFlagsFd); } else if (EMode == SELECT_MODE_WRITE) { @@ -817,7 +844,8 @@ LPSELECTDATA select_data_dispatch (LPSELECTDATA lpSelectData, SELECTMODE EMode, } else if (EMode == SELECT_MODE_WRITE) { - DEBUG_PRINT("No need to check availability of data on pipe, write operation always possible"); + DEBUG_PRINT("No need to check availability of data on pipe, " + "write operation always possible"); res = static_poll_add(res, EMode, hFileDescr, lpOrigIdx, uFlagsFd); }; break; @@ -868,7 +896,8 @@ static DWORD caml_list_length (value lst) CAMLreturnT(DWORD, res); } -static value find_handle(LPSELECTRESULT iterResult, value readfds, value writefds, value exceptfds) +static value find_handle(LPSELECTRESULT iterResult, value readfds, + value writefds, value exceptfds) { CAMLparam3(readfds, writefds, exceptfds); CAMLlocal2(result, list); @@ -902,8 +931,9 @@ static value find_handle(LPSELECTRESULT iterResult, value readfds, value writefd #define MAX(a, b) ((a) > (b) ? (a) : (b)) -/* Convert fdlist to an fd_set if all the handles in fdlist are sockets and return 0. - * Returns 1 if a non-socket value is encountered. +/* Convert fdlist to an fd_set if all the handles in fdlist are + * sockets and return 0. Returns 1 if a non-socket value is + * encountered. */ static int fdlist_to_fdset(value fdlist, fd_set *fdset) { @@ -938,7 +968,8 @@ static value fdset_to_fdlist(value fdlist, fd_set *fdset) return res; } -CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value timeout) +CAMLprim value unix_select(value readfds, value writefds, value exceptfds, + value timeout) { /* Event associated to handle */ DWORD nEventsCount; @@ -990,7 +1021,9 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value err = 0; tm = Double_val(timeout); - if (readfds == Val_int(0) && writefds == Val_int(0) && exceptfds == Val_int(0)) { + if (readfds == Val_int(0) + && writefds == Val_int(0) + && exceptfds == Val_int(0)) { DEBUG_PRINT("nothing to do"); if ( tm > 0.0 ) { enter_blocking_section(); @@ -999,7 +1032,9 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value } read_list = write_list = except_list = Val_int(0); } else { - if (fdlist_to_fdset(readfds, &read) && fdlist_to_fdset(writefds, &write) && fdlist_to_fdset(exceptfds, &except)) { + if (fdlist_to_fdset(readfds, &read) + && fdlist_to_fdset(writefds, &write) + && fdlist_to_fdset(exceptfds, &except)) { DEBUG_PRINT("only sockets to select on, using classic select"); if (tm < 0.0) { tvp = (struct timeval *) NULL; @@ -1049,7 +1084,8 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value } - /* Create list of select data, based on the different list of fd to watch */ + /* Create list of select data, based on the different list of fd + to watch */ DEBUG_PRINT("Dispatch read fd"); handle_set_init(&hds, hdsData, hdsMax); i=0; @@ -1059,11 +1095,13 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value if (!handle_set_mem(&hds, Handle_val(fd))) { handle_set_add(&hds, Handle_val(fd)); - lpSelectData = select_data_dispatch(lpSelectData, SELECT_MODE_READ, fd, i++); + lpSelectData = select_data_dispatch(lpSelectData, + SELECT_MODE_READ, fd, i++); } else { - DEBUG_PRINT("Discarding handle %x which is already monitor for read", Handle_val(fd)); + DEBUG_PRINT("Discarding handle %x which is already monitor " + "for read", Handle_val(fd)); } } handle_set_reset(&hds); @@ -1077,11 +1115,13 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value if (!handle_set_mem(&hds, Handle_val(fd))) { handle_set_add(&hds, Handle_val(fd)); - lpSelectData = select_data_dispatch(lpSelectData, SELECT_MODE_WRITE, fd, i++); + lpSelectData = select_data_dispatch(lpSelectData, + SELECT_MODE_WRITE, fd, i++); } else { - DEBUG_PRINT("Discarding handle %x which is already monitor for write", Handle_val(fd)); + DEBUG_PRINT("Discarding handle %x which is already monitor " + "for write", Handle_val(fd)); } } handle_set_reset(&hds); @@ -1095,11 +1135,13 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value if (!handle_set_mem(&hds, Handle_val(fd))) { handle_set_add(&hds, Handle_val(fd)); - lpSelectData = select_data_dispatch(lpSelectData, SELECT_MODE_EXCEPT, fd, i++); + lpSelectData = select_data_dispatch(lpSelectData, + SELECT_MODE_EXCEPT, fd, i++); } else { - DEBUG_PRINT("Discarding handle %x which is already monitor for exceptional", Handle_val(fd)); + DEBUG_PRINT("Discarding handle %x which is already monitor " + "for exceptional", Handle_val(fd)); } } handle_set_reset(&hds); @@ -1130,8 +1172,10 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value worker_job_submit( iterSelectData->funcWorker, (void *)iterSelectData); - DEBUG_PRINT("Job submitted to worker %x", iterSelectData->lpWorker); - lpEventsDone[nEventsCount] = worker_job_event_done(iterSelectData->lpWorker); + DEBUG_PRINT("Job submitted to worker %x", + iterSelectData->lpWorker); + lpEventsDone[nEventsCount] + = worker_job_event_done(iterSelectData->lpWorker); nEventsCount++; }; iterSelectData = LIST_NEXT(LPSELECTDATA, iterSelectData); @@ -1148,7 +1192,8 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value if (err == 0 && !hasStaticData) { DEBUG_PRINT("Waiting for one select worker to be done"); - switch (WaitForMultipleObjects(nEventsCount, lpEventsDone, FALSE, milliseconds)) + switch (WaitForMultipleObjects(nEventsCount, lpEventsDone, FALSE, + milliseconds)) { case WAIT_FAILED: err = GetLastError(); @@ -1177,7 +1222,8 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value }; DEBUG_PRINT("Waiting for every select worker to be done"); - switch (WaitForMultipleObjects(nEventsCount, lpEventsDone, TRUE, INFINITE)) + switch (WaitForMultipleObjects(nEventsCount, lpEventsDone, TRUE, + INFINITE)) { case WAIT_FAILED: err = GetLastError(); @@ -1211,7 +1257,8 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, value { iterResult = &(iterSelectData->aResults[i]); l = alloc_small(2, 0); - Store_field(l, 0, find_handle(iterResult, readfds, writefds, exceptfds)); + Store_field(l, 0, find_handle(iterResult, readfds, writefds, + exceptfds)); switch (iterResult->EMode) { case SELECT_MODE_READ: diff --git a/otherlibs/win32unix/sendrecv.c b/otherlibs/win32unix/sendrecv.c index 5957f6ed..1c9ed08a 100644 --- a/otherlibs/win32unix/sendrecv.c +++ b/otherlibs/win32unix/sendrecv.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/shutdown.c b/otherlibs/win32unix/shutdown.c index 96023111..d70f280e 100644 --- a/otherlibs/win32unix/shutdown.c +++ b/otherlibs/win32unix/shutdown.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" diff --git a/otherlibs/win32unix/sleep.c b/otherlibs/win32unix/sleep.c index 6d630d20..1b7af930 100644 --- a/otherlibs/win32unix/sleep.c +++ b/otherlibs/win32unix/sleep.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -19,7 +21,7 @@ CAMLprim value unix_sleep(t) value t; { enter_blocking_section(); - Sleep(Int_val(t) * 1000); + Sleep(Double_val(t) * 1e3); leave_blocking_section(); return Val_unit; } diff --git a/otherlibs/win32unix/socket.c b/otherlibs/win32unix/socket.c index 9385e82e..d684034f 100644 --- a/otherlibs/win32unix/socket.c +++ b/otherlibs/win32unix/socket.c @@ -1,19 +1,20 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include "unixsupport.h" -#include // for SO_OPENTYPE and SO_SYNCHRONOUS_NONALERT int socket_domain_table[] = { PF_UNIX, PF_INET, @@ -32,7 +33,6 @@ CAMLprim value unix_socket(domain, type, proto) value domain, type, proto; { SOCKET s; - int oldvalue, oldvaluelen, newvalue, retcode; #ifndef HAS_IPV6 /* IPv6 requires WinSock2, we must raise an error on PF_INET6 */ @@ -42,23 +42,9 @@ CAMLprim value unix_socket(domain, type, proto) } #endif - oldvaluelen = sizeof(oldvalue); - retcode = getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &oldvalue, &oldvaluelen); - if (retcode == 0) { - /* Set sockets to synchronous mode */ - newvalue = SO_SYNCHRONOUS_NONALERT; - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &newvalue, sizeof(newvalue)); - } s = socket(socket_domain_table[Int_val(domain)], socket_type_table[Int_val(type)], Int_val(proto)); - if (retcode == 0) { - /* Restore initial mode */ - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, - (char *) &oldvalue, oldvaluelen); - } if (s == INVALID_SOCKET) { win32_maperr(WSAGetLastError()); uerror("socket", Nothing); diff --git a/otherlibs/win32unix/socketaddr.h b/otherlibs/win32unix/socketaddr.h index f3b6caf0..e951bece 100644 --- a/otherlibs/win32unix/socketaddr.h +++ b/otherlibs/win32unix/socketaddr.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_SOCKETADDR_H #define CAML_SOCKETADDR_H diff --git a/otherlibs/win32unix/sockopt.c b/otherlibs/win32unix/sockopt.c index aebc517a..53219fe9 100644 --- a/otherlibs/win32unix/sockopt.c +++ b/otherlibs/win32unix/sockopt.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/startup.c b/otherlibs/win32unix/startup.c index be66c8a8..844ebd5b 100644 --- a/otherlibs/win32unix/startup.c +++ b/otherlibs/win32unix/startup.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/stat.c b/otherlibs/win32unix/stat.c index 46fc9841..12f5af53 100644 --- a/otherlibs/win32unix/stat.c +++ b/otherlibs/win32unix/stat.c @@ -1,28 +1,38 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* David Allsopp, MetaStack Solutions Ltd. */ +/* */ +/* Copyright 2015 MetaStack Solutions Ltd. */ +/* */ +/* 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 #include #include #include +#include #include "unixsupport.h" #include "cst2constr.h" #define _INTEGRAL_MAX_BITS 64 #include #include +#include +#include #ifndef S_IFLNK -#define S_IFLNK 0 +/* + * The Microsoft CRT doesn't support lstat and so has no S_IFLNK + * The implementation uses comparison, so rather than allocating another bit, in + * a potentially future-incompatible way, just create a value with multiple bits + * set. + */ +#define S_IFLNK (S_IFDIR | S_IFREG) #endif #ifndef S_IFIFO #define S_IFIFO 0 @@ -38,14 +48,14 @@ static int file_kind_table[] = { S_IFREG, S_IFDIR, S_IFCHR, S_IFBLK, S_IFLNK, S_IFIFO, S_IFSOCK }; -static value stat_aux(int use_64, struct _stati64 *buf) +static value stat_aux(int use_64, __int64 st_ino, struct _stat64 *buf) { CAMLparam0 (); CAMLlocal1 (v); v = caml_alloc (12, 0); Store_field (v, 0, Val_int (buf->st_dev)); - Store_field (v, 1, Val_int (buf->st_ino)); + Store_field (v, 1, Val_int (st_ino ? st_ino & Max_long : buf->st_ino)); Store_field (v, 2, cst_to_constr (buf->st_mode & S_IFMT, file_kind_table, sizeof(file_kind_table) / sizeof(int), 0)); Store_field (v, 3, Val_int(buf->st_mode & 07777)); @@ -61,49 +71,292 @@ static value stat_aux(int use_64, struct _stati64 *buf) CAMLreturn (v); } +/* + * The long and ugly story of Microsoft CRT stat and symbolic links + * + * msvcrt.dll - which is now a core Windows component - is basically Visual + * Studio .NET 2003 CRT (Version 7). It is the version usually linked against by + * mingw64-gcc Its behaviour is as follows: + * a) st_mode is correctly populated + * b) st_atime, st_mtime and st_ctime are those for the symbolic link, not the + * target + * c) stat incorrectly returns information even if the target doesn't exist + * + * The next CRT of interest is Visual Studio 2008 (Version 9 - msvcr900.dll), as + * that's included with the Windows 7 SDK. This worked until 2011 when Microsoft + * produced security advisory KB2467174 (see https://bugs.python.org/issue6727) + * at which point stat returns ENOENT for symbolic links. + * + * This persists until Visual Studio 2010, when a hotfix + * (https://support.microsoft.com/en-gb/kb/2890375) was produced which was + * supposed to fix this behaviour. This CRT has one problem: it returns S_REG + * instead of S_DIR for directory symbolic links because of a subtle error in + * its implementation (it calls fstat which quite reasonably always assumes its + * looking at a regular file). + * + * The bug persists in Visual Studio 2012. Visual Studio 2015 features the + * "great refactored" CRT (written in C++!). This CRT correctly returns st_mode + * for directory symbolic links. Its two limitations are that it doesn't return + * the st_size correctly for symbolic links and it doesn't populate st_nlink + * correctly. + * + * However, even if fixed, mingw64 is limited to msvcrt.dll (by default, anyway) + * and that's a lot of buggy CRTs out there. + * + * There is also no implementation given for lstat in any CRT. + * + * do_stat therefore reimplements stat - but the algorithms for populating the + * resulting _stat64 are identical to Microsoft's (with the exception of correct + * handling of st_nlink for symbolic links), being based upon the code for the + * Microsoft CRT given in Microsoft Visual Studio 2013 Express + */ + +static int convert_time(FILETIME* time, __time64_t* result, __time64_t def) +{ + SYSTEMTIME sys; + FILETIME local; + + 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); + } + } + else { + *result = def; + } + + return 1; +} + +static int do_stat(int do_lstat, int use_64, char* path, mlsize_t l, HANDLE fstat, __int64* st_ino, struct _stat64* res) +{ + BY_HANDLE_FILE_INFORMATION info; + int i; + char* ptr; + char c; + HANDLE h; + unsigned short mode; + int is_symlink = 0; + + if (!path) { + h = fstat; + } + else { + caml_enter_blocking_section(); + h = CreateFile(path, + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, + NULL); + caml_leave_blocking_section(); + } + if (h == INVALID_HANDLE_VALUE) { + errno = ENOENT; + return 0; + } + else { + caml_enter_blocking_section(); + if (!GetFileInformationByHandle(h, &info)) { + win32_maperr(GetLastError()); + caml_leave_blocking_section(); + if (path) CloseHandle(h); + return 0; + } + caml_leave_blocking_section(); + + /* + * It shouldn't be possible to call this via fstat and have a reparse point + * open, but the test on path guarantees this. + */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && path) { + /* + * Only symbolic links should be processed specially. The call to + * DeviceIoControl solves two problems at the same time: + * a) Although FindFirstFileEx gives the reparse tag in dwReserved0, + * GetFileInformationByHandle does not and using the Ex version (or + * GetFileAttributesEx) makes Windows XP support harder + * b) Windows returns 0 for the size of a symbolic link - reading the + * reparse point allows a POSIX-compatible value to be returned in + * st_size + */ + char buffer[16384]; + DWORD read; + REPARSE_DATA_BUFFER* point; + + caml_enter_blocking_section(); + if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, 16384, &read, NULL)) { + if (((REPARSE_DATA_BUFFER*)buffer)->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + is_symlink = do_lstat; + res->st_size = ((REPARSE_DATA_BUFFER*)buffer)->SymbolicLinkReparseBuffer.SubstituteNameLength / 2; + } + } + caml_leave_blocking_section(); + + if (!is_symlink) { + CloseHandle(h); + caml_enter_blocking_section(); + if ((h = CreateFile(path, + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL)) == INVALID_HANDLE_VALUE) { + errno = ENOENT; + caml_leave_blocking_section(); + return 0; + } + else { + if (!GetFileInformationByHandle(h, &info)) { + win32_maperr(GetLastError()); + caml_leave_blocking_section(); + CloseHandle(h); + return 0; + } + caml_leave_blocking_section(); + } + } + } + + if (path) CloseHandle(h); + + if (!is_symlink) { + /* + * The size returned seems to vary depending on whether it's a directory + * (in which case it's 0) or a symbolic link (in which case it looks like + * allocated sector size). + * Neither is interesting, so return 0. + */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + res->st_size = 0; + } + else { + res->st_size = ((__int64)(info.nFileSizeHigh)) << 32 | + ((__int64)info.nFileSizeLow); + } + } + + if (!use_64 && res->st_size > Max_long) { + win32_maperr(ERROR_ARITHMETIC_OVERFLOW); + return 0; + } + + if (!convert_time(&info.ftLastWriteTime, &res->st_mtime, 0) || + !convert_time(&info.ftLastAccessTime, &res->st_atime, res->st_mtime) || + !convert_time(&info.ftCreationTime, &res->st_ctime, res->st_mtime)) { + win32_maperr(GetLastError()); + return 0; + } + + /* + * Note MS CRT (still) puts st_nlink = 1 and gives st_ino = 0 + */ + res->st_nlink = info.nNumberOfLinks; + res->st_dev = info.dwVolumeSerialNumber; + *st_ino = ((__int64)(info.nFileIndexHigh)) << 32 | ((__int64)info.nFileIndexLow); + } + + if (do_lstat && is_symlink) { + mode = S_IFLNK | S_IEXEC | S_IWRITE; + } + else { + mode = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? _S_IFDIR | _S_IEXEC : _S_IFREG); + } + mode |= (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? _S_IREAD : _S_IREAD | _S_IWRITE); + /* + * The simulation of the execute bit is ignored for fstat. It could be + * emulated using GetFinalPathNameByHandle, but the pre-Vista emulation is a + * bit too much effort for a simulated value, so it's simply ignored! + */ + if (path && (ptr = strrchr(path, '.')) && (!_stricmp(ptr, ".exe") || + !_stricmp(ptr, ".cmd") || + !_stricmp(ptr, ".bat") || + !_stricmp(ptr, ".com"))) { + mode |= _S_IEXEC; + } + mode |= (mode & 0700) >> 3; + mode |= (mode & 0700) >> 6; + res->st_mode = mode; + res->st_uid = res->st_gid = res->st_ino = 0; + res->st_rdev = res->st_dev; + + return 1; +} + CAMLprim value unix_stat(value path) { - int ret; - struct _stati64 buf; + struct _stat64 buf; + __int64 st_ino; - ret = _stati64(String_val(path), &buf); - if (ret == -1) uerror("stat", path); - if (buf.st_size > Max_long) { - win32_maperr(ERROR_ARITHMETIC_OVERFLOW); + caml_unix_check_path(path, "stat"); + if (!do_stat(0, 0, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) { uerror("stat", path); } - return stat_aux(0, &buf); + return stat_aux(0, st_ino, &buf); } CAMLprim value unix_stat_64(value path) { - int ret; - struct _stati64 buf; - ret = _stati64(String_val(path), &buf); - if (ret == -1) uerror("stat", path); - return stat_aux(1, &buf); + struct _stat64 buf; + __int64 st_ino; + + caml_unix_check_path(path, "stat"); + if (!do_stat(0, 1, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) { + uerror("stat", path); + } + return stat_aux(1, st_ino, &buf); +} + +CAMLprim value unix_lstat(value path) +{ + struct _stat64 buf; + __int64 st_ino; + if (!do_stat(1, 0, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) { + uerror("lstat", path); + } + return stat_aux(0, st_ino, &buf); +} + +CAMLprim value unix_lstat_64(value path) +{ + struct _stat64 buf; + __int64 st_ino; + if (!do_stat(1, 1, String_val(path), caml_string_length(path), NULL, &st_ino, &buf)) { + uerror("lstat", path); + } + return stat_aux(1, st_ino, &buf); } CAMLprim value unix_fstat(value handle) { int ret; - struct _stati64 buf; - - ret = _fstati64(win_CRT_fd_of_filedescr(handle), &buf); - if (ret == -1) uerror("fstat", Nothing); - if (buf.st_size > Max_long) { - win32_maperr(ERROR_ARITHMETIC_OVERFLOW); + struct _stat64 buf; + __int64 st_ino; + if (!do_stat(0, 0, NULL, 0, Handle_val(handle), &st_ino, &buf)) { uerror("fstat", Nothing); } - return stat_aux(0, &buf); + return stat_aux(0, st_ino, &buf); } CAMLprim value unix_fstat_64(value handle) { int ret; - struct _stati64 buf; - - ret = _fstati64(win_CRT_fd_of_filedescr(handle), &buf); - if (ret == -1) uerror("fstat", Nothing); - return stat_aux(1, &buf); + struct _stat64 buf; + __int64 st_ino; + if (!do_stat(0, 1, NULL, 0, Handle_val(handle), &st_ino, &buf)) { + uerror("fstat", Nothing); + } + return stat_aux(1, st_ino, &buf); } diff --git a/otherlibs/win32unix/symlink.c b/otherlibs/win32unix/symlink.c new file mode 100644 index 00000000..ec1c4a03 --- /dev/null +++ b/otherlibs/win32unix/symlink.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* David Allsopp, MetaStack Solutions Ltd. */ +/* */ +/* Copyright 2015 MetaStack Solutions Ltd. */ +/* */ +/* 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. */ +/* */ +/**************************************************************************/ + +/* + * Windows Vista functions enabled + */ +#define _WIN32_WINNT 0x0600 + +#include +#include +#include +#include +#include +#include "unixsupport.h" + +typedef BOOLEAN (WINAPI *LPFN_CREATESYMBOLICLINK) (LPTSTR, LPTSTR, DWORD); + +static LPFN_CREATESYMBOLICLINK pCreateSymbolicLink = NULL; +static int no_symlink = 0; + +CAMLprim value unix_symlink(value to_dir, value source, value dest) +{ + CAMLparam3(to_dir, source, dest); + DWORD flags = (Bool_val(to_dir) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0); + BOOLEAN result; + +again: + if (no_symlink) { + invalid_argument("symlink not available"); + } + + if (!pCreateSymbolicLink) { + pCreateSymbolicLink = (LPFN_CREATESYMBOLICLINK)GetProcAddress(GetModuleHandle("kernel32"), "CreateSymbolicLinkA"); + no_symlink = !pCreateSymbolicLink; + goto again; + } + + caml_enter_blocking_section(); + result = pCreateSymbolicLink(String_val(dest), String_val(source), flags); + caml_leave_blocking_section(); + + if (!result) { + win32_maperr(GetLastError()); + uerror("symlink", dest); + } + + CAMLreturn(Val_unit); +} + +#define luid_eq(l, r) (l.LowPart == r.LowPart && l.HighPart == r.HighPart) + +CAMLprim value unix_has_symlink(value unit) +{ + CAMLparam1(unit); + HANDLE hProcess = GetCurrentProcess(); + BOOL result = FALSE; + + if (OpenProcessToken(hProcess, TOKEN_READ, &hProcess)) { + LUID seCreateSymbolicLinkPrivilege; + + if (LookupPrivilegeValue(NULL, + SE_CREATE_SYMBOLIC_LINK_NAME, + &seCreateSymbolicLinkPrivilege)) { + DWORD length; + + if (!GetTokenInformation(hProcess, TokenPrivileges, NULL, 0, &length)) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + TOKEN_PRIVILEGES* privileges = (TOKEN_PRIVILEGES*)malloc(length); + if (GetTokenInformation(hProcess, + TokenPrivileges, + privileges, + length, + &length)) { + DWORD count = privileges->PrivilegeCount; + + if (count) { + LUID_AND_ATTRIBUTES* privs = privileges->Privileges; + while (count-- && !(result = luid_eq(privs->Luid, seCreateSymbolicLinkPrivilege))) + privs++; + } + } + + free(privileges); + } + } + } + + CloseHandle(hProcess); + } + + CAMLreturn(Val_bool(result)); +} diff --git a/otherlibs/win32unix/system.c b/otherlibs/win32unix/system.c index 202dcd08..aff4033f 100644 --- a/otherlibs/win32unix/system.c +++ b/otherlibs/win32unix/system.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -27,6 +29,7 @@ CAMLprim value win_system(cmd) char *buf; intnat len; + caml_unix_check_path(cmd, "system"); len = caml_string_length (cmd); buf = caml_stat_alloc (len + 1); memmove (buf, String_val (cmd), len + 1); diff --git a/otherlibs/win32unix/times.c b/otherlibs/win32unix/times.c index e97d3a5c..00f3bae9 100644 --- a/otherlibs/win32unix/times.c +++ b/otherlibs/win32unix/times.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* File contributed by Josh Berdine */ -/* */ -/* Copyright 2011 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* File contributed by Josh Berdine */ +/* */ +/* Copyright 2011 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 #include diff --git a/otherlibs/win32unix/unix.ml b/otherlibs/win32unix/unix.ml index b74f063e..d24bb679 100644 --- a/otherlibs/win32unix/unix.ml +++ b/otherlibs/win32unix/unix.ml @@ -1,15 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Initialization *) @@ -251,7 +253,7 @@ type stats = st_ctime : float } external stat : string -> stats = "unix_stat" -let lstat = stat +external lstat : string -> stats = "unix_lstat" external fstat : file_descr -> stats = "unix_fstat" let isatty fd = match (fstat fd).st_kind with S_CHR -> true | _ -> false @@ -287,7 +289,7 @@ module LargeFile = st_ctime : float; } external stat : string -> stats = "unix_stat_64" - let lstat = stat + external lstat : string -> stats = "unix_lstat_64" external fstat : file_descr -> stats = "unix_fstat_64" end @@ -373,8 +375,23 @@ let mkfifo name perm = invalid_arg "Unix.mkfifo not implemented" (* Symbolic links *) -let readlink path = invalid_arg "Unix.readlink not implemented" -let symlink path1 path2 = invalid_arg "Unix.symlink not implemented" +external readlink : string -> string = "unix_readlink" +external symlink_stub : bool -> string -> string -> unit = "unix_symlink" + +let symlink ?to_dir source dest = + let to_dir = + match to_dir with + Some to_dir -> + to_dir + | None -> + try + LargeFile.((stat source).st_kind = S_DIR) + with _ -> + false + in + symlink_stub to_dir source dest + +external has_symlink : unit -> bool = "unix_has_symlink" (* Locking *) @@ -429,7 +446,8 @@ external gmtime : float -> tm = "unix_gmtime" external localtime : float -> tm = "unix_localtime" external mktime : tm -> float * tm = "unix_mktime" let alarm n = invalid_arg "Unix.alarm not implemented" -external sleep : int -> unit = "unix_sleep" +external sleepf : float -> unit = "unix_sleep" +let sleep n = sleepf (float n) external times: unit -> process_times = "unix_times" external utimes : string -> float -> float -> unit = "unix_utimes" @@ -813,12 +831,18 @@ let make_cmdline args = else f in String.concat " " (List.map maybe_quote (Array.to_list args)) +let make_process_env env = + Array.iter + (fun s -> if String.contains s '\000' then raise(Unix_error(EINVAL, "", s))) + env; + String.concat "\000" (Array.to_list env) ^ "\000" + let create_process prog args fd1 fd2 fd3 = win_create_process prog (make_cmdline args) None fd1 fd2 fd3 let create_process_env prog args env fd1 fd2 fd3 = win_create_process prog (make_cmdline args) - (Some(String.concat "\000" (Array.to_list env) ^ "\000")) + (Some(make_process_env env)) fd1 fd2 fd3 external system: string -> process_status = "win_system" @@ -877,7 +901,7 @@ let open_process_full cmd env = 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(String.concat "\000" (Array.to_list env) ^ "\000")) + 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; diff --git a/otherlibs/win32unix/unixsupport.c b/otherlibs/win32unix/unixsupport.c index 5c606e0d..9fddba6c 100644 --- a/otherlibs/win32unix/unixsupport.c +++ b/otherlibs/win32unix/unixsupport.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -170,44 +172,80 @@ void win32_maperr(DWORD errcode) } /* Windows socket errors */ - +#undef EWOULDBLOCK #define EWOULDBLOCK -WSAEWOULDBLOCK +#undef EINPROGRESS #define EINPROGRESS -WSAEINPROGRESS +#undef EALREADY #define EALREADY -WSAEALREADY +#undef ENOTSOCK #define ENOTSOCK -WSAENOTSOCK +#undef EDESTADDRREQ #define EDESTADDRREQ -WSAEDESTADDRREQ +#undef EMSGSIZE #define EMSGSIZE -WSAEMSGSIZE +#undef EPROTOTYPE #define EPROTOTYPE -WSAEPROTOTYPE +#undef ENOPROTOOPT #define ENOPROTOOPT -WSAENOPROTOOPT +#undef EPROTONOSUPPORT #define EPROTONOSUPPORT -WSAEPROTONOSUPPORT +#undef ESOCKTNOSUPPORT #define ESOCKTNOSUPPORT -WSAESOCKTNOSUPPORT +#undef EOPNOTSUPP #define EOPNOTSUPP -WSAEOPNOTSUPP +#undef EPFNOSUPPORT #define EPFNOSUPPORT -WSAEPFNOSUPPORT +#undef EAFNOSUPPORT #define EAFNOSUPPORT -WSAEAFNOSUPPORT +#undef EADDRINUSE #define EADDRINUSE -WSAEADDRINUSE +#undef EADDRNOTAVAIL #define EADDRNOTAVAIL -WSAEADDRNOTAVAIL +#undef ENETDOWN #define ENETDOWN -WSAENETDOWN +#undef ENETUNREACH #define ENETUNREACH -WSAENETUNREACH +#undef ENETRESET #define ENETRESET -WSAENETRESET +#undef ECONNABORTED #define ECONNABORTED -WSAECONNABORTED +#undef ECONNRESET #define ECONNRESET -WSAECONNRESET +#undef ENOBUFS #define ENOBUFS -WSAENOBUFS +#undef EISCONN #define EISCONN -WSAEISCONN +#undef ENOTCONN #define ENOTCONN -WSAENOTCONN +#undef ESHUTDOWN #define ESHUTDOWN -WSAESHUTDOWN +#undef ETOOMANYREFS #define ETOOMANYREFS -WSAETOOMANYREFS +#undef ETIMEDOUT #define ETIMEDOUT -WSAETIMEDOUT +#undef ECONNREFUSED #define ECONNREFUSED -WSAECONNREFUSED +#undef ELOOP #define ELOOP -WSAELOOP +#undef EHOSTDOWN #define EHOSTDOWN -WSAEHOSTDOWN +#undef EHOSTUNREACH #define EHOSTUNREACH -WSAEHOSTUNREACH +#undef EPROCLIM #define EPROCLIM -WSAEPROCLIM +#undef EUSERS #define EUSERS -WSAEUSERS +#undef EDQUOT #define EDQUOT -WSAEDQUOT +#undef ESTALE #define ESTALE -WSAESTALE +#undef EREMOTE #define EREMOTE -WSAEREMOTE +#undef EOVERFLOW #define EOVERFLOW -ERROR_ARITHMETIC_OVERFLOW +#undef EACCESS #define EACCESS EACCES int error_table[] = { @@ -267,9 +305,12 @@ void unix_error(int errcode, char *cmdname, value cmdarg) mlraise(res); } -void uerror(cmdname, cmdarg) - char * cmdname; - value cmdarg; +void uerror(char * cmdname, value cmdarg) { unix_error(errno, cmdname, cmdarg); } + +void caml_unix_check_path(value path, char * cmdname) +{ + if (! caml_string_is_c_safe(path)) unix_error(ENOENT, cmdname, path); +} diff --git a/otherlibs/win32unix/unixsupport.h b/otherlibs/win32unix/unixsupport.h index b8efb278..3bfeb0c6 100644 --- a/otherlibs/win32unix/unixsupport.h +++ b/otherlibs/win32unix/unixsupport.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ #ifndef CAML_UNIXSUPPORT_H #define CAML_UNIXSUPPORT_H @@ -59,7 +61,9 @@ 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); +extern void caml_unix_check_path(value path, char * cmdname); extern value unix_freeze_buffer (value); +extern char ** cstringvect(value arg, char * cmdname); /* Information stored in flags_fd, describing more precisely the socket * and its status. The whole flags_fd is initialized to 0. @@ -74,4 +78,43 @@ extern value unix_freeze_buffer (value); } #endif +/* + * This structure is defined inconsistently. mingw64 has it in ntdef.h (which + * doesn't look like a primary header) and technically it's part of ntifs.h in + * the WDK. Requiring the WDK is a bit extreme, so the definition is taken from + * ntdef.h. Both ntdef.h and ntifs.h define REPARSE_DATA_BUFFER_HEADER_SIZE + */ +#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE +typedef struct _REPARSE_DATA_BUFFER +{ + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union + { + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct + { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + }; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; +#endif + #endif /* CAML_UNIXSUPPORT_H */ diff --git a/otherlibs/win32unix/windbug.c b/otherlibs/win32unix/windbug.c index a5e0d649..424dd920 100644 --- a/otherlibs/win32unix/windbug.c +++ b/otherlibs/win32unix/windbug.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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 "windbug.h" diff --git a/otherlibs/win32unix/windbug.h b/otherlibs/win32unix/windbug.h index eb7c94f1..8427ebfc 100644 --- a/otherlibs/win32unix/windbug.h +++ b/otherlibs/win32unix/windbug.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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. */ +/* */ +/**************************************************************************/ #ifdef DEBUG diff --git a/otherlibs/win32unix/windir.c b/otherlibs/win32unix/windir.c index ef952aa9..fcf68c1d 100644 --- a/otherlibs/win32unix/windir.c +++ b/otherlibs/win32unix/windir.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Pascal Cuoq and Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Pascal Cuoq and Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include @@ -18,8 +20,7 @@ #include #include "unixsupport.h" -CAMLprim value win_findfirst(name) - value name; +CAMLprim value win_findfirst(value name) { HANDLE h; value v; @@ -27,6 +28,7 @@ CAMLprim value win_findfirst(name) value valname = Val_unit; value valh = Val_unit; + caml_unix_check_path(name, "opendir"); Begin_roots2 (valname,valh); h = FindFirstFile(String_val(name),&fileinfo); if (h == INVALID_HANDLE_VALUE) { @@ -47,8 +49,7 @@ CAMLprim value win_findfirst(name) return v; } -CAMLprim value win_findnext(valh) - value valh; +CAMLprim value win_findnext(value valh) { WIN32_FIND_DATA fileinfo; BOOL retcode; @@ -66,8 +67,7 @@ CAMLprim value win_findnext(valh) return copy_string(fileinfo.cFileName); } -CAMLprim value win_findclose(valh) - value valh; +CAMLprim value win_findclose(value valh) { if (! FindClose(Handle_val(valh))) { win32_maperr(GetLastError()); diff --git a/otherlibs/win32unix/winlist.c b/otherlibs/win32unix/winlist.c index 3c80b334..c05dd11d 100644 --- a/otherlibs/win32unix/winlist.c +++ b/otherlibs/win32unix/winlist.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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. */ +/* */ +/**************************************************************************/ /* Basic list function in C. */ diff --git a/otherlibs/win32unix/winlist.h b/otherlibs/win32unix/winlist.h index 8b35c551..f5040060 100644 --- a/otherlibs/win32unix/winlist.h +++ b/otherlibs/win32unix/winlist.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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. */ +/* */ +/**************************************************************************/ #ifndef _WINLIST_H #define _WINLIST_H diff --git a/otherlibs/win32unix/winwait.c b/otherlibs/win32unix/winwait.c index 510a16fe..2be7a564 100644 --- a/otherlibs/win32unix/winwait.c +++ b/otherlibs/win32unix/winwait.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Pascal Cuoq and Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Pascal Cuoq and Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/otherlibs/win32unix/winworker.c b/otherlibs/win32unix/winworker.c index bcd5947a..dff729d6 100644 --- a/otherlibs/win32unix/winworker.c +++ b/otherlibs/win32unix/winworker.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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 #include diff --git a/otherlibs/win32unix/winworker.h b/otherlibs/win32unix/winworker.h index cb9bf4f8..fbe4af26 100644 --- a/otherlibs/win32unix/winworker.h +++ b/otherlibs/win32unix/winworker.h @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Contributed by Sylvain Le Gall for Lexifi */ -/* */ -/* Copyright 2008 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Contributed by Sylvain Le Gall for Lexifi */ +/* */ +/* Copyright 2008 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. */ +/* */ +/**************************************************************************/ #ifndef _WINWORKER_H #define _WINWORKER_H diff --git a/otherlibs/win32unix/write.c b/otherlibs/win32unix/write.c index dc0ae91b..866eb06a 100644 --- a/otherlibs/win32unix/write.c +++ b/otherlibs/win32unix/write.c @@ -1,15 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. All rights reserved. This file is distributed */ -/* under the terms of the GNU Library General Public License, with */ -/* the special exception on linking described in file ../../LICENSE. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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 #include diff --git a/parsing/.ignore b/parsing/.ignore deleted file mode 100644 index 5602bf8a..00000000 --- a/parsing/.ignore +++ /dev/null @@ -1,9 +0,0 @@ -parser.ml -parser.mli -lexer.ml -lexer_tmp.mll -lexer_tmp.ml -linenum.ml -parser.output -parser.automaton -parser.conflicts diff --git a/parsing/ast_helper.ml b/parsing/ast_helper.ml index b84cda8c..e3bf483d 100644 --- a/parsing/ast_helper.ml +++ b/parsing/ast_helper.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Alain Frisch, LexiFi *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Alain Frisch, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) (** Helpers to produce Parsetree fragments *) @@ -29,6 +32,17 @@ let with_default_loc l f = try let r = f () in default_loc := old; r with exn -> default_loc := old; raise exn +module Const = struct + let integer ?suffix i = Pconst_integer (i, suffix) + let int ?suffix i = integer ?suffix (string_of_int i) + let int32 ?(suffix='l') i = integer ~suffix (Int32.to_string i) + let int64 ?(suffix='L') i = integer ~suffix (Int64.to_string i) + let nativeint ?(suffix='n') i = integer ~suffix (Nativeint.to_string i) + let float ?suffix f = Pconst_float (f, suffix) + let char c = Pconst_char c + let string ?quotation_delimiter s = Pconst_string (s, quotation_delimiter) +end + module Typ = struct let mk ?(loc = !default_loc) ?(attrs = []) d = {ptyp_desc = d; ptyp_loc = loc; ptyp_attributes = attrs} @@ -116,6 +130,7 @@ module Exp = struct let pack ?loc ?attrs a = mk ?loc ?attrs (Pexp_pack a) let open_ ?loc ?attrs a b c = mk ?loc ?attrs (Pexp_open (a, b, c)) let extension ?loc ?attrs a = mk ?loc ?attrs (Pexp_extension a) + let unreachable ?loc ?attrs () = mk ?loc ?attrs Pexp_unreachable let case lhs ?guard rhs = { @@ -158,7 +173,7 @@ module Sig = struct let mk ?(loc = !default_loc) d = {psig_desc = d; psig_loc = loc} let value ?loc a = mk ?loc (Psig_value a) - let type_ ?loc a = mk ?loc (Psig_type a) + let type_ ?loc rec_flag a = mk ?loc (Psig_type (rec_flag, a)) let type_extension ?loc a = mk ?loc (Psig_typext a) let exception_ ?loc a = mk ?loc (Psig_exception a) let module_ ?loc a = mk ?loc (Psig_module a) @@ -182,7 +197,7 @@ module Str = struct let eval ?loc ?(attrs = []) a = mk ?loc (Pstr_eval (a, attrs)) let value ?loc a b = mk ?loc (Pstr_value (a, b)) let primitive ?loc a = mk ?loc (Pstr_primitive a) - let type_ ?loc a = mk ?loc (Pstr_type a) + let type_ ?loc rec_flag a = mk ?loc (Pstr_type (rec_flag, a)) let type_extension ?loc a = mk ?loc (Pstr_typext a) let exception_ ?loc a = mk ?loc (Pstr_exception a) let module_ ?loc a = mk ?loc (Pstr_module a) @@ -403,7 +418,7 @@ module Type = struct } let constructor ?(loc = !default_loc) ?(attrs = []) ?(info = empty_info) - ?(args = []) ?res name = + ?(args = Pcstr_tuple []) ?res name = { pcd_name = name; pcd_args = args; @@ -445,8 +460,8 @@ module Te = struct pext_attributes = add_docs_attrs docs (add_info_attrs info attrs); } - let decl ?(loc = !default_loc) ?(attrs = []) - ?(docs = empty_docs) ?(info = empty_info) ?(args = []) ?res name = + let decl ?(loc = !default_loc) ?(attrs = []) ?(docs = empty_docs) + ?(info = empty_info) ?(args = Pcstr_tuple []) ?res name = { pext_name = name; pext_kind = Pext_decl(args, res); @@ -480,4 +495,3 @@ module Cstr = struct pcstr_fields = fields; } end - diff --git a/parsing/ast_helper.mli b/parsing/ast_helper.mli index 4dc96169..6a527feb 100644 --- a/parsing/ast_helper.mli +++ b/parsing/ast_helper.mli @@ -1,20 +1,23 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Alain Frisch, LexiFi *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Alain Frisch, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) (** Helpers to produce Parsetree fragments *) -open Parsetree open Asttypes open Docstrings +open Parsetree type lid = Longident.t loc type str = string loc @@ -30,6 +33,19 @@ val with_default_loc: loc -> (unit -> 'a) -> 'a (** Set the [default_loc] within the scope of the execution of the provided function. *) +(** {2 Constants} *) + +module Const : sig + val char : char -> constant + val string : ?quotation_delimiter:string -> string -> constant + val integer : ?suffix:char -> string -> constant + val int : ?suffix:char -> int -> constant + val int32 : ?suffix:char -> int32 -> constant + val int64 : ?suffix:char -> int64 -> constant + val nativeint : ?suffix:char -> nativeint -> constant + val float : ?suffix:char -> string -> constant +end + (** {2 Core language} *) (** Type expressions *) @@ -40,7 +56,7 @@ module Typ : val any: ?loc:loc -> ?attrs:attrs -> unit -> core_type val var: ?loc:loc -> ?attrs:attrs -> string -> core_type - val arrow: ?loc:loc -> ?attrs:attrs -> label -> core_type -> core_type + val arrow: ?loc:loc -> ?attrs:attrs -> arg_label -> core_type -> core_type -> core_type val tuple: ?loc:loc -> ?attrs:attrs -> core_type list -> core_type val constr: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type @@ -95,11 +111,11 @@ module Exp: val constant: ?loc:loc -> ?attrs:attrs -> constant -> expression val let_: ?loc:loc -> ?attrs:attrs -> rec_flag -> value_binding list -> expression -> expression - val fun_: ?loc:loc -> ?attrs:attrs -> label -> expression option -> pattern - -> expression -> expression + val fun_: ?loc:loc -> ?attrs:attrs -> arg_label -> expression option + -> pattern -> expression -> expression val function_: ?loc:loc -> ?attrs:attrs -> case list -> expression val apply: ?loc:loc -> ?attrs:attrs -> expression - -> (label * expression) list -> expression + -> (arg_label * expression) list -> expression val match_: ?loc:loc -> ?attrs:attrs -> expression -> case list -> expression val try_: ?loc:loc -> ?attrs:attrs -> expression -> case list -> expression @@ -135,12 +151,15 @@ module Exp: -> expression val assert_: ?loc:loc -> ?attrs:attrs -> expression -> expression val lazy_: ?loc:loc -> ?attrs:attrs -> expression -> expression - val poly: ?loc:loc -> ?attrs:attrs -> expression -> core_type option -> expression + 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 pack: ?loc:loc -> ?attrs:attrs -> module_expr -> expression - val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> expression -> expression + val open_: ?loc:loc -> ?attrs:attrs -> override_flag -> lid -> expression + -> expression val extension: ?loc:loc -> ?attrs:attrs -> extension -> expression + val unreachable: ?loc:loc -> ?attrs:attrs -> unit -> expression val case: pattern -> ?guard:expression -> expression -> case end @@ -156,12 +175,14 @@ module Val: module Type: sig val mk: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?text:text -> - ?params:(core_type * variance) list -> ?cstrs:(core_type * core_type * loc) list -> + ?params:(core_type * variance) list -> + ?cstrs:(core_type * core_type * loc) list -> ?kind:type_kind -> ?priv:private_flag -> ?manifest:core_type -> str -> type_declaration val constructor: ?loc:loc -> ?attrs:attrs -> ?info:info -> - ?args:core_type list -> ?res:core_type -> str -> constructor_declaration + ?args:constructor_arguments -> ?res:core_type -> str -> + constructor_declaration val field: ?loc:loc -> ?attrs:attrs -> ?info:info -> ?mut:mutable_flag -> str -> core_type -> label_declaration end @@ -177,7 +198,8 @@ module Te: str -> extension_constructor_kind -> extension_constructor val decl: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?info:info -> - ?args:core_type list -> ?res:core_type -> str -> extension_constructor + ?args:constructor_arguments -> ?res:core_type -> str -> + extension_constructor val rebind: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?info:info -> str -> lid -> extension_constructor end @@ -195,7 +217,8 @@ module Mty: val signature: ?loc:loc -> ?attrs:attrs -> signature -> module_type val functor_: ?loc:loc -> ?attrs:attrs -> str -> module_type option -> module_type -> module_type - val with_: ?loc:loc -> ?attrs:attrs -> module_type -> with_constraint list -> module_type + val with_: ?loc:loc -> ?attrs:attrs -> module_type -> + with_constraint list -> module_type val typeof_: ?loc:loc -> ?attrs:attrs -> module_expr -> module_type val extension: ?loc:loc -> ?attrs:attrs -> extension -> module_type end @@ -210,8 +233,10 @@ module Mod: val structure: ?loc:loc -> ?attrs:attrs -> structure -> module_expr val functor_: ?loc:loc -> ?attrs:attrs -> str -> module_type option -> module_expr -> module_expr - val apply: ?loc:loc -> ?attrs:attrs -> module_expr -> module_expr -> module_expr - val constraint_: ?loc:loc -> ?attrs:attrs -> module_expr -> module_type -> module_expr + val apply: ?loc:loc -> ?attrs:attrs -> module_expr -> module_expr -> + module_expr + val constraint_: ?loc:loc -> ?attrs:attrs -> module_expr -> module_type -> + module_expr val unpack: ?loc:loc -> ?attrs:attrs -> expression -> module_expr val extension: ?loc:loc -> ?attrs:attrs -> extension -> module_expr end @@ -222,7 +247,7 @@ module Sig: val mk: ?loc:loc -> signature_item_desc -> signature_item val value: ?loc:loc -> value_description -> signature_item - val type_: ?loc:loc -> type_declaration list -> signature_item + val type_: ?loc:loc -> rec_flag -> type_declaration list -> signature_item val type_extension: ?loc:loc -> type_extension -> signature_item val exception_: ?loc:loc -> extension_constructor -> signature_item val module_: ?loc:loc -> module_declaration -> signature_item @@ -245,7 +270,7 @@ module Str: val eval: ?loc:loc -> ?attrs:attributes -> expression -> structure_item val value: ?loc:loc -> rec_flag -> value_binding list -> structure_item val primitive: ?loc:loc -> value_description -> structure_item - val type_: ?loc:loc -> type_declaration list -> structure_item + val type_: ?loc:loc -> rec_flag -> type_declaration list -> structure_item val type_extension: ?loc:loc -> type_extension -> structure_item val exception_: ?loc:loc -> extension_constructor -> structure_item val module_: ?loc:loc -> module_binding -> structure_item @@ -313,7 +338,8 @@ module Cty: val constr: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> class_type val signature: ?loc:loc -> ?attrs:attrs -> class_signature -> class_type - val arrow: ?loc:loc -> ?attrs:attrs -> label -> core_type -> class_type -> class_type + val arrow: ?loc:loc -> ?attrs:attrs -> arg_label -> core_type -> + class_type -> class_type val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_type end @@ -325,9 +351,12 @@ 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 -> virtual_flag -> core_type -> class_type_field - val method_: ?loc:loc -> ?attrs:attrs -> string -> private_flag -> virtual_flag -> core_type -> class_type_field - val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> class_type_field + val val_: ?loc:loc -> ?attrs:attrs -> string -> mutable_flag -> + virtual_flag -> core_type -> class_type_field + val method_: ?loc:loc -> ?attrs:attrs -> string -> private_flag -> + virtual_flag -> core_type -> class_type_field + val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> + class_type_field val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_type_field val attribute: ?loc:loc -> attribute -> class_type_field val text: text -> class_type_field list @@ -341,23 +370,32 @@ module Cl: val constr: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> class_expr val structure: ?loc:loc -> ?attrs:attrs -> class_structure -> class_expr - val fun_: ?loc:loc -> ?attrs:attrs -> label -> expression option -> pattern -> class_expr -> class_expr - val apply: ?loc:loc -> ?attrs:attrs -> class_expr -> (label * expression) list -> class_expr - val let_: ?loc:loc -> ?attrs:attrs -> rec_flag -> value_binding list -> class_expr -> class_expr - val constraint_: ?loc:loc -> ?attrs:attrs -> class_expr -> class_type -> class_expr + val fun_: ?loc:loc -> ?attrs:attrs -> arg_label -> expression option -> + pattern -> class_expr -> class_expr + val apply: ?loc:loc -> ?attrs:attrs -> class_expr -> + (arg_label * expression) list -> class_expr + val let_: ?loc:loc -> ?attrs:attrs -> rec_flag -> value_binding list -> + class_expr -> class_expr + val constraint_: ?loc:loc -> ?attrs:attrs -> class_expr -> class_type -> + class_expr val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_expr end (** Class fields *) module Cf: sig - val mk: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> class_field_desc -> class_field + val mk: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> class_field_desc -> + class_field val attr: class_field -> attribute -> class_field - val inherit_: ?loc:loc -> ?attrs:attrs -> override_flag -> class_expr -> string 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 -> class_field_kind -> class_field - val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> class_field + val inherit_: ?loc:loc -> ?attrs:attrs -> override_flag -> class_expr -> + string 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 -> + class_field_kind -> class_field + val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> + class_field val initializer_: ?loc:loc -> ?attrs:attrs -> expression -> class_field val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_field val attribute: ?loc:loc -> attribute -> class_field diff --git a/parsing/ast_invariants.ml b/parsing/ast_invariants.ml new file mode 100644 index 00000000..31ee17eb --- /dev/null +++ b/parsing/ast_invariants.ml @@ -0,0 +1,166 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +open Asttypes +open Parsetree +open Ast_iterator + +let err = Syntaxerr.ill_formed_ast + +let empty_record loc = err loc "Records cannot be empty." +let empty_variant loc = err loc "Variant types cannot be empty." +let invalid_tuple loc = err loc "Tuples must have at least 2 components." +let no_args loc = err loc "Function application with no argument." +let empty_let loc = err loc "Let with no bindings." +let empty_type loc = err loc "Type declarations cannot be empty." +let complex_id loc = err loc "Functor application not allowed here." + +let simple_longident id = + let rec is_simple = function + | Longident.Lident _ -> true + | Longident.Ldot (id, _) -> is_simple id + | Longident.Lapply _ -> false + in + if not (is_simple id.txt) then complex_id id.loc + +let iterator = + let super = Ast_iterator.default_iterator in + let type_declaration self td = + super.type_declaration self td; + let loc = td.ptype_loc in + match td.ptype_kind with + | Ptype_record [] -> empty_record loc + | Ptype_variant [] -> empty_variant loc + | _ -> () + in + let typ self ty = + super.typ self ty; + let loc = ty.ptyp_loc in + match ty.ptyp_desc with + | Ptyp_tuple ([] | [_]) -> invalid_tuple loc + | Ptyp_class (id, _) -> simple_longident id + | Ptyp_package (_, cstrs) -> + List.iter (fun (id, _) -> simple_longident id) cstrs + | _ -> () + in + let pat self pat = + begin match pat.ppat_desc with + | Ppat_construct (_, Some ({ppat_desc = Ppat_tuple _} as p)) + when Builtin_attributes.explicit_arity pat.ppat_attributes -> + super.pat self p (* allow unary tuple, see GPR#523. *) + | _ -> + super.pat self pat + end; + let loc = pat.ppat_loc in + match pat.ppat_desc with + | Ppat_tuple ([] | [_]) -> invalid_tuple loc + | Ppat_record ([], _) -> empty_record loc + | Ppat_construct (id, _) -> simple_longident id + | Ppat_record (fields, _) -> + List.iter (fun (id, _) -> simple_longident id) fields + | _ -> () + in + let expr self exp = + begin match exp.pexp_desc with + | Pexp_construct (_, Some ({pexp_desc = Pexp_tuple _} as e)) + when Builtin_attributes.explicit_arity exp.pexp_attributes -> + super.expr self e (* allow unary tuple, see GPR#523. *) + | _ -> + super.expr self exp + end; + let loc = exp.pexp_loc in + match exp.pexp_desc with + | Pexp_tuple ([] | [_]) -> invalid_tuple loc + | Pexp_record ([], _) -> empty_record loc + | Pexp_apply (_, []) -> no_args loc + | Pexp_let (_, [], _) -> empty_let loc + | Pexp_ident id + | Pexp_construct (id, _) + | Pexp_field (_, id) + | Pexp_setfield (_, id, _) + | Pexp_new id + | Pexp_open (_, id, _) -> simple_longident id + | Pexp_record (fields, _) -> + List.iter (fun (id, _) -> simple_longident id) fields + | _ -> () + in + let extension_constructor self ec = + super.extension_constructor self ec; + match ec.pext_kind with + | Pext_rebind id -> simple_longident id + | _ -> () + in + let class_expr self ce = + super.class_expr self ce; + let loc = ce.pcl_loc in + match ce.pcl_desc with + | Pcl_apply (_, []) -> no_args loc + | Pcl_constr (id, _) -> simple_longident id + | _ -> () + in + let module_type self mty = + super.module_type self mty; + match mty.pmty_desc with + | Pmty_alias id -> simple_longident id + | _ -> () + in + let open_description self opn = + super.open_description self opn; + simple_longident opn.popen_lid + in + let with_constraint self wc = + super.with_constraint self wc; + match wc with + | Pwith_type (id, _) + | Pwith_module (id, _) -> simple_longident id + | _ -> () + in + let module_expr self me = + super.module_expr self me; + match me.pmod_desc with + | Pmod_ident id -> simple_longident id + | _ -> () + in + let structure_item self st = + super.structure_item self st; + let loc = st.pstr_loc in + match st.pstr_desc with + | Pstr_type (_, []) -> empty_type loc + | Pstr_value (_, []) -> empty_let loc + | _ -> () + in + let signature_item self sg = + super.signature_item self sg; + let loc = sg.psig_loc in + match sg.psig_desc with + | Psig_type (_, []) -> empty_type loc + | _ -> () + in + { super with + type_declaration + ; typ + ; pat + ; expr + ; extension_constructor + ; class_expr + ; module_expr + ; module_type + ; open_description + ; with_constraint + ; structure_item + ; signature_item + } + +let structure st = iterator.structure iterator st +let signature sg = iterator.signature iterator sg diff --git a/parsing/ast_invariants.mli b/parsing/ast_invariants.mli new file mode 100644 index 00000000..51d3f9de --- /dev/null +++ b/parsing/ast_invariants.mli @@ -0,0 +1,18 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +(** Check AST invariants *) + +val structure : Parsetree.structure -> unit +val signature : Parsetree.signature -> unit diff --git a/parsing/ast_iterator.ml b/parsing/ast_iterator.ml new file mode 100755 index 00000000..2f8798a5 --- /dev/null +++ b/parsing/ast_iterator.ml @@ -0,0 +1,591 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Nicolas Ojeda Bar, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) + +(* A generic Parsetree mapping class *) + +(* +[@@@ocaml.warning "+9"] + (* Ensure that record patterns don't miss any field. *) +*) + + +open Parsetree +open Location + +type iterator = { + attribute: iterator -> attribute -> unit; + attributes: iterator -> attribute list -> unit; + case: iterator -> case -> unit; + cases: iterator -> case list -> unit; + class_declaration: iterator -> class_declaration -> unit; + class_description: iterator -> class_description -> unit; + class_expr: iterator -> class_expr -> unit; + class_field: iterator -> class_field -> unit; + class_signature: iterator -> class_signature -> unit; + class_structure: iterator -> class_structure -> unit; + class_type: iterator -> class_type -> unit; + class_type_declaration: iterator -> class_type_declaration -> unit; + class_type_field: iterator -> class_type_field -> unit; + constructor_declaration: iterator -> constructor_declaration -> unit; + expr: iterator -> expression -> unit; + extension: iterator -> extension -> unit; + extension_constructor: iterator -> extension_constructor -> unit; + include_declaration: iterator -> include_declaration -> unit; + include_description: iterator -> include_description -> unit; + label_declaration: iterator -> label_declaration -> unit; + location: iterator -> Location.t -> unit; + module_binding: iterator -> module_binding -> unit; + module_declaration: iterator -> module_declaration -> unit; + module_expr: iterator -> module_expr -> unit; + module_type: iterator -> module_type -> unit; + module_type_declaration: iterator -> module_type_declaration -> unit; + open_description: iterator -> open_description -> unit; + pat: iterator -> pattern -> unit; + payload: iterator -> payload -> unit; + signature: iterator -> signature -> unit; + signature_item: iterator -> signature_item -> unit; + structure: iterator -> structure -> unit; + structure_item: iterator -> structure_item -> unit; + typ: iterator -> core_type -> unit; + type_declaration: iterator -> type_declaration -> unit; + type_extension: iterator -> type_extension -> unit; + type_kind: iterator -> type_kind -> unit; + value_binding: iterator -> value_binding -> unit; + value_description: iterator -> value_description -> unit; + with_constraint: iterator -> with_constraint -> unit; +} +(** A [iterator] record implements one "method" per syntactic category, + using an open recursion style: each method takes as its first + argument the iterator to be applied to children in the syntax + tree. *) + +let iter_fst f (x, _) = f x +let iter_snd f (_, y) = f y +let iter_tuple f1 f2 (x, y) = f1 x; f2 y +let iter_tuple3 f1 f2 f3 (x, y, z) = f1 x; f2 y; f3 z +let iter_opt f = function None -> () | Some x -> f x + +let iter_loc sub {loc; txt = _} = sub.location sub loc + +module T = struct + (* Type expressions for the core language *) + + let row_field sub = function + | Rtag (_, attrs, _, tl) -> + sub.attributes sub attrs; List.iter (sub.typ sub) tl + | Rinherit t -> sub.typ sub t + + let iter sub {ptyp_desc = desc; ptyp_loc = loc; ptyp_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Ptyp_any + | Ptyp_var _ -> () + | Ptyp_arrow (_lab, t1, t2) -> + sub.typ sub t1; sub.typ sub t2 + | Ptyp_tuple tyl -> List.iter (sub.typ sub) tyl + | Ptyp_constr (lid, tl) -> + iter_loc sub lid; List.iter (sub.typ sub) tl + | Ptyp_object (l, o) -> + let f (_, a, t) = sub.attributes sub a; sub.typ sub t in + List.iter f l + | Ptyp_class (lid, tl) -> + iter_loc sub lid; List.iter (sub.typ sub) tl + | Ptyp_alias (t, _) -> sub.typ sub t + | Ptyp_variant (rl, b, ll) -> + List.iter (row_field sub) rl + | Ptyp_poly (_, t) -> sub.typ sub t + | Ptyp_package (lid, l) -> + iter_loc sub lid; + List.iter (iter_tuple (iter_loc sub) (sub.typ sub)) l + | Ptyp_extension x -> sub.extension sub x + + let iter_type_declaration sub + {ptype_name; ptype_params; ptype_cstrs; + ptype_kind; + ptype_private; + ptype_manifest; + ptype_attributes; + ptype_loc} = + iter_loc sub ptype_name; + List.iter (iter_fst (sub.typ sub)) ptype_params; + List.iter + (iter_tuple3 (sub.typ sub) (sub.typ sub) (sub.location sub)) + ptype_cstrs; + sub.type_kind sub ptype_kind; + iter_opt (sub.typ sub) ptype_manifest; + sub.location sub ptype_loc; + sub.attributes sub ptype_attributes + + let iter_type_kind sub = function + | Ptype_abstract -> () + | Ptype_variant l -> + List.iter (sub.constructor_declaration sub) l + | Ptype_record l -> List.iter (sub.label_declaration sub) l + | Ptype_open -> () + + let iter_constructor_arguments sub = function + | Pcstr_tuple l -> List.iter (sub.typ sub) l + | Pcstr_record l -> + List.iter (sub.label_declaration sub) l + + let iter_type_extension sub + {ptyext_path; ptyext_params; + ptyext_constructors; + ptyext_private; + ptyext_attributes} = + iter_loc sub ptyext_path; + List.iter (sub.extension_constructor sub) ptyext_constructors; + List.iter (iter_fst (sub.typ sub)) ptyext_params; + sub.attributes sub ptyext_attributes + + let iter_extension_constructor_kind sub = function + Pext_decl(ctl, cto) -> + iter_constructor_arguments sub ctl; iter_opt (sub.typ sub) cto + | Pext_rebind li -> + iter_loc sub li + + let iter_extension_constructor sub + {pext_name; + pext_kind; + pext_loc; + pext_attributes} = + iter_loc sub pext_name; + iter_extension_constructor_kind sub pext_kind; + sub.location sub pext_loc; + sub.attributes sub pext_attributes + +end + +module CT = struct + (* Type expressions for the class language *) + + let iter sub {pcty_loc = loc; pcty_desc = desc; pcty_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pcty_constr (lid, tys) -> + iter_loc sub lid; List.iter (sub.typ sub) tys + | Pcty_signature x -> sub.class_signature sub x + | Pcty_arrow (_lab, t, ct) -> + sub.typ sub t; sub.class_type sub ct + | Pcty_extension x -> sub.extension sub x + + let iter_field sub {pctf_desc = desc; pctf_loc = loc; pctf_attributes = attrs} + = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pctf_inherit ct -> sub.class_type sub ct + | Pctf_val (s, m, v, t) -> sub.typ sub t + | Pctf_method (s, p, v, t) -> sub.typ sub t + | Pctf_constraint (t1, t2) -> + sub.typ sub t1; sub.typ sub t2 + | Pctf_attribute x -> sub.attribute sub x + | Pctf_extension x -> sub.extension sub x + + let iter_signature sub {pcsig_self; pcsig_fields} = + sub.typ sub pcsig_self; + List.iter (sub.class_type_field sub) pcsig_fields +end + +module MT = struct + (* Type expressions for the module language *) + + let iter sub {pmty_desc = desc; pmty_loc = loc; pmty_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pmty_ident s -> iter_loc sub s + | Pmty_alias s -> iter_loc sub s + | Pmty_signature sg -> sub.signature sub sg + | Pmty_functor (s, mt1, mt2) -> + iter_loc sub s; + iter_opt (sub.module_type sub) mt1; + sub.module_type sub mt2 + | Pmty_with (mt, l) -> + sub.module_type sub mt; + List.iter (sub.with_constraint sub) l + | Pmty_typeof me -> sub.module_expr sub me + | Pmty_extension x -> sub.extension sub x + + let iter_with_constraint sub = function + | Pwith_type (lid, d) -> + iter_loc sub lid; sub.type_declaration sub d + | Pwith_module (lid, lid2) -> + iter_loc sub lid; iter_loc sub lid2 + | Pwith_typesubst d -> sub.type_declaration sub d + | Pwith_modsubst (s, lid) -> + iter_loc sub s; iter_loc sub lid + + let iter_signature_item sub {psig_desc = desc; psig_loc = loc} = + sub.location sub loc; + match desc with + | Psig_value vd -> sub.value_description sub vd + | Psig_type (rf, l) -> List.iter (sub.type_declaration sub) l + | Psig_typext te -> sub.type_extension sub te + | Psig_exception ed -> sub.extension_constructor sub ed + | Psig_module x -> sub.module_declaration sub x + | Psig_recmodule l -> + List.iter (sub.module_declaration sub) l + | Psig_modtype x -> sub.module_type_declaration sub x + | Psig_open x -> sub.open_description sub x + | Psig_include x -> sub.include_description sub x + | Psig_class l -> List.iter (sub.class_description sub) l + | Psig_class_type l -> + List.iter (sub.class_type_declaration sub) l + | Psig_extension (x, attrs) -> + sub.extension sub x; sub.attributes sub attrs + | Psig_attribute x -> sub.attribute sub x +end + + +module M = struct + (* Value expressions for the module language *) + + let iter sub {pmod_loc = loc; pmod_desc = desc; pmod_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pmod_ident x -> iter_loc sub x + | Pmod_structure str -> sub.structure sub str + | Pmod_functor (arg, arg_ty, body) -> + iter_loc sub arg; + iter_opt (sub.module_type sub) arg_ty; + sub.module_expr sub body + | Pmod_apply (m1, m2) -> + sub.module_expr sub m1; sub.module_expr sub m2 + | Pmod_constraint (m, mty) -> + sub.module_expr sub m; sub.module_type sub mty + | Pmod_unpack e -> sub.expr sub e + | Pmod_extension x -> sub.extension sub x + + let iter_structure_item sub {pstr_loc = loc; pstr_desc = desc} = + sub.location sub loc; + match desc with + | Pstr_eval (x, attrs) -> + sub.expr sub x; sub.attributes sub attrs + | Pstr_value (r, vbs) -> List.iter (sub.value_binding sub) vbs + | Pstr_primitive vd -> sub.value_description sub vd + | Pstr_type (rf, l) -> List.iter (sub.type_declaration sub) l + | Pstr_typext te -> sub.type_extension sub te + | Pstr_exception ed -> sub.extension_constructor sub ed + | Pstr_module x -> sub.module_binding sub x + | Pstr_recmodule l -> List.iter (sub.module_binding sub) l + | Pstr_modtype x -> sub.module_type_declaration sub x + | Pstr_open x -> sub.open_description sub x + | Pstr_class l -> List.iter (sub.class_declaration sub) l + | Pstr_class_type l -> + List.iter (sub.class_type_declaration sub) l + | Pstr_include x -> sub.include_declaration sub x + | Pstr_extension (x, attrs) -> + sub.extension sub x; sub.attributes sub attrs + | Pstr_attribute x -> sub.attribute sub x +end + +module E = struct + (* Value expressions for the core language *) + + let iter sub {pexp_loc = loc; pexp_desc = desc; pexp_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pexp_ident x -> iter_loc sub x + | Pexp_constant x -> () + | Pexp_let (r, vbs, e) -> + List.iter (sub.value_binding sub) vbs; + sub.expr sub e + | Pexp_fun (lab, def, p, e) -> + iter_opt (sub.expr sub) def; + sub.pat sub p; + sub.expr sub e + | Pexp_function pel -> sub.cases sub pel + | Pexp_apply (e, l) -> + sub.expr sub e; List.iter (iter_snd (sub.expr sub)) l + | Pexp_match (e, pel) -> + sub.expr sub e; sub.cases sub pel + | Pexp_try (e, pel) -> sub.expr sub e; sub.cases sub pel + | Pexp_tuple el -> List.iter (sub.expr sub) el + | Pexp_construct (lid, arg) -> + iter_loc sub lid; iter_opt (sub.expr sub) arg + | Pexp_variant (lab, eo) -> + iter_opt (sub.expr sub) eo + | Pexp_record (l, eo) -> + List.iter (iter_tuple (iter_loc sub) (sub.expr sub)) l; + iter_opt (sub.expr sub) eo + | Pexp_field (e, lid) -> + sub.expr sub e; iter_loc sub lid + | Pexp_setfield (e1, lid, e2) -> + sub.expr sub e1; iter_loc sub lid; + sub.expr sub e2 + | Pexp_array el -> List.iter (sub.expr sub) el + | Pexp_ifthenelse (e1, e2, e3) -> + sub.expr sub e1; sub.expr sub e2; + iter_opt (sub.expr sub) e3 + | Pexp_sequence (e1, e2) -> + sub.expr sub e1; sub.expr sub e2 + | Pexp_while (e1, e2) -> + sub.expr sub e1; sub.expr sub e2 + | Pexp_for (p, e1, e2, d, e3) -> + sub.pat sub p; sub.expr sub e1; sub.expr sub e2; + sub.expr sub e3 + | Pexp_coerce (e, t1, t2) -> + sub.expr sub e; iter_opt (sub.typ sub) t1; + sub.typ sub t2 + | Pexp_constraint (e, t) -> + sub.expr sub e; sub.typ sub t + | Pexp_send (e, s) -> sub.expr sub e + | Pexp_new lid -> iter_loc sub lid + | Pexp_setinstvar (s, e) -> + iter_loc sub s; sub.expr sub e + | Pexp_override sel -> + List.iter (iter_tuple (iter_loc sub) (sub.expr sub)) sel + | Pexp_letmodule (s, me, e) -> + iter_loc sub s; sub.module_expr sub me; + sub.expr sub e + | Pexp_assert e -> sub.expr sub e + | Pexp_lazy e -> sub.expr sub e + | Pexp_poly (e, t) -> + sub.expr sub e; iter_opt (sub.typ sub) t + | Pexp_object cls -> sub.class_structure sub cls + | Pexp_newtype (s, e) -> sub.expr sub e + | Pexp_pack me -> sub.module_expr sub me + | Pexp_open (ovf, lid, e) -> + iter_loc sub lid; sub.expr sub e + | Pexp_extension x -> sub.extension sub x + | Pexp_unreachable -> () +end + +module P = struct + (* Patterns *) + + let iter sub {ppat_desc = desc; ppat_loc = loc; ppat_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Ppat_any -> () + | Ppat_var s -> iter_loc sub s + | Ppat_alias (p, s) -> sub.pat sub p; iter_loc sub s + | Ppat_constant c -> () + | Ppat_interval (c1, c2) -> () + | Ppat_tuple pl -> List.iter (sub.pat sub) pl + | Ppat_construct (l, p) -> + iter_loc sub l; iter_opt (sub.pat sub) p + | Ppat_variant (l, p) -> iter_opt (sub.pat sub) p + | Ppat_record (lpl, cf) -> + List.iter (iter_tuple (iter_loc sub) (sub.pat sub)) lpl + | Ppat_array pl -> List.iter (sub.pat sub) pl + | Ppat_or (p1, p2) -> sub.pat sub p1; sub.pat sub p2 + | Ppat_constraint (p, t) -> + sub.pat sub p; sub.typ sub t + | Ppat_type s -> iter_loc sub s + | Ppat_lazy p -> sub.pat sub p + | Ppat_unpack s -> iter_loc sub s + | Ppat_exception p -> sub.pat sub p + | Ppat_extension x -> sub.extension sub x +end + +module CE = struct + (* Value expressions for the class language *) + + let iter sub {pcl_loc = loc; pcl_desc = desc; pcl_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pcl_constr (lid, tys) -> + iter_loc sub lid; List.iter (sub.typ sub) tys + | Pcl_structure s -> + sub.class_structure sub s + | Pcl_fun (lab, e, p, ce) -> + iter_opt (sub.expr sub) e; + sub.pat sub p; + sub.class_expr sub ce + | Pcl_apply (ce, l) -> + sub.class_expr sub ce; + List.iter (iter_snd (sub.expr sub)) l + | Pcl_let (r, vbs, ce) -> + List.iter (sub.value_binding sub) vbs; + sub.class_expr sub ce + | Pcl_constraint (ce, ct) -> + sub.class_expr sub ce; sub.class_type sub ct + | Pcl_extension x -> sub.extension sub x + + let iter_kind sub = function + | Cfk_concrete (o, e) -> sub.expr sub e + | Cfk_virtual t -> sub.typ sub t + + let iter_field sub {pcf_desc = desc; pcf_loc = loc; pcf_attributes = attrs} = + sub.location sub loc; + sub.attributes sub attrs; + match desc with + | Pcf_inherit (o, ce, s) -> sub.class_expr sub ce + | Pcf_val (s, m, k) -> iter_loc sub s; iter_kind sub k + | Pcf_method (s, p, k) -> + iter_loc sub s; iter_kind sub k + | Pcf_constraint (t1, t2) -> + sub.typ sub t1; sub.typ sub t2 + | Pcf_initializer e -> sub.expr sub e + | Pcf_attribute x -> sub.attribute sub x + | Pcf_extension x -> sub.extension sub x + + let iter_structure sub {pcstr_self; pcstr_fields} = + sub.pat sub pcstr_self; + List.iter (sub.class_field sub) pcstr_fields + + let class_infos sub f {pci_virt; pci_params = pl; pci_name; pci_expr; + pci_loc; pci_attributes} = + List.iter (iter_fst (sub.typ sub)) pl; + iter_loc sub pci_name; + f pci_expr; + sub.location sub pci_loc; + sub.attributes sub pci_attributes +end + +(* Now, a generic AST mapper, to be extended to cover all kinds and + cases of the OCaml grammar. The default behavior of the mapper is + the identity. *) + +let default_iterator = + { + structure = (fun this l -> List.iter (this.structure_item this) l); + structure_item = M.iter_structure_item; + module_expr = M.iter; + signature = (fun this l -> List.iter (this.signature_item this) l); + signature_item = MT.iter_signature_item; + module_type = MT.iter; + with_constraint = MT.iter_with_constraint; + class_declaration = + (fun this -> CE.class_infos this (this.class_expr this)); + class_expr = CE.iter; + class_field = CE.iter_field; + class_structure = CE.iter_structure; + class_type = CT.iter; + class_type_field = CT.iter_field; + class_signature = CT.iter_signature; + class_type_declaration = + (fun this -> CE.class_infos this (this.class_type this)); + class_description = + (fun this -> CE.class_infos this (this.class_type this)); + type_declaration = T.iter_type_declaration; + type_kind = T.iter_type_kind; + typ = T.iter; + type_extension = T.iter_type_extension; + extension_constructor = T.iter_extension_constructor; + value_description = + (fun this {pval_name; pval_type; pval_prim; pval_loc; + pval_attributes} -> + iter_loc this pval_name; + this.typ this pval_type; + this.attributes this pval_attributes; + this.location this pval_loc + ); + + pat = P.iter; + expr = E.iter; + + module_declaration = + (fun this {pmd_name; pmd_type; pmd_attributes; pmd_loc} -> + iter_loc this pmd_name; + this.module_type this pmd_type; + this.attributes this pmd_attributes; + this.location this pmd_loc + ); + + module_type_declaration = + (fun this {pmtd_name; pmtd_type; pmtd_attributes; pmtd_loc} -> + iter_loc this pmtd_name; + iter_opt (this.module_type this) pmtd_type; + this.attributes this pmtd_attributes; + this.location this pmtd_loc + ); + + module_binding = + (fun this {pmb_name; pmb_expr; pmb_attributes; pmb_loc} -> + iter_loc this pmb_name; this.module_expr this pmb_expr; + this.attributes this pmb_attributes; + this.location this pmb_loc + ); + + + open_description = + (fun this {popen_lid; popen_override; popen_attributes; popen_loc} -> + iter_loc this popen_lid; + this.location this popen_loc; + this.attributes this popen_attributes + ); + + + include_description = + (fun this {pincl_mod; pincl_attributes; pincl_loc} -> + this.module_type this pincl_mod; + this.location this pincl_loc; + this.attributes this pincl_attributes + ); + + include_declaration = + (fun this {pincl_mod; pincl_attributes; pincl_loc} -> + this.module_expr this pincl_mod; + this.location this pincl_loc; + this.attributes this pincl_attributes + ); + + + value_binding = + (fun this {pvb_pat; pvb_expr; pvb_attributes; pvb_loc} -> + this.pat this pvb_pat; + this.expr this pvb_expr; + this.location this pvb_loc; + this.attributes this pvb_attributes + ); + + + constructor_declaration = + (fun this {pcd_name; pcd_args; pcd_res; pcd_loc; pcd_attributes} -> + iter_loc this pcd_name; + T.iter_constructor_arguments this pcd_args; + iter_opt (this.typ this) pcd_res; + this.location this pcd_loc; + this.attributes this pcd_attributes + ); + + label_declaration = + (fun this {pld_name; pld_type; pld_loc; pld_mutable; pld_attributes} -> + iter_loc this pld_name; + this.typ this pld_type; + this.location this pld_loc; + this.attributes this pld_attributes + ); + + cases = (fun this l -> List.iter (this.case this) l); + case = + (fun this {pc_lhs; pc_guard; pc_rhs} -> + this.pat this pc_lhs; + iter_opt (this.expr this) pc_guard; + this.expr this pc_rhs + ); + + location = (fun this l -> ()); + + extension = (fun this (s, e) -> iter_loc this s; this.payload this e); + attribute = (fun this (s, e) -> iter_loc this s; this.payload this e); + attributes = (fun this l -> List.iter (this.attribute this) l); + payload = + (fun this -> function + | PStr x -> this.structure this x + | PSig x -> this.signature this x + | PTyp x -> this.typ this x + | PPat (x, g) -> this.pat this x; iter_opt (this.expr this) g + ); + } diff --git a/parsing/ast_iterator.mli b/parsing/ast_iterator.mli new file mode 100755 index 00000000..28df9af1 --- /dev/null +++ b/parsing/ast_iterator.mli @@ -0,0 +1,72 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Nicolas Ojeda Bar, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) + +(** {!iterator} allows to implement AST inspection using open recursion. A + typical mapper would be based on {!default_iterator}, a trivial iterator, + and will fall back on it for handling the syntax it does not modify. *) + +open Parsetree + +(** {2 A generic Parsetree iterator} *) + +type iterator = { + attribute: iterator -> attribute -> unit; + attributes: iterator -> attribute list -> unit; + case: iterator -> case -> unit; + cases: iterator -> case list -> unit; + class_declaration: iterator -> class_declaration -> unit; + class_description: iterator -> class_description -> unit; + class_expr: iterator -> class_expr -> unit; + class_field: iterator -> class_field -> unit; + class_signature: iterator -> class_signature -> unit; + class_structure: iterator -> class_structure -> unit; + class_type: iterator -> class_type -> unit; + class_type_declaration: iterator -> class_type_declaration -> unit; + class_type_field: iterator -> class_type_field -> unit; + constructor_declaration: iterator -> constructor_declaration -> unit; + expr: iterator -> expression -> unit; + extension: iterator -> extension -> unit; + extension_constructor: iterator -> extension_constructor -> unit; + include_declaration: iterator -> include_declaration -> unit; + include_description: iterator -> include_description -> unit; + label_declaration: iterator -> label_declaration -> unit; + location: iterator -> Location.t -> unit; + module_binding: iterator -> module_binding -> unit; + module_declaration: iterator -> module_declaration -> unit; + module_expr: iterator -> module_expr -> unit; + module_type: iterator -> module_type -> unit; + module_type_declaration: iterator -> module_type_declaration -> unit; + open_description: iterator -> open_description -> unit; + pat: iterator -> pattern -> unit; + payload: iterator -> payload -> unit; + signature: iterator -> signature -> unit; + signature_item: iterator -> signature_item -> unit; + structure: iterator -> structure -> unit; + structure_item: iterator -> structure_item -> unit; + typ: iterator -> core_type -> unit; + type_declaration: iterator -> type_declaration -> unit; + type_extension: iterator -> type_extension -> unit; + type_kind: iterator -> type_kind -> unit; + value_binding: iterator -> value_binding -> unit; + value_description: iterator -> value_description -> unit; + with_constraint: iterator -> with_constraint -> unit; +} +(** A [iterator] record implements one "method" per syntactic category, + using an open recursion style: each method takes as its first + argument the iterator to be applied to children in the syntax + tree. *) + +val default_iterator: iterator +(** A default iterator, which implements a "do not do anything" mapping. *) diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml index d57dabb9..8b72b496 100644 --- a/parsing/ast_mapper.ml +++ b/parsing/ast_mapper.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Alain Frisch, LexiFi *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Alain Frisch, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) (* A generic Parsetree mapping class *) @@ -18,7 +21,6 @@ *) -open Asttypes open Parsetree open Ast_helper open Location @@ -137,6 +139,11 @@ module T = struct | Ptype_record l -> Ptype_record (List.map (sub.label_declaration sub) l) | Ptype_open -> Ptype_open + let map_constructor_arguments sub = function + | Pcstr_tuple l -> Pcstr_tuple (List.map (sub.typ sub) l) + | Pcstr_record l -> + Pcstr_record (List.map (sub.label_declaration sub) l) + let map_type_extension sub {ptyext_path; ptyext_params; ptyext_constructors; @@ -151,7 +158,7 @@ module T = struct let map_extension_constructor_kind sub = function Pext_decl(ctl, cto) -> - Pext_decl(List.map (sub.typ sub) ctl, map_opt (sub.typ sub) cto) + Pext_decl(map_constructor_arguments sub ctl, map_opt (sub.typ sub) cto) | Pext_rebind li -> Pext_rebind (map_loc sub li) @@ -238,7 +245,7 @@ module MT = struct let loc = sub.location sub loc in match desc with | Psig_value vd -> value ~loc (sub.value_description sub vd) - | Psig_type l -> type_ ~loc (List.map (sub.type_declaration sub) l) + | Psig_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l) | Psig_typext te -> type_extension ~loc (sub.type_extension sub te) | Psig_exception ed -> exception_ ~loc (sub.extension_constructor sub ed) | Psig_module x -> module_ ~loc (sub.module_declaration sub x) @@ -286,7 +293,7 @@ module M = struct eval ~loc ~attrs:(sub.attributes sub attrs) (sub.expr sub x) | Pstr_value (r, vbs) -> value ~loc r (List.map (sub.value_binding sub) vbs) | Pstr_primitive vd -> primitive ~loc (sub.value_description sub vd) - | Pstr_type l -> type_ ~loc (List.map (sub.type_declaration sub) l) + | Pstr_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l) | Pstr_typext te -> type_extension ~loc (sub.type_extension sub te) | Pstr_exception ed -> exception_ ~loc (sub.extension_constructor sub ed) | Pstr_module x -> module_ ~loc (sub.module_binding sub x) @@ -373,6 +380,7 @@ module E = struct | Pexp_open (ovf, lid, e) -> open_ ~loc ~attrs ovf (map_loc sub lid) (sub.expr sub e) | Pexp_extension x -> extension ~loc ~attrs (sub.extension sub x) + | Pexp_unreachable -> unreachable ~loc ~attrs () end module P = struct @@ -577,7 +585,7 @@ let default_mapper = (fun this {pcd_name; pcd_args; pcd_res; pcd_loc; pcd_attributes} -> Type.constructor (map_loc this pcd_name) - ~args:(List.map (this.typ this) pcd_args) + ~args:(T.map_constructor_arguments this pcd_args) ?res:(map_opt (this.typ this) pcd_res) ~loc:(this.location this pcd_loc) ~attrs:(this.attributes this pcd_attributes) @@ -613,6 +621,7 @@ let default_mapper = payload = (fun this -> function | PStr x -> PStr (this.structure this x) + | PSig x -> PSig (this.signature this x) | PTyp x -> PTyp (this.typ this x) | PPat (x, g) -> PPat (this.pat this x, map_opt (this.expr this) g) ); @@ -620,13 +629,13 @@ let default_mapper = let rec extension_of_error {loc; msg; if_highlight; sub} = { loc; txt = "ocaml.error" }, - PStr ([Str.eval (Exp.constant (Const_string (msg, None))); - Str.eval (Exp.constant (Const_string (if_highlight, None)))] @ + PStr ([Str.eval (Exp.constant (Pconst_string (msg, None))); + Str.eval (Exp.constant (Pconst_string (if_highlight, None)))] @ (List.map (fun ext -> Str.extension (extension_of_error ext)) sub)) let attribute_of_warning loc s = { loc; txt = "ocaml.ppwarning" }, - PStr ([Str.eval ~loc (Exp.constant (Const_string (s, None)))]) + PStr ([Str.eval ~loc (Exp.constant (Pconst_string (s, None)))]) module StringMap = Map.Make(struct type t = string @@ -654,7 +663,7 @@ module PpxContext = struct let lid name = { txt = Lident name; loc = Location.none } - let make_string x = Exp.constant (Const_string (x, None)) + let make_string x = Exp.constant (Pconst_string (x, None)) let make_bool x = if x @@ -709,21 +718,19 @@ module PpxContext = struct let restore fields = let field name payload = let rec get_string = function - | { pexp_desc = Pexp_constant (Const_string (str, None)) } -> str - | _ -> - raise_errorf - "Internal error: invalid [@@@ocaml.ppx.context { %s }] string syntax" - name + | { pexp_desc = Pexp_constant (Pconst_string (str, None)) } -> str + | _ -> raise_errorf "Internal error: invalid [@@@ocaml.ppx.context \ + { %s }] string syntax" name and get_bool pexp = match pexp with - | {pexp_desc = Pexp_construct ({txt = Longident.Lident "true"}, None)} -> + | {pexp_desc = Pexp_construct ({txt = Longident.Lident "true"}, + None)} -> true - | {pexp_desc = Pexp_construct ({txt = Longident.Lident "false"}, None)} -> + | {pexp_desc = Pexp_construct ({txt = Longident.Lident "false"}, + None)} -> false - | _ -> - raise_errorf - "Internal error: invalid [@@@ocaml.ppx.context { %s }] bool syntax" - name + | _ -> raise_errorf "Internal error: invalid [@@@ocaml.ppx.context \ + { %s }] bool syntax" name and get_list elem = function | {pexp_desc = Pexp_construct ({txt = Longident.Lident "::"}, @@ -732,17 +739,13 @@ module PpxContext = struct | {pexp_desc = Pexp_construct ({txt = Longident.Lident "[]"}, None)} -> [] - | _ -> - raise_errorf - "Internal error: invalid [@@@ocaml.ppx.context { %s }] list syntax" - name + | _ -> raise_errorf "Internal error: invalid [@@@ocaml.ppx.context \ + { %s }] list syntax" name and get_pair f1 f2 = function | {pexp_desc = Pexp_tuple [e1; e2]} -> (f1 e1, f2 e2) - | _ -> - raise_errorf - "Internal error: invalid [@@@ocaml.ppx.context { %s }] pair syntax" - name + | _ -> raise_errorf "Internal error: invalid [@@@ocaml.ppx.context \ + { %s }] pair syntax" name and get_option elem = function | { pexp_desc = Pexp_construct ({ txt = Longident.Lident "Some" }, Some exp) } -> @@ -750,10 +753,8 @@ module PpxContext = struct | { pexp_desc = Pexp_construct ({ txt = Longident.Lident "None" }, None) } -> None - | _ -> - raise_errorf - "Internal error: invalid [@@@ocaml.ppx.context { %s }] option syntax" - name + | _ -> raise_errorf "Internal error: invalid [@@@ocaml.ppx.context \ + { %s }] option syntax" name in match name with | "tool_name" -> @@ -790,69 +791,77 @@ end let ppx_context = PpxContext.make +let ext_of_exn exn = + match error_of_exn exn with + | Some error -> extension_of_error error + | None -> raise exn + let apply_lazy ~source ~target mapper = + let implem ast = + let fields, ast = + match ast with + | {pstr_desc = Pstr_attribute ({txt = "ocaml.ppx.context"}, x)} :: l -> + PpxContext.get_fields x, l + | _ -> [], ast + in + PpxContext.restore fields; + let ast = + try + let mapper = mapper () in + mapper.structure mapper ast + with exn -> + [{pstr_desc = Pstr_extension (ext_of_exn exn, []); + pstr_loc = Location.none}] + in + let fields = PpxContext.update_cookies fields in + Str.attribute (PpxContext.mk fields) :: ast + in + let iface ast = + let fields, ast = + match ast with + | {psig_desc = Psig_attribute ({txt = "ocaml.ppx.context"}, x)} :: l -> + PpxContext.get_fields x, l + | _ -> [], ast + in + PpxContext.restore fields; + let ast = + try + let mapper = mapper () in + mapper.signature mapper ast + with exn -> + [{psig_desc = Psig_extension (ext_of_exn exn, []); + psig_loc = Location.none}] + in + let fields = PpxContext.update_cookies fields in + Sig.attribute (PpxContext.mk fields) :: ast + in + let ic = open_in_bin source in let magic = really_input_string ic (String.length Config.ast_impl_magic_number) in - if magic <> Config.ast_impl_magic_number - && magic <> Config.ast_intf_magic_number then - failwith "Ast_mapper: OCaml version mismatch or malformed input"; - Location.input_name := input_value ic; - let ast = input_value ic in - close_in ic; - let implem ast = - try - let fields, ast = - match ast with - | {pstr_desc = Pstr_attribute ({txt = "ocaml.ppx.context"}, x)} :: l -> - PpxContext.get_fields x, l - | _ -> [], ast - in - PpxContext.restore fields; - let mapper = mapper () in - let ast = mapper.structure mapper ast in - let fields = PpxContext.update_cookies fields in - Str.attribute (PpxContext.mk fields) :: ast - with exn -> - match error_of_exn exn with - | Some error -> - [{pstr_desc = Pstr_extension (extension_of_error error, []); - pstr_loc = Location.none}] - | None -> raise exn - in - let iface ast = - try - let fields, ast = - match ast with - | {psig_desc = Psig_attribute ({txt = "ocaml.ppx.context"}, x)} :: l -> - PpxContext.get_fields x, l - | _ -> [], ast - in - PpxContext.restore fields; - let mapper = mapper () in - let ast = mapper.signature mapper ast in - let fields = PpxContext.update_cookies fields in - Sig.attribute (PpxContext.mk fields) :: ast - with exn -> - match error_of_exn exn with - | Some error -> - [{psig_desc = Psig_extension (extension_of_error error, []); - psig_loc = Location.none}] - | None -> raise exn - in - let ast = - if magic = Config.ast_impl_magic_number - then Obj.magic (implem (Obj.magic ast)) - else Obj.magic (iface (Obj.magic ast)) + let rewrite transform = + Location.input_name := input_value ic; + let ast = input_value ic in + close_in ic; + let ast = transform ast in + let oc = open_out_bin target in + output_string oc magic; + output_value oc !Location.input_name; + output_value oc ast; + close_out oc + and fail () = + close_in ic; + failwith "Ast_mapper: OCaml version mismatch or malformed input"; in - let oc = open_out_bin target in - output_string oc magic; - output_value oc !Location.input_name; - output_value oc ast; - close_out oc + + if magic = Config.ast_impl_magic_number then + rewrite (implem : structure -> structure) + else if magic = Config.ast_intf_magic_number then + rewrite (iface : signature -> signature) + else fail () let drop_ppx_context_str ~restore = function | {pstr_desc = Pstr_attribute({Location.txt = "ocaml.ppx.context"}, a)} diff --git a/parsing/ast_mapper.mli b/parsing/ast_mapper.mli index d48971d5..95c365f7 100644 --- a/parsing/ast_mapper.mli +++ b/parsing/ast_mapper.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Alain Frisch, LexiFi *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Alain Frisch, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) (** The interface of a -ppx rewriter @@ -166,21 +169,25 @@ val attribute_of_warning: Location.t -> string -> attribute (** {2 Helper functions to call external mappers} *) -val add_ppx_context_str: tool_name:string -> Parsetree.structure -> Parsetree.structure +val add_ppx_context_str: + tool_name:string -> Parsetree.structure -> Parsetree.structure (** Extract information from the current environment and encode it into an attribute which is prepended to the list of structure items in order to pass the information to an external processor. *) -val add_ppx_context_sig: tool_name:string -> Parsetree.signature -> Parsetree.signature +val add_ppx_context_sig: + tool_name:string -> Parsetree.signature -> Parsetree.signature (** Same as [add_ppx_context_str], but for signatures. *) -val drop_ppx_context_str: restore:bool -> Parsetree.structure -> Parsetree.structure +val drop_ppx_context_str: + restore:bool -> Parsetree.structure -> Parsetree.structure (** Drop the ocaml.ppx.context attribute from a structure. If [restore] is true, also restore the associated data in the current process. *) -val drop_ppx_context_sig: restore:bool -> Parsetree.signature -> Parsetree.signature +val drop_ppx_context_sig: + restore:bool -> Parsetree.signature -> Parsetree.signature (** Same as [drop_ppx_context_str], but for signatures. *) (** {2 Cookies} *) diff --git a/parsing/asttypes.mli b/parsing/asttypes.mli index b212a2b9..5188b69c 100644 --- a/parsing/asttypes.mli +++ b/parsing/asttypes.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Auxiliary a.s.t. types used by parsetree and typedtree. *) @@ -25,6 +28,7 @@ type rec_flag = Nonrecursive | Recursive type direction_flag = Upto | Downto +(* Order matters, used in polymorphic comparison *) type private_flag = Private | Public type mutable_flag = Immutable | Mutable @@ -37,6 +41,11 @@ type closed_flag = Closed | Open type label = string +type arg_label = + Nolabel + | Labelled of string (* label:T -> ... *) + | Optional of string (* ?label:T -> ... *) + type 'a loc = 'a Location.loc = { txt : 'a; loc : Location.t; diff --git a/parsing/attr_helper.ml b/parsing/attr_helper.ml new file mode 100644 index 00000000..ecf87787 --- /dev/null +++ b/parsing/attr_helper.ml @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +open Asttypes +open Parsetree + +type error = + | Multiple_attributes of string + | No_payload_expected of string + +exception Error of Location.t * error + +let get_no_payload_attribute alt_names attrs = + match List.filter (fun (n, _) -> List.mem n.txt alt_names) attrs with + | [] -> None + | [ (name, PStr []) ] -> Some name + | [ (name, _) ] -> + raise (Error (name.loc, No_payload_expected name.txt)) + | _ :: (name, _) :: _ -> + raise (Error (name.loc, Multiple_attributes name.txt)) + +let has_no_payload_attribute alt_names attrs = + match get_no_payload_attribute alt_names attrs with + | None -> false + | Some _ -> true + +open Format + +let report_error ppf = function + | Multiple_attributes name -> + fprintf ppf "Too many `%s' attributes" name + | No_payload_expected name -> + fprintf ppf "Attribute `%s' does not accept a payload" name + +let () = + Location.register_error_of_exn + (function + | Error (loc, err) -> + Some (Location.error_of_printer loc report_error err) + | _ -> + None + ) diff --git a/parsing/attr_helper.mli b/parsing/attr_helper.mli new file mode 100644 index 00000000..3d7145c3 --- /dev/null +++ b/parsing/attr_helper.mli @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +(** Helpers for attributes *) + +open Asttypes +open Parsetree + +type error = + | Multiple_attributes of string + | No_payload_expected of string + +(** The [string list] argument of the following functions is a list of + alternative names for the attribute we are looking for. For instance: + + {[ + ["foo"; "ocaml.foo"] + ]} *) +val get_no_payload_attribute : string list -> attributes -> string loc option +val has_no_payload_attribute : string list -> attributes -> bool + +exception Error of Location.t * error + +val report_error: Format.formatter -> error -> unit diff --git a/parsing/builtin_attributes.ml b/parsing/builtin_attributes.ml new file mode 100755 index 00000000..9e452ce1 --- /dev/null +++ b/parsing/builtin_attributes.ml @@ -0,0 +1,190 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Alain Frisch, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) + +open Asttypes +open Parsetree + +let string_of_cst = function + | Pconst_string(s, _) -> Some s + | _ -> None + +let string_of_payload = function + | PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant c},_)}] -> + string_of_cst c + | _ -> None + +let rec error_of_extension ext = + match ext with + | ({txt = ("ocaml.error"|"error") as txt; loc}, p) -> + let rec sub_from inner = + match inner with + | {pstr_desc=Pstr_extension (ext, _)} :: rest -> + error_of_extension ext :: sub_from rest + | {pstr_loc} :: rest -> + (Location.errorf ~loc + "Invalid syntax for sub-error of extension '%s'." txt) :: + sub_from rest + | [] -> [] + in + begin match p with + | PStr({pstr_desc=Pstr_eval + ({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}:: + {pstr_desc=Pstr_eval + ({pexp_desc=Pexp_constant(Pconst_string(if_highlight,_))}, _)}:: + inner) -> + Location.error ~loc ~if_highlight ~sub:(sub_from inner) msg + | PStr({pstr_desc=Pstr_eval + ({pexp_desc=Pexp_constant(Pconst_string(msg,_))}, _)}::inner) -> + Location.error ~loc ~sub:(sub_from inner) msg + | _ -> Location.errorf ~loc "Invalid syntax for extension '%s'." txt + end + | ({txt; loc}, _) -> + Location.errorf ~loc "Uninterpreted extension '%s'." txt + +let rec deprecated_of_attrs = function + | [] -> None + | ({txt = "ocaml.deprecated"|"deprecated"; _}, p) :: _ -> + begin match string_of_payload p with + | Some txt -> Some txt + | None -> Some "" + end + | _ :: tl -> deprecated_of_attrs tl + +let check_deprecated loc attrs s = + match deprecated_of_attrs attrs with + | None -> () + | Some "" -> Location.prerr_warning loc (Warnings.Deprecated s) + | Some txt -> + Location.prerr_warning loc (Warnings.Deprecated (s ^ "\n" ^ txt)) + +let rec check_deprecated_mutable loc attrs s = + match attrs with + | [] -> () + | ({txt = "ocaml.deprecated_mutable"|"deprecated_mutable"; _}, p) :: _ -> + let txt = + match string_of_payload p with + | Some txt -> "\n" ^ txt + | None -> "" + in + Location.prerr_warning loc + (Warnings.Deprecated (Printf.sprintf "mutating field %s%s" + s txt)) + | _ :: tl -> check_deprecated_mutable loc tl s + +let rec deprecated_of_sig = function + | {psig_desc = Psig_attribute a} :: tl -> + begin match deprecated_of_attrs [a] with + | None -> deprecated_of_sig tl + | Some _ as r -> r + end + | _ -> None + + +let rec deprecated_of_str = function + | {pstr_desc = Pstr_attribute a} :: tl -> + begin match deprecated_of_attrs [a] with + | None -> deprecated_of_str tl + | Some _ as r -> r + end + | _ -> None + + +let emit_external_warnings = + (* Note: this is run as a preliminary pass when type-checking an + interface or implementation. This allows to cover all kinds of + attributes, but the drawback is that it doesn't take local + configuration of warnings (with '@@warning'/'@@warnerror' + attributes) into account. We should rather check for + 'ppwarning' attributes during the actual type-checking, making + sure to cover all contexts (easier and more ugly alternative: + duplicate here the logic which control warnings locally). *) + let open Ast_iterator in + { + default_iterator with + attribute = (fun _ a -> + match a with + | {txt="ocaml.ppwarning"|"ppwarning"}, + PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant + (Pconst_string (s, _))},_); + pstr_loc}] -> + Location.prerr_warning pstr_loc (Warnings.Preprocessor s) + | _ -> () + ) + } + + +let warning_scope = ref [] + +let warning_enter_scope () = + warning_scope := (Warnings.backup ()) :: !warning_scope +let warning_leave_scope () = + match !warning_scope with + | [] -> assert false + | hd :: tl -> + Warnings.restore hd; + warning_scope := tl + +let warning_attribute attrs = + let process loc txt errflag payload = + match string_of_payload payload with + | Some s -> + begin try Warnings.parse_options errflag s + with Arg.Bad _ -> + Location.prerr_warning loc + (Warnings.Attribute_payload + (txt, "Ill-formed list of warnings")) + end + | None -> + Location.prerr_warning loc + (Warnings.Attribute_payload + (txt, "A single string literal is expected")) + in + List.iter + (function + | ({txt = ("ocaml.warning"|"warning") as txt; loc}, payload) -> + process loc txt false payload + | ({txt = ("ocaml.warnerror"|"warnerror") as txt; loc}, payload) -> + process loc txt true payload + | _ -> + () + ) + attrs + +let with_warning_attribute attrs f = + try + warning_enter_scope (); + warning_attribute attrs; + let ret = f () in + warning_leave_scope (); + ret + with exn -> + warning_leave_scope (); + raise exn + + +let warn_on_literal_pattern = + List.exists + (function + | ({txt="ocaml.warn_on_literal_pattern"|"warn_on_literal_pattern"; _}, _) + -> true + | _ -> false + ) + +let explicit_arity = + List.exists + (function + | ({txt="ocaml.explicit_arity"|"explicit_arity"; _}, _) -> true + | _ -> false + ) diff --git a/parsing/builtin_attributes.mli b/parsing/builtin_attributes.mli new file mode 100755 index 00000000..60b709a8 --- /dev/null +++ b/parsing/builtin_attributes.mli @@ -0,0 +1,47 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Alain Frisch, LexiFi *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) + +(* Support for some of the builtin attributes: + + ocaml.deprecated + ocaml.error + ocaml.ppwarning + ocaml.warning + ocaml.warnerror + ocaml.explicit_arity (for camlp4/camlp5) + ocaml.warn_on_literal_pattern + ocaml.deprecated_mutable +*) + + +val check_deprecated: Location.t -> Parsetree.attributes -> string -> unit +val deprecated_of_attrs: Parsetree.attributes -> string option +val deprecated_of_sig: Parsetree.signature -> string option +val deprecated_of_str: Parsetree.structure -> string option + +val check_deprecated_mutable: + Location.t -> Parsetree.attributes -> string -> unit + +val error_of_extension: Parsetree.extension -> Location.error + +val warning_enter_scope: unit -> unit +val warning_leave_scope: unit -> unit +val warning_attribute: Parsetree.attributes -> unit +val with_warning_attribute: Parsetree.attributes -> (unit -> 'a) -> 'a + +val emit_external_warnings: Ast_iterator.iterator + +val warn_on_literal_pattern: Parsetree.attributes -> bool +val explicit_arity: Parsetree.attributes -> bool diff --git a/parsing/docstrings.ml b/parsing/docstrings.ml index 389f6cf7..724a499d 100644 --- a/parsing/docstrings.ml +++ b/parsing/docstrings.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Leo White *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Leo White *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Location @@ -83,10 +86,9 @@ let empty_docs = { docs_pre = None; docs_post = None } let doc_loc = {txt = "ocaml.doc"; loc = Location.none} let docs_attr ds = - let open Asttypes in let open Parsetree in let exp = - { pexp_desc = Pexp_constant (Const_string(ds.ds_body, None)); + { pexp_desc = Pexp_constant (Pconst_string(ds.ds_body, None)); pexp_loc = ds.ds_loc; pexp_attributes = []; } in @@ -117,26 +119,23 @@ let empty_info = None let info_attr = docs_attr let add_info_attrs info attrs = - let attrs = - match info with - | None -> attrs - | Some ds -> attrs @ [info_attr ds] - in - attrs + match info with + | None -> attrs + | Some ds -> attrs @ [info_attr ds] (* Docstrings not attached to a specifc item *) type text = docstring list let empty_text = [] +let empty_text_lazy = lazy [] let text_loc = {txt = "ocaml.text"; loc = Location.none} let text_attr ds = - let open Asttypes in let open Parsetree in let exp = - { pexp_desc = Pexp_constant (Const_string(ds.ds_body, None)); + { pexp_desc = Pexp_constant (Pconst_string(ds.ds_body, None)); pexp_loc = ds.ds_loc; pexp_attributes = []; } in @@ -339,6 +338,3 @@ let init () = Hashtbl.reset floating_table; Hashtbl.reset pre_extra_table; Hashtbl.reset post_extra_table - - - diff --git a/parsing/docstrings.mli b/parsing/docstrings.mli index e8737850..01103b7e 100644 --- a/parsing/docstrings.mli +++ b/parsing/docstrings.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Leo White *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Leo White *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** (Re)Initialise all docstring state *) val init : unit -> unit @@ -114,6 +117,7 @@ val rhs_info : int -> info type text = docstring list val empty_text : text +val empty_text_lazy : text Lazy.t val text_attr : docstring -> Parsetree.attribute diff --git a/parsing/lexer.mli b/parsing/lexer.mli index 4878a36e..846745da 100644 --- a/parsing/lexer.mli +++ b/parsing/lexer.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexical analyzer *) @@ -23,7 +26,7 @@ type error = | Unterminated_string | Unterminated_string_in_comment of Location.t * Location.t | Keyword_as_label of string - | Literal_overflow of string + | Invalid_literal of string ;; exception Error of error * Location.t @@ -38,6 +41,7 @@ val in_string : unit -> bool;; val print_warnings : bool ref +val handle_docstrings: bool ref val comments : unit -> (string * Location.t) list val token_with_comments : Lexing.lexbuf -> Parser.token diff --git a/parsing/lexer.mll b/parsing/lexer.mll index ad716781..0100867e 100644 --- a/parsing/lexer.mll +++ b/parsing/lexer.mll @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexer definition *) @@ -24,7 +27,7 @@ type error = | Unterminated_string | Unterminated_string_in_comment of Location.t * Location.t | Keyword_as_label of string - | Literal_overflow of string + | Invalid_literal of string ;; exception Error of error * Location.t;; @@ -84,10 +87,10 @@ let keyword_table = "while", WHILE; "with", WITH; + "lor", INFIXOP3("lor"); (* Should be INFIXOP2 *) + "lxor", INFIXOP3("lxor"); (* Should be INFIXOP2 *) "mod", INFIXOP3("mod"); "land", INFIXOP3("land"); - "lor", INFIXOP3("lor"); - "lxor", INFIXOP3("lxor"); "lsl", INFIXOP4("lsl"); "lsr", INFIXOP4("lsr"); "asr", INFIXOP4("asr") @@ -133,6 +136,10 @@ let is_in_string = ref false let in_string () = !is_in_string let print_warnings = ref true +(* Escaped chars are interpreted in strings unless they are in comments. *) +let store_escaped_char lexbuf c = + if in_comment () then store_lexeme lexbuf else store_string_char c + let with_comment_buffer comment lexbuf = let start_loc = Location.curr lexbuf in comment_start_loc := [start_loc]; @@ -163,6 +170,12 @@ let char_for_decimal_code lexbuf i = Location.curr lexbuf)) else Char.chr c +let char_for_octal_code lexbuf i = + let c = 64 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) + + 8 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) + + (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in + Char.chr c + let char_for_hexadecimal_code lexbuf i = let d1 = Char.code (Lexing.lexeme_char lexbuf i) in let val1 = if d1 >= 97 then d1 - 87 @@ -176,32 +189,6 @@ let char_for_hexadecimal_code lexbuf i = in Char.chr (val1 * 16 + val2) -(* To convert integer literals, allowing max_int + 1 (PR#4210) *) - -let cvt_int_literal s = - - int_of_string ("-" ^ s) -let cvt_int32_literal s = - Int32.neg (Int32.of_string ("-" ^ String.sub s 0 (String.length s - 1))) -let cvt_int64_literal s = - Int64.neg (Int64.of_string ("-" ^ String.sub s 0 (String.length s - 1))) -let cvt_nativeint_literal s = - Nativeint.neg (Nativeint.of_string ("-" ^ String.sub s 0 - (String.length s - 1))) - -(* Remove underscores from float literals *) - -let remove_underscores s = - let l = String.length s in - let b = Bytes.create l in - let rec remove src dst = - if src >= l then - if dst >= l then s else Bytes.sub_string b 0 dst - else - match s.[src] with - '_' -> remove (src + 1) dst - | c -> Bytes.set b dst c; remove (src + 1) (dst + 1) - in remove 0 0 - (* recover the name from a LABEL or OPTLABEL token *) let get_label_name lexbuf = @@ -238,13 +225,16 @@ let warn_latin1 lexbuf = (Warnings.Deprecated "ISO-Latin1 characters in identifiers") ;; +let handle_docstrings = ref true let comment_list = ref [] let add_comment com = comment_list := com :: !comment_list let add_docstring_comment ds = - let com = (Docstrings.docstring_body ds, Docstrings.docstring_loc ds) in + let com = + ("*" ^ Docstrings.docstring_body ds, Docstrings.docstring_loc ds) + in add_comment com let comments () = List.rev !comment_list @@ -268,9 +258,8 @@ let report_error ppf = function Location.print_error loc | Keyword_as_label kwd -> fprintf ppf "`%s' is a keyword, it cannot be used as label name" kwd - | Literal_overflow ty -> - fprintf ppf "Integer literal exceeds the range of representable \ - integers of type %s" ty + | Invalid_literal s -> + fprintf ppf "Invalid literal %s" s let () = Location.register_error_of_exn @@ -307,7 +296,13 @@ let int_literal = let float_literal = ['0'-'9'] ['0'-'9' '_']* ('.' ['0'-'9' '_']* )? - (['e' 'E'] ['+' '-']? ['0'-'9'] ['0'-'9' '_']*)? + (['e' 'E'] ['+' '-']? ['0'-'9'] ['0'-'9' '_']* )? +let hex_float_literal = + '0' ['x' 'X'] + ['0'-'9' 'A'-'F' 'a'-'f'] ['0'-'9' 'A'-'F' 'a'-'f' '_']* + ('.' ['0'-'9' 'A'-'F' 'a'-'f' '_']* )? + (['p' 'P'] ['+' '-']? ['0'-'9'] ['0'-'9' '_']* )? +let literal_modifier = ['G'-'Z' 'g'-'z'] rule token = parse | "\\" newline { @@ -345,29 +340,16 @@ rule token = parse { UIDENT(Lexing.lexeme lexbuf) } (* No capitalized keywords *) | uppercase_latin1 identchar_latin1 * { warn_latin1 lexbuf; UIDENT(Lexing.lexeme lexbuf) } - | int_literal - { try - INT (cvt_int_literal (Lexing.lexeme lexbuf)) - with Failure _ -> - raise (Error(Literal_overflow "int", Location.curr lexbuf)) - } - | float_literal - { FLOAT (remove_underscores(Lexing.lexeme lexbuf)) } - | int_literal "l" - { try - INT32 (cvt_int32_literal (Lexing.lexeme lexbuf)) - with Failure _ -> - raise (Error(Literal_overflow "int32", Location.curr lexbuf)) } - | int_literal "L" - { try - INT64 (cvt_int64_literal (Lexing.lexeme lexbuf)) - with Failure _ -> - raise (Error(Literal_overflow "int64", Location.curr lexbuf)) } - | int_literal "n" - { try - NATIVEINT (cvt_nativeint_literal (Lexing.lexeme lexbuf)) - with Failure _ -> - raise (Error(Literal_overflow "nativeint", Location.curr lexbuf)) } + | int_literal { INT (Lexing.lexeme lexbuf, None) } + | (int_literal as lit) (literal_modifier as modif) + { INT (lit, Some modif) } + | float_literal | hex_float_literal + { FLOAT (Lexing.lexeme lexbuf, None) } + | ((float_literal | hex_float_literal) as lit) (literal_modifier as modif) + { FLOAT (lit, Some modif) } + | (float_literal | hex_float_literal | int_literal) identchar+ + { raise (Error(Invalid_literal (Lexing.lexeme lexbuf), + Location.curr lexbuf)) } | "\"" { reset_string_buffer(); is_in_string := true; @@ -388,18 +370,20 @@ rule token = parse is_in_string := false; lexbuf.lex_start_p <- string_start; STRING (get_stored_string(), Some delim) } - | "'" newline "'" + | "\'" newline "\'" { update_loc lexbuf None 1 false 1; CHAR (Lexing.lexeme_char lexbuf 1) } - | "'" [^ '\\' '\'' '\010' '\013'] "'" + | "\'" [^ '\\' '\'' '\010' '\013'] "\'" { CHAR(Lexing.lexeme_char lexbuf 1) } - | "'\\" ['\\' '\'' '"' 'n' 't' 'b' 'r' ' '] "'" + | "\'\\" ['\\' '\'' '\"' 'n' 't' 'b' 'r' ' '] "\'" { CHAR(char_for_backslash (Lexing.lexeme_char lexbuf 2)) } - | "'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "'" + | "\'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "\'" { CHAR(char_for_decimal_code lexbuf 2) } - | "'\\" 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "'" + | "\'\\" 'o' ['0'-'3'] ['0'-'7'] ['0'-'7'] "\'" + { CHAR(char_for_octal_code lexbuf 3) } + | "\'\\" 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "\'" { CHAR(char_for_hexadecimal_code lexbuf 3) } - | "'\\" _ + | "\'\\" _ { let l = Lexing.lexeme lexbuf in let esc = String.sub l 1 (String.length l - 1) in raise (Error(Illegal_escape esc, Location.curr lexbuf)) @@ -409,7 +393,11 @@ rule token = parse COMMENT (s, loc) } | "(**" { let s, loc = with_comment_buffer comment lexbuf in - DOCSTRING (Docstrings.docstring s loc) } + if !handle_docstrings then + DOCSTRING (Docstrings.docstring s loc) + else + COMMENT ("*" ^ s, loc) + } | "(**" ('*'+) as stars { let s, loc = with_comment_buffer @@ -435,7 +423,7 @@ rule token = parse STAR } | "#" [' ' '\t']* (['0'-'9']+ as num) [' ' '\t']* - ("\"" ([^ '\010' '\013' '"' ] * as name) "\"")? + ("\"" ([^ '\010' '\013' '\"' ] * as name) "\"")? [^ '\010' '\013'] * newline { update_loc lexbuf name (int_of_string num) true 0; token lexbuf @@ -444,7 +432,7 @@ rule token = parse | "&" { AMPERSAND } | "&&" { AMPERAMPER } | "`" { BACKQUOTE } - | "'" { QUOTE } + | "\'" { QUOTE } | "(" { LPAREN } | ")" { RPAREN } | "*" { STAR } @@ -476,10 +464,10 @@ rule token = parse | "}" { RBRACE } | ">}" { GREATERRBRACE } | "[@" { LBRACKETAT } - | "[%" { LBRACKETPERCENT } - | "[%%" { LBRACKETPERCENTPERCENT } - | "[@@" { LBRACKETATAT } + | "[@@" { LBRACKETATAT } | "[@@@" { LBRACKETATATAT } + | "[%" { LBRACKETPERCENT } + | "[%%" { LBRACKETPERCENTPERCENT } | "!" { BANG } | "!=" { INFIXOP0 "!=" } | "+" { PLUS } @@ -528,7 +516,7 @@ and comment = parse | "\"" { string_start_loc := Location.curr lexbuf; - store_string_char '"'; + store_string_char '\"'; is_in_string := true; begin try string lexbuf with Error (Unterminated_string, str_start) -> @@ -541,7 +529,7 @@ and comment = parse loc)) end; is_in_string := false; - store_string_char '"'; + store_string_char '\"'; comment lexbuf } | "{" lowercase* "|" { @@ -566,20 +554,20 @@ and comment = parse store_string_char '}'; comment lexbuf } - | "''" + | "\'\'" { store_lexeme lexbuf; comment lexbuf } - | "'" newline "'" + | "\'" newline "\'" { update_loc lexbuf None 1 false 1; store_lexeme lexbuf; comment lexbuf } - | "'" [^ '\\' '\'' '\010' '\013' ] "'" + | "\'" [^ '\\' '\'' '\010' '\013' ] "\'" { store_lexeme lexbuf; comment lexbuf } - | "'\\" ['\\' '"' '\'' 'n' 't' 'b' 'r' ' '] "'" + | "\'\\" ['\\' '\"' '\'' 'n' 't' 'b' 'r' ' '] "\'" { store_lexeme lexbuf; comment lexbuf } - | "'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "'" + | "\'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "\'" { store_lexeme lexbuf; comment lexbuf } - | "'\\" 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "'" + | "\'\\" 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] "\'" { store_lexeme lexbuf; comment lexbuf } | eof { match !comment_start_loc with @@ -598,35 +586,37 @@ and comment = parse { store_lexeme lexbuf; comment lexbuf } and string = parse - '"' + '\"' { () } | '\\' newline ([' ' '\t'] * as space) { update_loc lexbuf None 1 false (String.length space); + if in_comment () then store_lexeme lexbuf; string lexbuf } - | '\\' ['\\' '\'' '"' 'n' 't' 'b' 'r' ' '] - { store_string_char(char_for_backslash(Lexing.lexeme_char lexbuf 1)); + | '\\' ['\\' '\'' '\"' 'n' 't' 'b' 'r' ' '] + { store_escaped_char lexbuf + (char_for_backslash(Lexing.lexeme_char lexbuf 1)); string lexbuf } | '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] - { store_string_char(char_for_decimal_code lexbuf 1); + { store_escaped_char lexbuf (char_for_decimal_code lexbuf 1); + string lexbuf } + | '\\' 'o' ['0'-'3'] ['0'-'7'] ['0'-'7'] + { store_escaped_char lexbuf (char_for_octal_code lexbuf 2); string lexbuf } | '\\' 'x' ['0'-'9' 'a'-'f' 'A'-'F'] ['0'-'9' 'a'-'f' 'A'-'F'] - { store_string_char(char_for_hexadecimal_code lexbuf 2); + { store_escaped_char lexbuf (char_for_hexadecimal_code lexbuf 2); string lexbuf } | '\\' _ - { if in_comment () - then string lexbuf - else begin + { if not (in_comment ()) then begin (* Should be an error, but we are very lax. raise (Error (Illegal_escape (Lexing.lexeme lexbuf), Location.curr lexbuf)) *) let loc = Location.curr lexbuf in Location.prerr_warning loc Warnings.Illegal_backslash; - store_string_char (Lexing.lexeme_char lexbuf 0); - store_string_char (Lexing.lexeme_char lexbuf 1); - string lexbuf - end + end; + store_lexeme lexbuf; + string lexbuf } | newline { if not (in_comment ()) then diff --git a/parsing/location.ml b/parsing/location.ml index a4910bdc..96d0c0cf 100644 --- a/parsing/location.ml +++ b/parsing/location.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Lexing @@ -250,7 +253,11 @@ let get_pos_info pos = (pos.pos_fname, pos.pos_lnum, pos.pos_cnum - pos.pos_bol) ;; +let setup_colors () = + Misc.Color.setup !Clflags.color + let print_loc ppf loc = + setup_colors (); let (file, line, startchar) = get_pos_info loc.loc_start in let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + startchar in if file = "//toplevel//" then begin @@ -258,29 +265,52 @@ let print_loc ppf loc = fprintf ppf "Characters %i-%i" loc.loc_start.pos_cnum loc.loc_end.pos_cnum end else begin - fprintf ppf "%s%a%s%i" msg_file print_filename file msg_line line; + fprintf ppf "%s@{%a%s%i" msg_file print_filename file msg_line line; if startchar >= 0 then - fprintf ppf "%s%i%s%i" msg_chars startchar msg_to endchar + fprintf ppf "%s%i%s%i" msg_chars startchar msg_to endchar; + fprintf ppf "@}" end ;; let print ppf loc = + setup_colors (); + if loc.loc_start.pos_fname = "//toplevel//" + && highlight_locations ppf [loc] then () + else fprintf ppf "@{%a@}%s@." print_loc loc msg_colon +;; + +let error_prefix = "Error" +let warning_prefix = "Warning" + +let print_error_prefix ppf () = + setup_colors (); + fprintf ppf "@{%s@}:" error_prefix; + () +;; + +let print_compact ppf loc = if loc.loc_start.pos_fname = "//toplevel//" && highlight_locations ppf [loc] then () - else fprintf ppf "%a%s@." print_loc loc msg_colon + else begin + let (file, line, startchar) = get_pos_info loc.loc_start in + let endchar = loc.loc_end.pos_cnum - loc.loc_start.pos_cnum + startchar in + fprintf ppf "%a:%i" print_filename file line; + if startchar >= 0 then fprintf ppf ",%i--%i" startchar endchar + end ;; let print_error ppf loc = print ppf loc; - fprintf ppf "Error: "; + print_error_prefix ppf () ;; -let print_error_cur_file ppf = print_error ppf (in_file !input_name);; +let print_error_cur_file ppf () = print_error ppf (in_file !input_name);; let default_warning_printer loc ppf w = if Warnings.is_active w then begin + setup_colors (); print ppf loc; - fprintf ppf "Warning %a@." Warnings.print w + fprintf ppf "@{%s@} %a@." warning_prefix Warnings.print w end ;; @@ -314,8 +344,31 @@ type error = if_highlight: string; (* alternative message if locations are highlighted *) } -let errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") = - Printf.ksprintf (fun msg -> {loc; msg; sub; if_highlight}) +let pp_ksprintf ?before k fmt = + let buf = Buffer.create 64 in + let ppf = Format.formatter_of_buffer buf in + Misc.Color.set_color_tag_handling ppf; + begin match before with + | None -> () + | Some f -> f ppf + end; + kfprintf + (fun _ -> + pp_print_flush ppf (); + let msg = Buffer.contents buf in + k msg) + ppf fmt + +let errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") fmt = + pp_ksprintf + (fun msg -> {loc; msg; sub; if_highlight}) + fmt + +let errorf_prefixed ?(loc=none) ?(sub=[]) ?(if_highlight="") fmt = + pp_ksprintf + ~before:(fun ppf -> fprintf ppf "%a " print_error_prefix ()) + (fun msg -> {loc; msg; sub; if_highlight}) + fmt let error ?(loc = none) ?(sub = []) ?(if_highlight = "") msg = {loc; msg; sub; if_highlight} @@ -336,7 +389,7 @@ let error_of_exn exn = let rec default_error_reporter ppf ({loc; msg; sub; if_highlight} as err) = let highlighted = - if if_highlight <> "" then + if if_highlight <> "" && loc.loc_start.pos_fname = "//toplevel//" then let rec collect_locs locs {loc; sub; if_highlight; _} = List.fold_left collect_locs (loc :: locs) sub in @@ -350,8 +403,7 @@ let rec default_error_reporter ppf ({loc; msg; sub; if_highlight} as err) = else begin print ppf loc; Format.pp_print_string ppf msg; - List.iter (fun err -> Format.fprintf ppf "@\n@[<2>%a@]" default_error_reporter err) - sub + List.iter (Format.fprintf ppf "@\n@[<2>%a@]" default_error_reporter) sub end let error_reporter = ref default_error_reporter @@ -361,13 +413,7 @@ let report_error ppf err = ;; let error_of_printer loc print x = - let buf = Buffer.create 64 in - let ppf = Format.formatter_of_buffer buf in - pp_print_string ppf "Error: "; - print ppf x; - pp_print_flush ppf (); - let msg = Buffer.contents buf in - errorf ~loc "%s" msg + errorf_prefixed ~loc "%a@?" print x let error_of_printer_file print x = error_of_printer (in_file !input_name) print x @@ -376,21 +422,24 @@ let () = register_error_of_exn (function | Sys_error msg -> - Some (errorf ~loc:(in_file !input_name) "Error: I/O error: %s" msg) + Some (errorf_prefixed ~loc:(in_file !input_name) + "I/O error: %s" msg) | Warnings.Errors n -> Some - (errorf ~loc:(in_file !input_name) - "Error: Some fatal warnings were triggered (%d occurrences)" n) + (errorf_prefixed ~loc:(in_file !input_name) + "Some fatal warnings were triggered (%d occurrences)" n) | _ -> None ) +external reraise : exn -> 'a = "%reraise" + let rec report_exception_rec n ppf exn = try match error_of_exn exn with | Some err -> fprintf ppf "@[%a@]@." report_error err - | None -> raise exn + | None -> reraise exn with exn when n > 0 -> report_exception_rec (n-1) ppf exn @@ -407,4 +456,4 @@ let () = ) let raise_errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") = - Printf.ksprintf (fun msg -> raise (Error ({loc; msg; sub; if_highlight}))) + pp_ksprintf (fun msg -> raise (Error ({loc; msg; sub; if_highlight}))) diff --git a/parsing/location.mli b/parsing/location.mli index 77b754f7..866914ad 100644 --- a/parsing/location.mli +++ b/parsing/location.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Source code locations (ranges of positions), used in parsetree. *) @@ -53,7 +56,7 @@ val input_lexbuf: Lexing.lexbuf option ref val get_pos_info: Lexing.position -> string * int * int (* file, line, char *) val print_loc: formatter -> t -> unit val print_error: formatter -> t -> unit -val print_error_cur_file: formatter -> unit +val print_error_cur_file: formatter -> unit -> unit val print_warning: t -> formatter -> Warnings.t -> unit val formatter_for_warnings : formatter ref val prerr_warning: t -> Warnings.t -> unit @@ -77,6 +80,7 @@ val mknoloc : 'a -> 'a loc val mkloc : 'a -> t -> 'a loc val print: formatter -> t -> unit +val print_compact: formatter -> t -> unit val print_filename: formatter -> string -> unit val absolute_path: string -> string @@ -88,7 +92,6 @@ val show_filename: string -> string val absname: bool ref - (* Support for located errors *) type error = @@ -101,13 +104,21 @@ type error = exception Error of error +val print_error_prefix: formatter -> unit -> unit + (* print the prefix "Error:" possibly with style *) + val error: ?loc:t -> ?sub:error list -> ?if_highlight:string -> string -> error val errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string - -> ('a, unit, string, error) format4 -> 'a + -> ('a, Format.formatter, unit, error) format4 -> 'a + +val errorf_prefixed : ?loc:t -> ?sub:error list -> ?if_highlight:string + -> ('a, Format.formatter, unit, error) format4 -> 'a + (* same as {!errorf}, but prints the error prefix "Error:" before yielding + * to the format string *) val raise_errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string - -> ('a, unit, string, 'b) format4 -> 'a + -> ('a, Format.formatter, unit, 'b) format4 -> 'a val error_of_printer: t -> (formatter -> 'a -> unit) -> 'a -> error diff --git a/parsing/longident.ml b/parsing/longident.ml index 706881af..04677ca0 100644 --- a/parsing/longident.ml +++ b/parsing/longident.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 t = Lident of string diff --git a/parsing/longident.mli b/parsing/longident.mli index 9e795855..6f364a0e 100644 --- a/parsing/longident.mli +++ b/parsing/longident.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Long identifiers, used in parsetree. *) diff --git a/parsing/parse.ml b/parsing/parse.ml index 0941bf80..ba89f0e2 100644 --- a/parsing/parse.ml +++ b/parsing/parse.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Entry points in the parser *) diff --git a/parsing/parse.mli b/parsing/parse.mli index 9d17a24b..78223a3b 100644 --- a/parsing/parse.mli +++ b/parsing/parse.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Entry points in the parser *) diff --git a/parsing/parser.mly b/parsing/parser.mly index 863651c7..684565fa 100644 --- a/parsing/parser.mly +++ b/parsing/parser.mly @@ -1,14 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 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. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The parser definition */ @@ -23,21 +26,18 @@ open Docstrings let mktyp d = Typ.mk ~loc:(symbol_rloc()) d let mkpat d = Pat.mk ~loc:(symbol_rloc()) d let mkexp d = Exp.mk ~loc:(symbol_rloc()) d -let mkmty d = Mty.mk ~loc:(symbol_rloc()) d +let mkmty ?attrs d = Mty.mk ~loc:(symbol_rloc()) ?attrs d let mksig d = Sig.mk ~loc:(symbol_rloc()) d -let mkmod d = Mod.mk ~loc:(symbol_rloc()) d +let mkmod ?attrs d = Mod.mk ~loc:(symbol_rloc()) ?attrs d let mkstr d = Str.mk ~loc:(symbol_rloc()) d -let mkclass d = Cl.mk ~loc:(symbol_rloc()) d -let mkcty d = Cty.mk ~loc:(symbol_rloc()) d +let mkclass ?attrs d = Cl.mk ~loc:(symbol_rloc()) ?attrs d +let mkcty ?attrs d = Cty.mk ~loc:(symbol_rloc()) ?attrs d let mkctf ?attrs ?docs d = Ctf.mk ~loc:(symbol_rloc()) ?attrs ?docs d let mkcf ?attrs ?docs d = Cf.mk ~loc:(symbol_rloc()) ?attrs ?docs d let mkrhs rhs pos = mkloc rhs (rhs_loc pos) -let mkoption d = - let loc = {d.ptyp_loc with loc_ghost = true} in - Typ.mk ~loc (Ptyp_constr(mkloc (Ldot (Lident "*predef*", "option")) loc,[d])) let reloc_pat x = { x with ppat_loc = symbol_rloc () };; let reloc_exp x = { x with pexp_loc = symbol_rloc () };; @@ -71,43 +71,32 @@ let ghpat d = Pat.mk ~loc:(symbol_gloc ()) d let ghtyp d = Typ.mk ~loc:(symbol_gloc ()) d let ghloc d = { txt = d; loc = symbol_gloc () } let ghstr d = Str.mk ~loc:(symbol_gloc()) d - -let ghunit () = - ghexp (Pexp_construct (mknoloc (Lident "()"), None)) +let ghsig d = Sig.mk ~loc:(symbol_gloc()) d let mkinfix arg1 name arg2 = - mkexp(Pexp_apply(mkoperator name 2, ["", arg1; "", arg2])) + mkexp(Pexp_apply(mkoperator name 2, [Nolabel, arg1; Nolabel, arg2])) -let neg_float_string f = +let neg_string f = if String.length f > 0 && f.[0] = '-' then String.sub f 1 (String.length f - 1) else "-" ^ f let mkuminus name arg = match name, arg.pexp_desc with - | "-", Pexp_constant(Const_int n) -> - mkexp(Pexp_constant(Const_int(-n))) - | "-", Pexp_constant(Const_int32 n) -> - mkexp(Pexp_constant(Const_int32(Int32.neg n))) - | "-", Pexp_constant(Const_int64 n) -> - mkexp(Pexp_constant(Const_int64(Int64.neg n))) - | "-", Pexp_constant(Const_nativeint n) -> - mkexp(Pexp_constant(Const_nativeint(Nativeint.neg n))) - | ("-" | "-."), Pexp_constant(Const_float f) -> - mkexp(Pexp_constant(Const_float(neg_float_string f))) + | "-", Pexp_constant(Pconst_integer (n,m)) -> + mkexp(Pexp_constant(Pconst_integer(neg_string n,m))) + | ("-" | "-."), Pexp_constant(Pconst_float (f, m)) -> + mkexp(Pexp_constant(Pconst_float(neg_string f, m))) | _ -> - mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, ["", arg])) + mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, [Nolabel, arg])) let mkuplus name arg = let desc = arg.pexp_desc in match name, desc with - | "+", Pexp_constant(Const_int _) - | "+", Pexp_constant(Const_int32 _) - | "+", Pexp_constant(Const_int64 _) - | "+", Pexp_constant(Const_nativeint _) - | ("+" | "+."), Pexp_constant(Const_float _) -> mkexp desc + | "+", Pexp_constant(Pconst_integer _) + | ("+" | "+."), Pexp_constant(Pconst_float _) -> mkexp desc | _ -> - mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, ["", arg])) + mkexp(Pexp_apply(mkoperator ("~" ^ name) 1, [Nolabel, arg])) let mkexp_cons consloc args loc = Exp.mk ~loc (Pexp_construct(mkloc (Lident "::") consloc, Some args)) @@ -152,6 +141,14 @@ let mkexp_constraint e (t1, t2) = | _, Some t -> ghexp(Pexp_coerce(e, t1, t)) | None, None -> assert false +let mkexp_opt_constraint e = function + | None -> e + | Some constraint_ -> mkexp_constraint e constraint_ + +let mkpat_opt_constraint p = function + | None -> p + | Some typ -> mkpat (Ppat_constraint(p, typ)) + let array_function str name = ghloc (Ldot(Lident str, (if !Clflags.fast then "unsafe_" ^ name else name))) @@ -180,34 +177,36 @@ let bigarray_get arr arg = match bigarray_untuplify arg with [c1] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" get)), - ["", arr; "", c1])) + [Nolabel, arr; Nolabel, c1])) | [c1;c2] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array2" get)), - ["", arr; "", c1; "", c2])) + [Nolabel, arr; Nolabel, c1; Nolabel, c2])) | [c1;c2;c3] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array3" get)), - ["", arr; "", c1; "", c2; "", c3])) + [Nolabel, arr; Nolabel, c1; Nolabel, c2; Nolabel, c3])) | coords -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "get")), - ["", arr; "", ghexp(Pexp_array coords)])) + [Nolabel, arr; Nolabel, ghexp(Pexp_array coords)])) let bigarray_set arr arg newval = let set = if !Clflags.fast then "unsafe_set" else "set" in match bigarray_untuplify arg with [c1] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array1" set)), - ["", arr; "", c1; "", newval])) + [Nolabel, arr; Nolabel, c1; Nolabel, newval])) | [c1;c2] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array2" set)), - ["", arr; "", c1; "", c2; "", newval])) + [Nolabel, arr; Nolabel, c1; + Nolabel, c2; Nolabel, newval])) | [c1;c2;c3] -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Array3" set)), - ["", arr; "", c1; "", c2; "", c3; "", newval])) + [Nolabel, arr; Nolabel, c1; + Nolabel, c2; Nolabel, c3; Nolabel, newval])) | coords -> mkexp(Pexp_apply(ghexp(Pexp_ident(bigarray_function "Genarray" "set")), - ["", arr; - "", ghexp(Pexp_array coords); - "", newval])) + [Nolabel, arr; + Nolabel, ghexp(Pexp_array coords); + Nolabel, newval])) let lapply p1 p2 = if !Clflags.applicative_functors @@ -268,12 +267,13 @@ let varify_constructors var_names t = in loop t +let mk_newtypes newtypes exp = + List.fold_right (fun newtype exp -> mkexp (Pexp_newtype (newtype, exp))) + newtypes exp + let wrap_type_annotation newtypes core_type body = let exp = mkexp(Pexp_constraint(body,core_type)) in - let exp = - List.fold_right (fun newtype exp -> mkexp (Pexp_newtype (newtype, exp))) - newtypes exp - in + let exp = mk_newtypes newtypes exp in (exp, ghtyp(Ptyp_poly(newtypes,varify_constructors newtypes core_type))) let wrap_exp_attrs body (ext, attrs) = @@ -286,6 +286,49 @@ let wrap_exp_attrs body (ext, attrs) = let mkexp_attrs d attrs = wrap_exp_attrs (mkexp d) attrs +let wrap_typ_attrs typ (ext, attrs) = + (* todo: keep exact location for the entire attribute *) + let typ = {typ with ptyp_attributes = attrs @ typ.ptyp_attributes} in + match ext with + | None -> typ + | Some id -> ghtyp(Ptyp_extension (id, PTyp typ)) + +let mktyp_attrs d attrs = + wrap_typ_attrs (mktyp d) attrs + +let wrap_pat_attrs pat (ext, attrs) = + (* todo: keep exact location for the entire attribute *) + let pat = {pat with ppat_attributes = attrs @ pat.ppat_attributes} in + match ext with + | None -> pat + | Some id -> ghpat(Ppat_extension (id, PPat (pat, None))) + +let mkpat_attrs d attrs = + wrap_pat_attrs (mkpat d) attrs + +let wrap_class_attrs body attrs = + {body with pcl_attributes = attrs @ body.pcl_attributes} +let wrap_mod_attrs body attrs = + {body with pmod_attributes = attrs @ body.pmod_attributes} +let wrap_mty_attrs body attrs = + {body with pmty_attributes = attrs @ body.pmty_attributes} + +let wrap_str_ext body ext = + match ext with + | None -> body + | Some id -> ghstr(Pstr_extension ((id, PStr [body]), [])) + +let mkstr_ext d ext = + wrap_str_ext (mkstr d) ext + +let wrap_sig_ext body ext = + match ext with + | None -> body + | Some id -> ghsig(Psig_extension ((id, PSig [body]), [])) + +let mksig_ext d ext = + wrap_sig_ext (mksig d) ext + let text_str pos = Str.text (rhs_text pos) let text_sig pos = Sig.text (rhs_text pos) let text_cstr pos = Cf.text (rhs_text pos) @@ -304,12 +347,9 @@ let extra_csig pos items = extra_text Ctf.text pos items let extra_def pos items = extra_text (fun txt -> [Ptop_def (Str.text txt)]) pos items -let add_nonrec rf attrs pos = - match rf with - | Recursive -> attrs - | Nonrecursive -> - let name = { txt = "nonrec"; loc = rhs_loc pos } in - (name, PStr []) :: attrs +let extra_rhs_core_type ct ~pos = + let docs = rhs_info pos in + { ct with ptyp_attributes = add_info_attrs docs ct.ptyp_attributes } type let_binding = { lb_pattern: pattern; @@ -323,48 +363,37 @@ type let_bindings = { lbs_bindings: let_binding list; lbs_rec: rec_flag; lbs_extension: string Asttypes.loc option; - lbs_attributes: attributes; lbs_loc: Location.t } -let mklb (p, e) attrs = +let mklb first (p, e) attrs = { lb_pattern = p; lb_expression = e; lb_attributes = attrs; lb_docs = symbol_docs_lazy (); - lb_text = symbol_text_lazy (); + lb_text = if first then empty_text_lazy + else symbol_text_lazy (); lb_loc = symbol_rloc (); } -let mklbs (ext, attrs) rf lb = +let mklbs ext rf lb = { lbs_bindings = [lb]; lbs_rec = rf; lbs_extension = ext ; - lbs_attributes = attrs; lbs_loc = symbol_rloc (); } let addlb lbs lb = { lbs with lbs_bindings = lb :: lbs.lbs_bindings } let val_of_let_bindings lbs = - let str = - match lbs.lbs_bindings with - | [ {lb_pattern = { ppat_desc = Ppat_any; ppat_loc = _ }; _} as lb ] -> - let exp = wrap_exp_attrs lb.lb_expression - (None, lbs.lbs_attributes) in - mkstr (Pstr_eval (exp, lb.lb_attributes)) - | bindings -> - if lbs.lbs_attributes <> [] then - raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "attributes"))); - let bindings = - List.map - (fun lb -> - Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes - ~docs:(Lazy.force lb.lb_docs) - ~text:(Lazy.force lb.lb_text) - lb.lb_pattern lb.lb_expression) - bindings - in - mkstr(Pstr_value(lbs.lbs_rec, List.rev bindings)) + let bindings = + List.map + (fun lb -> + Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes + ~docs:(Lazy.force lb.lb_docs) + ~text:(Lazy.force lb.lb_text) + lb.lb_pattern lb.lb_expression) + lbs.lbs_bindings in + let str = mkstr(Pstr_value(lbs.lbs_rec, List.rev bindings)) in match lbs.lbs_extension with | None -> str | Some id -> ghstr (Pstr_extension((id, PStr [str]), [])) @@ -373,29 +402,64 @@ let expr_of_let_bindings lbs body = let bindings = List.map (fun lb -> - if lb.lb_attributes <> [] then - raise Syntaxerr.(Error(Not_expecting(lb.lb_loc, "item attribute"))); - Vb.mk ~loc:lb.lb_loc lb.lb_pattern lb.lb_expression) + Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes + lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in mkexp_attrs (Pexp_let(lbs.lbs_rec, List.rev bindings, body)) - (lbs.lbs_extension, lbs.lbs_attributes) + (lbs.lbs_extension, []) let class_of_let_bindings lbs body = let bindings = List.map (fun lb -> - if lb.lb_attributes <> [] then - raise Syntaxerr.(Error(Not_expecting(lb.lb_loc, "item attribute"))); - Vb.mk ~loc:lb.lb_loc lb.lb_pattern lb.lb_expression) + Vb.mk ~loc:lb.lb_loc ~attrs:lb.lb_attributes + lb.lb_pattern lb.lb_expression) lbs.lbs_bindings in if lbs.lbs_extension <> None then raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "extension"))); - if lbs.lbs_attributes <> [] then - raise Syntaxerr.(Error(Not_expecting(lbs.lbs_loc, "attributes"))); mkclass(Pcl_let (lbs.lbs_rec, List.rev bindings, body)) + +(* Alternatively, we could keep the generic module type in the Parsetree + and extract the package type during type-checking. In that case, + the assertions below should be turned into explicit checks. *) +let package_type_of_module_type pmty = + let err loc s = + raise (Syntaxerr.Error (Syntaxerr.Invalid_package_type (loc, s))) + in + let map_cstr = function + | Pwith_type (lid, ptyp) -> + let loc = ptyp.ptype_loc in + if ptyp.ptype_params <> [] then + err loc "parametrized types are not supported"; + if ptyp.ptype_cstrs <> [] then + err loc "constrained types are not supported"; + if ptyp.ptype_private <> Public then + err loc "private types are not supported"; + + (* restrictions below are checked by the 'with_constraint' rule *) + assert (ptyp.ptype_kind = Ptype_abstract); + assert (ptyp.ptype_attributes = []); + let ty = + match ptyp.ptype_manifest with + | Some ty -> ty + | None -> assert false + in + (lid, ty) + | _ -> + err pmty.pmty_loc "only 'with type t =' constraints are supported" + in + match pmty with + | {pmty_desc = Pmty_ident lid} -> (lid, []) + | {pmty_desc = Pmty_with({pmty_desc = Pmty_ident lid}, cstrs)} -> + (lid, List.map map_cstr cstrs) + | _ -> + err pmty.pmty_loc + "only module type identifier and 'with type' constraints are supported" + + %} /* Tokens */ @@ -431,7 +495,7 @@ let class_of_let_bindings lbs body = %token EXCEPTION %token EXTERNAL %token FALSE -%token FLOAT +%token FLOAT %token FOR %token FUN %token FUNCTION @@ -449,9 +513,7 @@ let class_of_let_bindings lbs body = %token INFIXOP4 %token INHERIT %token INITIALIZER -%token INT -%token INT32 -%token INT64 +%token INT %token LABEL %token LAZY %token LBRACE @@ -477,7 +539,6 @@ let class_of_let_bindings lbs body = %token MINUSGREATER %token MODULE %token MUTABLE -%token NATIVEINT %token NEW %token NONREC %token OBJECT @@ -584,9 +645,9 @@ The precedences must be listed from low to high. %nonassoc below_DOT %nonassoc DOT /* Finally, the first tokens of simple_expr are above everything else. */ -%nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT INT32 INT64 +%nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT LBRACE LBRACELESS LBRACKET LBRACKETBAR LIDENT LPAREN - NEW NATIVEINT PREFIXOP STRING TRUE UIDENT + NEW PREFIXOP STRING TRUE UIDENT LBRACKETPERCENT LBRACKETPERCENTPERCENT @@ -692,13 +753,16 @@ functor_args: module_expr: mod_longident { mkmod(Pmod_ident (mkrhs $1 1)) } - | STRUCT structure END - { mkmod(Pmod_structure(extra_str 2 $2)) } - | STRUCT structure error - { unclosed "struct" 1 "end" 3 } - | FUNCTOR functor_args MINUSGREATER module_expr - { List.fold_left (fun acc (n, t) -> mkmod(Pmod_functor(n, t, acc))) - $4 $2 } + | STRUCT attributes structure END + { mkmod ~attrs:$2 (Pmod_structure(extra_str 3 $3)) } + | STRUCT attributes structure error + { unclosed "struct" 1 "end" 4 } + | FUNCTOR attributes functor_args MINUSGREATER module_expr + { let modexp = + List.fold_left + (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 LPAREN RPAREN @@ -713,24 +777,28 @@ module_expr: { $2 } | LPAREN module_expr error { unclosed "(" 1 ")" 3 } - | LPAREN VAL expr RPAREN - { mkmod(Pmod_unpack $3) } - | LPAREN VAL expr COLON package_type RPAREN - { mkmod(Pmod_unpack( - ghexp(Pexp_constraint($3, ghtyp(Ptyp_package $5))))) } - | LPAREN VAL expr COLON package_type COLONGREATER package_type RPAREN - { mkmod(Pmod_unpack( - ghexp(Pexp_coerce($3, Some(ghtyp(Ptyp_package $5)), - ghtyp(Ptyp_package $7))))) } - | LPAREN VAL expr COLONGREATER package_type RPAREN - { mkmod(Pmod_unpack( - ghexp(Pexp_coerce($3, None, ghtyp(Ptyp_package $5))))) } - | LPAREN VAL expr COLON error - { unclosed "(" 1 ")" 5 } - | LPAREN VAL expr COLONGREATER error + | LPAREN VAL attributes expr RPAREN + { mkmod ~attrs:$3 (Pmod_unpack $4)} + | LPAREN VAL attributes expr COLON package_type RPAREN + { mkmod ~attrs:$3 + (Pmod_unpack( + ghexp(Pexp_constraint($4, ghtyp(Ptyp_package $6))))) } + | LPAREN VAL attributes expr COLON package_type COLONGREATER package_type + RPAREN + { mkmod ~attrs:$3 + (Pmod_unpack( + ghexp(Pexp_coerce($4, Some(ghtyp(Ptyp_package $6)), + ghtyp(Ptyp_package $8))))) } + | LPAREN VAL attributes expr COLONGREATER package_type RPAREN + { mkmod ~attrs:$3 + (Pmod_unpack( + ghexp(Pexp_coerce($4, None, ghtyp(Ptyp_package $6))))) } + | LPAREN VAL attributes expr COLON error + { unclosed "(" 1 ")" 6 } + | LPAREN VAL attributes expr COLONGREATER error + { unclosed "(" 1 ")" 6 } + | LPAREN VAL attributes expr error { unclosed "(" 1 ")" 5 } - | LPAREN VAL expr error - { unclosed "(" 1 ")" 4 } | module_expr attribute { Mod.attr $1 $2 } | extension @@ -752,26 +820,29 @@ structure_item: let_bindings { val_of_let_bindings $1 } | primitive_declaration - { mkstr (Pstr_primitive $1) } + { let (body, ext) = $1 in mkstr_ext (Pstr_primitive body) ext } + | value_description + { let (body, ext) = $1 in mkstr_ext (Pstr_primitive body) ext } | type_declarations - { mkstr(Pstr_type (List.rev $1)) } + { let (nr, l, ext ) = $1 in mkstr_ext (Pstr_type (nr, List.rev l)) ext } | str_type_extension - { mkstr(Pstr_typext $1) } + { let (l, ext) = $1 in mkstr_ext (Pstr_typext l) ext } | str_exception_declaration - { mkstr(Pstr_exception $1) } + { let (l, ext) = $1 in mkstr_ext (Pstr_exception l) ext } | module_binding - { mkstr(Pstr_module $1) } + { let (body, ext) = $1 in mkstr_ext (Pstr_module body) ext } | rec_module_bindings - { mkstr(Pstr_recmodule(List.rev $1)) } + { let (l, ext) = $1 in mkstr_ext (Pstr_recmodule(List.rev l)) ext } | module_type_declaration - { mkstr(Pstr_modtype $1) } - | open_statement { mkstr(Pstr_open $1) } + { let (body, ext) = $1 in mkstr_ext (Pstr_modtype body) ext } + | open_statement + { let (body, ext) = $1 in mkstr_ext (Pstr_open body) ext } | class_declarations - { mkstr(Pstr_class (List.rev $1)) } + { let (l, ext) = $1 in mkstr_ext (Pstr_class (List.rev l)) ext } | class_type_declarations - { mkstr(Pstr_class_type (List.rev $1)) } + { let (l, ext) = $1 in mkstr_ext (Pstr_class_type (List.rev l)) ext } | str_include_statement - { mkstr(Pstr_include $1) } + { let (body, ext) = $1 in mkstr_ext (Pstr_include body) ext } | item_extension post_item_attributes { mkstr(Pstr_extension ($1, (add_docs_attrs (symbol_docs ()) $2))) } | floating_attribute @@ -779,9 +850,11 @@ structure_item: mkstr(Pstr_attribute $1) } ; str_include_statement: - INCLUDE module_expr post_item_attributes - { Incl.mk $2 ~attrs:$3 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + INCLUDE ext_attributes module_expr post_item_attributes + { let (ext, attrs) = $2 in + Incl.mk $3 ~attrs:(attrs@$4) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; module_binding_body: EQUAL module_expr @@ -792,22 +865,27 @@ module_binding_body: { mkmod(Pmod_functor(fst $1, snd $1, $2)) } ; module_binding: - MODULE UIDENT module_binding_body post_item_attributes - { Mb.mk (mkrhs $2 2) $3 ~attrs:$4 - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + MODULE ext_attributes UIDENT module_binding_body post_item_attributes + { let (ext, attrs) = $2 in + Mb.mk (mkrhs $3 3) $4 ~attrs:(attrs@$5) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + , ext } ; rec_module_bindings: - rec_module_binding { [$1] } - | rec_module_bindings and_module_binding { $2 :: $1 } + rec_module_binding { let (b, ext) = $1 in ([b], ext) } + | rec_module_bindings and_module_binding + { let (l, ext) = $1 in ($2 :: l, ext) } ; rec_module_binding: - MODULE REC UIDENT module_binding_body post_item_attributes - { Mb.mk (mkrhs $3 3) $4 ~attrs:$5 - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + MODULE ext_attributes REC UIDENT module_binding_body post_item_attributes + { let (ext, attrs) = $2 in + Mb.mk (mkrhs $4 4) $5 ~attrs:(attrs@$6) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + , ext } ; and_module_binding: - AND UIDENT module_binding_body post_item_attributes - { Mb.mk (mkrhs $2 2) $3 ~attrs:$4 ~loc:(symbol_rloc ()) + AND attributes UIDENT module_binding_body post_item_attributes + { Mb.mk (mkrhs $3 3) $4 ~attrs:($2@$5) ~loc:(symbol_rloc ()) ~text:(symbol_text ()) ~docs:(symbol_docs ()) } ; @@ -816,18 +894,24 @@ and_module_binding: module_type: mty_longident { mkmty(Pmty_ident (mkrhs $1 1)) } - | SIG signature END - { mkmty(Pmty_signature (extra_sig 2 $2)) } - | SIG signature error - { unclosed "sig" 1 "end" 3 } - | FUNCTOR functor_args MINUSGREATER module_type + | SIG attributes signature END + { mkmty ~attrs:$2 (Pmty_signature (extra_sig 3 $3)) } + | SIG attributes signature error + { unclosed "sig" 1 "end" 4 } + | FUNCTOR attributes functor_args MINUSGREATER module_type %prec below_WITH - { List.fold_left (fun acc (n, t) -> mkmty(Pmty_functor(n, t, acc))) - $4 $2 } + { let mty = + List.fold_left + (fun acc (n, t) -> mkmty(Pmty_functor(n, t, acc))) + $5 $3 + in wrap_mty_attrs mty $2 } + | module_type MINUSGREATER module_type + %prec below_WITH + { mkmty(Pmty_functor(mknoloc "_", Some $1, $3)) } | module_type WITH with_constraints { mkmty(Pmty_with($1, List.rev $3)) } - | MODULE TYPE OF module_expr %prec below_LBRACKETAT - { mkmty(Pmty_typeof $4) } + | MODULE TYPE OF attributes module_expr %prec below_LBRACKETAT + { mkmty ~attrs:$4 (Pmty_typeof $5) } /* | LPAREN MODULE mod_longident RPAREN { mkmty (Pmty_alias (mkrhs $3 3)) } */ | LPAREN module_type RPAREN @@ -846,31 +930,31 @@ signature: ; signature_item: value_description - { mksig(Psig_value $1) } + { let (body, ext) = $1 in mksig_ext (Psig_value body) ext } | primitive_declaration - { mksig(Psig_value $1) } + { let (body, ext) = $1 in mksig_ext (Psig_value body) ext} | type_declarations - { mksig(Psig_type (List.rev $1)) } + { let (nr, l, ext) = $1 in mksig_ext (Psig_type (nr, List.rev l)) ext } | sig_type_extension - { mksig(Psig_typext $1) } + { let (l, ext) = $1 in mksig_ext (Psig_typext l) ext } | sig_exception_declaration - { mksig(Psig_exception $1) } + { let (l, ext) = $1 in mksig_ext (Psig_exception l) ext } | module_declaration - { mksig(Psig_module $1) } + { let (body, ext) = $1 in mksig_ext (Psig_module body) ext } | module_alias - { mksig(Psig_module $1) } + { let (body, ext) = $1 in mksig_ext (Psig_module body) ext } | rec_module_declarations - { mksig(Psig_recmodule (List.rev $1)) } + { let (l, ext) = $1 in mksig_ext (Psig_recmodule (List.rev l)) ext } | module_type_declaration - { mksig(Psig_modtype $1) } + { let (body, ext) = $1 in mksig_ext (Psig_modtype body) ext } | open_statement - { mksig(Psig_open $1) } + { let (body, ext) = $1 in mksig_ext (Psig_open body) ext } | sig_include_statement - { mksig(Psig_include $1) } + { let (body, ext) = $1 in mksig_ext (Psig_include body) ext } | class_descriptions - { mksig(Psig_class (List.rev $1)) } + { let (l, ext) = $1 in mksig_ext (Psig_class (List.rev l)) ext } | class_type_declarations - { mksig(Psig_class_type (List.rev $1)) } + { let (l, ext) = $1 in mksig_ext (Psig_class_type (List.rev l)) ext } | item_extension post_item_attributes { mksig(Psig_extension ($1, (add_docs_attrs (symbol_docs ()) $2))) } | floating_attribute @@ -878,14 +962,18 @@ signature_item: mksig(Psig_attribute $1) } ; open_statement: - | OPEN override_flag mod_longident post_item_attributes - { Opn.mk (mkrhs $3 3) ~override:$2 ~attrs:$4 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + | OPEN override_flag ext_attributes mod_longident post_item_attributes + { let (ext, attrs) = $3 in + Opn.mk (mkrhs $4 4) ~override:$2 ~attrs:(attrs@$5) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext} ; sig_include_statement: - INCLUDE module_type post_item_attributes %prec below_WITH - { Incl.mk $2 ~attrs:$3 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + INCLUDE ext_attributes module_type post_item_attributes %prec below_WITH + { let (ext, attrs) = $2 in + Incl.mk $3 ~attrs:(attrs@$4) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext} ; module_declaration_body: COLON module_type @@ -896,28 +984,36 @@ module_declaration_body: { mkmty(Pmty_functor(mkrhs "*" 1, None, $3)) } ; module_declaration: - MODULE UIDENT module_declaration_body post_item_attributes - { Md.mk (mkrhs $2 2) $3 ~attrs:$4 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + MODULE ext_attributes UIDENT module_declaration_body post_item_attributes + { let (ext, attrs) = $2 in + Md.mk (mkrhs $3 3) $4 ~attrs:(attrs@$5) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; module_alias: - MODULE UIDENT EQUAL mod_longident post_item_attributes - { Md.mk (mkrhs $2 2) - (Mty.alias ~loc:(rhs_loc 4) (mkrhs $4 4)) ~attrs:$5 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + MODULE ext_attributes UIDENT EQUAL mod_longident post_item_attributes + { let (ext, attrs) = $2 in + Md.mk (mkrhs $3 3) + (Mty.alias ~loc:(rhs_loc 5) (mkrhs $5 5)) ~attrs:(attrs@$6) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; rec_module_declarations: - rec_module_declaration { [$1] } - | rec_module_declarations and_module_declaration { $2 :: $1 } + rec_module_declaration + { let (body, ext) = $1 in ([body], ext) } + | rec_module_declarations and_module_declaration + { let (l, ext) = $1 in ($2 :: l, ext) } ; rec_module_declaration: - MODULE REC UIDENT COLON module_type post_item_attributes - { Md.mk (mkrhs $3 3) $5 ~attrs:$6 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + MODULE ext_attributes REC UIDENT COLON module_type post_item_attributes + { let (ext, attrs) = $2 in + Md.mk (mkrhs $4 4) $6 ~attrs:(attrs@$7) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext} ; and_module_declaration: - AND UIDENT COLON module_type post_item_attributes - { Md.mk (mkrhs $2 2) $4 ~attrs:$5 ~loc:(symbol_rloc()) + AND attributes UIDENT COLON module_type post_item_attributes + { Md.mk (mkrhs $3 3) $5 ~attrs:($2@$6) ~loc:(symbol_rloc()) ~text:(symbol_text()) ~docs:(symbol_docs()) } ; module_type_declaration_body: @@ -925,27 +1021,34 @@ module_type_declaration_body: | EQUAL module_type { Some $2 } ; module_type_declaration: - MODULE TYPE ident module_type_declaration_body post_item_attributes - { Mtd.mk (mkrhs $3 3) ?typ:$4 ~attrs:$5 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + MODULE TYPE ext_attributes ident module_type_declaration_body + post_item_attributes + { let (ext, attrs) = $3 in + Mtd.mk (mkrhs $4 4) ?typ:$5 ~attrs:(attrs@$6) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; /* Class expressions */ class_declarations: - class_declaration { [$1] } - | class_declarations and_class_declaration { $2 :: $1 } + class_declaration + { let (body, ext) = $1 in ([body], ext) } + | class_declarations and_class_declaration + { let (l, ext) = $1 in ($2 :: l, ext) } ; class_declaration: - CLASS virtual_flag class_type_parameters LIDENT class_fun_binding - post_item_attributes - { Ci.mk (mkrhs $4 4) $5 ~virt:$2 ~params:$3 ~attrs:$6 - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + CLASS ext_attributes virtual_flag class_type_parameters LIDENT + class_fun_binding post_item_attributes + { let (ext, attrs) = $2 in + Ci.mk (mkrhs $5 5) $6 ~virt:$3 ~params:$4 ~attrs:(attrs@$7) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + , ext } ; and_class_declaration: - AND virtual_flag class_type_parameters LIDENT class_fun_binding + AND attributes virtual_flag class_type_parameters LIDENT class_fun_binding post_item_attributes - { Ci.mk (mkrhs $4 4) $5 ~virt:$2 ~params:$3 - ~attrs:$6 ~loc:(symbol_rloc ()) + { Ci.mk (mkrhs $5 5) $6 ~virt:$3 ~params:$4 + ~attrs:($2@$7) ~loc:(symbol_rloc ()) ~text:(symbol_text ()) ~docs:(symbol_docs ()) } ; class_fun_binding: @@ -969,8 +1072,8 @@ class_fun_def: class_expr: class_simple_expr { $1 } - | FUN class_fun_def - { $2 } + | FUN attributes class_fun_def + { wrap_class_attrs $3 $2 } | class_simple_expr simple_labeled_expr_list { mkclass(Pcl_apply($1, List.rev $2)) } | let_bindings IN class_expr @@ -985,10 +1088,10 @@ class_simple_expr: { mkclass(Pcl_constr(mkloc $4 (rhs_loc 4), List.rev $2)) } | class_longident { mkclass(Pcl_constr(mkrhs $1 1, [])) } - | OBJECT class_structure END - { mkclass(Pcl_structure $2) } - | OBJECT class_structure error - { unclosed "object" 1 "end" 3 } + | OBJECT attributes class_structure END + { mkclass ~attrs:$2 (Pcl_structure $3) } + | OBJECT attributes class_structure error + { unclosed "object" 1 "end" 4 } | LPAREN class_expr COLON class_type RPAREN { mkclass(Pcl_constraint($2, $4)) } | LPAREN class_expr COLON class_type error @@ -1017,16 +1120,19 @@ class_fields: { $2 :: (text_cstr 2) @ $1 } ; class_field: - | INHERIT override_flag class_expr parent_binder post_item_attributes - { mkcf (Pcf_inherit ($2, $3, $4)) ~attrs:$5 ~docs:(symbol_docs ()) } + | INHERIT override_flag attributes class_expr parent_binder + post_item_attributes + { mkcf (Pcf_inherit ($2, $4, $5)) ~attrs:($3@$6) ~docs:(symbol_docs ()) } | VAL value post_item_attributes - { mkcf (Pcf_val $2) ~attrs:$3 ~docs:(symbol_docs ()) } + { let v, attrs = $2 in + mkcf (Pcf_val v) ~attrs:(attrs@$3) ~docs:(symbol_docs ()) } | METHOD method_ post_item_attributes - { mkcf (Pcf_method $2) ~attrs:$3 ~docs:(symbol_docs ()) } - | CONSTRAINT constrain_field post_item_attributes - { mkcf (Pcf_constraint $2) ~attrs:$3 ~docs:(symbol_docs ()) } - | INITIALIZER seq_expr post_item_attributes - { mkcf (Pcf_initializer $2) ~attrs:$3 ~docs:(symbol_docs ()) } + { let meth, attrs = $2 in + mkcf (Pcf_method meth) ~attrs:(attrs@$3) ~docs:(symbol_docs ()) } + | CONSTRAINT attributes constrain_field post_item_attributes + { mkcf (Pcf_constraint $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + | INITIALIZER attributes seq_expr post_item_attributes + { mkcf (Pcf_initializer $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } | item_extension post_item_attributes { mkcf (Pcf_extension $1) ~attrs:$2 ~docs:(symbol_docs ()) } | floating_attribute @@ -1041,38 +1147,39 @@ parent_binder: ; value: /* TODO: factorize these rules (also with method): */ - override_flag MUTABLE VIRTUAL label COLON core_type + override_flag attributes MUTABLE VIRTUAL label COLON core_type + { if $1 = Override then syntax_error (); + (mkloc $5 (rhs_loc 5), Mutable, Cfk_virtual $7), $2 } + | override_flag attributes VIRTUAL mutable_flag label COLON core_type { if $1 = Override then syntax_error (); - mkloc $4 (rhs_loc 4), Mutable, Cfk_virtual $6 } - | VIRTUAL mutable_flag label COLON core_type - { mkrhs $3 3, $2, Cfk_virtual $5 } - | override_flag mutable_flag label EQUAL seq_expr - { mkrhs $3 3, $2, Cfk_concrete ($1, $5) } - | override_flag mutable_flag label type_constraint EQUAL seq_expr + (mkrhs $5 5, $4, Cfk_virtual $7), $2 } + | override_flag attributes mutable_flag label EQUAL seq_expr + { (mkrhs $4 4, $3, Cfk_concrete ($1, $6)), $2 } + | override_flag attributes mutable_flag label type_constraint EQUAL seq_expr { - let e = mkexp_constraint $6 $4 in - mkrhs $3 3, $2, Cfk_concrete ($1, e) + let e = mkexp_constraint $7 $5 in + (mkrhs $4 4, $3, Cfk_concrete ($1, e)), $2 } ; method_: /* TODO: factorize those rules... */ - override_flag PRIVATE VIRTUAL label COLON poly_type + override_flag attributes PRIVATE VIRTUAL label COLON poly_type { if $1 = Override then syntax_error (); - mkloc $4 (rhs_loc 4), Private, Cfk_virtual $6 } - | override_flag VIRTUAL private_flag label COLON poly_type + (mkloc $5 (rhs_loc 5), Private, Cfk_virtual $7), $2 } + | override_flag attributes VIRTUAL private_flag label COLON poly_type { if $1 = Override then syntax_error (); - mkloc $4 (rhs_loc 4), $3, Cfk_virtual $6 } - | override_flag private_flag label strict_binding - { mkloc $3 (rhs_loc 3), $2, - Cfk_concrete ($1, ghexp(Pexp_poly ($4, None))) } - | override_flag private_flag label COLON poly_type EQUAL seq_expr - { mkloc $3 (rhs_loc 3), $2, - Cfk_concrete ($1, ghexp(Pexp_poly($7, Some $5))) } - | override_flag private_flag label COLON TYPE lident_list + (mkloc $5 (rhs_loc 5), $4, Cfk_virtual $7), $2 } + | override_flag attributes private_flag label strict_binding + { (mkloc $4 (rhs_loc 4), $3, + Cfk_concrete ($1, ghexp(Pexp_poly ($5, None)))), $2 } + | override_flag attributes private_flag label COLON poly_type EQUAL seq_expr + { (mkloc $4 (rhs_loc 4), $3, + Cfk_concrete ($1, ghexp(Pexp_poly($8, Some $6)))), $2 } + | override_flag attributes private_flag label COLON TYPE lident_list DOT core_type EQUAL seq_expr - { let exp, poly = wrap_type_annotation $6 $8 $10 in - mkloc $3 (rhs_loc 3), $2, - Cfk_concrete ($1, ghexp(Pexp_poly(exp, Some poly))) } + { let exp, poly = wrap_type_annotation $7 $9 $11 in + (mkloc $4 (rhs_loc 4), $3, + Cfk_concrete ($1, ghexp(Pexp_poly(exp, Some poly)))), $2 } ; /* Class types */ @@ -1080,25 +1187,25 @@ method_: class_type: class_signature { $1 } - | QUESTION LIDENT COLON simple_core_type_or_tuple_no_attr MINUSGREATER + | QUESTION LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type - { mkcty(Pcty_arrow("?" ^ $2 , mkoption $4, $6)) } - | OPTLABEL simple_core_type_or_tuple_no_attr MINUSGREATER class_type - { mkcty(Pcty_arrow("?" ^ $1, mkoption $2, $4)) } - | LIDENT COLON simple_core_type_or_tuple_no_attr MINUSGREATER class_type - { mkcty(Pcty_arrow($1, $3, $5)) } - | simple_core_type_or_tuple_no_attr MINUSGREATER class_type - { mkcty(Pcty_arrow("", $1, $3)) } + { mkcty(Pcty_arrow(Optional $2 , $4, $6)) } + | OPTLABEL simple_core_type_or_tuple MINUSGREATER class_type + { mkcty(Pcty_arrow(Optional $1, $2, $4)) } + | LIDENT COLON simple_core_type_or_tuple MINUSGREATER class_type + { mkcty(Pcty_arrow(Labelled $1, $3, $5)) } + | simple_core_type_or_tuple MINUSGREATER class_type + { mkcty(Pcty_arrow(Nolabel, $1, $3)) } ; class_signature: LBRACKET core_type_comma_list RBRACKET clty_longident { mkcty(Pcty_constr (mkloc $4 (rhs_loc 4), List.rev $2)) } | clty_longident { mkcty(Pcty_constr (mkrhs $1 1, [])) } - | OBJECT class_sig_body END - { mkcty(Pcty_signature $2) } - | OBJECT class_sig_body error - { unclosed "object" 1 "end" 3 } + | OBJECT attributes class_sig_body END + { mkcty ~attrs:$2 (Pcty_signature $3) } + | OBJECT attributes class_sig_body error + { unclosed "object" 1 "end" 4 } | class_signature attribute { Cty.attr $1 $2 } | extension @@ -1119,17 +1226,18 @@ class_sig_fields: | class_sig_fields class_sig_field { $2 :: (text_csig 2) @ $1 } ; class_sig_field: - INHERIT class_signature post_item_attributes - { mkctf (Pctf_inherit $2) ~attrs:$3 ~docs:(symbol_docs ()) } - | VAL value_type post_item_attributes - { mkctf (Pctf_val $2) ~attrs:$3 ~docs:(symbol_docs ()) } - | METHOD private_virtual_flags label COLON poly_type post_item_attributes + INHERIT attributes class_signature post_item_attributes + { mkctf (Pctf_inherit $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + | VAL attributes value_type post_item_attributes + { mkctf (Pctf_val $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } + | METHOD attributes private_virtual_flags label COLON poly_type + post_item_attributes { - let (p, v) = $2 in - mkctf (Pctf_method ($3, p, v, $5)) ~attrs:$6 ~docs:(symbol_docs ()) + let (p, v) = $3 in + mkctf (Pctf_method ($4, p, v, $6)) ~attrs:($2@$7) ~docs:(symbol_docs ()) } - | CONSTRAINT constrain_field post_item_attributes - { mkctf (Pctf_constraint $2) ~attrs:$3 ~docs:(symbol_docs ()) } + | CONSTRAINT attributes constrain_field post_item_attributes + { mkctf (Pctf_constraint $3) ~attrs:($2@$4) ~docs:(symbol_docs ()) } | item_extension post_item_attributes { mkctf (Pctf_extension $1) ~attrs:$2 ~docs:(symbol_docs ()) } | floating_attribute @@ -1151,37 +1259,45 @@ constrain_field: core_type EQUAL core_type { $1, $3 } ; class_descriptions: - class_description { [$1] } - | class_descriptions and_class_description { $2 :: $1 } + class_description + { let (body, ext) = $1 in ([body],ext) } + | class_descriptions and_class_description + { let (l, ext) = $1 in ($2 :: l, ext) } ; class_description: - CLASS virtual_flag class_type_parameters LIDENT COLON class_type - post_item_attributes - { Ci.mk (mkrhs $4 4) $6 ~virt:$2 ~params:$3 ~attrs:$7 - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + CLASS ext_attributes virtual_flag class_type_parameters LIDENT COLON + class_type post_item_attributes + { let (ext, attrs) = $2 in + Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 ~attrs:(attrs@$8) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + , ext } ; and_class_description: - AND virtual_flag class_type_parameters LIDENT COLON class_type + AND attributes virtual_flag class_type_parameters LIDENT COLON class_type post_item_attributes - { Ci.mk (mkrhs $4 4) $6 ~virt:$2 ~params:$3 - ~attrs:$7 ~loc:(symbol_rloc ()) + { Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 + ~attrs:($2@$8) ~loc:(symbol_rloc ()) ~text:(symbol_text ()) ~docs:(symbol_docs ()) } ; class_type_declarations: - class_type_declaration { [$1] } - | class_type_declarations and_class_type_declaration { $2 :: $1 } + class_type_declaration + { let (body, ext) = $1 in ([body],ext) } + | class_type_declarations and_class_type_declaration + { let (l, ext) = $1 in ($2 :: l, ext) } ; class_type_declaration: - CLASS TYPE virtual_flag class_type_parameters LIDENT EQUAL + CLASS TYPE ext_attributes virtual_flag class_type_parameters LIDENT EQUAL class_signature post_item_attributes - { Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 ~attrs:$8 - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + { let (ext, attrs) = $3 in + Ci.mk (mkrhs $6 6) $8 ~virt:$4 ~params:$5 ~attrs:(attrs@$9) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + , ext} ; and_class_type_declaration: - AND virtual_flag class_type_parameters LIDENT EQUAL + AND attributes virtual_flag class_type_parameters LIDENT EQUAL class_signature post_item_attributes - { Ci.mk (mkrhs $4 4) $6 ~virt:$2 ~params:$3 - ~attrs:$7 ~loc:(symbol_rloc ()) + { Ci.mk (mkrhs $5 5) $7 ~virt:$3 ~params:$4 + ~attrs:($2@$8) ~loc:(symbol_rloc ()) ~text:(symbol_text ()) ~docs:(symbol_docs ()) } ; @@ -1194,21 +1310,21 @@ seq_expr: ; labeled_simple_pattern: QUESTION LPAREN label_let_pattern opt_default RPAREN - { ("?" ^ fst $3, $4, snd $3) } + { (Optional (fst $3), $4, snd $3) } | QUESTION label_var - { ("?" ^ fst $2, None, snd $2) } + { (Optional (fst $2), None, snd $2) } | OPTLABEL LPAREN let_pattern opt_default RPAREN - { ("?" ^ $1, $4, $3) } + { (Optional $1, $4, $3) } | OPTLABEL pattern_var - { ("?" ^ $1, None, $2) } + { (Optional $1, None, $2) } | TILDE LPAREN label_let_pattern RPAREN - { (fst $3, None, snd $3) } + { (Labelled (fst $3), None, snd $3) } | TILDE label_var - { (fst $2, None, snd $2) } + { (Labelled (fst $2), None, snd $2) } | LABEL simple_pattern - { ($1, None, $2) } + { (Labelled $1, None, $2) } | simple_pattern - { ("", None, $1) } + { (Nolabel, None, $1) } ; pattern_var: LIDENT { mkpat(Ppat_var (mkrhs $1 1)) } @@ -1249,8 +1365,8 @@ expr: | FUN ext_attributes labeled_simple_pattern fun_def { let (l,o,p) = $3 in mkexp_attrs (Pexp_fun(l, o, p, $4)) $2 } - | FUN ext_attributes LPAREN TYPE LIDENT RPAREN fun_def - { mkexp_attrs (Pexp_newtype($5, $7)) $2 } + | FUN ext_attributes LPAREN TYPE lident_list RPAREN fun_def + { mkexp_attrs (mk_newtypes $5 $7).pexp_desc $2 } | MATCH ext_attributes seq_expr WITH opt_bar match_cases { mkexp_attrs (Pexp_match($3, List.rev $6)) $2 } | TRY ext_attributes seq_expr WITH opt_bar match_cases @@ -1324,10 +1440,10 @@ expr: { mkexp(Pexp_setfield($1, mkrhs $3 3, $5)) } | simple_expr DOT LPAREN seq_expr RPAREN LESSMINUS expr { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "Array" "set")), - ["",$1; "",$4; "",$7])) } + [Nolabel,$1; Nolabel,$4; Nolabel,$7])) } | simple_expr DOT LBRACKET seq_expr RBRACKET LESSMINUS expr { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "String" "set")), - ["",$1; "",$4; "",$7])) } + [Nolabel,$1; Nolabel,$4; Nolabel,$7])) } | simple_expr DOT LBRACE expr RBRACE LESSMINUS expr { bigarray_set $1 $4 $7 } | label LESSMINUS expr @@ -1342,6 +1458,8 @@ expr: { unclosed "object" 1 "end" 4 } | expr attribute { Exp.attr $1 $2 } + | UNDERSCORE + { not_expecting 1 "wildcard \"_\"" } ; simple_expr: val_longident @@ -1362,23 +1480,26 @@ simple_expr: { mkexp_attrs (Pexp_construct (mkloc (Lident "()") (symbol_rloc ()), None)) $2 } | BEGIN ext_attributes seq_expr error - { unclosed "begin" 1 "end" 3 } + { unclosed "begin" 1 "end" 4 } | LPAREN seq_expr type_constraint RPAREN { mkexp_constraint $2 $3 } | simple_expr DOT label_longident { mkexp(Pexp_field($1, mkrhs $3 3)) } | mod_longident DOT LPAREN seq_expr RPAREN { mkexp(Pexp_open(Fresh, mkrhs $1 1, $4)) } + | mod_longident DOT LPAREN RPAREN + { mkexp(Pexp_open(Fresh, mkrhs $1 1, + mkexp(Pexp_construct(mkrhs (Lident "()") 1, None)))) } | mod_longident DOT LPAREN seq_expr error { unclosed "(" 3 ")" 5 } | simple_expr DOT LPAREN seq_expr RPAREN { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "Array" "get")), - ["",$1; "",$4])) } + [Nolabel,$1; Nolabel,$4])) } | simple_expr DOT LPAREN seq_expr error { unclosed "(" 3 ")" 5 } | simple_expr DOT LBRACKET seq_expr RBRACKET { mkexp(Pexp_apply(ghexp(Pexp_ident(array_function "String" "get")), - ["",$1; "",$4])) } + [Nolabel,$1; Nolabel,$4])) } | simple_expr DOT LBRACKET seq_expr error { unclosed "[" 3 "]" 5 } | simple_expr DOT LBRACE expr RBRACE @@ -1403,6 +1524,8 @@ simple_expr: { mkexp (Pexp_array []) } | mod_longident DOT LBRACKETBAR expr_semi_list opt_semi BARRBRACKET { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp(Pexp_array(List.rev $4)))) } + | mod_longident DOT LBRACKETBAR BARRBRACKET + { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp(Pexp_array []))) } | mod_longident DOT LBRACKETBAR expr_semi_list opt_semi error { unclosed "[|" 3 "|]" 6 } | LBRACKET expr_semi_list opt_semi RBRACKET @@ -1412,41 +1535,49 @@ simple_expr: | mod_longident DOT LBRACKET expr_semi_list opt_semi RBRACKET { let list_exp = reloc_exp (mktailexp (rhs_loc 6) (List.rev $4)) in mkexp(Pexp_open(Fresh, mkrhs $1 1, list_exp)) } + | mod_longident DOT LBRACKET RBRACKET + { mkexp(Pexp_open(Fresh, mkrhs $1 1, + mkexp(Pexp_construct(mkrhs (Lident "[]") 1, None)))) } | mod_longident DOT LBRACKET expr_semi_list opt_semi error { unclosed "[" 3 "]" 6 } | PREFIXOP simple_expr - { mkexp(Pexp_apply(mkoperator $1 1, ["",$2])) } + { mkexp(Pexp_apply(mkoperator $1 1, [Nolabel,$2])) } | BANG simple_expr - { mkexp(Pexp_apply(mkoperator "!" 1, ["",$2])) } + { mkexp(Pexp_apply(mkoperator "!" 1, [Nolabel,$2])) } | NEW ext_attributes class_longident { mkexp_attrs (Pexp_new(mkrhs $3 3)) $2 } - | LBRACELESS field_expr_list opt_semi GREATERRBRACE - { mkexp (Pexp_override(List.rev $2)) } - | LBRACELESS field_expr_list opt_semi error - { unclosed "{<" 1 ">}" 4 } + | LBRACELESS field_expr_list GREATERRBRACE + { mkexp (Pexp_override $2) } + | LBRACELESS field_expr_list error + { unclosed "{<" 1 ">}" 3 } | LBRACELESS GREATERRBRACE { mkexp (Pexp_override [])} - | mod_longident DOT LBRACELESS field_expr_list opt_semi GREATERRBRACE - { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override(List.rev $4))))} - | mod_longident DOT LBRACELESS field_expr_list opt_semi error - { unclosed "{<" 3 ">}" 6 } + | mod_longident DOT LBRACELESS field_expr_list GREATERRBRACE + { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override $4)))} + | mod_longident DOT LBRACELESS GREATERRBRACE + { mkexp(Pexp_open(Fresh, mkrhs $1 1, mkexp (Pexp_override [])))} + | mod_longident DOT LBRACELESS field_expr_list error + { unclosed "{<" 3 ">}" 5 } | simple_expr SHARP label { mkexp(Pexp_send($1, $3)) } | simple_expr SHARPOP simple_expr { mkinfix $1 $2 $3 } - | LPAREN MODULE module_expr RPAREN - { mkexp (Pexp_pack $3) } - | LPAREN MODULE module_expr COLON package_type RPAREN - { mkexp (Pexp_constraint (ghexp (Pexp_pack $3), - ghtyp (Ptyp_package $5))) } - | LPAREN MODULE module_expr COLON error - { unclosed "(" 1 ")" 5 } - | mod_longident DOT LPAREN MODULE module_expr COLON package_type RPAREN + | LPAREN MODULE ext_attributes module_expr RPAREN + { mkexp_attrs (Pexp_pack $4) $3 } + | LPAREN MODULE ext_attributes module_expr COLON package_type RPAREN + { mkexp_attrs (Pexp_constraint (ghexp (Pexp_pack $4), + ghtyp (Ptyp_package $6))) + $3 } + | LPAREN MODULE ext_attributes module_expr COLON error + { unclosed "(" 1 ")" 6 } + | mod_longident DOT LPAREN MODULE ext_attributes module_expr COLON + package_type RPAREN { mkexp(Pexp_open(Fresh, mkrhs $1 1, - mkexp (Pexp_constraint (ghexp (Pexp_pack $5), - ghtyp (Ptyp_package $7))))) } - | mod_longident DOT LPAREN MODULE module_expr COLON error - { unclosed "(" 3 ")" 7 } + mkexp_attrs (Pexp_constraint (ghexp (Pexp_pack $6), + ghtyp (Ptyp_package $8))) + $5 )) } + | mod_longident DOT LPAREN MODULE ext_attributes module_expr COLON error + { unclosed "(" 3 ")" 8 } | extension { mkexp (Pexp_extension $1) } ; @@ -1458,19 +1589,19 @@ simple_labeled_expr_list: ; labeled_simple_expr: simple_expr %prec below_SHARP - { ("", $1) } + { (Nolabel, $1) } | label_expr { $1 } ; label_expr: LABEL simple_expr %prec below_SHARP - { ($1, $2) } + { (Labelled $1, $2) } | TILDE label_ident - { $2 } + { (Labelled (fst $2), snd $2) } | QUESTION label_ident - { ("?" ^ fst $2, snd $2) } + { (Optional (fst $2), snd $2) } | OPTLABEL simple_expr %prec below_SHARP - { ("?" ^ $1, $2) } + { (Optional $1, $2) } ; label_ident: LIDENT { ($1, mkexp(Pexp_ident(mkrhs (Lident $1) 1))) } @@ -1500,11 +1631,12 @@ let_bindings: ; let_binding: LET ext_attributes rec_flag let_binding_body post_item_attributes - { mklbs $2 $3 (mklb $4 $5) } + { let (ext, attr) = $2 in + mklbs ext $3 (mklb true $4 (attr@$5)) } ; and_let_binding: - AND let_binding_body post_item_attributes - { mklb $2 $3 } + AND attributes let_binding_body post_item_attributes + { mklb false $3 ($2@$4) } ; fun_binding: strict_binding @@ -1517,8 +1649,8 @@ strict_binding: { $2 } | labeled_simple_pattern fun_binding { let (l, o, p) = $1 in ghexp(Pexp_fun(l, o, p, $2)) } - | LPAREN TYPE LIDENT RPAREN fun_binding - { mkexp(Pexp_newtype($3, $5)) } + | LPAREN TYPE lident_list RPAREN fun_binding + { mk_newtypes $3 $5 } ; match_cases: match_case { [$1] } @@ -1529,17 +1661,22 @@ match_case: { Exp.case $1 $3 } | pattern WHEN seq_expr MINUSGREATER seq_expr { Exp.case $1 ~guard:$3 $5 } + | pattern MINUSGREATER DOT + { Exp.case $1 (Exp.unreachable ~loc:(rhs_loc 3) ())} ; fun_def: - MINUSGREATER seq_expr { $2 } + MINUSGREATER seq_expr + { $2 } + | COLON simple_core_type MINUSGREATER seq_expr + { mkexp (Pexp_constraint ($4, $2)) } /* Cf #5939: we used to accept (fun p when e0 -> e) */ | labeled_simple_pattern fun_def { let (l,o,p) = $1 in ghexp(Pexp_fun(l, o, p, $2)) } - | LPAREN TYPE LIDENT RPAREN fun_def - { mkexp(Pexp_newtype($3, $5)) } + | LPAREN TYPE lident_list RPAREN fun_def + { mk_newtypes $3 $5 } ; expr_comma_list: expr_comma_list COMMA expr { $3 :: $1 } @@ -1555,16 +1692,20 @@ lbl_expr_list: | lbl_expr SEMI { [$1] } ; lbl_expr: - label_longident EQUAL expr - { (mkrhs $1 1,$3) } - | label_longident - { (mkrhs $1 1, exp_of_label $1 1) } + label_longident opt_type_constraint EQUAL expr + { (mkrhs $1 1, mkexp_opt_constraint $4 $2) } + | label_longident opt_type_constraint + { (mkrhs $1 1, mkexp_opt_constraint (exp_of_label $1 1) $2) } ; field_expr_list: + field_expr opt_semi { [$1] } + | field_expr SEMI field_expr_list { $1 :: $3 } +; +field_expr: label EQUAL expr - { [mkrhs $1 1,$3] } - | field_expr_list SEMI label EQUAL expr - { (mkrhs $3 3, $5) :: $1 } + { (mkrhs $1 1, $3) } + | label + { (mkrhs $1 1, exp_of_label (Lident $1) 1) } ; expr_semi_list: expr { [$1] } @@ -1577,6 +1718,10 @@ type_constraint: | COLON error { syntax_error() } | COLONGREATER error { syntax_error() } ; +opt_type_constraint: + type_constraint { Some $1 } + | /* empty */ { None } +; /* Patterns */ @@ -1605,10 +1750,10 @@ pattern: { mkpat(Ppat_or($1, $3)) } | pattern BAR error { expecting 3 "pattern" } - | LAZY simple_pattern - { mkpat(Ppat_lazy $2) } - | EXCEPTION pattern %prec prec_constr_appl - { mkpat(Ppat_exception $2) } + | LAZY ext_attributes simple_pattern + { mkpat_attrs (Ppat_lazy $3) $2} + | EXCEPTION ext_attributes pattern %prec prec_constr_appl + { mkpat_attrs (Ppat_exception $3) $2} | pattern attribute { Pat.attr $1 $2 } ; @@ -1654,13 +1799,15 @@ simple_pattern_not_ident: { unclosed "(" 1 ")" 5 } | LPAREN pattern COLON error { expecting 4 "type" } - | LPAREN MODULE UIDENT RPAREN - { mkpat(Ppat_unpack (mkrhs $3 3)) } - | LPAREN MODULE UIDENT COLON package_type RPAREN - { mkpat(Ppat_constraint(mkpat(Ppat_unpack (mkrhs $3 3)), - ghtyp(Ptyp_package $5))) } - | LPAREN MODULE UIDENT COLON package_type error - { unclosed "(" 1 ")" 6 } + | LPAREN MODULE ext_attributes UIDENT RPAREN + { mkpat_attrs (Ppat_unpack (mkrhs $4 4)) $3 } + | LPAREN MODULE ext_attributes UIDENT COLON package_type RPAREN + { mkpat_attrs + (Ppat_constraint(mkpat(Ppat_unpack (mkrhs $4 4)), + ghtyp(Ptyp_package $6))) + $3 } + | LPAREN MODULE ext_attributes UIDENT COLON package_type error + { unclosed "(" 1 ")" 7 } | extension { mkpat(Ppat_extension $1) } ; @@ -1682,18 +1829,24 @@ lbl_pattern_list: { let (fields, closed) = $3 in $1 :: fields, closed } ; lbl_pattern: - label_longident EQUAL pattern - { (mkrhs $1 1,$3) } - | label_longident - { (mkrhs $1 1, pat_of_label $1 1) } + label_longident opt_pattern_type_constraint EQUAL pattern + { (mkrhs $1 1, mkpat_opt_constraint $4 $2) } + | label_longident opt_pattern_type_constraint + { (mkrhs $1 1, mkpat_opt_constraint (pat_of_label $1 1) $2) } +; +opt_pattern_type_constraint: + COLON core_type { Some $2 } + | /* empty */ { None } ; /* Value descriptions */ value_description: - VAL val_ident COLON core_type post_item_attributes - { Val.mk (mkrhs $2 2) $4 ~attrs:$5 - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + VAL ext_attributes val_ident COLON core_type post_item_attributes + { let (ext, attrs) = $2 in + Val.mk (mkrhs $3 3) $5 ~attrs:(attrs@$6) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; /* Primitive declarations */ @@ -1703,33 +1856,41 @@ primitive_declaration_body: | STRING primitive_declaration_body { fst $1 :: $2 } ; primitive_declaration: - EXTERNAL val_ident COLON core_type EQUAL primitive_declaration_body - post_item_attributes - { Val.mk (mkrhs $2 2) $4 ~prim:$6 ~attrs:$7 - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + EXTERNAL ext_attributes val_ident COLON core_type EQUAL + primitive_declaration_body post_item_attributes + { let (ext, attrs) = $2 in + Val.mk (mkrhs $3 3) $5 ~prim:$7 ~attrs:(attrs@$8) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + , ext } ; /* Type declarations */ type_declarations: - type_declaration { [$1] } - | type_declarations and_type_declaration { $2 :: $1 } + type_declaration + { let (nonrec_flag, ty, ext) = $1 in (nonrec_flag, [ty], ext) } + | type_declarations and_type_declaration + { let (nonrec_flag, tys, ext) = $1 in (nonrec_flag, $2 :: tys, ext) } ; type_declaration: - TYPE nonrec_flag optional_type_parameters LIDENT type_kind constraints - post_item_attributes - { let (kind, priv, manifest) = $5 in - Type.mk (mkrhs $4 4) ~params:$3 ~cstrs:(List.rev $6) ~kind - ~priv ?manifest ~attrs:(add_nonrec $2 $7 2) - ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) } + TYPE ext_attributes nonrec_flag optional_type_parameters LIDENT + type_kind constraints post_item_attributes + { let (kind, priv, manifest) = $6 in + let (ext, attrs) = $2 in + let ty = + Type.mk (mkrhs $5 5) ~params:$4 ~cstrs:(List.rev $7) ~kind + ~priv ?manifest ~attrs:(attrs@$8) + ~loc:(symbol_rloc ()) ~docs:(symbol_docs ()) + in + ($3, ty, ext) } ; and_type_declaration: - AND optional_type_parameters LIDENT type_kind constraints + AND attributes optional_type_parameters LIDENT type_kind constraints post_item_attributes - { let (kind, priv, manifest) = $4 in - Type.mk (mkrhs $3 3) ~params:$2 ~cstrs:(List.rev $5) - ~kind ~priv ?manifest ~attrs:$6 ~loc:(symbol_rloc ()) + { let (kind, priv, manifest) = $5 in + Type.mk (mkrhs $4 4) ~params:$3 ~cstrs:(List.rev $6) + ~kind ~priv ?manifest ~attrs:($2@$7) ~loc:(symbol_rloc ()) ~text:(symbol_text ()) ~docs:(symbol_docs ()) } ; constraints: @@ -1819,29 +1980,35 @@ bar_constructor_declaration: ; str_exception_declaration: | sig_exception_declaration { $1 } - | EXCEPTION constr_ident EQUAL constr_longident attributes + | EXCEPTION ext_attributes constr_ident EQUAL constr_longident attributes post_item_attributes - { Te.rebind (mkrhs $2 2) (mkrhs $4 4) ~attrs:($5 @ $6) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + { let (ext,attrs) = $2 in + Te.rebind (mkrhs $3 3) (mkrhs $5 5) ~attrs:(attrs @ $6 @ $7) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; sig_exception_declaration: - | EXCEPTION constr_ident generalized_constructor_arguments attributes - post_item_attributes - { let args, res = $3 in - Te.decl (mkrhs $2 2) ~args ?res ~attrs:($4 @ $5) - ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) } + | EXCEPTION ext_attributes constr_ident generalized_constructor_arguments + attributes post_item_attributes + { let args, res = $4 in + let (ext,attrs) = $2 in + Te.decl (mkrhs $3 3) ~args ?res ~attrs:(attrs @ $5 @ $6) + ~loc:(symbol_rloc()) ~docs:(symbol_docs ()) + , ext } ; generalized_constructor_arguments: - /*empty*/ { ([],None) } - | OF core_type_list_no_attr { (List.rev $2,None) } - | COLON core_type_list_no_attr MINUSGREATER simple_core_type_no_attr - { (List.rev $2,Some $4) } - | COLON simple_core_type_no_attr - { ([],Some $2) } + /*empty*/ { (Pcstr_tuple [],None) } + | OF constructor_arguments { ($2,None) } + | COLON constructor_arguments MINUSGREATER simple_core_type + { ($2,Some $4) } + | COLON simple_core_type + { (Pcstr_tuple [],Some $2) } ; - - +constructor_arguments: + | core_type_list { Pcstr_tuple (List.rev $1) } + | LBRACE label_declarations RBRACE { Pcstr_record $2 } +; label_declarations: label_declaration { [$1] } | label_declaration_semi { [$1] } @@ -1870,18 +2037,22 @@ label_declaration_semi: /* Type Extensions */ str_type_extension: - TYPE nonrec_flag optional_type_parameters type_longident + TYPE ext_attributes nonrec_flag optional_type_parameters type_longident PLUSEQ private_flag str_extension_constructors post_item_attributes - { if $2 <> Recursive then not_expecting 2 "nonrec flag"; - Te.mk (mkrhs $4 4) (List.rev $7) ~params:$3 ~priv:$6 - ~attrs:$8 ~docs:(symbol_docs ()) } + { let (ext, attrs) = $2 in + if $3 <> Recursive then not_expecting 3 "nonrec flag"; + Te.mk (mkrhs $5 5) (List.rev $8) ~params:$4 ~priv:$7 + ~attrs:(attrs@$9) ~docs:(symbol_docs ()) + , ext } ; sig_type_extension: - TYPE nonrec_flag optional_type_parameters type_longident + TYPE ext_attributes nonrec_flag optional_type_parameters type_longident PLUSEQ private_flag sig_extension_constructors post_item_attributes - { if $2 <> Recursive then not_expecting 2 "nonrec flag"; - Te.mk (mkrhs $4 4) (List.rev $7) ~params:$3 ~priv:$6 - ~attrs:$8 ~docs:(symbol_docs ()) } + { let (ext, attrs) = $2 in + if $3 <> Recursive then not_expecting 3 "nonrec flag"; + Te.mk (mkrhs $5 5) (List.rev $8) ~params:$4 ~priv:$7 + ~attrs:(attrs @ $9) ~docs:(symbol_docs ()) + , ext } ; str_extension_constructors: extension_constructor_declaration { [$1] } @@ -1929,7 +2100,8 @@ with_constraints: | with_constraints AND with_constraint { $3 :: $1 } ; with_constraint: - TYPE type_parameters label_longident with_type_binder core_type_no_attr constraints + TYPE type_parameters label_longident with_type_binder core_type_no_attr + constraints { Pwith_type (mkrhs $3 3, (Type.mk (mkrhs (Longident.last $3) 3) @@ -1984,7 +2156,7 @@ core_type: { Typ.attr $1 $2 } ; core_type_no_attr: - core_type2 + core_type2 %prec MINUSGREATER { $1 } | core_type2 AS QUOTE ident { mktyp(Ptyp_alias($1, $4)) } @@ -1993,13 +2165,18 @@ core_type2: simple_core_type_or_tuple { $1 } | QUESTION LIDENT COLON core_type2 MINUSGREATER core_type2 - { mktyp(Ptyp_arrow("?" ^ $2 , mkoption $4, $6)) } + { let param = extra_rhs_core_type $4 ~pos:4 in + mktyp (Ptyp_arrow(Optional $2 , param, $6)) } | OPTLABEL core_type2 MINUSGREATER core_type2 - { mktyp(Ptyp_arrow("?" ^ $1 , mkoption $2, $4)) } + { let param = extra_rhs_core_type $2 ~pos:2 in + mktyp(Ptyp_arrow(Optional $1 , param, $4)) + } | LIDENT COLON core_type2 MINUSGREATER core_type2 - { mktyp(Ptyp_arrow($1, $3, $5)) } + { let param = extra_rhs_core_type $3 ~pos:3 in + mktyp(Ptyp_arrow(Labelled $1, param, $5)) } | core_type2 MINUSGREATER core_type2 - { mktyp(Ptyp_arrow("", $1, $3)) } + { let param = extra_rhs_core_type $1 ~pos:1 in + mktyp(Ptyp_arrow(Nolabel, param, $3)) } ; simple_core_type: @@ -2009,13 +2186,6 @@ simple_core_type: { match $2 with [sty] -> sty | _ -> raise Parse_error } ; -simple_core_type_no_attr: - simple_core_type2 %prec below_SHARP - { $1 } - | LPAREN core_type_comma_list RPAREN %prec below_SHARP - { match $2 with [sty] -> sty | _ -> raise Parse_error } -; - simple_core_type2: QUOTE ident { mktyp(Ptyp_var $2) } @@ -2055,21 +2225,13 @@ simple_core_type2: { mktyp(Ptyp_variant(List.rev $3, Closed, Some [])) } | LBRACKETLESS opt_bar row_field_list GREATER name_tag_list RBRACKET { mktyp(Ptyp_variant(List.rev $3, Closed, Some (List.rev $5))) } - | LPAREN MODULE package_type RPAREN - { mktyp(Ptyp_package $3) } + | LPAREN MODULE ext_attributes package_type RPAREN + { mktyp_attrs (Ptyp_package $4) $3 } | extension { mktyp (Ptyp_extension $1) } ; package_type: - mty_longident { (mkrhs $1 1, []) } - | mty_longident WITH package_type_cstrs { (mkrhs $1 1, $3) } -; -package_type_cstr: - TYPE label_longident EQUAL core_type { (mkrhs $2 2, $4) } -; -package_type_cstrs: - package_type_cstr { [$1] } - | package_type_cstr AND package_type_cstrs { $1::$3 } + module_type { package_type_of_module_type $1 } ; row_field_list: row_field { [$1] } @@ -2081,9 +2243,9 @@ row_field: ; tag_field: name_tag OF opt_ampersand amper_type_list attributes - { Rtag ($1, $5, $3, List.rev $4) } + { Rtag ($1, add_info_attrs (symbol_info ()) $5, $3, List.rev $4) } | name_tag attributes - { Rtag ($1, $2, true, []) } + { Rtag ($1, add_info_attrs (symbol_info ()) $2, true, []) } ; opt_ampersand: AMPERSAND { true } @@ -2098,36 +2260,39 @@ name_tag_list: | name_tag_list name_tag { $2 :: $1 } ; simple_core_type_or_tuple: - simple_core_type %prec below_LBRACKETAT { $1 } + simple_core_type { $1 } | simple_core_type STAR core_type_list { mktyp(Ptyp_tuple($1 :: List.rev $3)) } ; -simple_core_type_or_tuple_no_attr: - simple_core_type_no_attr - { $1 } - | simple_core_type_no_attr STAR core_type_list_no_attr - { mktyp(Ptyp_tuple($1 :: List.rev $3)) } -; core_type_comma_list: core_type { [$1] } | core_type_comma_list COMMA core_type { $3 :: $1 } ; core_type_list: - simple_core_type %prec below_LBRACKETAT { [$1] } + simple_core_type { [$1] } | core_type_list STAR simple_core_type { $3 :: $1 } ; -core_type_list_no_attr: - simple_core_type_no_attr { [$1] } - | core_type_list STAR simple_core_type_no_attr { $3 :: $1 } -; meth_list: - field SEMI meth_list { let (f, c) = $3 in ($1 :: f, c) } - | field opt_semi { [$1], Closed } + field_semi meth_list { let (f, c) = $2 in ($1 :: f, c) } + | field_semi { [$1], Closed } + | field { [$1], Closed } | DOTDOT { [], Open } ; field: - label COLON poly_type_no_attr attributes { ($1, $4, $3) } + label COLON poly_type_no_attr attributes + { ($1, add_info_attrs (symbol_info ()) $4, $3) } ; + +field_semi: + label COLON poly_type_no_attr attributes SEMI attributes + { let info = + match rhs_info 4 with + | Some _ as info_before_semi -> info_before_semi + | None -> symbol_info () + in + ($1, add_info_attrs info ($4 @ $6), $3) } +; + label: LIDENT { $1 } ; @@ -2135,26 +2300,17 @@ label: /* Constants */ constant: - INT { Const_int $1 } - | CHAR { Const_char $1 } - | STRING { let (s, d) = $1 in Const_string (s, d) } - | FLOAT { Const_float $1 } - | INT32 { Const_int32 $1 } - | INT64 { Const_int64 $1 } - | NATIVEINT { Const_nativeint $1 } + | INT { let (n, m) = $1 in Pconst_integer (n, m) } + | CHAR { Pconst_char $1 } + | STRING { let (s, d) = $1 in Pconst_string (s, d) } + | FLOAT { let (f, m) = $1 in Pconst_float (f, m) } ; signed_constant: - constant { $1 } - | MINUS INT { Const_int(- $2) } - | MINUS FLOAT { Const_float("-" ^ $2) } - | MINUS INT32 { Const_int32(Int32.neg $2) } - | MINUS INT64 { Const_int64(Int64.neg $2) } - | MINUS NATIVEINT { Const_nativeint(Nativeint.neg $2) } - | PLUS INT { Const_int $2 } - | PLUS FLOAT { Const_float $2 } - | PLUS INT32 { Const_int32 $2 } - | PLUS INT64 { Const_int64 $2 } - | PLUS NATIVEINT { Const_nativeint $2 } + constant { $1 } + | MINUS INT { let (n, m) = $2 in Pconst_integer("-" ^ n, m) } + | MINUS FLOAT { let (f, m) = $2 in Pconst_float("-" ^ f, m) } + | PLUS INT { let (n, m) = $2 in Pconst_integer (n, m) } + | PLUS FLOAT { let (f, m) = $2 in Pconst_float(f, m) } ; /* Identifiers and long identifiers */ @@ -2197,10 +2353,10 @@ operator: ; constr_ident: UIDENT { $1 } -/* | LBRACKET RBRACKET { "[]" } */ + | LBRACKET RBRACKET { "[]" } | LPAREN RPAREN { "()" } - | COLONCOLON { "::" } -/* | LPAREN COLONCOLON RPAREN { "::" } */ + /* | COLONCOLON { "::" } */ + | LPAREN COLONCOLON RPAREN { "::" } | FALSE { "false" } | TRUE { "true" } ; @@ -2251,7 +2407,8 @@ class_longident: toplevel_directive: SHARP ident { Ptop_dir($2, Pdir_none) } | SHARP ident STRING { Ptop_dir($2, Pdir_string (fst $3)) } - | SHARP ident INT { Ptop_dir($2, Pdir_int $3) } + | SHARP ident INT { let (n, m) = $3 in + Ptop_dir($2, Pdir_int (n ,m)) } | SHARP ident val_longident { Ptop_dir($2, Pdir_ident $3) } | SHARP ident mod_longident { Ptop_dir($2, Pdir_ident $3) } | SHARP ident FALSE { Ptop_dir($2, Pdir_bool false) } @@ -2350,6 +2507,7 @@ single_attr_id: | MODULE { "module" } | MUTABLE { "mutable" } | NEW { "new" } + | NONREC { "nonrec" } | OBJECT { "object" } | OF { "of" } | OPEN { "open" } @@ -2405,6 +2563,7 @@ item_extension: ; payload: structure { PStr $1 } + | COLON signature { PSig $2 } | COLON core_type { PTyp $2 } | QUESTION pattern { PPat ($2, None) } | QUESTION pattern WHEN seq_expr { PPat ($2, Some $4) } diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli index 295e3eaa..d3796f78 100644 --- a/parsing/parsetree.mli +++ b/parsing/parsetree.mli @@ -1,19 +1,42 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (** Abstract syntax tree produced by parsing *) open Asttypes +type constant = + Pconst_integer of string * char option + (* 3 3l 3L 3n + + Suffixes [g-z][G-Z] are accepted by the parser. + Suffixes except 'l', 'L' and 'n' are rejected by the typechecker + *) + | Pconst_char of char + (* 'c' *) + | Pconst_string of string * string option + (* "constant" + {delim|other constant|delim} + *) + | Pconst_float of string * char option + (* 3.4 2e5 1.4e-4 + + Suffixes [g-z][G-Z] are accepted by the parser. + Suffixes are rejected by the typechecker. + *) + (** {2 Extension points} *) type attribute = string loc * payload @@ -35,6 +58,7 @@ and attributes = attribute list and payload = | PStr of structure + | PSig of signature (* : SIG *) | PTyp of core_type (* : T *) | PPat of pattern * expression option (* ? P or ? P when E *) @@ -54,10 +78,10 @@ and core_type_desc = (* _ *) | Ptyp_var of string (* 'a *) - | Ptyp_arrow of label * core_type * core_type - (* T1 -> T2 (label = "") - ~l:T1 -> T2 (label = "l") - ?l:T1 -> T2 (label = "?l") + | Ptyp_arrow of arg_label * core_type * core_type + (* T1 -> T2 Simple + ~l:T1 -> T2 Labelled + ?l:T1 -> T2 Otional *) | Ptyp_tuple of core_type list (* T1 * ... * Tn @@ -219,18 +243,18 @@ and expression_desc = *) | Pexp_function of case list (* function P1 -> E1 | ... | Pn -> En *) - | Pexp_fun of label * expression option * pattern * expression - (* fun P -> E1 (lab = "", None) - fun ~l:P -> E1 (lab = "l", None) - fun ?l:P -> E1 (lab = "?l", None) - fun ?l:(P = E0) -> E1 (lab = "?l", Some E0) + | Pexp_fun of arg_label * expression option * pattern * expression + (* fun P -> E1 (Simple, None) + fun ~l:P -> E1 (Labelled l, None) + fun ?l:P -> E1 (Optional l, None) + fun ?l:(P = E0) -> E1 (Optional l, Some E0) Notes: - - If E0 is provided, lab must start with '?'. + - If E0 is provided, only Optional is allowed. - "fun P1 P2 .. Pn -> E1" is represented as nested Pexp_fun. - "let f P = E" is represented using Pexp_fun. *) - | Pexp_apply of expression * (label * expression) list + | Pexp_apply of expression * (arg_label * expression) list (* E0 ~l1:E1 ... ~ln:En li can be empty (non labeled argument) or start with '?' (optional argument). @@ -320,6 +344,8 @@ and expression_desc = *) | Pexp_extension of extension (* [%id] *) + | Pexp_unreachable + (* . *) and case = (* (P -> E) or (P when E0 -> E) *) { @@ -342,8 +368,6 @@ and value_description = (* val x: T (prim = []) external x: T = "s1" ... "sn" (prim = ["s1";..."sn"]) - - Note: when used under Pstr_primitive, prim cannot be empty *) (* Type declarations *) @@ -398,15 +422,23 @@ and label_declaration = and constructor_declaration = { pcd_name: string loc; - pcd_args: core_type list; + pcd_args: constructor_arguments; pcd_res: core_type option; pcd_loc: Location.t; pcd_attributes: attributes; (* C [@id1] [@id2] of ... *) } + +and constructor_arguments = + | Pcstr_tuple of core_type list + | Pcstr_record of label_declaration list + (* - | C of T1 * ... * Tn (res = None) - | C: T0 (args = [], res = Some T0) - | C: T1 * ... * Tn -> T0 (res = Some T0) + | C of T1 * ... * Tn (res = None, args = Pcstr_tuple []) + | C: T0 (res = Some T0, args = []) + | C: T1 * ... * Tn -> T0 (res = Some T0, args = Pcstr_tuple) + | C of {...} (res = None, args = Pcstr_record) + | C: {...} -> T0 (res = Some T0, args = Pcstr_record) + | C of {...} as t (res = None, args = Pcstr_record) *) and type_extension = @@ -430,7 +462,7 @@ and extension_constructor = } and extension_constructor_kind = - Pext_decl of core_type list * core_type option + Pext_decl of constructor_arguments * core_type option (* | C of T1 * ... * Tn ([T1; ...; Tn], None) | C: T0 ([], Some T0) @@ -458,10 +490,10 @@ and class_type_desc = ['a1, ..., 'an] c *) | Pcty_signature of class_signature (* object ... end *) - | Pcty_arrow of label * core_type * class_type - (* T -> CT (label = "") - ~l:T -> CT (label = "l") - ?l:T -> CT (label = "?l") + | Pcty_arrow of arg_label * core_type * class_type + (* T -> CT Simple + ~l:T -> CT Labelled l + ?l:T -> CT Optional l *) | Pcty_extension of extension (* [%id] *) @@ -534,13 +566,13 @@ and class_expr_desc = ['a1, ..., 'an] c *) | Pcl_structure of class_structure (* object ... end *) - | Pcl_fun of label * expression option * pattern * class_expr - (* fun P -> CE (lab = "", None) - fun ~l:P -> CE (lab = "l", None) - fun ?l:P -> CE (lab = "?l", None) - fun ?l:(P = E0) -> CE (lab = "?l", Some E0) + | Pcl_fun of arg_label * expression option * pattern * class_expr + (* fun P -> CE (Simple, None) + fun ~l:P -> CE (Labelled l, None) + fun ?l:P -> CE (Optional l, None) + fun ?l:(P = E0) -> CE (Optional l, Some E0) *) - | Pcl_apply of class_expr * (label * expression) list + | Pcl_apply of class_expr * (arg_label * expression) list (* CE ~l1:E1 ... ~ln:En li can be empty (non labeled argument) or start with '?' (optional argument). @@ -643,7 +675,7 @@ and signature_item_desc = val x: T external x: T = "s1" ... "sn" *) - | Psig_type of type_declaration list + | Psig_type of rec_flag * type_declaration list (* type t1 = ... and ... and tn = ... *) | Psig_typext of type_extension (* type t1 += ... *) @@ -768,8 +800,9 @@ and structure_item_desc = let rec P1 = E1 and ... and Pn = EN (flag = Recursive) *) | Pstr_primitive of value_description - (* external x: T = "s1" ... "sn" *) - | Pstr_type of type_declaration list + (* val x: T + external x: T = "s1" ... "sn" *) + | Pstr_type of rec_flag * type_declaration list (* type t1 = ... and ... and tn = ... *) | Pstr_typext of type_extension (* type t1 += ... *) @@ -824,6 +857,6 @@ type toplevel_phrase = and directive_argument = | Pdir_none | Pdir_string of string - | Pdir_int of int + | Pdir_int of string * char option | Pdir_ident of Longident.t | Pdir_bool of bool diff --git a/parsing/pprintast.ml b/parsing/pprintast.ml index 5e9b9455..90bfaa51 100644 --- a/parsing/pprintast.ml +++ b/parsing/pprintast.ml @@ -1,12 +1,17 @@ (**************************************************************************) (* *) -(* OCaml *) +(* OCaml *) +(* *) +(* Thomas Gazagnaire, OCamlPro *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* Hongbo Zhang, University of Pennsylvania *) (* *) -(* Thomas Gazagnaire (OCamlPro), Fabrice Le Fessant (INRIA Saclay) *) -(* Hongbo Zhang (University of Pennsylvania) *) (* Copyright 2007 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. *) +(* 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. *) (* *) (**************************************************************************) @@ -25,11 +30,6 @@ open Parsetree let prefix_symbols = [ '!'; '?'; '~' ] ;; let infix_symbols = [ '='; '<'; '>'; '@'; '^'; '|'; '&'; '+'; '-'; '*'; '/'; '$'; '%' ] -let operator_chars = [ '!'; '$'; '%'; '&'; '*'; '+'; '-'; '.'; '/'; - ':'; '<'; '='; '>'; '?'; '@'; '^'; '|'; '~' ] -let numeric_chars = [ '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9' ] - -(* type fixity = Infix| Prefix *) let special_infix_strings = ["asr"; "land"; "lor"; "lsl"; "lsr"; "lxor"; "mod"; "or"; ":="; "!=" ] @@ -51,10 +51,6 @@ let view_fixity_of_exp = function let is_infix = function | `Infix _ -> true | _ -> false -let is_predef_option = function - | (Ldot (Lident "*predef*","option")) -> true - | _ -> false - (* which identifiers are in fact operators needing parentheses *) let needs_parens txt = is_infix (fixity_of_string txt) @@ -141,9 +137,9 @@ class printer ()= object(self:'self) ?last:space_formatter -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a list -> unit = fun ?sep ?first ?last fu f xs -> - let first = match first with Some x -> x |None -> "" - and last = match last with Some x -> x |None -> "" - and sep = match sep with Some x -> x |None -> "@ " in + let first = match first with Some x -> x |None -> ("" : _ format6) + and last = match last with Some x -> x |None -> ("" : _ format6) + and sep = match sep with Some x -> x |None -> ("@ " : _ format6) in let aux f = function | [] -> () | [x] -> fu f x @@ -158,14 +154,14 @@ class printer ()= object(self:'self) method option : 'a. ?first:space_formatter -> ?last:space_formatter -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a option -> unit = fun ?first ?last fu f a -> - let first = match first with Some x -> x | None -> "" - and last = match last with Some x -> x | None -> "" in + let first = match first with Some x -> x | None -> ("" : _ format6) + and last = match last with Some x -> x | None -> ("" : _ format6) in match a with | None -> () | Some x -> pp f first; fu f x; pp f last; method paren: 'a . ?first:space_formatter -> ?last:space_formatter -> bool -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a -> unit = - fun ?(first="") ?(last="") b fu f x -> + fun ?(first=("" : _ format6)) ?(last=("" : _ format6)) b fu f x -> if b then (pp f "("; pp f first; fu f x; pp f last; pp f ")") else fu f x @@ -177,16 +173,15 @@ class printer ()= object(self:'self) pp f "%a(%a)" self#longident y self#longident s method longident_loc f x = pp f "%a" self#longident x.txt method constant f = function - | Const_char i -> pp f "%C" i - | Const_string (i, None) -> pp f "%S" i - | Const_string (i, Some delim) -> pp f "{%s|%s|%s}" delim i delim - | Const_int i -> self#paren (i<0) (fun f -> pp f "%d") f i - | Const_float i -> self#paren (i.[0]='-') (fun f -> pp f "%s") f i - | Const_int32 i -> self#paren (i<0l) (fun f -> pp f "%ldl") f i - | Const_int64 i -> self#paren (i<0L) (fun f -> pp f "%LdL") f i - (* pp f "%LdL" i *) - | Const_nativeint i -> self#paren (i<0n) (fun f -> pp f "%ndn") f i - (* pp f "%ndn" i *) + | Pconst_char i -> pp f "%C" i + | Pconst_string (i, None) -> pp f "%S" i + | Pconst_string (i, Some delim) -> pp f "{%s|%s|%s}" delim i delim + | Pconst_integer (i,None) -> self#paren (i.[0]='-') (fun f -> pp f "%s") f i + | Pconst_integer (i,Some m) -> + self#paren (i.[0]='-') (fun f (i,m) -> pp f "%s%c" i m) f (i,m) + | Pconst_float (i,None) -> self#paren (i.[0]='-') (fun f -> pp f "%s") f i + | Pconst_float (i, Some m) -> self#paren (i.[0]='-') (fun f (i,m) -> + pp f "%s%c" i m) f (i,m) (* trailing space*) method mutable_flag f = function @@ -225,15 +220,9 @@ class printer ()= object(self:'self) method type_with_label f (label,({ptyp_desc;_}as c) ) = match label with - | "" -> self#core_type1 f c (* otherwise parenthesize *) - | s -> - if s.[0]='?' then - match ptyp_desc with - | Ptyp_constr ({txt;_}, l) -> - assert (is_predef_option txt); - pp f "%s:%a" s (self#list self#core_type1) l - | _ -> failwith "invalid input in print_type_with_label" - else pp f "%s:%a" s self#core_type1 c + | Nolabel -> self#core_type1 f c (* otherwise parenthesize *) + | Labelled s -> pp f "%s:%a" s self#core_type1 c + | Optional s -> pp f "?%s:%a" s self#core_type1 c method core_type f x = if x.ptyp_attributes <> [] then begin pp f "((%a)%a)" self#core_type {x with ptyp_attributes=[]} @@ -351,14 +340,15 @@ class printer ()= object(self:'self) Ppat_construct ({ txt = Lident("::") ;_}, Some ({ppat_desc = Ppat_tuple([pat1; pat2]);_})); _} - -> - pp f "%a::%a" self#simple_pattern pat1 pattern_list_helper pat2 (*RA*) + -> pp f "%a::%a" self#simple_pattern pat1 pattern_list_helper pat2 + (*RA*) | p -> self#pattern1 f p in if x.ppat_attributes <> [] then self#pattern f x else match x.ppat_desc with | Ppat_variant (l, Some p) -> pp f "@[<2>`%s@;%a@]" l self#simple_pattern p | Ppat_construct (({txt=Lident("()"|"[]");_}), _) -> self#simple_pattern f x - | Ppat_construct (({txt;_} as li), po) -> (* FIXME The third field always false *) + | Ppat_construct (({txt;_} as li), po) -> + (* FIXME The third field always false *) if txt = Lident "::" then pp f "%a" pattern_list_helper x else @@ -393,7 +383,8 @@ class printer ()= object(self:'self) | _ -> pp f "@[<2>{@;%a;_}@]" (self#list longident_x_pattern ~sep:";@;") l) - | Ppat_tuple l -> pp f "@[<1>(%a)@]" (self#list ~sep:"," self#pattern1) l (* level1*) + | Ppat_tuple l -> pp f "@[<1>(%a)@]" (self#list ~sep:"," self#pattern1) l + (* level1*) | Ppat_constant (c) -> pp f "%a" self#constant c | Ppat_interval (c1, c2) -> pp f "%a..%a" self#constant c1 self#constant c2 | Ppat_variant (l,None) -> pp f "`%s" l @@ -407,13 +398,12 @@ class printer ()= object(self:'self) | _ -> self#paren true self#pattern f x method label_exp f (l,opt,p) = - if l = "" then - pp f "%a@ " self#simple_pattern p (*single case pattern parens needed here *) - else - if l.[0] = '?' then - let len = String.length l - 1 in - let rest = String.sub l 1 len in begin - match p.ppat_desc with + match l with + | Nolabel -> + pp f "%a@ " self#simple_pattern p + (*single case pattern parens needed here *) + | Optional rest -> + begin match p.ppat_desc with | Ppat_var {txt;_} when txt = rest -> (match opt with | Some o -> pp f "?(%s=@;%a)@;" rest self#expression o @@ -421,106 +411,62 @@ class printer ()= object(self:'self) | _ -> (match opt with | Some o -> - pp f "%s:(%a=@;%a)@;" l self#pattern1 p self#expression o - | None -> pp f "%s:%a@;" l self#simple_pattern p) + pp f "?%s:(%a=@;%a)@;" rest self#pattern1 p self#expression o + | None -> pp f "?%s:%a@;" rest self#simple_pattern p) end - else + | Labelled l -> (match p.ppat_desc with | Ppat_var {txt;_} when txt = l -> pp f "~%s@;" l | _ -> pp f "~%s:%a@;" l self#simple_pattern p ) method sugar_expr f e = if e.pexp_attributes <> [] then false - (* should also check attributes underneath *) else match e.pexp_desc with - | Pexp_apply - ({pexp_desc= - Pexp_ident - {txt= Ldot (Lident (("Array"|"String") as s),"get");_};_}, - [(_,e1);(_,e2)]) -> begin - let fmt:(_,_,_)format = - if s= "Array" then "@[%a.(%a)@]" else "@[%a.[%a]@]" in - pp f fmt self#simple_expr e1 self#expression e2; - true - end - |Pexp_apply - ({pexp_desc= - Pexp_ident - {txt= Ldot (Lident (("Array"|"String") as s), - "set");_};_},[(_,e1);(_,e2);(_,e3)]) - -> - let fmt :(_,_,_) format= - if s= "Array" then - "@[%a.(%a)@ <-@;%a@]" - else - "@[%a.[%a]@ <-@;%a@]" in (* @;< gives error here *) - pp f fmt self#simple_expr e1 self#expression e2 self#expression e3; - true - | Pexp_apply ({pexp_desc=Pexp_ident {txt=Lident "!";_};_}, [(_,e)]) -> begin - pp f "@[!%a@]" self#simple_expr e; - true - end - | Pexp_apply - ({pexp_desc=Pexp_ident - {txt= Ldot (Ldot (Lident "Bigarray", array), - ("get"|"set" as gs)) ;_};_}, - label_exprs) -> - begin match array, gs, label_exprs with - | "Genarray", "get", - [(_,a);(_,{pexp_desc=Pexp_array ls;_})] -> - pp f "@[%a.{%a}@]" self#simple_expr a - (self#list ~sep:"," self#simple_expr ) ls; - true - | "Genarray", "set", - [(_,a);(_,{pexp_desc=Pexp_array ls;_});(_,c)] -> - pp f "@[%a.{%a}@ <-@ %a@]" self#simple_expr a - (self#list ~sep:"," self#simple_expr ) ls self#simple_expr c; - true - | "Array1", "set", [(_,a);(_,i);(_,v)] -> - pp f "@[%a.{%a}@ <-@ %a@]" - self#simple_expr a - self#simple_expr i - self#simple_expr v; - true - | "Array2", "set", [(_,a);(_,i1);(_,i2);(_,v)] -> - pp f "@[%a.{%a,%a}@ <-@ %a@]" + | Pexp_apply ({ pexp_desc = Pexp_ident { txt = id; _ }; + pexp_attributes=[]; _ }, args) + when List.for_all (fun (lab, _) -> lab = Nolabel) args -> begin + match id, List.map snd args with + | Lident "!", [e] -> + pp f "@[!%a@]" self#simple_expr e; + true + | Ldot (path, ("get"|"set" as func)), a :: other_args -> begin + let print left right print_index indexes rem_args = + match func, rem_args with + | "get", [] -> + pp f "@[%a.%s%a%s@]" self#simple_expr a - self#simple_expr i1 - self#simple_expr i2 - self#simple_expr v; - true - | "Array3", "set", [(_,a);(_,i1);(_,i2);(_,i3);(_,v)] -> - pp f "@[%a.{%a,%a,%a}@ <-@ %a@]" + left (self#list ~sep:"," print_index) indexes right; + true + | "set", [v] -> + pp f "@[%a.%s%a%s@ <-@;<1 2>%a@]" self#simple_expr a - self#simple_expr i1 - self#simple_expr i2 - self#simple_expr i3 + left (self#list ~sep:"," print_index) indexes right self#simple_expr v; - true - | "Array1", "get", [(_,a);(_,i)] -> - pp f "@[%a.{%a}@]" - self#simple_expr a - self#simple_expr i; - true - | "Array2", "get", [(_,a);(_,i1);(_,i2)] -> - pp f "@[%a.{%a,%a}@]" - self#simple_expr a - self#simple_expr i1 - self#simple_expr i2; - true - | "Array3", "get", [(_,a);(_,i1);(_,i2);(_,i3)] -> - pp f "@[%a.{%a,%a,%a}@]" - self#simple_expr a - self#simple_expr i1 - self#simple_expr i2 - self#simple_expr i3; - true - | _ -> false - end + true + | _ -> false + in + match path, other_args with + | Lident "Array", i :: rest -> + print "(" ")" self#expression [i] rest + | Lident "String", i :: rest -> + print "[" "]" self#expression [i] rest + | Ldot (Lident "Bigarray", "Array1"), i1 :: rest -> + print "{" "}" self#simple_expr [i1] rest + | Ldot (Lident "Bigarray", "Array2"), i1 :: i2 :: rest -> + print "{" "}" self#simple_expr [i1; i2] rest + | Ldot (Lident "Bigarray", "Array3"), i1 :: i2 :: i3 :: rest -> + print "{" "}" self#simple_expr [i1; i2; i3] rest + | Ldot (Lident "Bigarray", "Genarray"), + {pexp_desc = Pexp_array indexes; pexp_attributes = []} :: rest -> + print "{" "}" self#simple_expr indexes rest + | _ -> false + end + | _ -> false + end | _ -> false method expression f x = if x.pexp_attributes <> [] then begin - pp f "((%a)%a)" self#expression {x with pexp_attributes=[]} + pp f "((%a)@,%a)" self#expression {x with pexp_attributes=[]} self#attributes x.pexp_attributes end else match x.pexp_desc with @@ -529,7 +475,7 @@ class printer ()= object(self:'self) self#paren true self#reset#expression f x | Pexp_ifthenelse _ | Pexp_sequence _ when ifthenelse -> self#paren true self#reset#expression f x - | Pexp_let _ | Pexp_letmodule _ when semi -> + | Pexp_let _ | Pexp_letmodule _ | Pexp_open _ when semi -> self#paren true self#reset#expression f x | Pexp_fun (l, e0, p, e) -> pp f "@[<2>fun@;%a@;->@;%a@]" @@ -538,13 +484,16 @@ class printer ()= object(self:'self) | Pexp_function l -> pp f "@[function%a@]" self#case_list l | Pexp_match (e, l) -> - pp f "@[@[@[<2>match %a@]@ with@]%a@]" self#reset#expression e self#case_list l + pp f "@[@[@[<2>match %a@]@ with@]%a@]" self#reset#expression + e self#case_list l | Pexp_try (e, l) -> - pp f "@[<0>@[try@ %a@]@ @[<0>with%a@]@]" (* "try@;@[<2>%a@]@\nwith@\n%a"*) + pp f "@[<0>@[try@ %a@]@ @[<0>with%a@]@]" + (* "try@;@[<2>%a@]@\nwith@\n%a"*) self#reset#expression e self#case_list l | Pexp_let (rf, l, e) -> - (* pp f "@[<2>let %a%a in@;<1 -2>%a@]" (\*no identation here, a new line*\) *) + (* pp f "@[<2>let %a%a in@;<1 -2>%a@]" + (*no identation here, a new line*) *) (* self#rec_flag rf *) pp f "@[<2>%a in@;<1 -2>%a@]" self#reset#bindings (rf,l) @@ -554,24 +503,33 @@ class printer ()= object(self:'self) match view_fixity_of_exp e with | `Infix s -> (match l with - | [ arg1; arg2 ] -> - pp f "@[<2>%a@;%s@;%a@]" (* FIXME associativity lable_x_expression_parm*) - self#reset#label_x_expression_param arg1 s self#label_x_expression_param arg2 + | [ (Nolabel, _) as arg1; (Nolabel, _) as arg2 ] -> + pp f "@[<2>%a@;%s@;%a@]" + (* FIXME associativity lable_x_expression_parm*) + self#reset#label_x_expression_param arg1 s + self#label_x_expression_param arg2 | _ -> - pp f "@[<2>%a %a@]" self#simple_expr e (self#list self#label_x_expression_param) l) + pp f "@[<2>%a %a@]" self#simple_expr e + (self#list self#label_x_expression_param) l) | `Prefix s -> let s = - if List.mem s ["~+";"~-";"~+.";"~-."] then String.sub s 1 (String.length s -1) - else s in + if List.mem s ["~+";"~-";"~+.";"~-."] + then String.sub s 1 (String.length s -1) + else s + in (match l with - |[v] -> pp f "@[<2>%s@;%a@]" s self#label_x_expression_param v - | _ -> pp f "@[<2>%s@;%a@]" s (self#list self#label_x_expression_param) l (*FIXME assert false*) + | [(Nolabel, _) as v] -> + pp f "@[<2>%s@;%a@]" s self#label_x_expression_param v + | _ -> + pp f "@[<2>%a %a@]" self#simple_expr e + (self#list self#label_x_expression_param) l ) | _ -> pp f "@[%a@]" begin fun f (e,l) -> pp f "%a@ %a" self#expression2 e - (self#list self#reset#label_x_expression_param) l - (*reset here only because [function,match,try,sequence] are lower priority*) + (self#list self#reset#label_x_expression_param) l + (*reset here only because [function,match,try,sequence] are + lower priority*) end (e,l)) | Pexp_construct (li, Some eo) @@ -583,11 +541,13 @@ class printer ()= object(self:'self) self#simple_expr eo | _ -> assert false) | Pexp_setfield (e1, li, e2) -> - pp f "@[<2>%a.%a@ <-@ %a@]" self#simple_expr e1 self#longident_loc li self#expression e2; + pp f "@[<2>%a.%a@ <-@ %a@]" self#simple_expr e1 self#longident_loc li + self#expression e2; | Pexp_ifthenelse (e1, e2, eo) -> (* @;@[<2>else@ %a@]@] *) let fmt:(_,_,_)format ="@[@[<2>if@ %a@]@;@[<2>then@ %a@]%a@]" in - pp f fmt self#under_ifthenelse#expression e1 self#under_ifthenelse#expression e2 + pp f fmt self#under_ifthenelse#expression e1 + self#under_ifthenelse#expression e2 (fun f eo -> match eo with | Some x -> pp f "@;@[<2>else@;%a@]" self#under_semi#expression x | None -> () (* pp f "()" *)) eo @@ -615,7 +575,8 @@ class printer ()= object(self:'self) pp f "@[assert@ %a@]" self#simple_expr e | Pexp_lazy (e) -> pp f "@[lazy@ %a@]" self#simple_expr e - (* Pexp_poly: impossible but we should print it anyway, rather than assert false *) + (* Pexp_poly: impossible but we should print it anyway, rather + than assert false *) | Pexp_poly (e, None) -> pp f "@[!poly!@ %a@]" self#simple_expr e | Pexp_poly (e, Some ct) -> @@ -626,6 +587,8 @@ class printer ()= object(self:'self) | Pexp_variant (l,Some eo) -> pp f "@[<2>`%s@;%a@]" l self#simple_expr eo | Pexp_extension e -> self#extension f e + | Pexp_unreachable -> + pp f "." | _ -> self#expression1 f x method expression1 f x = if x.pexp_attributes <> [] then self#expression f x @@ -636,7 +599,8 @@ class printer ()= object(self:'self) method expression2 f x = if x.pexp_attributes <> [] then self#expression f x else match x.pexp_desc with - | Pexp_field (e, li) -> pp f "@[%a.%a@]" self#simple_expr e self#longident_loc li + | Pexp_field (e, li) -> + pp f "@[%a.%a@]" self#simple_expr e self#longident_loc li | Pexp_send (e, s) -> pp f "@[%a#%s@]" self#simple_expr e s | _ -> self#simple_expr f x @@ -647,7 +611,9 @@ class printer ()= object(self:'self) (match view_expr x with | `nil -> pp f "[]" | `tuple -> pp f "()" - | `list xs -> pp f "@[[%a]@]" (self#list self#under_semi#expression ~sep:";@;") xs + | `list xs -> + pp f "@[[%a]@]" + (self#list self#under_semi#expression ~sep:";@;") xs | `simple x -> self#longident f x | _ -> assert false) | Pexp_ident li -> @@ -666,7 +632,8 @@ class printer ()= object(self:'self) pp f "(%a : %a)" self#expression e self#core_type ct | Pexp_coerce (e, cto1, ct) -> pp f "(%a%a :> %a)" self#expression e - (self#option self#core_type ~first:" : " ~last:" ") cto1 (* no sep hint*) + (self#option self#core_type ~first:" : " ~last:" ") + cto1 (* no sep hint*) self#core_type ct | Pexp_variant (l, None) -> pp f "`%s" l | Pexp_record (l, eo) -> @@ -675,7 +642,9 @@ class printer ()= object(self:'self) | Pexp_ident {txt;_} when li.txt = txt -> pp f "@[%a@]" self#longident_loc li | _ -> - pp f "@[%a@;=@;%a@]" self#longident_loc li self#simple_expr e in + pp f "@[%a@;=@;%a@]" self#longident_loc li self#simple_expr + e + in pp f "@[@[{@;%a%a@]@;}@]"(* "@[{%a%a}@]" *) (self#option ~last:" with@;" self#simple_expr) eo (self#list longident_x_expression ~sep:";@;") l @@ -688,7 +657,8 @@ class printer ()= object(self:'self) | Pexp_for (s, e1, e2, df, e3) -> let fmt:(_,_,_)format = "@[@[@[<2>for %a =@;%a@;%a%a@;do@]@;%a@]@;done@]" in - pp f fmt self#pattern s self#expression e1 self#direction_flag df self#expression e2 self#expression e3 + pp f fmt self#pattern s self#expression e1 self#direction_flag df + self#expression e2 self#expression e3 | _ -> self#paren true self#expression f x method attributes f l = @@ -707,6 +677,8 @@ class printer ()= object(self:'self) pp f "@[<2>[@@@@@@%s@ %a]@]" s.txt self#payload e method value_description f x = + (* note: value_description has an attribute field, + but they're already printed by the callers this method *) pp f "@[%a%a@]" self#core_type x.pval_type (fun f x -> if x.pval_prim<>[] then begin @@ -904,8 +876,12 @@ class printer ()= object(self:'self) | Pmty_functor (_, None, mt2) -> pp f "@[functor () ->@ %a@]" self#module_type mt2 | Pmty_functor (s, Some mt1, mt2) -> - pp f "@[functor@ (%s@ :@ %a)@ ->@ %a@]" s.txt - self#module_type mt1 self#module_type mt2 + if s.txt = "_" then + pp f "@[%a@ ->@ %a@]" + self#module_type mt1 self#module_type mt2 + else + pp f "@[functor@ (%s@ :@ %a)@ ->@ %a@]" s.txt + self#module_type mt1 self#module_type mt2 | Pmty_with (mt, l) -> let with_constraint f = function | Pwith_type (li, ({ptype_params= ls ;_} as td)) -> @@ -914,7 +890,8 @@ class printer ()= object(self:'self) (self#list self#core_type ~sep:"," ~first:"(" ~last:")") ls self#longident_loc li self#type_declaration td | Pwith_module (li, li2) -> - pp f "module %a =@ %a" self#longident_loc li self#longident_loc li2; + pp f "module %a =@ %a" self#longident_loc li self#longident_loc + li2; | Pwith_typesubst ({ptype_params=ls;_} as td) -> let ls = List.map fst ls in pp f "type@ %a %s :=@ %a" @@ -936,8 +913,8 @@ class printer ()= object(self:'self) method signature_item f x :unit= begin match x.psig_desc with - | Psig_type l -> - self#type_def_list f l + | Psig_type (rf, l) -> + self#type_def_list f (rf, l) | Psig_value vd -> let intro = if vd.pval_prim = [] then "val" else "external" in pp f "@[<2>%s@ %a@ :@ %a@]%a" intro @@ -1050,6 +1027,7 @@ class printer ()= object(self:'self) self#item_attributes attrs | PStr x -> self#structure f x | PTyp x -> pp f ":"; self#core_type f x + | PSig x -> pp f ":"; self#signature f x | PPat (x, None) -> pp f "?"; self#pattern f x | PPat (x, Some e) -> pp f "?"; self#pattern f x; @@ -1057,11 +1035,12 @@ class printer ()= object(self:'self) (* transform [f = fun g h -> ..] to [f g h = ... ] could be improved *) method binding f {pvb_pat=p; pvb_expr=x; _} = + (* .pvb_attributes have already been printed by the caller, #bindings *) let rec pp_print_pexp_function f x = if x.pexp_attributes <> [] then pp f "=@;%a" self#expression x else match x.pexp_desc with | Pexp_fun (label, eo, p, e) -> - if label="" then + if label=Nolabel then pp f "%a@ %a" self#simple_pattern p pp_print_pexp_function e else pp f "%a@ %a" self#label_exp (label,eo,p) pp_print_pexp_function e @@ -1074,13 +1053,14 @@ class printer ()= object(self:'self) | ( _ , Ppat_constraint( p ,ty)) -> (* special case for the first*) (match ty.ptyp_desc with | Ptyp_poly _ -> - pp f "%a@;:@;%a=@;%a" self#simple_pattern p + pp f "%a@;:@;%a@;=@;%a" self#simple_pattern p self#core_type ty self#expression x | _ -> - pp f "(%a@;:%a)=@;%a" self#simple_pattern p + pp f "(%a@;:@;%a)@;=@;%a" self#simple_pattern p self#core_type ty self#expression x) | Pexp_constraint (e,t1),Ppat_var {txt;_} -> - pp f "%s:@ %a@;=@;%a" txt self#core_type t1 self#expression e + pp f "%a@;:@ %a@;=@;%a" protect_ident txt self#core_type t1 + self#expression e | (_, Ppat_var _) -> pp f "%a@ %a" self#simple_pattern p pp_print_pexp_function x | _ -> @@ -1088,7 +1068,7 @@ class printer ()= object(self:'self) (* [in] is not printed *) method bindings f (rf,l) = let binding kwd rf f x = - pp f "@[<2>%s %a%a@]%a" kwd self#rec_flag rf + pp f "@[<2>%s %a%a@]@ %a" kwd self#rec_flag rf self#binding x self#item_attributes x.pvb_attributes in begin match l with @@ -1103,12 +1083,13 @@ class printer ()= object(self:'self) method structure_item f x = begin match x.pstr_desc with | Pstr_eval (e, attrs) -> - pp f "@[let@ _ =@ %a@]%a" + pp f "@[;;%a@]%a" self#expression e self#item_attributes attrs - | Pstr_type [] -> assert false - | Pstr_type l -> self#type_def_list f l - | Pstr_value (rf, l) -> (* pp f "@[let %a%a@]" self#rec_flag rf self#bindings l *) + | Pstr_type (_, []) -> assert false + | Pstr_type (rf, l) -> self#type_def_list f (rf, l) + | Pstr_value (rf, l) -> + (* pp f "@[let %a%a@]" self#rec_flag rf self#bindings l *) pp f "@[<2>%a@]" self#bindings (rf,l) | Pstr_typext te -> self#type_extension f te | Pstr_exception ed -> self#exception_declaration f ed @@ -1131,7 +1112,7 @@ class printer ()= object(self:'self) ({pmty_desc=(Pmty_ident (_) | Pmty_signature (_));_} as mt)) when me.pmod_attributes = [] -> - pp f " :@;%a@;=@;%a@;" self#module_type mt self#module_expr me' + pp f " :@;%a@;=@;%a@;" self#module_type mt self#module_expr me' | _ -> pp f " =@ %a" self#module_expr me )) x.pmb_expr @@ -1202,7 +1183,7 @@ class printer ()= object(self:'self) | Pstr_recmodule decls -> (* 3.07 *) let aux f = function | ({pmb_expr={pmod_desc=Pmod_constraint (expr, typ)}} as pmb) -> - pp f "@[and@ %s:%a@ =@ %a@]%a" pmb.pmb_name.txt + pp f "@[@ and@ %s:%a@ =@ %a@]%a" pmb.pmb_name.txt self#module_type typ self#module_expr expr self#item_attributes pmb.pmb_attributes @@ -1228,17 +1209,7 @@ class printer ()= object(self:'self) method type_params f = function [] -> () | l -> pp f "%a " (self#list self#type_param ~first:"(" ~last:")" ~sep:",") l - method type_def_list f l = - let rf = - let is_nonrec = - List.exists - (fun td -> - List.exists (fun (n, _) -> n.txt = "nonrec") - td.ptype_attributes) - l - in - if is_nonrec then Nonrecursive else Recursive - in + method type_def_list f (rf, l) = let type_decl kwd rf f x = let eq = if (x.ptype_kind = Ptype_abstract) @@ -1258,7 +1229,21 @@ class printer ()= object(self:'self) | x :: xs -> pp f "@[%a@,%a@]" (type_decl "type" rf) x (self#list ~sep:"@," (type_decl "and" Recursive)) xs + + method record_declaration f lbls = + let type_record_field f pld = + pp f "@[<2>%a%s:@;%a@;%a@]" + self#mutable_flag pld.pld_mutable + pld.pld_name.txt + self#core_type pld.pld_type + self#attributes pld.pld_attributes + in + pp f "{@\n%a}" + (self#list type_record_field ~sep:";@\n" ) lbls + method type_declaration f x = + (* type_declaration has an attribute field, + but it's been printed by the caller of this method *) let priv f = match x.ptype_private with Public -> () @@ -1267,33 +1252,16 @@ class printer ()= object(self:'self) let manifest f = match x.ptype_manifest with | None -> () - | Some y -> pp f "@;%a" self#core_type y + | Some y -> + if x.ptype_kind = Ptype_abstract then + pp f "%t@;%a" priv self#core_type y + else + pp f "@;%a" self#core_type y in let constructor_declaration f pcd = - match pcd.pcd_args, pcd.pcd_res with - | _, None -> - pp f "|@;%s%a%a" pcd.pcd_name.txt - (fun f -> function - | [] -> () - | l -> pp f "@;of@;%a" (self#list self#core_type1 ~sep:"*@;") l) - pcd.pcd_args - self#attributes pcd.pcd_attributes - | [], Some x -> - pp f "|@;%s:@;%a%a" pcd.pcd_name.txt - self#core_type1 x - self#attributes pcd.pcd_attributes - | args, Some x -> - pp f "|@;%s:@;%a@;->@;%a%a" pcd.pcd_name.txt - (self#list self#core_type1 ~sep:"*@;") args - self#core_type1 x - self#attributes pcd.pcd_attributes - in - let label_declaration f pld = - pp f "@[<2>%a%s:@;%a%a;@]" - self#mutable_flag pld.pld_mutable - pld.pld_name.txt - self#core_type pld.pld_type - self#attributes pld.pld_attributes + pp f "|@;"; + self#constructor_declaration f (pcd.pcd_name.txt, pcd.pcd_args, + pcd.pcd_res, pcd.pcd_attributes) in let repr f = let intro f = @@ -1302,22 +1270,21 @@ class printer ()= object(self:'self) in match x.ptype_kind with | Ptype_variant xs -> - pp f "%t@\n%a" intro + pp f "%t%t@\n%a" intro priv (self#list ~sep:"@\n" constructor_declaration) xs | Ptype_abstract -> () | Ptype_record l -> - pp f "%t@;{@\n%a}" intro - (self#list ~sep:"@\n" label_declaration) l ; - | Ptype_open -> pp f "%t@;.." intro + pp f "%t%t@;%a" intro priv self#record_declaration l + | Ptype_open -> pp f "%t%t@;.." intro priv in let constraints f = - self#list ~first:"@ " - (fun f (ct1,ct2,_) -> - pp f "@[ constraint@ %a@ =@ %a@]" + List.iter + (fun (ct1,ct2,_) -> + pp f "@[@ constraint@ %a@ =@ %a@]" self#core_type ct1 self#core_type ct2) - f x.ptype_cstrs + x.ptype_cstrs in - pp f "%t%t%t%t" priv manifest repr constraints + pp f "%t%t%t" manifest repr constraints method type_extension f x = let extension_constructor f x = @@ -1326,30 +1293,45 @@ class printer ()= object(self:'self) pp f "@[<2>type %a%a +=%a@]%a" (fun f -> function | [] -> () - | l -> pp f "%a@;" (self#list self#type_param ~first:"(" ~last:")" ~sep:",") l) + | l -> pp f "%a@;" (self#list self#type_param ~first:"(" + ~last:")" ~sep:",") + l) x.ptyext_params self#longident_loc x.ptyext_path (self#list ~sep:"" extension_constructor) x.ptyext_constructors self#item_attributes x.ptyext_attributes - method extension_constructor f x = - match x.pext_kind with - | Pext_decl(l, None) -> - pp f "%s%a%a" x.pext_name.txt - self#attributes x.pext_attributes + method constructor_declaration f (name, args, res, attrs) = + match res with + | None -> + pp f "%s%a@;%a" name (fun f -> function - | [] -> () - | l -> pp f "@;of@;%a" (self#list self#core_type1 ~sep:"*@;") l) l - | Pext_decl(l, Some r) -> - pp f "%s%a:@;%a" x.pext_name.txt - self#attributes x.pext_attributes + | Pcstr_tuple [] -> () + | Pcstr_tuple l -> + pp f "@;of@;%a" (self#list self#core_type1 ~sep:"*@;") l + | Pcstr_record l -> pp f "@;of@;%a" (self#record_declaration) l + ) args + self#attributes attrs + | Some r -> + pp f "%s:@;%a@;%a" name (fun f -> function - | [] -> self#core_type1 f r - | l -> pp f "%a@;->@;%a" - (self#list self#core_type1 ~sep:"*@;") l - self#core_type1 r) - l + | Pcstr_tuple [] -> self#core_type1 f r + | Pcstr_tuple l -> pp f "%a@;->@;%a" + (self#list self#core_type1 ~sep:"*@;") l + self#core_type1 r + | Pcstr_record l -> + pp f "%a@;->@;%a" (self#record_declaration) l self#core_type1 r + ) + args + self#attributes attrs + + + method extension_constructor f x = + match x.pext_kind with + | Pext_decl(l, r) -> + self#constructor_declaration f (x.pext_name.txt, l, r, + x.pext_attributes) | Pext_rebind li -> pp f "%s%a@;=@;%a" x.pext_name.txt self#attributes x.pext_attributes @@ -1358,22 +1340,22 @@ class printer ()= object(self:'self) method case_list f l : unit = let aux f {pc_lhs; pc_guard; pc_rhs} = pp f "@;| @[<2>%a%a@;->@;%a@]" - self#pattern pc_lhs (self#option self#expression ~first:"@;when@;") pc_guard self#under_pipe#expression pc_rhs in + self#pattern pc_lhs (self#option self#expression ~first:"@;when@;") + pc_guard self#under_pipe#expression pc_rhs + in self#list aux f l ~sep:"" method label_x_expression_param f (l,e) = - match l with - | "" -> self#expression2 f e ; (* level 2*) - | lbl -> - let simple_name = match e.pexp_desc with - | Pexp_ident {txt=Lident l;_} -> Some l - | _ -> None in - if lbl.[0] = '?' then - let str = String.sub lbl 1 (String.length lbl-1) in + let simple_name = match e.pexp_desc with + | Pexp_ident {txt=Lident l;_} -> Some l + | _ -> None + in match l with + | Nolabel -> self#expression2 f e ; (* level 2*) + | Optional str -> if Some str = simple_name then - pp f "%s" lbl + pp f "?%s" str else - pp f "%s:%a" lbl self#simple_expr e - else + pp f "?%s:%a" str self#simple_expr e + | Labelled lbl -> if Some lbl = simple_name then pp f "~%s" lbl else @@ -1383,7 +1365,8 @@ class printer ()= object(self:'self) (match x with | Pdir_none -> () | Pdir_string (s) -> pp f "@ %S" s - | Pdir_int (i) -> pp f "@ %d" i + | Pdir_int (n,None) -> pp f "@ %s" n + | Pdir_int (n,Some m) -> pp f "@ %s%c" n m | Pdir_ident (li) -> pp f "@ %a" self#longident li | Pdir_bool (b) -> pp f "@ %s" (string_of_bool b)) diff --git a/parsing/pprintast.mli b/parsing/pprintast.mli index 45556b84..ec272254 100644 --- a/parsing/pprintast.mli +++ b/parsing/pprintast.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Hongbo Zhang (University of Pennsylvania) *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Hongbo Zhang (University of Pennsylvania) *) +(* *) +(* Copyright 1996 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 space_formatter = (unit, Format.formatter, unit) format class printer : @@ -35,8 +38,12 @@ class printer : method class_type : Format.formatter -> Parsetree.class_type -> unit method class_type_declaration_list : Format.formatter -> Parsetree.class_type_declaration list -> unit - method constant : Format.formatter -> Asttypes.constant -> unit + method constant : Format.formatter -> Parsetree.constant -> unit method constant_string : Format.formatter -> string -> unit + method constructor_declaration : + Format.formatter -> (string * Parsetree.constructor_arguments + * Parsetree.core_type option * Parsetree.attributes) + -> unit method core_type : Format.formatter -> Parsetree.core_type -> unit method core_type1 : Format.formatter -> Parsetree.core_type -> unit method direction_flag : @@ -52,10 +59,10 @@ class printer : Format.formatter -> Parsetree.extension_constructor -> unit method label_exp : Format.formatter -> - Asttypes.label * Parsetree.expression option * Parsetree.pattern -> + Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern -> unit method label_x_expression_param : - Format.formatter -> Asttypes.label * Parsetree.expression -> unit + Format.formatter -> Asttypes.arg_label * Parsetree.expression -> unit method list : ?sep:space_formatter -> ?first:space_formatter -> @@ -81,6 +88,8 @@ class printer : method private_flag : Format.formatter -> Asttypes.private_flag -> unit method rec_flag : Format.formatter -> Asttypes.rec_flag -> unit method nonrec_flag : Format.formatter -> Asttypes.rec_flag -> unit + method record_declaration : + Format.formatter -> Parsetree.label_declaration list -> unit method reset : 'b method reset_semi : 'b @@ -104,7 +113,8 @@ class printer : method type_declaration : Format.formatter -> Parsetree.type_declaration -> unit method type_def_list : - Format.formatter -> Parsetree.type_declaration list -> unit + Format.formatter -> Asttypes.rec_flag * Parsetree.type_declaration list + -> unit method type_extension : Format.formatter -> Parsetree.type_extension -> unit method type_param : @@ -112,7 +122,7 @@ class printer : method type_params : Format.formatter -> (Parsetree.core_type * Asttypes.variance) list -> unit method type_with_label : - Format.formatter -> Asttypes.label * Parsetree.core_type -> unit + Format.formatter -> Asttypes.arg_label * Parsetree.core_type -> unit method tyvar : Format.formatter -> string -> unit method under_pipe : 'b method under_semi : 'b diff --git a/parsing/printast.ml b/parsing/printast.ml index cb94856a..0f246db4 100644 --- a/parsing/printast.ml +++ b/parsing/printast.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Para, 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 Q Public License version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Para, 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. *) +(* *) +(**************************************************************************) open Asttypes;; open Format;; @@ -41,25 +44,26 @@ let rec fmt_longident_aux f x = let fmt_longident f x = fprintf f "\"%a\"" fmt_longident_aux x;; -let fmt_longident_loc f x = +let fmt_longident_loc f (x : Longident.t loc) = fprintf f "\"%a\" %a" fmt_longident_aux x.txt fmt_location x.loc; ;; -let fmt_string_loc f x = +let fmt_string_loc f (x : string loc) = fprintf f "\"%s\" %a" x.txt fmt_location x.loc; ;; +let fmt_char_option f = function + | None -> fprintf f "None" + | Some c -> fprintf f "Some %c" c + let fmt_constant f x = match x with - | Const_int (i) -> fprintf f "Const_int %d" i; - | Const_char (c) -> fprintf f "Const_char %02x" (Char.code c); - | Const_string (s, None) -> fprintf f "Const_string(%S,None)" s; - | Const_string (s, Some delim) -> - fprintf f "Const_string (%S,Some %S)" s delim; - | Const_float (s) -> fprintf f "Const_float %s" s; - | Const_int32 (i) -> fprintf f "Const_int32 %ld" i; - | Const_int64 (i) -> fprintf f "Const_int64 %Ld" i; - | Const_nativeint (i) -> fprintf f "Const_nativeint %nd" i; + | Pconst_integer (i,m) -> fprintf f "PConst_int (%s,%a)" i fmt_char_option m; + | Pconst_char (c) -> fprintf f "PConst_char %02x" (Char.code c); + | Pconst_string (s, None) -> fprintf f "PConst_string(%S,None)" s; + | Pconst_string (s, Some delim) -> + fprintf f "PConst_string (%S,Some %S)" s delim; + | Pconst_float (s,m) -> fprintf f "PConst_float (%s,%a)" s fmt_char_option m; ;; let fmt_mutable_flag f x = @@ -128,8 +132,11 @@ let option i f ppf x = let longident_loc i ppf li = line i ppf "%a\n" fmt_longident_loc li;; let string i ppf s = line i ppf "\"%s\"\n" s;; let string_loc i ppf s = line i ppf "%a\n" fmt_string_loc s;; -let bool i ppf x = line i ppf "%s\n" (string_of_bool x);; -let label i ppf x = line i ppf "label=\"%s\"\n" x;; +let arg_label i ppf = function + | Nolabel -> line i ppf "Nolabel\n" + | Optional s -> line i ppf "Optional \"%s\"\n" s + | Labelled s -> line i ppf "Labelled \"%s\"\n" s +;; let rec core_type i ppf x = line i ppf "core_type %a\n" fmt_location x.ptyp_loc; @@ -140,7 +147,7 @@ let rec core_type i ppf x = | Ptyp_var (s) -> line i ppf "Ptyp_var %s\n" s; | Ptyp_arrow (l, ct1, ct2) -> line i ppf "Ptyp_arrow\n"; - string i ppf l; + arg_label i ppf l; core_type i ppf ct1; core_type i ppf ct2; | Ptyp_tuple l -> @@ -250,7 +257,8 @@ and expression i ppf x = line i ppf "Pexp_function\n"; list i case ppf l; | Pexp_fun (l, eo, p, e) -> - line i ppf "Pexp_fun \"%s\"\n" l; + line i ppf "Pexp_fun\n"; + arg_label i ppf l; option i expression ppf eo; pattern i ppf p; expression i ppf e; @@ -359,6 +367,8 @@ and expression i ppf x = | Pexp_extension (s, arg) -> line i ppf "Pexp_extension \"%s\"\n" s.txt; payload i ppf arg + | Pexp_unreachable -> + line i ppf "Pexp_unreachable" and value_description i ppf x = line i ppf "value_description %a %a\n" fmt_string_loc @@ -395,6 +405,7 @@ and attributes i ppf l = and payload i ppf = function | PStr x -> structure i ppf x + | PSig x -> signature i ppf x | PTyp x -> core_type i ppf x | PPat (x, None) -> pattern i ppf x | PPat (x, Some g) -> @@ -439,7 +450,7 @@ and extension_constructor_kind i ppf x = match x with Pext_decl(a, r) -> line i ppf "Pext_decl\n"; - list (i+1) core_type ppf a; + constructor_arguments (i+1) ppf a; option (i+1) core_type ppf r; | Pext_rebind li -> line i ppf "Pext_rebind\n"; @@ -457,7 +468,8 @@ and class_type i ppf x = line i ppf "Pcty_signature\n"; class_signature i ppf cs; | Pcty_arrow (l, co, cl) -> - line i ppf "Pcty_arrow \"%s\"\n" l; + line i ppf "Pcty_arrow\n"; + arg_label i ppf l; core_type i ppf co; class_type i ppf cl; | Pcty_extension (s, arg) -> @@ -531,7 +543,7 @@ and class_expr i ppf x = class_structure i ppf cs; | Pcl_fun (l, eo, p, e) -> line i ppf "Pcl_fun\n"; - label i ppf l; + arg_label i ppf l; option i expression ppf eo; pattern i ppf p; class_expr i ppf e; @@ -640,8 +652,8 @@ and signature_item i ppf x = | Psig_value vd -> line i ppf "Psig_value\n"; value_description i ppf vd; - | Psig_type l -> - line i ppf "Psig_type\n"; + | Psig_type (rf, l) -> + line i ppf "Psig_type %a\n" fmt_rec_flag rf; list i type_declaration ppf l; | Psig_typext te -> line i ppf "Psig_typext\n"; @@ -748,8 +760,8 @@ and structure_item i ppf x = | Pstr_primitive vd -> line i ppf "Pstr_primitive\n"; value_description i ppf vd; - | Pstr_type l -> - line i ppf "Pstr_type\n"; + | Pstr_type (rf, l) -> + line i ppf "Pstr_type %a\n" fmt_rec_flag rf; list i type_declaration ppf l; | Pstr_typext te -> line i ppf "Pstr_typext\n"; @@ -810,9 +822,13 @@ and constructor_decl i ppf line i ppf "%a\n" fmt_location pcd_loc; line (i+1) ppf "%a\n" fmt_string_loc pcd_name; attributes i ppf pcd_attributes; - list (i+1) core_type ppf pcd_args; + constructor_arguments (i+1) ppf pcd_args; option (i+1) core_type ppf pcd_res +and constructor_arguments i ppf = function + | Pcstr_tuple l -> list i core_type ppf l + | Pcstr_record l -> list i label_decl ppf l + and label_decl i ppf {pld_name; pld_mutable; pld_type; pld_loc; pld_attributes}= line i ppf "%a\n" fmt_location pld_loc; attributes i ppf pld_attributes; @@ -848,7 +864,8 @@ and longident_x_expression i ppf (li, e) = expression (i+1) ppf e; and label_x_expression i ppf (l,e) = - line i ppf "
    0 - 0 - - - 0 - 0 - - - +\n\ +\n\ +\n\ +\ \n\ +]>\n\ +\n\ + \n\ +\n\ +\n\ +\t65\n\ +\t20\n\ +\t300\n\ +\t2400\n\ +\t300\n\ +\t25\n\ +\t50\n\ +\n\ +\n\ +\tAvocado Dip\n\ +\tSunnydale\n\ +\t29\n\ +\t\n\ +\t11\n\ +\t3\n\ +\t5\n\ +\t210\n\ +\t2\n\ +\t0\n\ +\t1\n\ +\t\n\ +\t\t0\n\ +\t\t0\n\ +\t\n\ +\t\n\ +\t\t0\n\ +\t\t0\n\ +\t\n\ +\n\ +\n\ " in let result = [ ""; @@ -974,7 +1028,29 @@ escaped text]]> "\n"; ""; "\n"; - ""; + ""; "\n"] in let re = Str.regexp _XML_SPE in let rec process i l = diff --git a/testsuite/tests/lib-str/t01.reference b/testsuite/tests/lib-str/t01.reference index ade95dea..0a719240 100644 --- a/testsuite/tests/lib-str/t01.reference +++ b/testsuite/tests/lib-str/t01.reference @@ -85,6 +85,8 @@ Search for /a$/ .. Null characters in regexps .. +Many groups + . Backward search for /the quick/ .... Backward search for /a\([0-9]+\)/ diff --git a/testsuite/tests/lib-stream/Makefile b/testsuite/tests/lib-stream/Makefile index e5bd381a..77b26912 100644 --- a/testsuite/tests/lib-stream/Makefile +++ b/testsuite/tests/lib-stream/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 diff --git a/testsuite/tests/lib-stream/count_concat_bug.ml b/testsuite/tests/lib-stream/count_concat_bug.ml index 986a2ea0..37793891 100644 --- a/testsuite/tests/lib-stream/count_concat_bug.ml +++ b/testsuite/tests/lib-stream/count_concat_bug.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Gabriel Scherer, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Gabriel Scherer, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) let is_empty s = try Stream.empty s; true with Stream.Failure -> false diff --git a/testsuite/tests/lib-string/Makefile b/testsuite/tests/lib-string/Makefile new file mode 100644 index 00000000..b25e53f9 --- /dev/null +++ b/testsuite/tests/lib-string/Makefile @@ -0,0 +1,22 @@ +#************************************************************************** +#* * +#* 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=str +ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/str +LD_PATH=$(TOPDIR)/otherlibs/str + +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-string/test_string.ml b/testsuite/tests/lib-string/test_string.ml new file mode 100644 index 00000000..8fe0521a --- /dev/null +++ b/testsuite/tests/lib-string/test_string.ml @@ -0,0 +1,38 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, Jane Street Group, LLC *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +let rec build_string f n accu = + if n <= 0 + then String.concat "" accu + else build_string f (n-1) (f (n-1) :: accu) +;; + +let char n = String.make 1 (Char.chr n);; + +let reference n = + if n = 8 then "\\b" + else if n = 9 then "\\t" + else if n = 10 then "\\n" + else if n = 13 then "\\r" + else if n = Char.code '\"' then "\\\"" + else if n = Char.code '\\' then "\\\\" + else if n < 32 || n > 126 then Printf.sprintf "\\%03d" n + else char n +;; + +let raw_string = build_string char 256 [];; +let ref_string = build_string reference 256 [];; + +if String.escaped raw_string <> ref_string then failwith "test:String.escaped";; diff --git a/testsuite/tests/lib-string/test_string.reference b/testsuite/tests/lib-string/test_string.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/lib-systhreads/Makefile b/testsuite/tests/lib-systhreads/Makefile index fc098713..280f16d5 100644 --- a/testsuite/tests/lib-systhreads/Makefile +++ b/testsuite/tests/lib-systhreads/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 threads diff --git a/testsuite/tests/lib-systhreads/testfork.ml b/testsuite/tests/lib-systhreads/testfork.ml index 843e5ed2..2f019fa3 100644 --- a/testsuite/tests/lib-systhreads/testfork.ml +++ b/testsuite/tests/lib-systhreads/testfork.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* POSIX threads and fork() *) diff --git a/testsuite/tests/lib-systhreads/testfork.precheck b/testsuite/tests/lib-systhreads/testfork.precheck index f93abf1a..0dfed5de 100644 --- a/testsuite/tests/lib-systhreads/testfork.precheck +++ b/testsuite/tests/lib-systhreads/testfork.precheck @@ -1,16 +1,23 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** + +case `grep '^SYSTEM=' ../../../config/Makefile` in + SYSTEM=bsd_elf) exit 3;; +esac case `sed -n -e '/OTHERLIBRARIES=/s// /p' ../../../config/Makefile` in - *' unix '*) exit 0;; + *' unix'*) exit 0;; *) exit 3;; esac diff --git a/testsuite/tests/lib-threads/.ignore b/testsuite/tests/lib-threads/.ignore deleted file mode 100644 index e6d9e45b..00000000 --- a/testsuite/tests/lib-threads/.ignore +++ /dev/null @@ -1 +0,0 @@ -*.byt diff --git a/testsuite/tests/lib-threads/Makefile b/testsuite/tests/lib-threads/Makefile index fc098713..8288dfdc 100644 --- a/testsuite/tests/lib-threads/Makefile +++ b/testsuite/tests/lib-threads/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 threads @@ -16,5 +19,15 @@ ADD_COMPFLAGS=-thread -I $(OTOPDIR)/otherlibs/systhreads \ -I $(OTOPDIR)/otherlibs/$(UNIXLIBVAR)unix LD_PATH=$(TOPDIR)/otherlibs/systhreads:$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix +default: + @$(if $(filter msvc mingw,$(TOOLCHAIN)),$(MAKE) sigint.exe,true) + @$(SET_LD_PATH) $(MAKE) run-all + include $(BASEDIR)/makefiles/Makefile.several include $(BASEDIR)/makefiles/Makefile.common + +sigint.exe: sigint.$(O) + @$(CC) $(if $(filter msvc,$(CCOMPTYPE)),/Fe$@,-o $@) $^ + +%.obj: %.c + @$(CC) -c $*.c > /dev/null diff --git a/testsuite/tests/lib-threads/bank.ml b/testsuite/tests/lib-threads/bank.ml new file mode 100644 index 00000000..7474d983 --- /dev/null +++ b/testsuite/tests/lib-threads/bank.ml @@ -0,0 +1,42 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* The bank account example, using events and channels *) + +open Printf +open Event + +type account = int channel * int channel + +let account (put_ch, get_ch) = + let rec acc balance = + select [ + wrap (send get_ch balance) (fun () -> acc balance); + wrap (receive put_ch) (fun amount -> + if balance + amount < 0 then failwith "negative balance"; + acc (balance + amount)) + ] + in acc 0 + +let get ((put_ch, get_ch): account) = sync (receive get_ch) +let put ((put_ch, get_ch): account) amount = sync (send put_ch amount) + +let _ = + let a : account = (new_channel(), new_channel()) in + ignore (Thread.create account a); + put a 100; + printf "Current balance: %d\n" (get a); + for i = 1 to 99 do put a (-2); put a 1 done; + printf "Final balance: %d\n" (get a) diff --git a/testsuite/tests/lib-threads/bank.reference b/testsuite/tests/lib-threads/bank.reference new file mode 100644 index 00000000..80ad5cd5 --- /dev/null +++ b/testsuite/tests/lib-threads/bank.reference @@ -0,0 +1,2 @@ +Current balance: 100 +Final balance: 1 diff --git a/testsuite/tests/lib-threads/beat.ml b/testsuite/tests/lib-threads/beat.ml new file mode 100644 index 00000000..f269baa7 --- /dev/null +++ b/testsuite/tests/lib-threads/beat.ml @@ -0,0 +1,34 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* Test Thread.delay and its scheduling *) + +open Printf + +let tick (delay, count) = + while true do + Thread.delay delay; + incr count + done + +let _ = + let c1 = ref 0 and c2 = ref 0 in + ignore (Thread.create tick (0.333333333, c1)); + ignore (Thread.create tick (0.5, c2)); + Thread.delay 3.0; + let n1 = !c1 and n2 = !c2 in + if n1 >= 8 && n1 <= 10 && n2 >= 5 && n2 <= 7 + then printf "passed\n" + else printf "FAILED (n1 = %d, n2 = %d)\n" n1 n2 diff --git a/testsuite/tests/lib-threads/beat.reference b/testsuite/tests/lib-threads/beat.reference new file mode 100644 index 00000000..b0aad4de --- /dev/null +++ b/testsuite/tests/lib-threads/beat.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/lib-threads/bufchan.ml b/testsuite/tests/lib-threads/bufchan.ml new file mode 100644 index 00000000..a686a94e --- /dev/null +++ b/testsuite/tests/lib-threads/bufchan.ml @@ -0,0 +1,66 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +open Event + +type 'a buffer_channel = { + input: 'a channel; + output: 'a channel; + thread: Thread.t; +} + +let new_buffer_channel() = + let ic = new_channel() in + let oc = new_channel() in + let rec buffer_process front rear = + match (front, rear) with + | (["EOF"], []) -> Thread.exit () + | ([], []) -> buffer_process [sync(receive ic)] [] + | (hd::tl, _) -> + select [ + wrap (receive ic) (fun x -> buffer_process front (x::rear)); + wrap (send oc hd) (fun () -> buffer_process tl rear) + ] + | ([], _) -> buffer_process (List.rev rear) [] in + let t = Thread.create (buffer_process []) [] in + { input = ic; output = oc; thread = t } + +let buffer_send bc data = + sync(send bc.input data) + +let buffer_receive bc = + receive bc.output + +(* Test *) + +let box = new_buffer_channel() +let ch = new_channel() + +let f () = + buffer_send box "un"; + buffer_send box "deux"; + sync (send ch 3) + +let g () = + print_int (sync(receive ch)); print_newline(); + print_string (sync(buffer_receive box)); print_newline(); + print_string (sync(buffer_receive box)); print_newline() + +let _ = + let t = Thread.create f () in + g(); + buffer_send box "EOF"; + Thread.join box.thread; + Thread.join t diff --git a/testsuite/tests/lib-threads/test8.reference b/testsuite/tests/lib-threads/bufchan.reference similarity index 100% rename from testsuite/tests/lib-threads/test8.reference rename to testsuite/tests/lib-threads/bufchan.reference diff --git a/testsuite/tests/lib-threads/close.ml b/testsuite/tests/lib-threads/close.ml index 01b90afd..ff6b2b06 100644 --- a/testsuite/tests/lib-threads/close.ml +++ b/testsuite/tests/lib-threads/close.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let main () = let (rd, wr) = Unix.pipe() in diff --git a/testsuite/tests/lib-threads/fileio.ml b/testsuite/tests/lib-threads/fileio.ml new file mode 100644 index 00000000..370fee0a --- /dev/null +++ b/testsuite/tests/lib-threads/fileio.ml @@ -0,0 +1,132 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* Test a file copy function *) + +let test msg producer consumer src dst = + print_string msg; print_newline(); + let ic = open_in_bin src in + let oc = open_out_bin dst in + let (in_fd, out_fd) = Unix.pipe() in + let ipipe = Unix.in_channel_of_descr in_fd in + let opipe = Unix.out_channel_of_descr out_fd in + let prod = Thread.create producer (ic, opipe) in + let cons = Thread.create consumer (ipipe, oc) in + Thread.join prod; + Thread.join cons; + if Unix.system ("cmp " ^ src ^ " " ^ dst) = Unix.WEXITED 0 + then print_string "passed" + else print_string "FAILED"; + print_newline() + +(* File copy with constant-sized chunks *) + +let copy_file sz (ic, oc) = + let buffer = String.create sz in + let rec copy () = + let n = input ic buffer 0 sz in + if n = 0 then () else begin + output oc buffer 0 n; + copy () + end in + copy(); + close_in ic; + close_out oc + +(* File copy with random-sized chunks *) + +let copy_random sz (ic, oc) = + let buffer = String.create sz in + let rec copy () = + let s = 1 + Random.int sz in + let n = input ic buffer 0 s in + if n = 0 then () else begin + output oc buffer 0 n; + copy () + end in + copy(); + close_in ic; + close_out oc + +(* File copy line per line *) + +let copy_line (ic, oc) = + try + while true do + output_string oc (input_line ic); output_char oc '\n' + done + with End_of_file -> + close_in ic; + close_out oc + +(* Create long lines of text *) + +let make_lines ofile = + let oc = open_out ofile in + for i = 1 to 256 do + output_string oc (String.make (i*16) '.'); output_char oc '\n' + done; + close_out oc + +(* Test input_line on truncated lines *) + +let test_trunc_line ofile = + print_string "truncated line"; print_newline(); + let oc = open_out ofile in + output_string oc "A line without newline!"; + close_out oc; + try + let ic = open_in ofile in + let s = input_line ic in + close_in ic; + if s = "A line without newline!" + then print_string "passed" + else print_string "FAILED"; + print_newline() + with End_of_file -> + print_string "FAILED"; print_newline() + +(* The test *) + +let main() = + let ifile = if Array.length Sys.argv > 1 then Sys.argv.(1) else "fileio.ml" in + let ofile = Filename.temp_file "testio" "" in + test "256-byte chunks, 256-byte chunks" + (copy_file 256) (copy_file 256) ifile ofile; + test "4096-byte chunks, 4096-byte chunks" + (copy_file 4096) (copy_file 4096) ifile ofile; + test "65536-byte chunks, 65536-byte chunks" + (copy_file 65536) (copy_file 65536) ifile ofile; + test "256-byte chunks, 4096-byte chunks" + (copy_file 256) (copy_file 4096) ifile ofile; + test "4096-byte chunks, 256-byte chunks" + (copy_file 4096) (copy_file 256) ifile ofile; + test "4096-byte chunks, 65536-byte chunks" + (copy_file 4096) (copy_file 65536) ifile ofile; + test "263-byte chunks, 4011-byte chunks" + (copy_file 263) (copy_file 4011) ifile ofile; + test "613-byte chunks, 1027-byte chunks" + (copy_file 613) (copy_file 1027) ifile ofile; + test "0...8192 byte chunks" + (copy_random 8192) (copy_random 8192) ifile ofile; + let linesfile = Filename.temp_file "lines" "" in + make_lines linesfile; + test "line per line" + copy_line copy_line linesfile ofile; + test_trunc_line ofile; + Sys.remove linesfile; + Sys.remove ofile + +let _ = Unix.handle_unix_error main (); exit 0 diff --git a/testsuite/tests/lib-threads/fileio.reference b/testsuite/tests/lib-threads/fileio.reference new file mode 100644 index 00000000..24f04b9b --- /dev/null +++ b/testsuite/tests/lib-threads/fileio.reference @@ -0,0 +1,22 @@ +256-byte chunks, 256-byte chunks +passed +4096-byte chunks, 4096-byte chunks +passed +65536-byte chunks, 65536-byte chunks +passed +256-byte chunks, 4096-byte chunks +passed +4096-byte chunks, 256-byte chunks +passed +4096-byte chunks, 65536-byte chunks +passed +263-byte chunks, 4011-byte chunks +passed +613-byte chunks, 1027-byte chunks +passed +0...8192 byte chunks +passed +line per line +passed +truncated line +passed diff --git a/testsuite/tests/lib-threads/pr4466.ml b/testsuite/tests/lib-threads/pr4466.ml new file mode 100644 index 00000000..2f7092d7 --- /dev/null +++ b/testsuite/tests/lib-threads/pr4466.ml @@ -0,0 +1,85 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Paris *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +open Printf + +(* Regression test for PR#4466: select timeout with simultaneous read + and write on socket in Windows. *) + +(* Scenario: + - thread [server] implements a simple 'echo' server on a socket + - thread [reader] selects then reads from a socket connected to + the echo server and copies to standard output + - main program executes [writer], which writes to the same socket + (the one connected to the echo server) +*) + +let serve_connection s = + let buf = String.make 1024 '>' in + while true do + let n = Unix.recv s buf 2 (String.length buf - 2) [] in + if n = 0 then begin + Unix.close s; Thread.exit () + end else begin + ignore (Unix.send s buf 0 (n + 2) []) + end + done + +let server sock = + while true do + let (s, _) = Unix.accept sock in + ignore(Thread.create serve_connection s) + done + +let reader s = + let buf = String.make 16 ' ' in + match Unix.select [s] [] [] 10.0 with + | (_::_, _, _) -> + printf "Selected\n%!"; + let n = Unix.recv s buf 0 (String.length buf) [] in + printf "Data read: %s\n%!" (String.sub buf 0 n) + | ([], _, _) -> + printf "TIMEOUT\n%!" + +let writer s msg = + ignore (Unix.send s msg 0 (String.length msg) []) + +let _ = + let addr = Unix.ADDR_INET(Unix.inet_addr_loopback, 9876) in + let serv = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.setsockopt serv Unix.SO_REUSEADDR true; + Unix.bind serv addr; + Unix.listen serv 5; + ignore (Thread.create server serv); + Thread.delay 0.2; + let client = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.connect client addr; + (* Send before select & read *) + writer client "1111"; + let a = Thread.create reader client in + Thread.delay 0.1; + Thread.join a; + (* Select then send *) + let a = Thread.create reader client in + Thread.delay 0.1; + writer client "2222"; + Thread.join a; + (* Select then send again *) + let a = Thread.create reader client in + Thread.delay 0.1; + writer client "3333"; + Thread.join a diff --git a/testsuite/tests/lib-threads/pr4466.reference b/testsuite/tests/lib-threads/pr4466.reference new file mode 100644 index 00000000..ecfdf536 --- /dev/null +++ b/testsuite/tests/lib-threads/pr4466.reference @@ -0,0 +1,6 @@ +Selected +Data read: >>1111 +Selected +Data read: >>2222 +Selected +Data read: >>3333 diff --git a/testsuite/tests/lib-threads/pr5325.ml b/testsuite/tests/lib-threads/pr5325.ml new file mode 100644 index 00000000..508eb4a4 --- /dev/null +++ b/testsuite/tests/lib-threads/pr5325.ml @@ -0,0 +1,72 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Paris *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +open Printf + +(* Regression test for PR#5325: simultaneous read and write on socket + in Windows. *) + +(* Scenario: + - thread [server] implements a simple 'echo' server on a socket + - thread [reader] reads from a socket connected to the echo server + and copies to standard output + - main program executes [writer], which writes to the same socket + (the one connected to the echo server) + - thread [timeout] causes a failure if nothing happens in 10 seconds. +*) + +let serve_connection s = + let buf = String.make 1024 '>' in + let n = Unix.read s buf 2 (String.length buf - 2) in + ignore (Unix.write s buf 0 (n + 2)); + Unix.close s + +let server sock = + while true do + let (s, _) = Unix.accept sock in + ignore(Thread.create serve_connection s) + done + +let timeout () = + Thread.delay 10.0; + printf "Time out, exiting...\n%!"; + exit 2 + +let reader s = + let buf = String.make 1024 ' ' in + let n = Unix.read s buf 0 (String.length buf) in + print_string (String.sub buf 0 n); flush stdout + +let writer s msg = + ignore (Unix.write s msg 0 (String.length msg)); + Unix.shutdown s Unix.SHUTDOWN_SEND + +let _ = + let addr = Unix.ADDR_INET(Unix.inet_addr_loopback, 9876) in + let serv = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.setsockopt serv Unix.SO_REUSEADDR true; + Unix.bind serv addr; + Unix.listen serv 5; + ignore (Thread.create server serv); + ignore (Thread.create timeout ()); + Thread.delay 0.5; + let client = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.connect client addr; + let rd = Thread.create reader client in + Thread.delay 0.5; + writer client "Client data\n"; + Thread.join rd diff --git a/testsuite/tests/lib-threads/pr5325.reference b/testsuite/tests/lib-threads/pr5325.reference new file mode 100644 index 00000000..dd045794 --- /dev/null +++ b/testsuite/tests/lib-threads/pr5325.reference @@ -0,0 +1 @@ +>>Client data diff --git a/testsuite/tests/lib-threads/prodcons.ml b/testsuite/tests/lib-threads/prodcons.ml new file mode 100644 index 00000000..e243ce0f --- /dev/null +++ b/testsuite/tests/lib-threads/prodcons.ml @@ -0,0 +1,77 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* Classic producer-consumer *) + +type 'a prodcons = + { buffer: 'a array; + lock: Mutex.t; + mutable readpos: int; + mutable writepos: int; + notempty: Condition.t; + notfull: Condition.t } + +let create size init = + { buffer = Array.make size init; + lock = Mutex.create(); + readpos = 0; + writepos = 0; + notempty = Condition.create(); + notfull = Condition.create() } + +let put p data = + Mutex.lock p.lock; + while (p.writepos + 1) mod Array.length p.buffer = p.readpos do + Condition.wait p.notfull p.lock + done; + p.buffer.(p.writepos) <- data; + p.writepos <- (p.writepos + 1) mod Array.length p.buffer; + Condition.signal p.notempty; + Mutex.unlock p.lock + +let get p = + Mutex.lock p.lock; + while p.writepos = p.readpos do + Condition.wait p.notempty p.lock + done; + let data = p.buffer.(p.readpos) in + p.readpos <- (p.readpos + 1) mod Array.length p.buffer; + Condition.signal p.notfull; + Mutex.unlock p.lock; + data + +(* Test *) + +let rec produce buff n max = + put buff n; + if n < max then produce buff (n+1) max + +let rec consume buff cur max = + let n = get buff in + if n <> cur then false + else if n = max then true + else consume buff (cur + 1) max + +let _ = + let buff1 = create 20 0 and buff2 = create 30 0 in + let ok1 = ref false and ok2 = ref false in + let _p1 = Thread.create (fun () -> produce buff1 0 10000) () + and _p2 = Thread.create (fun () -> produce buff2 0 8000) () + and c1 = Thread.create (fun () -> ok1 := consume buff1 0 10000) () in + ok2 := consume buff2 0 8000; + Thread.join c1; + if !ok1 && !ok2 + then print_string "passed\n" + else print_string "FAILED\n" diff --git a/testsuite/tests/lib-threads/prodcons.reference b/testsuite/tests/lib-threads/prodcons.reference new file mode 100644 index 00000000..b0aad4de --- /dev/null +++ b/testsuite/tests/lib-threads/prodcons.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/lib-threads/prodcons2.ml b/testsuite/tests/lib-threads/prodcons2.ml new file mode 100644 index 00000000..6133e07b --- /dev/null +++ b/testsuite/tests/lib-threads/prodcons2.ml @@ -0,0 +1,48 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* Producer-consumer with events and multiple producers *) + +open Event + +let rec produce chan n max = + sync (send chan n); + if n < max then produce chan (n + 1) max else sync (send chan (-1)) + +let rec consume chans sum = + let rec mkreceive prev = function + | [] -> [] + | chan :: rem as chans -> + wrap (receive chan) (fun n -> + if n < 0 + then consume (List.rev_append rem prev) sum + else consume (List.rev_append chans prev) (sum + n)) + :: mkreceive (chan :: prev) rem + in + if chans = [] then sum else select (mkreceive [] chans) + +let sum_0_n n = n * (n + 1) / 2 + +let _ = + let chan1 = new_channel() + and chan2 = new_channel() + and chan3 = new_channel() in + ignore (Thread.create (fun () -> produce chan1 0 5000) ()); + ignore (Thread.create (fun () -> produce chan2 0 2000) ()); + ignore (Thread.create (fun () -> produce chan3 0 1000) ()); + let n = consume [chan1; chan2; chan3] 0 in + if n = sum_0_n 5000 + sum_0_n 2000 + sum_0_n 1000 + then print_string "passed\n" + else print_string "FAILED\n" diff --git a/testsuite/tests/lib-threads/prodcons2.reference b/testsuite/tests/lib-threads/prodcons2.reference new file mode 100644 index 00000000..b0aad4de --- /dev/null +++ b/testsuite/tests/lib-threads/prodcons2.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/lib-threads/sieve.ml b/testsuite/tests/lib-threads/sieve.ml index ac3a9d2f..6cee51a1 100644 --- a/testsuite/tests/lib-threads/sieve.ml +++ b/testsuite/tests/lib-threads/sieve.ml @@ -1,45 +1,43 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) -open Printf -open Thread +let sieve primes = + Event.sync (Event.send primes 2); + let integers = Event.new_channel () in + let rec enumerate n = + Event.sync (Event.send integers n); + enumerate (n + 2) + and filter input = + let n = Event.sync (Event.receive input) + and output = Event.new_channel () in + Event.sync (Event.send primes n); + ignore(Thread.create filter output); + (* We remove from the output the multiples of n *) + while true do + let m = Event.sync (Event.receive input) in + (* print_int n; print_string ": "; print_int m; print_newline(); *) + if m mod n <> 0 then Event.sync (Event.send output m) + done in + ignore(Thread.create filter integers); + ignore(Thread.create enumerate 3) -let rec integers n ch = - Event.sync (Event.send ch n); - integers (n+1) ch +let primes = Event.new_channel () -let rec sieve n chin chout = - let m = Event.sync (Event.receive chin) - in if m mod n = 0 - then sieve n chin chout - else Event.sync (Event.send chout m); - sieve n chin chout - -let rec print_primes ch max = - let n = Event.sync (Event.receive ch) - in if n > max - then () - else begin - printf "%d\n" n; flush stdout; - let ch_after_n = Event.new_channel () - in Thread.create (sieve n ch) ch_after_n; - print_primes ch_after_n max - end - -let go max = - let ch = Event.new_channel () - in Thread.create (integers 2) ch; - print_primes ch max;; - -let _ = go 500 - -;; +let _ = + ignore(Thread.create sieve primes); + for i = 1 to 50 do + let n = Event.sync (Event.receive primes) in + print_int n; print_newline() + done diff --git a/testsuite/tests/lib-threads/sieve.reference b/testsuite/tests/lib-threads/sieve.reference index 3e7998db..ad2c8fd7 100644 --- a/testsuite/tests/lib-threads/sieve.reference +++ b/testsuite/tests/lib-threads/sieve.reference @@ -48,48 +48,3 @@ 223 227 229 -233 -239 -241 -251 -257 -263 -269 -271 -277 -281 -283 -293 -307 -311 -313 -317 -331 -337 -347 -349 -353 -359 -367 -373 -379 -383 -389 -397 -401 -409 -419 -421 -431 -433 -439 -443 -449 -457 -461 -463 -467 -479 -487 -491 -499 diff --git a/testsuite/tests/lib-threads/sigint.c b/testsuite/tests/lib-threads/sigint.c new file mode 100644 index 00000000..4a5cac63 --- /dev/null +++ b/testsuite/tests/lib-threads/sigint.c @@ -0,0 +1,37 @@ +#include +#include + +int main(int argc, char** argv) +{ + DWORD pid; + HANDLE hProcess; + + if (argc != 2) { + printf("Usage: %s pid\n", argv[0]); + return 1; + } + + pid = atoi(argv[1]); + hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid); + + if (!hProcess) { + printf("Process %ul not found!\n", pid); + return 1; + } + + FreeConsole(); + + if (!AttachConsole(pid)) { + printf("Failed to attach to console of Process %ul\n", pid); + CloseHandle(hProcess); + return 1; + } + + SetConsoleCtrlHandler(NULL, TRUE); + GenerateConsoleCtrlEvent(0, 0); + WaitForSingleObject(hProcess, INFINITE); + CloseHandle(hProcess); + FreeConsole(); + + return 0; +} diff --git a/testsuite/tests/lib-threads/signal.checker b/testsuite/tests/lib-threads/signal.checker new file mode 100644 index 00000000..181d3c5a --- /dev/null +++ b/testsuite/tests/lib-threads/signal.checker @@ -0,0 +1,16 @@ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +sed -e 1q signal.result | grep -q '^[ab]*Got ctrl-C, exiting...$' diff --git a/testsuite/tests/lib-threads/signal.ml b/testsuite/tests/lib-threads/signal.ml new file mode 100644 index 00000000..e067ea06 --- /dev/null +++ b/testsuite/tests/lib-threads/signal.ml @@ -0,0 +1,28 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +let sighandler _ = + print_string "Got ctrl-C, exiting..."; print_newline(); + exit 0 + +let print_message delay c = + while true do + print_char c; flush stdout; Thread.delay delay + done + +let _ = + ignore (Sys.signal Sys.sigint (Sys.Signal_handle sighandler)); + ignore (Thread.create (print_message 0.6666666666) 'a'); + print_message 1.0 'b' diff --git a/testsuite/tests/lib-threads/signal.precheck b/testsuite/tests/lib-threads/signal.precheck new file mode 100644 index 00000000..d04af9a4 --- /dev/null +++ b/testsuite/tests/lib-threads/signal.precheck @@ -0,0 +1 @@ +test "$TOOLCHAIN" != "msvc" -a "$TOOLCHAIN" != "mingw" diff --git a/testsuite/tests/lib-threads/signal.runner b/testsuite/tests/lib-threads/signal.runner new file mode 100644 index 00000000..b90139a9 --- /dev/null +++ b/testsuite/tests/lib-threads/signal.runner @@ -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. * +#* * +#************************************************************************** + +$RUNTIME ./program >signal.result & +pid=$! +sleep 2 +test -e ./sigint.exe && ./sigint $pid || kill -INT $pid diff --git a/testsuite/tests/lib-threads/signal2.checker b/testsuite/tests/lib-threads/signal2.checker new file mode 100644 index 00000000..56fe7db3 --- /dev/null +++ b/testsuite/tests/lib-threads/signal2.checker @@ -0,0 +1,16 @@ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +sed -e 1q signal2.result | grep -q '^[ab]*' diff --git a/testsuite/tests/lib-threads/signal2.ml b/testsuite/tests/lib-threads/signal2.ml new file mode 100644 index 00000000..79e984e2 --- /dev/null +++ b/testsuite/tests/lib-threads/signal2.ml @@ -0,0 +1,26 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +let print_message delay c = + while true do + print_char c; flush stdout; Thread.delay delay + done + +let _ = + ignore (Thread.sigmask Unix.SIG_BLOCK [Sys.sigint; Sys.sigterm]); + ignore (Thread.create (print_message 0.6666666666) 'a'); + ignore (Thread.create (print_message 1.0) 'b'); + let s = Thread.wait_signal [Sys.sigint; Sys.sigterm] in + Printf.printf "Got signal %d, exiting...\n" s diff --git a/testsuite/tests/lib-threads/signal2.precheck b/testsuite/tests/lib-threads/signal2.precheck new file mode 100644 index 00000000..72b0054c --- /dev/null +++ b/testsuite/tests/lib-threads/signal2.precheck @@ -0,0 +1,16 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** + +test "$TOOLCHAIN" != "msvc" -a "$TOOLCHAIN" != "mingw" diff --git a/testsuite/tests/lib-threads/signal2.runner b/testsuite/tests/lib-threads/signal2.runner new file mode 100644 index 00000000..8369d636 --- /dev/null +++ b/testsuite/tests/lib-threads/signal2.runner @@ -0,0 +1,21 @@ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +$RUNTIME ./program >signal2.result & +pid=$! +sleep 2 +kill -INT $pid +sleep 1 +kill -9 $pid 2>&- || true diff --git a/testsuite/tests/lib-threads/sockets.ml b/testsuite/tests/lib-threads/sockets.ml new file mode 100644 index 00000000..b4adec36 --- /dev/null +++ b/testsuite/tests/lib-threads/sockets.ml @@ -0,0 +1,52 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +open Printf + +(* Threads and sockets *) + +let serve_connection s = + let buf = String.make 1024 '>' in + let n = Unix.read s buf 2 (String.length buf - 2) in + Thread.delay 1.0; + ignore (Unix.write s buf 0 (n + 2)); + Unix.close s + +let server sock = + while true do + let (s, _) = Unix.accept sock in + ignore(Thread.create serve_connection s) + done + +let client (addr, msg) = + let sock = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.connect sock addr; + let buf = String.make 1024 ' ' in + ignore(Unix.write sock msg 0 (String.length msg)); + let n = Unix.read sock buf 0 (String.length buf) in + print_string (String.sub buf 0 n); flush stdout + +let _ = + let addr = Unix.ADDR_INET(Unix.inet_addr_loopback, 9876) in + let sock = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.setsockopt sock Unix.SO_REUSEADDR true; + Unix.bind sock addr; + Unix.listen sock 5; + ignore (Thread.create server sock); + ignore (Thread.create client (addr, "Client #1\n")); + Thread.delay 0.5; + client (addr, "Client #2\n") diff --git a/testsuite/tests/lib-threads/sockets.reference b/testsuite/tests/lib-threads/sockets.reference new file mode 100644 index 00000000..a3f7067d --- /dev/null +++ b/testsuite/tests/lib-threads/sockets.reference @@ -0,0 +1,2 @@ +>>Client #1 +>>Client #2 diff --git a/testsuite/tests/lib-threads/socketsbuf.ml b/testsuite/tests/lib-threads/socketsbuf.ml new file mode 100644 index 00000000..d23d33e3 --- /dev/null +++ b/testsuite/tests/lib-threads/socketsbuf.ml @@ -0,0 +1,54 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +open Printf + +(* Threads, sockets, and buffered I/O channels *) +(* Serves as a regression test for PR#5578 *) + +let serve_connection s = + let ic = Unix.in_channel_of_descr s + and oc = Unix.out_channel_of_descr s in + let l = input_line ic in + fprintf oc ">>%s\n" l; + close_out oc + +let server sock = + while true do + let (s, _) = Unix.accept sock in + ignore(Thread.create serve_connection s) + done + +let client (addr, msg) = + let sock = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.connect sock addr; + let ic = Unix.in_channel_of_descr sock + and oc = Unix.out_channel_of_descr sock in + output_string oc msg; flush oc; + let l = input_line ic in + printf "%s\n%!" l + +let _ = + let addr = Unix.ADDR_INET(Unix.inet_addr_loopback, 9876) in + let sock = + Unix.socket (Unix.domain_of_sockaddr addr) Unix.SOCK_STREAM 0 in + Unix.setsockopt sock Unix.SO_REUSEADDR true; + Unix.bind sock addr; + Unix.listen sock 5; + ignore (Thread.create server sock); + ignore (Thread.create client (addr, "Client #1\n")); + Thread.delay 0.5; + client (addr, "Client #2\n") diff --git a/testsuite/tests/lib-threads/socketsbuf.reference b/testsuite/tests/lib-threads/socketsbuf.reference new file mode 100644 index 00000000..a3f7067d --- /dev/null +++ b/testsuite/tests/lib-threads/socketsbuf.reference @@ -0,0 +1,2 @@ +>>Client #1 +>>Client #2 diff --git a/testsuite/tests/lib-threads/swapchan.checker b/testsuite/tests/lib-threads/swapchan.checker new file mode 100644 index 00000000..bf957add --- /dev/null +++ b/testsuite/tests/lib-threads/swapchan.checker @@ -0,0 +1,16 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, Projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2015 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. * +#* * +#************************************************************************** + +$SORT swapchan.result | $DIFF swapchan.reference - >/dev/null diff --git a/testsuite/tests/lib-threads/swapchan.ml b/testsuite/tests/lib-threads/swapchan.ml new file mode 100644 index 00000000..8074b610 --- /dev/null +++ b/testsuite/tests/lib-threads/swapchan.ml @@ -0,0 +1,41 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +open Event + +type 'a swap_chan = ('a * 'a channel) channel + +let swap msg_out ch = + guard (fun () -> + let ic = new_channel() in + choose [ + wrap (receive ch) (fun (msg_in, oc) -> sync (send oc msg_out); msg_in); + wrap (send ch (msg_out, ic)) (fun () -> sync (receive ic)) + ]) + +let ch = new_channel() + +let f () = + let res = sync (swap "F" ch) in + print_string "f "; print_string res; print_newline() + +let g () = + let res = sync (swap "G" ch) in + print_string "g "; print_string res; print_newline() + +let _ = + let id = Thread.create f () in + g (); + Thread.join id diff --git a/testsuite/tests/lib-threads/test9.reference b/testsuite/tests/lib-threads/swapchan.reference similarity index 100% rename from testsuite/tests/lib-threads/test9.reference rename to testsuite/tests/lib-threads/swapchan.reference diff --git a/testsuite/tests/lib-threads/test-file-short-lines b/testsuite/tests/lib-threads/test-file-short-lines deleted file mode 100644 index 35abe7ca..00000000 --- a/testsuite/tests/lib-threads/test-file-short-lines +++ /dev/null @@ -1,10 +0,0 @@ -## -# Host Database -# -# localhost is used to configure the loopback interface -# when the system is booting. Do not change this entry. -## -127.0.0.1 localhost -255.255.255.255 broadcasthost -::1 localhost -fe80::1%lo0 localhost diff --git a/testsuite/tests/lib-threads/test1.checker b/testsuite/tests/lib-threads/test1.checker deleted file mode 100644 index 94778f23..00000000 --- a/testsuite/tests/lib-threads/test1.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -LC_ALL=C $SORT test1.result | $DIFF test1.reference - diff --git a/testsuite/tests/lib-threads/test1.ml b/testsuite/tests/lib-threads/test1.ml deleted file mode 100644 index c551fbc5..00000000 --- a/testsuite/tests/lib-threads/test1.ml +++ /dev/null @@ -1,75 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -(* Classic producer-consumer *) - -type 'a prodcons = - { buffer: 'a array; - lock: Mutex.t; - mutable readpos: int; - mutable writepos: int; - notempty: Condition.t; - notfull: Condition.t } - -let create size init = - { buffer = Array.make size init; - lock = Mutex.create(); - readpos = 0; - writepos = 0; - notempty = Condition.create(); - notfull = Condition.create() } - -let output_lock = Mutex.create() - -let put p data = - Mutex.lock p.lock; - while (p.writepos + 1) mod Array.length p.buffer = p.readpos do - Condition.wait p.notfull p.lock - done; - p.buffer.(p.writepos) <- data; - p.writepos <- (p.writepos + 1) mod Array.length p.buffer; - Condition.signal p.notempty; - Mutex.unlock p.lock - -let get p = - Mutex.lock p.lock; - while p.writepos = p.readpos do - Condition.wait p.notempty p.lock - done; - let data = p.buffer.(p.readpos) in - p.readpos <- (p.readpos + 1) mod Array.length p.buffer; - Condition.signal p.notfull; - Mutex.unlock p.lock; - data - -(* Test *) - -let buff = create 20 0 - -let rec produce n = - Mutex.lock output_lock; - print_int n; print_string "-->"; print_newline(); - Mutex.unlock output_lock; - put buff n; - if n < 10000 then produce (n+1) - -let rec consume () = - let n = get buff in - Mutex.lock output_lock; - print_string "-->"; print_int n; print_newline(); - Mutex.unlock output_lock; - if n < 10000 then consume () - -let t1 = Thread.create produce 0 -let _ = consume () - -;; diff --git a/testsuite/tests/lib-threads/test1.reference b/testsuite/tests/lib-threads/test1.reference deleted file mode 100644 index febf6610..00000000 --- a/testsuite/tests/lib-threads/test1.reference +++ /dev/null @@ -1,20002 +0,0 @@ --->0 --->1 --->10 --->100 --->1000 --->10000 --->1001 --->1002 --->1003 --->1004 --->1005 --->1006 --->1007 --->1008 --->1009 --->101 --->1010 --->1011 --->1012 --->1013 --->1014 --->1015 --->1016 --->1017 --->1018 --->1019 --->102 --->1020 --->1021 --->1022 --->1023 --->1024 --->1025 --->1026 --->1027 --->1028 --->1029 --->103 --->1030 --->1031 --->1032 --->1033 --->1034 --->1035 --->1036 --->1037 --->1038 --->1039 --->104 --->1040 --->1041 --->1042 --->1043 --->1044 --->1045 --->1046 --->1047 --->1048 --->1049 --->105 --->1050 --->1051 --->1052 --->1053 --->1054 --->1055 --->1056 --->1057 --->1058 --->1059 --->106 --->1060 --->1061 --->1062 --->1063 --->1064 --->1065 --->1066 --->1067 --->1068 --->1069 --->107 --->1070 --->1071 --->1072 --->1073 --->1074 --->1075 --->1076 --->1077 --->1078 --->1079 --->108 --->1080 --->1081 --->1082 --->1083 --->1084 --->1085 --->1086 --->1087 --->1088 --->1089 --->109 --->1090 --->1091 --->1092 --->1093 --->1094 --->1095 --->1096 --->1097 --->1098 --->1099 --->11 --->110 --->1100 --->1101 --->1102 --->1103 --->1104 --->1105 --->1106 --->1107 --->1108 --->1109 --->111 --->1110 --->1111 --->1112 --->1113 --->1114 --->1115 --->1116 --->1117 --->1118 --->1119 --->112 --->1120 --->1121 --->1122 --->1123 --->1124 --->1125 --->1126 --->1127 --->1128 --->1129 --->113 --->1130 --->1131 --->1132 --->1133 --->1134 --->1135 --->1136 --->1137 --->1138 --->1139 --->114 --->1140 --->1141 --->1142 --->1143 --->1144 --->1145 --->1146 --->1147 --->1148 --->1149 --->115 --->1150 --->1151 --->1152 --->1153 --->1154 --->1155 --->1156 --->1157 --->1158 --->1159 --->116 --->1160 --->1161 --->1162 --->1163 --->1164 --->1165 --->1166 --->1167 --->1168 --->1169 --->117 --->1170 --->1171 --->1172 --->1173 --->1174 --->1175 --->1176 --->1177 --->1178 --->1179 --->118 --->1180 --->1181 --->1182 --->1183 --->1184 --->1185 --->1186 --->1187 --->1188 --->1189 --->119 --->1190 --->1191 --->1192 --->1193 --->1194 --->1195 --->1196 --->1197 --->1198 --->1199 --->12 --->120 --->1200 --->1201 --->1202 --->1203 --->1204 --->1205 --->1206 --->1207 --->1208 --->1209 --->121 --->1210 --->1211 --->1212 --->1213 --->1214 --->1215 --->1216 --->1217 --->1218 --->1219 --->122 --->1220 --->1221 --->1222 --->1223 --->1224 --->1225 --->1226 --->1227 --->1228 --->1229 --->123 --->1230 --->1231 --->1232 --->1233 --->1234 --->1235 --->1236 --->1237 --->1238 --->1239 --->124 --->1240 --->1241 --->1242 --->1243 --->1244 --->1245 --->1246 --->1247 --->1248 --->1249 --->125 --->1250 --->1251 --->1252 --->1253 --->1254 --->1255 --->1256 --->1257 --->1258 --->1259 --->126 --->1260 --->1261 --->1262 --->1263 --->1264 --->1265 --->1266 --->1267 --->1268 --->1269 --->127 --->1270 --->1271 --->1272 --->1273 --->1274 --->1275 --->1276 --->1277 --->1278 --->1279 --->128 --->1280 --->1281 --->1282 --->1283 --->1284 --->1285 --->1286 --->1287 --->1288 --->1289 --->129 --->1290 --->1291 --->1292 --->1293 --->1294 --->1295 --->1296 --->1297 --->1298 --->1299 --->13 --->130 --->1300 --->1301 --->1302 --->1303 --->1304 --->1305 --->1306 --->1307 --->1308 --->1309 --->131 --->1310 --->1311 --->1312 --->1313 --->1314 --->1315 --->1316 --->1317 --->1318 --->1319 --->132 --->1320 --->1321 --->1322 --->1323 --->1324 --->1325 --->1326 --->1327 --->1328 --->1329 --->133 --->1330 --->1331 --->1332 --->1333 --->1334 --->1335 --->1336 --->1337 --->1338 --->1339 --->134 --->1340 --->1341 --->1342 --->1343 --->1344 --->1345 --->1346 --->1347 --->1348 --->1349 --->135 --->1350 --->1351 --->1352 --->1353 --->1354 --->1355 --->1356 --->1357 --->1358 --->1359 --->136 --->1360 --->1361 --->1362 --->1363 --->1364 --->1365 --->1366 --->1367 --->1368 --->1369 --->137 --->1370 --->1371 --->1372 --->1373 --->1374 --->1375 --->1376 --->1377 --->1378 --->1379 --->138 --->1380 --->1381 --->1382 --->1383 --->1384 --->1385 --->1386 --->1387 --->1388 --->1389 --->139 --->1390 --->1391 --->1392 --->1393 --->1394 --->1395 --->1396 --->1397 --->1398 --->1399 --->14 --->140 --->1400 --->1401 --->1402 --->1403 --->1404 --->1405 --->1406 --->1407 --->1408 --->1409 --->141 --->1410 --->1411 --->1412 --->1413 --->1414 --->1415 --->1416 --->1417 --->1418 --->1419 --->142 --->1420 --->1421 --->1422 --->1423 --->1424 --->1425 --->1426 --->1427 --->1428 --->1429 --->143 --->1430 --->1431 --->1432 --->1433 --->1434 --->1435 --->1436 --->1437 --->1438 --->1439 --->144 --->1440 --->1441 --->1442 --->1443 --->1444 --->1445 --->1446 --->1447 --->1448 --->1449 --->145 --->1450 --->1451 --->1452 --->1453 --->1454 --->1455 --->1456 --->1457 --->1458 --->1459 --->146 --->1460 --->1461 --->1462 --->1463 --->1464 --->1465 --->1466 --->1467 --->1468 --->1469 --->147 --->1470 --->1471 --->1472 --->1473 --->1474 --->1475 --->1476 --->1477 --->1478 --->1479 --->148 --->1480 --->1481 --->1482 --->1483 --->1484 --->1485 --->1486 --->1487 --->1488 --->1489 --->149 --->1490 --->1491 --->1492 --->1493 --->1494 --->1495 --->1496 --->1497 --->1498 --->1499 --->15 --->150 --->1500 --->1501 --->1502 --->1503 --->1504 --->1505 --->1506 --->1507 --->1508 --->1509 --->151 --->1510 --->1511 --->1512 --->1513 --->1514 --->1515 --->1516 --->1517 --->1518 --->1519 --->152 --->1520 --->1521 --->1522 --->1523 --->1524 --->1525 --->1526 --->1527 --->1528 --->1529 --->153 --->1530 --->1531 --->1532 --->1533 --->1534 --->1535 --->1536 --->1537 --->1538 --->1539 --->154 --->1540 --->1541 --->1542 --->1543 --->1544 --->1545 --->1546 --->1547 --->1548 --->1549 --->155 --->1550 --->1551 --->1552 --->1553 --->1554 --->1555 --->1556 --->1557 --->1558 --->1559 --->156 --->1560 --->1561 --->1562 --->1563 --->1564 --->1565 --->1566 --->1567 --->1568 --->1569 --->157 --->1570 --->1571 --->1572 --->1573 --->1574 --->1575 --->1576 --->1577 --->1578 --->1579 --->158 --->1580 --->1581 --->1582 --->1583 --->1584 --->1585 --->1586 --->1587 --->1588 --->1589 --->159 --->1590 --->1591 --->1592 --->1593 --->1594 --->1595 --->1596 --->1597 --->1598 --->1599 --->16 --->160 --->1600 --->1601 --->1602 --->1603 --->1604 --->1605 --->1606 --->1607 --->1608 --->1609 --->161 --->1610 --->1611 --->1612 --->1613 --->1614 --->1615 --->1616 --->1617 --->1618 --->1619 --->162 --->1620 --->1621 --->1622 --->1623 --->1624 --->1625 --->1626 --->1627 --->1628 --->1629 --->163 --->1630 --->1631 --->1632 --->1633 --->1634 --->1635 --->1636 --->1637 --->1638 --->1639 --->164 --->1640 --->1641 --->1642 --->1643 --->1644 --->1645 --->1646 --->1647 --->1648 --->1649 --->165 --->1650 --->1651 --->1652 --->1653 --->1654 --->1655 --->1656 --->1657 --->1658 --->1659 --->166 --->1660 --->1661 --->1662 --->1663 --->1664 --->1665 --->1666 --->1667 --->1668 --->1669 --->167 --->1670 --->1671 --->1672 --->1673 --->1674 --->1675 --->1676 --->1677 --->1678 --->1679 --->168 --->1680 --->1681 --->1682 --->1683 --->1684 --->1685 --->1686 --->1687 --->1688 --->1689 --->169 --->1690 --->1691 --->1692 --->1693 --->1694 --->1695 --->1696 --->1697 --->1698 --->1699 --->17 --->170 --->1700 --->1701 --->1702 --->1703 --->1704 --->1705 --->1706 --->1707 --->1708 --->1709 --->171 --->1710 --->1711 --->1712 --->1713 --->1714 --->1715 --->1716 --->1717 --->1718 --->1719 --->172 --->1720 --->1721 --->1722 --->1723 --->1724 --->1725 --->1726 --->1727 --->1728 --->1729 --->173 --->1730 --->1731 --->1732 --->1733 --->1734 --->1735 --->1736 --->1737 --->1738 --->1739 --->174 --->1740 --->1741 --->1742 --->1743 --->1744 --->1745 --->1746 --->1747 --->1748 --->1749 --->175 --->1750 --->1751 --->1752 --->1753 --->1754 --->1755 --->1756 --->1757 --->1758 --->1759 --->176 --->1760 --->1761 --->1762 --->1763 --->1764 --->1765 --->1766 --->1767 --->1768 --->1769 --->177 --->1770 --->1771 --->1772 --->1773 --->1774 --->1775 --->1776 --->1777 --->1778 --->1779 --->178 --->1780 --->1781 --->1782 --->1783 --->1784 --->1785 --->1786 --->1787 --->1788 --->1789 --->179 --->1790 --->1791 --->1792 --->1793 --->1794 --->1795 --->1796 --->1797 --->1798 --->1799 --->18 --->180 --->1800 --->1801 --->1802 --->1803 --->1804 --->1805 --->1806 --->1807 --->1808 --->1809 --->181 --->1810 --->1811 --->1812 --->1813 --->1814 --->1815 --->1816 --->1817 --->1818 --->1819 --->182 --->1820 --->1821 --->1822 --->1823 --->1824 --->1825 --->1826 --->1827 --->1828 --->1829 --->183 --->1830 --->1831 --->1832 --->1833 --->1834 --->1835 --->1836 --->1837 --->1838 --->1839 --->184 --->1840 --->1841 --->1842 --->1843 --->1844 --->1845 --->1846 --->1847 --->1848 --->1849 --->185 --->1850 --->1851 --->1852 --->1853 --->1854 --->1855 --->1856 --->1857 --->1858 --->1859 --->186 --->1860 --->1861 --->1862 --->1863 --->1864 --->1865 --->1866 --->1867 --->1868 --->1869 --->187 --->1870 --->1871 --->1872 --->1873 --->1874 --->1875 --->1876 --->1877 --->1878 --->1879 --->188 --->1880 --->1881 --->1882 --->1883 --->1884 --->1885 --->1886 --->1887 --->1888 --->1889 --->189 --->1890 --->1891 --->1892 --->1893 --->1894 --->1895 --->1896 --->1897 --->1898 --->1899 --->19 --->190 --->1900 --->1901 --->1902 --->1903 --->1904 --->1905 --->1906 --->1907 --->1908 --->1909 --->191 --->1910 --->1911 --->1912 --->1913 --->1914 --->1915 --->1916 --->1917 --->1918 --->1919 --->192 --->1920 --->1921 --->1922 --->1923 --->1924 --->1925 --->1926 --->1927 --->1928 --->1929 --->193 --->1930 --->1931 --->1932 --->1933 --->1934 --->1935 --->1936 --->1937 --->1938 --->1939 --->194 --->1940 --->1941 --->1942 --->1943 --->1944 --->1945 --->1946 --->1947 --->1948 --->1949 --->195 --->1950 --->1951 --->1952 --->1953 --->1954 --->1955 --->1956 --->1957 --->1958 --->1959 --->196 --->1960 --->1961 --->1962 --->1963 --->1964 --->1965 --->1966 --->1967 --->1968 --->1969 --->197 --->1970 --->1971 --->1972 --->1973 --->1974 --->1975 --->1976 --->1977 --->1978 --->1979 --->198 --->1980 --->1981 --->1982 --->1983 --->1984 --->1985 --->1986 --->1987 --->1988 --->1989 --->199 --->1990 --->1991 --->1992 --->1993 --->1994 --->1995 --->1996 --->1997 --->1998 --->1999 --->2 --->20 --->200 --->2000 --->2001 --->2002 --->2003 --->2004 --->2005 --->2006 --->2007 --->2008 --->2009 --->201 --->2010 --->2011 --->2012 --->2013 --->2014 --->2015 --->2016 --->2017 --->2018 --->2019 --->202 --->2020 --->2021 --->2022 --->2023 --->2024 --->2025 --->2026 --->2027 --->2028 --->2029 --->203 --->2030 --->2031 --->2032 --->2033 --->2034 --->2035 --->2036 --->2037 --->2038 --->2039 --->204 --->2040 --->2041 --->2042 --->2043 --->2044 --->2045 --->2046 --->2047 --->2048 --->2049 --->205 --->2050 --->2051 --->2052 --->2053 --->2054 --->2055 --->2056 --->2057 --->2058 --->2059 --->206 --->2060 --->2061 --->2062 --->2063 --->2064 --->2065 --->2066 --->2067 --->2068 --->2069 --->207 --->2070 --->2071 --->2072 --->2073 --->2074 --->2075 --->2076 --->2077 --->2078 --->2079 --->208 --->2080 --->2081 --->2082 --->2083 --->2084 --->2085 --->2086 --->2087 --->2088 --->2089 --->209 --->2090 --->2091 --->2092 --->2093 --->2094 --->2095 --->2096 --->2097 --->2098 --->2099 --->21 --->210 --->2100 --->2101 --->2102 --->2103 --->2104 --->2105 --->2106 --->2107 --->2108 --->2109 --->211 --->2110 --->2111 --->2112 --->2113 --->2114 --->2115 --->2116 --->2117 --->2118 --->2119 --->212 --->2120 --->2121 --->2122 --->2123 --->2124 --->2125 --->2126 --->2127 --->2128 --->2129 --->213 --->2130 --->2131 --->2132 --->2133 --->2134 --->2135 --->2136 --->2137 --->2138 --->2139 --->214 --->2140 --->2141 --->2142 --->2143 --->2144 --->2145 --->2146 --->2147 --->2148 --->2149 --->215 --->2150 --->2151 --->2152 --->2153 --->2154 --->2155 --->2156 --->2157 --->2158 --->2159 --->216 --->2160 --->2161 --->2162 --->2163 --->2164 --->2165 --->2166 --->2167 --->2168 --->2169 --->217 --->2170 --->2171 --->2172 --->2173 --->2174 --->2175 --->2176 --->2177 --->2178 --->2179 --->218 --->2180 --->2181 --->2182 --->2183 --->2184 --->2185 --->2186 --->2187 --->2188 --->2189 --->219 --->2190 --->2191 --->2192 --->2193 --->2194 --->2195 --->2196 --->2197 --->2198 --->2199 --->22 --->220 --->2200 --->2201 --->2202 --->2203 --->2204 --->2205 --->2206 --->2207 --->2208 --->2209 --->221 --->2210 --->2211 --->2212 --->2213 --->2214 --->2215 --->2216 --->2217 --->2218 --->2219 --->222 --->2220 --->2221 --->2222 --->2223 --->2224 --->2225 --->2226 --->2227 --->2228 --->2229 --->223 --->2230 --->2231 --->2232 --->2233 --->2234 --->2235 --->2236 --->2237 --->2238 --->2239 --->224 --->2240 --->2241 --->2242 --->2243 --->2244 --->2245 --->2246 --->2247 --->2248 --->2249 --->225 --->2250 --->2251 --->2252 --->2253 --->2254 --->2255 --->2256 --->2257 --->2258 --->2259 --->226 --->2260 --->2261 --->2262 --->2263 --->2264 --->2265 --->2266 --->2267 --->2268 --->2269 --->227 --->2270 --->2271 --->2272 --->2273 --->2274 --->2275 --->2276 --->2277 --->2278 --->2279 --->228 --->2280 --->2281 --->2282 --->2283 --->2284 --->2285 --->2286 --->2287 --->2288 --->2289 --->229 --->2290 --->2291 --->2292 --->2293 --->2294 --->2295 --->2296 --->2297 --->2298 --->2299 --->23 --->230 --->2300 --->2301 --->2302 --->2303 --->2304 --->2305 --->2306 --->2307 --->2308 --->2309 --->231 --->2310 --->2311 --->2312 --->2313 --->2314 --->2315 --->2316 --->2317 --->2318 --->2319 --->232 --->2320 --->2321 --->2322 --->2323 --->2324 --->2325 --->2326 --->2327 --->2328 --->2329 --->233 --->2330 --->2331 --->2332 --->2333 --->2334 --->2335 --->2336 --->2337 --->2338 --->2339 --->234 --->2340 --->2341 --->2342 --->2343 --->2344 --->2345 --->2346 --->2347 --->2348 --->2349 --->235 --->2350 --->2351 --->2352 --->2353 --->2354 --->2355 --->2356 --->2357 --->2358 --->2359 --->236 --->2360 --->2361 --->2362 --->2363 --->2364 --->2365 --->2366 --->2367 --->2368 --->2369 --->237 --->2370 --->2371 --->2372 --->2373 --->2374 --->2375 --->2376 --->2377 --->2378 --->2379 --->238 --->2380 --->2381 --->2382 --->2383 --->2384 --->2385 --->2386 --->2387 --->2388 --->2389 --->239 --->2390 --->2391 --->2392 --->2393 --->2394 --->2395 --->2396 --->2397 --->2398 --->2399 --->24 --->240 --->2400 --->2401 --->2402 --->2403 --->2404 --->2405 --->2406 --->2407 --->2408 --->2409 --->241 --->2410 --->2411 --->2412 --->2413 --->2414 --->2415 --->2416 --->2417 --->2418 --->2419 --->242 --->2420 --->2421 --->2422 --->2423 --->2424 --->2425 --->2426 --->2427 --->2428 --->2429 --->243 --->2430 --->2431 --->2432 --->2433 --->2434 --->2435 --->2436 --->2437 --->2438 --->2439 --->244 --->2440 --->2441 --->2442 --->2443 --->2444 --->2445 --->2446 --->2447 --->2448 --->2449 --->245 --->2450 --->2451 --->2452 --->2453 --->2454 --->2455 --->2456 --->2457 --->2458 --->2459 --->246 --->2460 --->2461 --->2462 --->2463 --->2464 --->2465 --->2466 --->2467 --->2468 --->2469 --->247 --->2470 --->2471 --->2472 --->2473 --->2474 --->2475 --->2476 --->2477 --->2478 --->2479 --->248 --->2480 --->2481 --->2482 --->2483 --->2484 --->2485 --->2486 --->2487 --->2488 --->2489 --->249 --->2490 --->2491 --->2492 --->2493 --->2494 --->2495 --->2496 --->2497 --->2498 --->2499 --->25 --->250 --->2500 --->2501 --->2502 --->2503 --->2504 --->2505 --->2506 --->2507 --->2508 --->2509 --->251 --->2510 --->2511 --->2512 --->2513 --->2514 --->2515 --->2516 --->2517 --->2518 --->2519 --->252 --->2520 --->2521 --->2522 --->2523 --->2524 --->2525 --->2526 --->2527 --->2528 --->2529 --->253 --->2530 --->2531 --->2532 --->2533 --->2534 --->2535 --->2536 --->2537 --->2538 --->2539 --->254 --->2540 --->2541 --->2542 --->2543 --->2544 --->2545 --->2546 --->2547 --->2548 --->2549 --->255 --->2550 --->2551 --->2552 --->2553 --->2554 --->2555 --->2556 --->2557 --->2558 --->2559 --->256 --->2560 --->2561 --->2562 --->2563 --->2564 --->2565 --->2566 --->2567 --->2568 --->2569 --->257 --->2570 --->2571 --->2572 --->2573 --->2574 --->2575 --->2576 --->2577 --->2578 --->2579 --->258 --->2580 --->2581 --->2582 --->2583 --->2584 --->2585 --->2586 --->2587 --->2588 --->2589 --->259 --->2590 --->2591 --->2592 --->2593 --->2594 --->2595 --->2596 --->2597 --->2598 --->2599 --->26 --->260 --->2600 --->2601 --->2602 --->2603 --->2604 --->2605 --->2606 --->2607 --->2608 --->2609 --->261 --->2610 --->2611 --->2612 --->2613 --->2614 --->2615 --->2616 --->2617 --->2618 --->2619 --->262 --->2620 --->2621 --->2622 --->2623 --->2624 --->2625 --->2626 --->2627 --->2628 --->2629 --->263 --->2630 --->2631 --->2632 --->2633 --->2634 --->2635 --->2636 --->2637 --->2638 --->2639 --->264 --->2640 --->2641 --->2642 --->2643 --->2644 --->2645 --->2646 --->2647 --->2648 --->2649 --->265 --->2650 --->2651 --->2652 --->2653 --->2654 --->2655 --->2656 --->2657 --->2658 --->2659 --->266 --->2660 --->2661 --->2662 --->2663 --->2664 --->2665 --->2666 --->2667 --->2668 --->2669 --->267 --->2670 --->2671 --->2672 --->2673 --->2674 --->2675 --->2676 --->2677 --->2678 --->2679 --->268 --->2680 --->2681 --->2682 --->2683 --->2684 --->2685 --->2686 --->2687 --->2688 --->2689 --->269 --->2690 --->2691 --->2692 --->2693 --->2694 --->2695 --->2696 --->2697 --->2698 --->2699 --->27 --->270 --->2700 --->2701 --->2702 --->2703 --->2704 --->2705 --->2706 --->2707 --->2708 --->2709 --->271 --->2710 --->2711 --->2712 --->2713 --->2714 --->2715 --->2716 --->2717 --->2718 --->2719 --->272 --->2720 --->2721 --->2722 --->2723 --->2724 --->2725 --->2726 --->2727 --->2728 --->2729 --->273 --->2730 --->2731 --->2732 --->2733 --->2734 --->2735 --->2736 --->2737 --->2738 --->2739 --->274 --->2740 --->2741 --->2742 --->2743 --->2744 --->2745 --->2746 --->2747 --->2748 --->2749 --->275 --->2750 --->2751 --->2752 --->2753 --->2754 --->2755 --->2756 --->2757 --->2758 --->2759 --->276 --->2760 --->2761 --->2762 --->2763 --->2764 --->2765 --->2766 --->2767 --->2768 --->2769 --->277 --->2770 --->2771 --->2772 --->2773 --->2774 --->2775 --->2776 --->2777 --->2778 --->2779 --->278 --->2780 --->2781 --->2782 --->2783 --->2784 --->2785 --->2786 --->2787 --->2788 --->2789 --->279 --->2790 --->2791 --->2792 --->2793 --->2794 --->2795 --->2796 --->2797 --->2798 --->2799 --->28 --->280 --->2800 --->2801 --->2802 --->2803 --->2804 --->2805 --->2806 --->2807 --->2808 --->2809 --->281 --->2810 --->2811 --->2812 --->2813 --->2814 --->2815 --->2816 --->2817 --->2818 --->2819 --->282 --->2820 --->2821 --->2822 --->2823 --->2824 --->2825 --->2826 --->2827 --->2828 --->2829 --->283 --->2830 --->2831 --->2832 --->2833 --->2834 --->2835 --->2836 --->2837 --->2838 --->2839 --->284 --->2840 --->2841 --->2842 --->2843 --->2844 --->2845 --->2846 --->2847 --->2848 --->2849 --->285 --->2850 --->2851 --->2852 --->2853 --->2854 --->2855 --->2856 --->2857 --->2858 --->2859 --->286 --->2860 --->2861 --->2862 --->2863 --->2864 --->2865 --->2866 --->2867 --->2868 --->2869 --->287 --->2870 --->2871 --->2872 --->2873 --->2874 --->2875 --->2876 --->2877 --->2878 --->2879 --->288 --->2880 --->2881 --->2882 --->2883 --->2884 --->2885 --->2886 --->2887 --->2888 --->2889 --->289 --->2890 --->2891 --->2892 --->2893 --->2894 --->2895 --->2896 --->2897 --->2898 --->2899 --->29 --->290 --->2900 --->2901 --->2902 --->2903 --->2904 --->2905 --->2906 --->2907 --->2908 --->2909 --->291 --->2910 --->2911 --->2912 --->2913 --->2914 --->2915 --->2916 --->2917 --->2918 --->2919 --->292 --->2920 --->2921 --->2922 --->2923 --->2924 --->2925 --->2926 --->2927 --->2928 --->2929 --->293 --->2930 --->2931 --->2932 --->2933 --->2934 --->2935 --->2936 --->2937 --->2938 --->2939 --->294 --->2940 --->2941 --->2942 --->2943 --->2944 --->2945 --->2946 --->2947 --->2948 --->2949 --->295 --->2950 --->2951 --->2952 --->2953 --->2954 --->2955 --->2956 --->2957 --->2958 --->2959 --->296 --->2960 --->2961 --->2962 --->2963 --->2964 --->2965 --->2966 --->2967 --->2968 --->2969 --->297 --->2970 --->2971 --->2972 --->2973 --->2974 --->2975 --->2976 --->2977 --->2978 --->2979 --->298 --->2980 --->2981 --->2982 --->2983 --->2984 --->2985 --->2986 --->2987 --->2988 --->2989 --->299 --->2990 --->2991 --->2992 --->2993 --->2994 --->2995 --->2996 --->2997 --->2998 --->2999 --->3 --->30 --->300 --->3000 --->3001 --->3002 --->3003 --->3004 --->3005 --->3006 --->3007 --->3008 --->3009 --->301 --->3010 --->3011 --->3012 --->3013 --->3014 --->3015 --->3016 --->3017 --->3018 --->3019 --->302 --->3020 --->3021 --->3022 --->3023 --->3024 --->3025 --->3026 --->3027 --->3028 --->3029 --->303 --->3030 --->3031 --->3032 --->3033 --->3034 --->3035 --->3036 --->3037 --->3038 --->3039 --->304 --->3040 --->3041 --->3042 --->3043 --->3044 --->3045 --->3046 --->3047 --->3048 --->3049 --->305 --->3050 --->3051 --->3052 --->3053 --->3054 --->3055 --->3056 --->3057 --->3058 --->3059 --->306 --->3060 --->3061 --->3062 --->3063 --->3064 --->3065 --->3066 --->3067 --->3068 --->3069 --->307 --->3070 --->3071 --->3072 --->3073 --->3074 --->3075 --->3076 --->3077 --->3078 --->3079 --->308 --->3080 --->3081 --->3082 --->3083 --->3084 --->3085 --->3086 --->3087 --->3088 --->3089 --->309 --->3090 --->3091 --->3092 --->3093 --->3094 --->3095 --->3096 --->3097 --->3098 --->3099 --->31 --->310 --->3100 --->3101 --->3102 --->3103 --->3104 --->3105 --->3106 --->3107 --->3108 --->3109 --->311 --->3110 --->3111 --->3112 --->3113 --->3114 --->3115 --->3116 --->3117 --->3118 --->3119 --->312 --->3120 --->3121 --->3122 --->3123 --->3124 --->3125 --->3126 --->3127 --->3128 --->3129 --->313 --->3130 --->3131 --->3132 --->3133 --->3134 --->3135 --->3136 --->3137 --->3138 --->3139 --->314 --->3140 --->3141 --->3142 --->3143 --->3144 --->3145 --->3146 --->3147 --->3148 --->3149 --->315 --->3150 --->3151 --->3152 --->3153 --->3154 --->3155 --->3156 --->3157 --->3158 --->3159 --->316 --->3160 --->3161 --->3162 --->3163 --->3164 --->3165 --->3166 --->3167 --->3168 --->3169 --->317 --->3170 --->3171 --->3172 --->3173 --->3174 --->3175 --->3176 --->3177 --->3178 --->3179 --->318 --->3180 --->3181 --->3182 --->3183 --->3184 --->3185 --->3186 --->3187 --->3188 --->3189 --->319 --->3190 --->3191 --->3192 --->3193 --->3194 --->3195 --->3196 --->3197 --->3198 --->3199 --->32 --->320 --->3200 --->3201 --->3202 --->3203 --->3204 --->3205 --->3206 --->3207 --->3208 --->3209 --->321 --->3210 --->3211 --->3212 --->3213 --->3214 --->3215 --->3216 --->3217 --->3218 --->3219 --->322 --->3220 --->3221 --->3222 --->3223 --->3224 --->3225 --->3226 --->3227 --->3228 --->3229 --->323 --->3230 --->3231 --->3232 --->3233 --->3234 --->3235 --->3236 --->3237 --->3238 --->3239 --->324 --->3240 --->3241 --->3242 --->3243 --->3244 --->3245 --->3246 --->3247 --->3248 --->3249 --->325 --->3250 --->3251 --->3252 --->3253 --->3254 --->3255 --->3256 --->3257 --->3258 --->3259 --->326 --->3260 --->3261 --->3262 --->3263 --->3264 --->3265 --->3266 --->3267 --->3268 --->3269 --->327 --->3270 --->3271 --->3272 --->3273 --->3274 --->3275 --->3276 --->3277 --->3278 --->3279 --->328 --->3280 --->3281 --->3282 --->3283 --->3284 --->3285 --->3286 --->3287 --->3288 --->3289 --->329 --->3290 --->3291 --->3292 --->3293 --->3294 --->3295 --->3296 --->3297 --->3298 --->3299 --->33 --->330 --->3300 --->3301 --->3302 --->3303 --->3304 --->3305 --->3306 --->3307 --->3308 --->3309 --->331 --->3310 --->3311 --->3312 --->3313 --->3314 --->3315 --->3316 --->3317 --->3318 --->3319 --->332 --->3320 --->3321 --->3322 --->3323 --->3324 --->3325 --->3326 --->3327 --->3328 --->3329 --->333 --->3330 --->3331 --->3332 --->3333 --->3334 --->3335 --->3336 --->3337 --->3338 --->3339 --->334 --->3340 --->3341 --->3342 --->3343 --->3344 --->3345 --->3346 --->3347 --->3348 --->3349 --->335 --->3350 --->3351 --->3352 --->3353 --->3354 --->3355 --->3356 --->3357 --->3358 --->3359 --->336 --->3360 --->3361 --->3362 --->3363 --->3364 --->3365 --->3366 --->3367 --->3368 --->3369 --->337 --->3370 --->3371 --->3372 --->3373 --->3374 --->3375 --->3376 --->3377 --->3378 --->3379 --->338 --->3380 --->3381 --->3382 --->3383 --->3384 --->3385 --->3386 --->3387 --->3388 --->3389 --->339 --->3390 --->3391 --->3392 --->3393 --->3394 --->3395 --->3396 --->3397 --->3398 --->3399 --->34 --->340 --->3400 --->3401 --->3402 --->3403 --->3404 --->3405 --->3406 --->3407 --->3408 --->3409 --->341 --->3410 --->3411 --->3412 --->3413 --->3414 --->3415 --->3416 --->3417 --->3418 --->3419 --->342 --->3420 --->3421 --->3422 --->3423 --->3424 --->3425 --->3426 --->3427 --->3428 --->3429 --->343 --->3430 --->3431 --->3432 --->3433 --->3434 --->3435 --->3436 --->3437 --->3438 --->3439 --->344 --->3440 --->3441 --->3442 --->3443 --->3444 --->3445 --->3446 --->3447 --->3448 --->3449 --->345 --->3450 --->3451 --->3452 --->3453 --->3454 --->3455 --->3456 --->3457 --->3458 --->3459 --->346 --->3460 --->3461 --->3462 --->3463 --->3464 --->3465 --->3466 --->3467 --->3468 --->3469 --->347 --->3470 --->3471 --->3472 --->3473 --->3474 --->3475 --->3476 --->3477 --->3478 --->3479 --->348 --->3480 --->3481 --->3482 --->3483 --->3484 --->3485 --->3486 --->3487 --->3488 --->3489 --->349 --->3490 --->3491 --->3492 --->3493 --->3494 --->3495 --->3496 --->3497 --->3498 --->3499 --->35 --->350 --->3500 --->3501 --->3502 --->3503 --->3504 --->3505 --->3506 --->3507 --->3508 --->3509 --->351 --->3510 --->3511 --->3512 --->3513 --->3514 --->3515 --->3516 --->3517 --->3518 --->3519 --->352 --->3520 --->3521 --->3522 --->3523 --->3524 --->3525 --->3526 --->3527 --->3528 --->3529 --->353 --->3530 --->3531 --->3532 --->3533 --->3534 --->3535 --->3536 --->3537 --->3538 --->3539 --->354 --->3540 --->3541 --->3542 --->3543 --->3544 --->3545 --->3546 --->3547 --->3548 --->3549 --->355 --->3550 --->3551 --->3552 --->3553 --->3554 --->3555 --->3556 --->3557 --->3558 --->3559 --->356 --->3560 --->3561 --->3562 --->3563 --->3564 --->3565 --->3566 --->3567 --->3568 --->3569 --->357 --->3570 --->3571 --->3572 --->3573 --->3574 --->3575 --->3576 --->3577 --->3578 --->3579 --->358 --->3580 --->3581 --->3582 --->3583 --->3584 --->3585 --->3586 --->3587 --->3588 --->3589 --->359 --->3590 --->3591 --->3592 --->3593 --->3594 --->3595 --->3596 --->3597 --->3598 --->3599 --->36 --->360 --->3600 --->3601 --->3602 --->3603 --->3604 --->3605 --->3606 --->3607 --->3608 --->3609 --->361 --->3610 --->3611 --->3612 --->3613 --->3614 --->3615 --->3616 --->3617 --->3618 --->3619 --->362 --->3620 --->3621 --->3622 --->3623 --->3624 --->3625 --->3626 --->3627 --->3628 --->3629 --->363 --->3630 --->3631 --->3632 --->3633 --->3634 --->3635 --->3636 --->3637 --->3638 --->3639 --->364 --->3640 --->3641 --->3642 --->3643 --->3644 --->3645 --->3646 --->3647 --->3648 --->3649 --->365 --->3650 --->3651 --->3652 --->3653 --->3654 --->3655 --->3656 --->3657 --->3658 --->3659 --->366 --->3660 --->3661 --->3662 --->3663 --->3664 --->3665 --->3666 --->3667 --->3668 --->3669 --->367 --->3670 --->3671 --->3672 --->3673 --->3674 --->3675 --->3676 --->3677 --->3678 --->3679 --->368 --->3680 --->3681 --->3682 --->3683 --->3684 --->3685 --->3686 --->3687 --->3688 --->3689 --->369 --->3690 --->3691 --->3692 --->3693 --->3694 --->3695 --->3696 --->3697 --->3698 --->3699 --->37 --->370 --->3700 --->3701 --->3702 --->3703 --->3704 --->3705 --->3706 --->3707 --->3708 --->3709 --->371 --->3710 --->3711 --->3712 --->3713 --->3714 --->3715 --->3716 --->3717 --->3718 --->3719 --->372 --->3720 --->3721 --->3722 --->3723 --->3724 --->3725 --->3726 --->3727 --->3728 --->3729 --->373 --->3730 --->3731 --->3732 --->3733 --->3734 --->3735 --->3736 --->3737 --->3738 --->3739 --->374 --->3740 --->3741 --->3742 --->3743 --->3744 --->3745 --->3746 --->3747 --->3748 --->3749 --->375 --->3750 --->3751 --->3752 --->3753 --->3754 --->3755 --->3756 --->3757 --->3758 --->3759 --->376 --->3760 --->3761 --->3762 --->3763 --->3764 --->3765 --->3766 --->3767 --->3768 --->3769 --->377 --->3770 --->3771 --->3772 --->3773 --->3774 --->3775 --->3776 --->3777 --->3778 --->3779 --->378 --->3780 --->3781 --->3782 --->3783 --->3784 --->3785 --->3786 --->3787 --->3788 --->3789 --->379 --->3790 --->3791 --->3792 --->3793 --->3794 --->3795 --->3796 --->3797 --->3798 --->3799 --->38 --->380 --->3800 --->3801 --->3802 --->3803 --->3804 --->3805 --->3806 --->3807 --->3808 --->3809 --->381 --->3810 --->3811 --->3812 --->3813 --->3814 --->3815 --->3816 --->3817 --->3818 --->3819 --->382 --->3820 --->3821 --->3822 --->3823 --->3824 --->3825 --->3826 --->3827 --->3828 --->3829 --->383 --->3830 --->3831 --->3832 --->3833 --->3834 --->3835 --->3836 --->3837 --->3838 --->3839 --->384 --->3840 --->3841 --->3842 --->3843 --->3844 --->3845 --->3846 --->3847 --->3848 --->3849 --->385 --->3850 --->3851 --->3852 --->3853 --->3854 --->3855 --->3856 --->3857 --->3858 --->3859 --->386 --->3860 --->3861 --->3862 --->3863 --->3864 --->3865 --->3866 --->3867 --->3868 --->3869 --->387 --->3870 --->3871 --->3872 --->3873 --->3874 --->3875 --->3876 --->3877 --->3878 --->3879 --->388 --->3880 --->3881 --->3882 --->3883 --->3884 --->3885 --->3886 --->3887 --->3888 --->3889 --->389 --->3890 --->3891 --->3892 --->3893 --->3894 --->3895 --->3896 --->3897 --->3898 --->3899 --->39 --->390 --->3900 --->3901 --->3902 --->3903 --->3904 --->3905 --->3906 --->3907 --->3908 --->3909 --->391 --->3910 --->3911 --->3912 --->3913 --->3914 --->3915 --->3916 --->3917 --->3918 --->3919 --->392 --->3920 --->3921 --->3922 --->3923 --->3924 --->3925 --->3926 --->3927 --->3928 --->3929 --->393 --->3930 --->3931 --->3932 --->3933 --->3934 --->3935 --->3936 --->3937 --->3938 --->3939 --->394 --->3940 --->3941 --->3942 --->3943 --->3944 --->3945 --->3946 --->3947 --->3948 --->3949 --->395 --->3950 --->3951 --->3952 --->3953 --->3954 --->3955 --->3956 --->3957 --->3958 --->3959 --->396 --->3960 --->3961 --->3962 --->3963 --->3964 --->3965 --->3966 --->3967 --->3968 --->3969 --->397 --->3970 --->3971 --->3972 --->3973 --->3974 --->3975 --->3976 --->3977 --->3978 --->3979 --->398 --->3980 --->3981 --->3982 --->3983 --->3984 --->3985 --->3986 --->3987 --->3988 --->3989 --->399 --->3990 --->3991 --->3992 --->3993 --->3994 --->3995 --->3996 --->3997 --->3998 --->3999 --->4 --->40 --->400 --->4000 --->4001 --->4002 --->4003 --->4004 --->4005 --->4006 --->4007 --->4008 --->4009 --->401 --->4010 --->4011 --->4012 --->4013 --->4014 --->4015 --->4016 --->4017 --->4018 --->4019 --->402 --->4020 --->4021 --->4022 --->4023 --->4024 --->4025 --->4026 --->4027 --->4028 --->4029 --->403 --->4030 --->4031 --->4032 --->4033 --->4034 --->4035 --->4036 --->4037 --->4038 --->4039 --->404 --->4040 --->4041 --->4042 --->4043 --->4044 --->4045 --->4046 --->4047 --->4048 --->4049 --->405 --->4050 --->4051 --->4052 --->4053 --->4054 --->4055 --->4056 --->4057 --->4058 --->4059 --->406 --->4060 --->4061 --->4062 --->4063 --->4064 --->4065 --->4066 --->4067 --->4068 --->4069 --->407 --->4070 --->4071 --->4072 --->4073 --->4074 --->4075 --->4076 --->4077 --->4078 --->4079 --->408 --->4080 --->4081 --->4082 --->4083 --->4084 --->4085 --->4086 --->4087 --->4088 --->4089 --->409 --->4090 --->4091 --->4092 --->4093 --->4094 --->4095 --->4096 --->4097 --->4098 --->4099 --->41 --->410 --->4100 --->4101 --->4102 --->4103 --->4104 --->4105 --->4106 --->4107 --->4108 --->4109 --->411 --->4110 --->4111 --->4112 --->4113 --->4114 --->4115 --->4116 --->4117 --->4118 --->4119 --->412 --->4120 --->4121 --->4122 --->4123 --->4124 --->4125 --->4126 --->4127 --->4128 --->4129 --->413 --->4130 --->4131 --->4132 --->4133 --->4134 --->4135 --->4136 --->4137 --->4138 --->4139 --->414 --->4140 --->4141 --->4142 --->4143 --->4144 --->4145 --->4146 --->4147 --->4148 --->4149 --->415 --->4150 --->4151 --->4152 --->4153 --->4154 --->4155 --->4156 --->4157 --->4158 --->4159 --->416 --->4160 --->4161 --->4162 --->4163 --->4164 --->4165 --->4166 --->4167 --->4168 --->4169 --->417 --->4170 --->4171 --->4172 --->4173 --->4174 --->4175 --->4176 --->4177 --->4178 --->4179 --->418 --->4180 --->4181 --->4182 --->4183 --->4184 --->4185 --->4186 --->4187 --->4188 --->4189 --->419 --->4190 --->4191 --->4192 --->4193 --->4194 --->4195 --->4196 --->4197 --->4198 --->4199 --->42 --->420 --->4200 --->4201 --->4202 --->4203 --->4204 --->4205 --->4206 --->4207 --->4208 --->4209 --->421 --->4210 --->4211 --->4212 --->4213 --->4214 --->4215 --->4216 --->4217 --->4218 --->4219 --->422 --->4220 --->4221 --->4222 --->4223 --->4224 --->4225 --->4226 --->4227 --->4228 --->4229 --->423 --->4230 --->4231 --->4232 --->4233 --->4234 --->4235 --->4236 --->4237 --->4238 --->4239 --->424 --->4240 --->4241 --->4242 --->4243 --->4244 --->4245 --->4246 --->4247 --->4248 --->4249 --->425 --->4250 --->4251 --->4252 --->4253 --->4254 --->4255 --->4256 --->4257 --->4258 --->4259 --->426 --->4260 --->4261 --->4262 --->4263 --->4264 --->4265 --->4266 --->4267 --->4268 --->4269 --->427 --->4270 --->4271 --->4272 --->4273 --->4274 --->4275 --->4276 --->4277 --->4278 --->4279 --->428 --->4280 --->4281 --->4282 --->4283 --->4284 --->4285 --->4286 --->4287 --->4288 --->4289 --->429 --->4290 --->4291 --->4292 --->4293 --->4294 --->4295 --->4296 --->4297 --->4298 --->4299 --->43 --->430 --->4300 --->4301 --->4302 --->4303 --->4304 --->4305 --->4306 --->4307 --->4308 --->4309 --->431 --->4310 --->4311 --->4312 --->4313 --->4314 --->4315 --->4316 --->4317 --->4318 --->4319 --->432 --->4320 --->4321 --->4322 --->4323 --->4324 --->4325 --->4326 --->4327 --->4328 --->4329 --->433 --->4330 --->4331 --->4332 --->4333 --->4334 --->4335 --->4336 --->4337 --->4338 --->4339 --->434 --->4340 --->4341 --->4342 --->4343 --->4344 --->4345 --->4346 --->4347 --->4348 --->4349 --->435 --->4350 --->4351 --->4352 --->4353 --->4354 --->4355 --->4356 --->4357 --->4358 --->4359 --->436 --->4360 --->4361 --->4362 --->4363 --->4364 --->4365 --->4366 --->4367 --->4368 --->4369 --->437 --->4370 --->4371 --->4372 --->4373 --->4374 --->4375 --->4376 --->4377 --->4378 --->4379 --->438 --->4380 --->4381 --->4382 --->4383 --->4384 --->4385 --->4386 --->4387 --->4388 --->4389 --->439 --->4390 --->4391 --->4392 --->4393 --->4394 --->4395 --->4396 --->4397 --->4398 --->4399 --->44 --->440 --->4400 --->4401 --->4402 --->4403 --->4404 --->4405 --->4406 --->4407 --->4408 --->4409 --->441 --->4410 --->4411 --->4412 --->4413 --->4414 --->4415 --->4416 --->4417 --->4418 --->4419 --->442 --->4420 --->4421 --->4422 --->4423 --->4424 --->4425 --->4426 --->4427 --->4428 --->4429 --->443 --->4430 --->4431 --->4432 --->4433 --->4434 --->4435 --->4436 --->4437 --->4438 --->4439 --->444 --->4440 --->4441 --->4442 --->4443 --->4444 --->4445 --->4446 --->4447 --->4448 --->4449 --->445 --->4450 --->4451 --->4452 --->4453 --->4454 --->4455 --->4456 --->4457 --->4458 --->4459 --->446 --->4460 --->4461 --->4462 --->4463 --->4464 --->4465 --->4466 --->4467 --->4468 --->4469 --->447 --->4470 --->4471 --->4472 --->4473 --->4474 --->4475 --->4476 --->4477 --->4478 --->4479 --->448 --->4480 --->4481 --->4482 --->4483 --->4484 --->4485 --->4486 --->4487 --->4488 --->4489 --->449 --->4490 --->4491 --->4492 --->4493 --->4494 --->4495 --->4496 --->4497 --->4498 --->4499 --->45 --->450 --->4500 --->4501 --->4502 --->4503 --->4504 --->4505 --->4506 --->4507 --->4508 --->4509 --->451 --->4510 --->4511 --->4512 --->4513 --->4514 --->4515 --->4516 --->4517 --->4518 --->4519 --->452 --->4520 --->4521 --->4522 --->4523 --->4524 --->4525 --->4526 --->4527 --->4528 --->4529 --->453 --->4530 --->4531 --->4532 --->4533 --->4534 --->4535 --->4536 --->4537 --->4538 --->4539 --->454 --->4540 --->4541 --->4542 --->4543 --->4544 --->4545 --->4546 --->4547 --->4548 --->4549 --->455 --->4550 --->4551 --->4552 --->4553 --->4554 --->4555 --->4556 --->4557 --->4558 --->4559 --->456 --->4560 --->4561 --->4562 --->4563 --->4564 --->4565 --->4566 --->4567 --->4568 --->4569 --->457 --->4570 --->4571 --->4572 --->4573 --->4574 --->4575 --->4576 --->4577 --->4578 --->4579 --->458 --->4580 --->4581 --->4582 --->4583 --->4584 --->4585 --->4586 --->4587 --->4588 --->4589 --->459 --->4590 --->4591 --->4592 --->4593 --->4594 --->4595 --->4596 --->4597 --->4598 --->4599 --->46 --->460 --->4600 --->4601 --->4602 --->4603 --->4604 --->4605 --->4606 --->4607 --->4608 --->4609 --->461 --->4610 --->4611 --->4612 --->4613 --->4614 --->4615 --->4616 --->4617 --->4618 --->4619 --->462 --->4620 --->4621 --->4622 --->4623 --->4624 --->4625 --->4626 --->4627 --->4628 --->4629 --->463 --->4630 --->4631 --->4632 --->4633 --->4634 --->4635 --->4636 --->4637 --->4638 --->4639 --->464 --->4640 --->4641 --->4642 --->4643 --->4644 --->4645 --->4646 --->4647 --->4648 --->4649 --->465 --->4650 --->4651 --->4652 --->4653 --->4654 --->4655 --->4656 --->4657 --->4658 --->4659 --->466 --->4660 --->4661 --->4662 --->4663 --->4664 --->4665 --->4666 --->4667 --->4668 --->4669 --->467 --->4670 --->4671 --->4672 --->4673 --->4674 --->4675 --->4676 --->4677 --->4678 --->4679 --->468 --->4680 --->4681 --->4682 --->4683 --->4684 --->4685 --->4686 --->4687 --->4688 --->4689 --->469 --->4690 --->4691 --->4692 --->4693 --->4694 --->4695 --->4696 --->4697 --->4698 --->4699 --->47 --->470 --->4700 --->4701 --->4702 --->4703 --->4704 --->4705 --->4706 --->4707 --->4708 --->4709 --->471 --->4710 --->4711 --->4712 --->4713 --->4714 --->4715 --->4716 --->4717 --->4718 --->4719 --->472 --->4720 --->4721 --->4722 --->4723 --->4724 --->4725 --->4726 --->4727 --->4728 --->4729 --->473 --->4730 --->4731 --->4732 --->4733 --->4734 --->4735 --->4736 --->4737 --->4738 --->4739 --->474 --->4740 --->4741 --->4742 --->4743 --->4744 --->4745 --->4746 --->4747 --->4748 --->4749 --->475 --->4750 --->4751 --->4752 --->4753 --->4754 --->4755 --->4756 --->4757 --->4758 --->4759 --->476 --->4760 --->4761 --->4762 --->4763 --->4764 --->4765 --->4766 --->4767 --->4768 --->4769 --->477 --->4770 --->4771 --->4772 --->4773 --->4774 --->4775 --->4776 --->4777 --->4778 --->4779 --->478 --->4780 --->4781 --->4782 --->4783 --->4784 --->4785 --->4786 --->4787 --->4788 --->4789 --->479 --->4790 --->4791 --->4792 --->4793 --->4794 --->4795 --->4796 --->4797 --->4798 --->4799 --->48 --->480 --->4800 --->4801 --->4802 --->4803 --->4804 --->4805 --->4806 --->4807 --->4808 --->4809 --->481 --->4810 --->4811 --->4812 --->4813 --->4814 --->4815 --->4816 --->4817 --->4818 --->4819 --->482 --->4820 --->4821 --->4822 --->4823 --->4824 --->4825 --->4826 --->4827 --->4828 --->4829 --->483 --->4830 --->4831 --->4832 --->4833 --->4834 --->4835 --->4836 --->4837 --->4838 --->4839 --->484 --->4840 --->4841 --->4842 --->4843 --->4844 --->4845 --->4846 --->4847 --->4848 --->4849 --->485 --->4850 --->4851 --->4852 --->4853 --->4854 --->4855 --->4856 --->4857 --->4858 --->4859 --->486 --->4860 --->4861 --->4862 --->4863 --->4864 --->4865 --->4866 --->4867 --->4868 --->4869 --->487 --->4870 --->4871 --->4872 --->4873 --->4874 --->4875 --->4876 --->4877 --->4878 --->4879 --->488 --->4880 --->4881 --->4882 --->4883 --->4884 --->4885 --->4886 --->4887 --->4888 --->4889 --->489 --->4890 --->4891 --->4892 --->4893 --->4894 --->4895 --->4896 --->4897 --->4898 --->4899 --->49 --->490 --->4900 --->4901 --->4902 --->4903 --->4904 --->4905 --->4906 --->4907 --->4908 --->4909 --->491 --->4910 --->4911 --->4912 --->4913 --->4914 --->4915 --->4916 --->4917 --->4918 --->4919 --->492 --->4920 --->4921 --->4922 --->4923 --->4924 --->4925 --->4926 --->4927 --->4928 --->4929 --->493 --->4930 --->4931 --->4932 --->4933 --->4934 --->4935 --->4936 --->4937 --->4938 --->4939 --->494 --->4940 --->4941 --->4942 --->4943 --->4944 --->4945 --->4946 --->4947 --->4948 --->4949 --->495 --->4950 --->4951 --->4952 --->4953 --->4954 --->4955 --->4956 --->4957 --->4958 --->4959 --->496 --->4960 --->4961 --->4962 --->4963 --->4964 --->4965 --->4966 --->4967 --->4968 --->4969 --->497 --->4970 --->4971 --->4972 --->4973 --->4974 --->4975 --->4976 --->4977 --->4978 --->4979 --->498 --->4980 --->4981 --->4982 --->4983 --->4984 --->4985 --->4986 --->4987 --->4988 --->4989 --->499 --->4990 --->4991 --->4992 --->4993 --->4994 --->4995 --->4996 --->4997 --->4998 --->4999 --->5 --->50 --->500 --->5000 --->5001 --->5002 --->5003 --->5004 --->5005 --->5006 --->5007 --->5008 --->5009 --->501 --->5010 --->5011 --->5012 --->5013 --->5014 --->5015 --->5016 --->5017 --->5018 --->5019 --->502 --->5020 --->5021 --->5022 --->5023 --->5024 --->5025 --->5026 --->5027 --->5028 --->5029 --->503 --->5030 --->5031 --->5032 --->5033 --->5034 --->5035 --->5036 --->5037 --->5038 --->5039 --->504 --->5040 --->5041 --->5042 --->5043 --->5044 --->5045 --->5046 --->5047 --->5048 --->5049 --->505 --->5050 --->5051 --->5052 --->5053 --->5054 --->5055 --->5056 --->5057 --->5058 --->5059 --->506 --->5060 --->5061 --->5062 --->5063 --->5064 --->5065 --->5066 --->5067 --->5068 --->5069 --->507 --->5070 --->5071 --->5072 --->5073 --->5074 --->5075 --->5076 --->5077 --->5078 --->5079 --->508 --->5080 --->5081 --->5082 --->5083 --->5084 --->5085 --->5086 --->5087 --->5088 --->5089 --->509 --->5090 --->5091 --->5092 --->5093 --->5094 --->5095 --->5096 --->5097 --->5098 --->5099 --->51 --->510 --->5100 --->5101 --->5102 --->5103 --->5104 --->5105 --->5106 --->5107 --->5108 --->5109 --->511 --->5110 --->5111 --->5112 --->5113 --->5114 --->5115 --->5116 --->5117 --->5118 --->5119 --->512 --->5120 --->5121 --->5122 --->5123 --->5124 --->5125 --->5126 --->5127 --->5128 --->5129 --->513 --->5130 --->5131 --->5132 --->5133 --->5134 --->5135 --->5136 --->5137 --->5138 --->5139 --->514 --->5140 --->5141 --->5142 --->5143 --->5144 --->5145 --->5146 --->5147 --->5148 --->5149 --->515 --->5150 --->5151 --->5152 --->5153 --->5154 --->5155 --->5156 --->5157 --->5158 --->5159 --->516 --->5160 --->5161 --->5162 --->5163 --->5164 --->5165 --->5166 --->5167 --->5168 --->5169 --->517 --->5170 --->5171 --->5172 --->5173 --->5174 --->5175 --->5176 --->5177 --->5178 --->5179 --->518 --->5180 --->5181 --->5182 --->5183 --->5184 --->5185 --->5186 --->5187 --->5188 --->5189 --->519 --->5190 --->5191 --->5192 --->5193 --->5194 --->5195 --->5196 --->5197 --->5198 --->5199 --->52 --->520 --->5200 --->5201 --->5202 --->5203 --->5204 --->5205 --->5206 --->5207 --->5208 --->5209 --->521 --->5210 --->5211 --->5212 --->5213 --->5214 --->5215 --->5216 --->5217 --->5218 --->5219 --->522 --->5220 --->5221 --->5222 --->5223 --->5224 --->5225 --->5226 --->5227 --->5228 --->5229 --->523 --->5230 --->5231 --->5232 --->5233 --->5234 --->5235 --->5236 --->5237 --->5238 --->5239 --->524 --->5240 --->5241 --->5242 --->5243 --->5244 --->5245 --->5246 --->5247 --->5248 --->5249 --->525 --->5250 --->5251 --->5252 --->5253 --->5254 --->5255 --->5256 --->5257 --->5258 --->5259 --->526 --->5260 --->5261 --->5262 --->5263 --->5264 --->5265 --->5266 --->5267 --->5268 --->5269 --->527 --->5270 --->5271 --->5272 --->5273 --->5274 --->5275 --->5276 --->5277 --->5278 --->5279 --->528 --->5280 --->5281 --->5282 --->5283 --->5284 --->5285 --->5286 --->5287 --->5288 --->5289 --->529 --->5290 --->5291 --->5292 --->5293 --->5294 --->5295 --->5296 --->5297 --->5298 --->5299 --->53 --->530 --->5300 --->5301 --->5302 --->5303 --->5304 --->5305 --->5306 --->5307 --->5308 --->5309 --->531 --->5310 --->5311 --->5312 --->5313 --->5314 --->5315 --->5316 --->5317 --->5318 --->5319 --->532 --->5320 --->5321 --->5322 --->5323 --->5324 --->5325 --->5326 --->5327 --->5328 --->5329 --->533 --->5330 --->5331 --->5332 --->5333 --->5334 --->5335 --->5336 --->5337 --->5338 --->5339 --->534 --->5340 --->5341 --->5342 --->5343 --->5344 --->5345 --->5346 --->5347 --->5348 --->5349 --->535 --->5350 --->5351 --->5352 --->5353 --->5354 --->5355 --->5356 --->5357 --->5358 --->5359 --->536 --->5360 --->5361 --->5362 --->5363 --->5364 --->5365 --->5366 --->5367 --->5368 --->5369 --->537 --->5370 --->5371 --->5372 --->5373 --->5374 --->5375 --->5376 --->5377 --->5378 --->5379 --->538 --->5380 --->5381 --->5382 --->5383 --->5384 --->5385 --->5386 --->5387 --->5388 --->5389 --->539 --->5390 --->5391 --->5392 --->5393 --->5394 --->5395 --->5396 --->5397 --->5398 --->5399 --->54 --->540 --->5400 --->5401 --->5402 --->5403 --->5404 --->5405 --->5406 --->5407 --->5408 --->5409 --->541 --->5410 --->5411 --->5412 --->5413 --->5414 --->5415 --->5416 --->5417 --->5418 --->5419 --->542 --->5420 --->5421 --->5422 --->5423 --->5424 --->5425 --->5426 --->5427 --->5428 --->5429 --->543 --->5430 --->5431 --->5432 --->5433 --->5434 --->5435 --->5436 --->5437 --->5438 --->5439 --->544 --->5440 --->5441 --->5442 --->5443 --->5444 --->5445 --->5446 --->5447 --->5448 --->5449 --->545 --->5450 --->5451 --->5452 --->5453 --->5454 --->5455 --->5456 --->5457 --->5458 --->5459 --->546 --->5460 --->5461 --->5462 --->5463 --->5464 --->5465 --->5466 --->5467 --->5468 --->5469 --->547 --->5470 --->5471 --->5472 --->5473 --->5474 --->5475 --->5476 --->5477 --->5478 --->5479 --->548 --->5480 --->5481 --->5482 --->5483 --->5484 --->5485 --->5486 --->5487 --->5488 --->5489 --->549 --->5490 --->5491 --->5492 --->5493 --->5494 --->5495 --->5496 --->5497 --->5498 --->5499 --->55 --->550 --->5500 --->5501 --->5502 --->5503 --->5504 --->5505 --->5506 --->5507 --->5508 --->5509 --->551 --->5510 --->5511 --->5512 --->5513 --->5514 --->5515 --->5516 --->5517 --->5518 --->5519 --->552 --->5520 --->5521 --->5522 --->5523 --->5524 --->5525 --->5526 --->5527 --->5528 --->5529 --->553 --->5530 --->5531 --->5532 --->5533 --->5534 --->5535 --->5536 --->5537 --->5538 --->5539 --->554 --->5540 --->5541 --->5542 --->5543 --->5544 --->5545 --->5546 --->5547 --->5548 --->5549 --->555 --->5550 --->5551 --->5552 --->5553 --->5554 --->5555 --->5556 --->5557 --->5558 --->5559 --->556 --->5560 --->5561 --->5562 --->5563 --->5564 --->5565 --->5566 --->5567 --->5568 --->5569 --->557 --->5570 --->5571 --->5572 --->5573 --->5574 --->5575 --->5576 --->5577 --->5578 --->5579 --->558 --->5580 --->5581 --->5582 --->5583 --->5584 --->5585 --->5586 --->5587 --->5588 --->5589 --->559 --->5590 --->5591 --->5592 --->5593 --->5594 --->5595 --->5596 --->5597 --->5598 --->5599 --->56 --->560 --->5600 --->5601 --->5602 --->5603 --->5604 --->5605 --->5606 --->5607 --->5608 --->5609 --->561 --->5610 --->5611 --->5612 --->5613 --->5614 --->5615 --->5616 --->5617 --->5618 --->5619 --->562 --->5620 --->5621 --->5622 --->5623 --->5624 --->5625 --->5626 --->5627 --->5628 --->5629 --->563 --->5630 --->5631 --->5632 --->5633 --->5634 --->5635 --->5636 --->5637 --->5638 --->5639 --->564 --->5640 --->5641 --->5642 --->5643 --->5644 --->5645 --->5646 --->5647 --->5648 --->5649 --->565 --->5650 --->5651 --->5652 --->5653 --->5654 --->5655 --->5656 --->5657 --->5658 --->5659 --->566 --->5660 --->5661 --->5662 --->5663 --->5664 --->5665 --->5666 --->5667 --->5668 --->5669 --->567 --->5670 --->5671 --->5672 --->5673 --->5674 --->5675 --->5676 --->5677 --->5678 --->5679 --->568 --->5680 --->5681 --->5682 --->5683 --->5684 --->5685 --->5686 --->5687 --->5688 --->5689 --->569 --->5690 --->5691 --->5692 --->5693 --->5694 --->5695 --->5696 --->5697 --->5698 --->5699 --->57 --->570 --->5700 --->5701 --->5702 --->5703 --->5704 --->5705 --->5706 --->5707 --->5708 --->5709 --->571 --->5710 --->5711 --->5712 --->5713 --->5714 --->5715 --->5716 --->5717 --->5718 --->5719 --->572 --->5720 --->5721 --->5722 --->5723 --->5724 --->5725 --->5726 --->5727 --->5728 --->5729 --->573 --->5730 --->5731 --->5732 --->5733 --->5734 --->5735 --->5736 --->5737 --->5738 --->5739 --->574 --->5740 --->5741 --->5742 --->5743 --->5744 --->5745 --->5746 --->5747 --->5748 --->5749 --->575 --->5750 --->5751 --->5752 --->5753 --->5754 --->5755 --->5756 --->5757 --->5758 --->5759 --->576 --->5760 --->5761 --->5762 --->5763 --->5764 --->5765 --->5766 --->5767 --->5768 --->5769 --->577 --->5770 --->5771 --->5772 --->5773 --->5774 --->5775 --->5776 --->5777 --->5778 --->5779 --->578 --->5780 --->5781 --->5782 --->5783 --->5784 --->5785 --->5786 --->5787 --->5788 --->5789 --->579 --->5790 --->5791 --->5792 --->5793 --->5794 --->5795 --->5796 --->5797 --->5798 --->5799 --->58 --->580 --->5800 --->5801 --->5802 --->5803 --->5804 --->5805 --->5806 --->5807 --->5808 --->5809 --->581 --->5810 --->5811 --->5812 --->5813 --->5814 --->5815 --->5816 --->5817 --->5818 --->5819 --->582 --->5820 --->5821 --->5822 --->5823 --->5824 --->5825 --->5826 --->5827 --->5828 --->5829 --->583 --->5830 --->5831 --->5832 --->5833 --->5834 --->5835 --->5836 --->5837 --->5838 --->5839 --->584 --->5840 --->5841 --->5842 --->5843 --->5844 --->5845 --->5846 --->5847 --->5848 --->5849 --->585 --->5850 --->5851 --->5852 --->5853 --->5854 --->5855 --->5856 --->5857 --->5858 --->5859 --->586 --->5860 --->5861 --->5862 --->5863 --->5864 --->5865 --->5866 --->5867 --->5868 --->5869 --->587 --->5870 --->5871 --->5872 --->5873 --->5874 --->5875 --->5876 --->5877 --->5878 --->5879 --->588 --->5880 --->5881 --->5882 --->5883 --->5884 --->5885 --->5886 --->5887 --->5888 --->5889 --->589 --->5890 --->5891 --->5892 --->5893 --->5894 --->5895 --->5896 --->5897 --->5898 --->5899 --->59 --->590 --->5900 --->5901 --->5902 --->5903 --->5904 --->5905 --->5906 --->5907 --->5908 --->5909 --->591 --->5910 --->5911 --->5912 --->5913 --->5914 --->5915 --->5916 --->5917 --->5918 --->5919 --->592 --->5920 --->5921 --->5922 --->5923 --->5924 --->5925 --->5926 --->5927 --->5928 --->5929 --->593 --->5930 --->5931 --->5932 --->5933 --->5934 --->5935 --->5936 --->5937 --->5938 --->5939 --->594 --->5940 --->5941 --->5942 --->5943 --->5944 --->5945 --->5946 --->5947 --->5948 --->5949 --->595 --->5950 --->5951 --->5952 --->5953 --->5954 --->5955 --->5956 --->5957 --->5958 --->5959 --->596 --->5960 --->5961 --->5962 --->5963 --->5964 --->5965 --->5966 --->5967 --->5968 --->5969 --->597 --->5970 --->5971 --->5972 --->5973 --->5974 --->5975 --->5976 --->5977 --->5978 --->5979 --->598 --->5980 --->5981 --->5982 --->5983 --->5984 --->5985 --->5986 --->5987 --->5988 --->5989 --->599 --->5990 --->5991 --->5992 --->5993 --->5994 --->5995 --->5996 --->5997 --->5998 --->5999 --->6 --->60 --->600 --->6000 --->6001 --->6002 --->6003 --->6004 --->6005 --->6006 --->6007 --->6008 --->6009 --->601 --->6010 --->6011 --->6012 --->6013 --->6014 --->6015 --->6016 --->6017 --->6018 --->6019 --->602 --->6020 --->6021 --->6022 --->6023 --->6024 --->6025 --->6026 --->6027 --->6028 --->6029 --->603 --->6030 --->6031 --->6032 --->6033 --->6034 --->6035 --->6036 --->6037 --->6038 --->6039 --->604 --->6040 --->6041 --->6042 --->6043 --->6044 --->6045 --->6046 --->6047 --->6048 --->6049 --->605 --->6050 --->6051 --->6052 --->6053 --->6054 --->6055 --->6056 --->6057 --->6058 --->6059 --->606 --->6060 --->6061 --->6062 --->6063 --->6064 --->6065 --->6066 --->6067 --->6068 --->6069 --->607 --->6070 --->6071 --->6072 --->6073 --->6074 --->6075 --->6076 --->6077 --->6078 --->6079 --->608 --->6080 --->6081 --->6082 --->6083 --->6084 --->6085 --->6086 --->6087 --->6088 --->6089 --->609 --->6090 --->6091 --->6092 --->6093 --->6094 --->6095 --->6096 --->6097 --->6098 --->6099 --->61 --->610 --->6100 --->6101 --->6102 --->6103 --->6104 --->6105 --->6106 --->6107 --->6108 --->6109 --->611 --->6110 --->6111 --->6112 --->6113 --->6114 --->6115 --->6116 --->6117 --->6118 --->6119 --->612 --->6120 --->6121 --->6122 --->6123 --->6124 --->6125 --->6126 --->6127 --->6128 --->6129 --->613 --->6130 --->6131 --->6132 --->6133 --->6134 --->6135 --->6136 --->6137 --->6138 --->6139 --->614 --->6140 --->6141 --->6142 --->6143 --->6144 --->6145 --->6146 --->6147 --->6148 --->6149 --->615 --->6150 --->6151 --->6152 --->6153 --->6154 --->6155 --->6156 --->6157 --->6158 --->6159 --->616 --->6160 --->6161 --->6162 --->6163 --->6164 --->6165 --->6166 --->6167 --->6168 --->6169 --->617 --->6170 --->6171 --->6172 --->6173 --->6174 --->6175 --->6176 --->6177 --->6178 --->6179 --->618 --->6180 --->6181 --->6182 --->6183 --->6184 --->6185 --->6186 --->6187 --->6188 --->6189 --->619 --->6190 --->6191 --->6192 --->6193 --->6194 --->6195 --->6196 --->6197 --->6198 --->6199 --->62 --->620 --->6200 --->6201 --->6202 --->6203 --->6204 --->6205 --->6206 --->6207 --->6208 --->6209 --->621 --->6210 --->6211 --->6212 --->6213 --->6214 --->6215 --->6216 --->6217 --->6218 --->6219 --->622 --->6220 --->6221 --->6222 --->6223 --->6224 --->6225 --->6226 --->6227 --->6228 --->6229 --->623 --->6230 --->6231 --->6232 --->6233 --->6234 --->6235 --->6236 --->6237 --->6238 --->6239 --->624 --->6240 --->6241 --->6242 --->6243 --->6244 --->6245 --->6246 --->6247 --->6248 --->6249 --->625 --->6250 --->6251 --->6252 --->6253 --->6254 --->6255 --->6256 --->6257 --->6258 --->6259 --->626 --->6260 --->6261 --->6262 --->6263 --->6264 --->6265 --->6266 --->6267 --->6268 --->6269 --->627 --->6270 --->6271 --->6272 --->6273 --->6274 --->6275 --->6276 --->6277 --->6278 --->6279 --->628 --->6280 --->6281 --->6282 --->6283 --->6284 --->6285 --->6286 --->6287 --->6288 --->6289 --->629 --->6290 --->6291 --->6292 --->6293 --->6294 --->6295 --->6296 --->6297 --->6298 --->6299 --->63 --->630 --->6300 --->6301 --->6302 --->6303 --->6304 --->6305 --->6306 --->6307 --->6308 --->6309 --->631 --->6310 --->6311 --->6312 --->6313 --->6314 --->6315 --->6316 --->6317 --->6318 --->6319 --->632 --->6320 --->6321 --->6322 --->6323 --->6324 --->6325 --->6326 --->6327 --->6328 --->6329 --->633 --->6330 --->6331 --->6332 --->6333 --->6334 --->6335 --->6336 --->6337 --->6338 --->6339 --->634 --->6340 --->6341 --->6342 --->6343 --->6344 --->6345 --->6346 --->6347 --->6348 --->6349 --->635 --->6350 --->6351 --->6352 --->6353 --->6354 --->6355 --->6356 --->6357 --->6358 --->6359 --->636 --->6360 --->6361 --->6362 --->6363 --->6364 --->6365 --->6366 --->6367 --->6368 --->6369 --->637 --->6370 --->6371 --->6372 --->6373 --->6374 --->6375 --->6376 --->6377 --->6378 --->6379 --->638 --->6380 --->6381 --->6382 --->6383 --->6384 --->6385 --->6386 --->6387 --->6388 --->6389 --->639 --->6390 --->6391 --->6392 --->6393 --->6394 --->6395 --->6396 --->6397 --->6398 --->6399 --->64 --->640 --->6400 --->6401 --->6402 --->6403 --->6404 --->6405 --->6406 --->6407 --->6408 --->6409 --->641 --->6410 --->6411 --->6412 --->6413 --->6414 --->6415 --->6416 --->6417 --->6418 --->6419 --->642 --->6420 --->6421 --->6422 --->6423 --->6424 --->6425 --->6426 --->6427 --->6428 --->6429 --->643 --->6430 --->6431 --->6432 --->6433 --->6434 --->6435 --->6436 --->6437 --->6438 --->6439 --->644 --->6440 --->6441 --->6442 --->6443 --->6444 --->6445 --->6446 --->6447 --->6448 --->6449 --->645 --->6450 --->6451 --->6452 --->6453 --->6454 --->6455 --->6456 --->6457 --->6458 --->6459 --->646 --->6460 --->6461 --->6462 --->6463 --->6464 --->6465 --->6466 --->6467 --->6468 --->6469 --->647 --->6470 --->6471 --->6472 --->6473 --->6474 --->6475 --->6476 --->6477 --->6478 --->6479 --->648 --->6480 --->6481 --->6482 --->6483 --->6484 --->6485 --->6486 --->6487 --->6488 --->6489 --->649 --->6490 --->6491 --->6492 --->6493 --->6494 --->6495 --->6496 --->6497 --->6498 --->6499 --->65 --->650 --->6500 --->6501 --->6502 --->6503 --->6504 --->6505 --->6506 --->6507 --->6508 --->6509 --->651 --->6510 --->6511 --->6512 --->6513 --->6514 --->6515 --->6516 --->6517 --->6518 --->6519 --->652 --->6520 --->6521 --->6522 --->6523 --->6524 --->6525 --->6526 --->6527 --->6528 --->6529 --->653 --->6530 --->6531 --->6532 --->6533 --->6534 --->6535 --->6536 --->6537 --->6538 --->6539 --->654 --->6540 --->6541 --->6542 --->6543 --->6544 --->6545 --->6546 --->6547 --->6548 --->6549 --->655 --->6550 --->6551 --->6552 --->6553 --->6554 --->6555 --->6556 --->6557 --->6558 --->6559 --->656 --->6560 --->6561 --->6562 --->6563 --->6564 --->6565 --->6566 --->6567 --->6568 --->6569 --->657 --->6570 --->6571 --->6572 --->6573 --->6574 --->6575 --->6576 --->6577 --->6578 --->6579 --->658 --->6580 --->6581 --->6582 --->6583 --->6584 --->6585 --->6586 --->6587 --->6588 --->6589 --->659 --->6590 --->6591 --->6592 --->6593 --->6594 --->6595 --->6596 --->6597 --->6598 --->6599 --->66 --->660 --->6600 --->6601 --->6602 --->6603 --->6604 --->6605 --->6606 --->6607 --->6608 --->6609 --->661 --->6610 --->6611 --->6612 --->6613 --->6614 --->6615 --->6616 --->6617 --->6618 --->6619 --->662 --->6620 --->6621 --->6622 --->6623 --->6624 --->6625 --->6626 --->6627 --->6628 --->6629 --->663 --->6630 --->6631 --->6632 --->6633 --->6634 --->6635 --->6636 --->6637 --->6638 --->6639 --->664 --->6640 --->6641 --->6642 --->6643 --->6644 --->6645 --->6646 --->6647 --->6648 --->6649 --->665 --->6650 --->6651 --->6652 --->6653 --->6654 --->6655 --->6656 --->6657 --->6658 --->6659 --->666 --->6660 --->6661 --->6662 --->6663 --->6664 --->6665 --->6666 --->6667 --->6668 --->6669 --->667 --->6670 --->6671 --->6672 --->6673 --->6674 --->6675 --->6676 --->6677 --->6678 --->6679 --->668 --->6680 --->6681 --->6682 --->6683 --->6684 --->6685 --->6686 --->6687 --->6688 --->6689 --->669 --->6690 --->6691 --->6692 --->6693 --->6694 --->6695 --->6696 --->6697 --->6698 --->6699 --->67 --->670 --->6700 --->6701 --->6702 --->6703 --->6704 --->6705 --->6706 --->6707 --->6708 --->6709 --->671 --->6710 --->6711 --->6712 --->6713 --->6714 --->6715 --->6716 --->6717 --->6718 --->6719 --->672 --->6720 --->6721 --->6722 --->6723 --->6724 --->6725 --->6726 --->6727 --->6728 --->6729 --->673 --->6730 --->6731 --->6732 --->6733 --->6734 --->6735 --->6736 --->6737 --->6738 --->6739 --->674 --->6740 --->6741 --->6742 --->6743 --->6744 --->6745 --->6746 --->6747 --->6748 --->6749 --->675 --->6750 --->6751 --->6752 --->6753 --->6754 --->6755 --->6756 --->6757 --->6758 --->6759 --->676 --->6760 --->6761 --->6762 --->6763 --->6764 --->6765 --->6766 --->6767 --->6768 --->6769 --->677 --->6770 --->6771 --->6772 --->6773 --->6774 --->6775 --->6776 --->6777 --->6778 --->6779 --->678 --->6780 --->6781 --->6782 --->6783 --->6784 --->6785 --->6786 --->6787 --->6788 --->6789 --->679 --->6790 --->6791 --->6792 --->6793 --->6794 --->6795 --->6796 --->6797 --->6798 --->6799 --->68 --->680 --->6800 --->6801 --->6802 --->6803 --->6804 --->6805 --->6806 --->6807 --->6808 --->6809 --->681 --->6810 --->6811 --->6812 --->6813 --->6814 --->6815 --->6816 --->6817 --->6818 --->6819 --->682 --->6820 --->6821 --->6822 --->6823 --->6824 --->6825 --->6826 --->6827 --->6828 --->6829 --->683 --->6830 --->6831 --->6832 --->6833 --->6834 --->6835 --->6836 --->6837 --->6838 --->6839 --->684 --->6840 --->6841 --->6842 --->6843 --->6844 --->6845 --->6846 --->6847 --->6848 --->6849 --->685 --->6850 --->6851 --->6852 --->6853 --->6854 --->6855 --->6856 --->6857 --->6858 --->6859 --->686 --->6860 --->6861 --->6862 --->6863 --->6864 --->6865 --->6866 --->6867 --->6868 --->6869 --->687 --->6870 --->6871 --->6872 --->6873 --->6874 --->6875 --->6876 --->6877 --->6878 --->6879 --->688 --->6880 --->6881 --->6882 --->6883 --->6884 --->6885 --->6886 --->6887 --->6888 --->6889 --->689 --->6890 --->6891 --->6892 --->6893 --->6894 --->6895 --->6896 --->6897 --->6898 --->6899 --->69 --->690 --->6900 --->6901 --->6902 --->6903 --->6904 --->6905 --->6906 --->6907 --->6908 --->6909 --->691 --->6910 --->6911 --->6912 --->6913 --->6914 --->6915 --->6916 --->6917 --->6918 --->6919 --->692 --->6920 --->6921 --->6922 --->6923 --->6924 --->6925 --->6926 --->6927 --->6928 --->6929 --->693 --->6930 --->6931 --->6932 --->6933 --->6934 --->6935 --->6936 --->6937 --->6938 --->6939 --->694 --->6940 --->6941 --->6942 --->6943 --->6944 --->6945 --->6946 --->6947 --->6948 --->6949 --->695 --->6950 --->6951 --->6952 --->6953 --->6954 --->6955 --->6956 --->6957 --->6958 --->6959 --->696 --->6960 --->6961 --->6962 --->6963 --->6964 --->6965 --->6966 --->6967 --->6968 --->6969 --->697 --->6970 --->6971 --->6972 --->6973 --->6974 --->6975 --->6976 --->6977 --->6978 --->6979 --->698 --->6980 --->6981 --->6982 --->6983 --->6984 --->6985 --->6986 --->6987 --->6988 --->6989 --->699 --->6990 --->6991 --->6992 --->6993 --->6994 --->6995 --->6996 --->6997 --->6998 --->6999 --->7 --->70 --->700 --->7000 --->7001 --->7002 --->7003 --->7004 --->7005 --->7006 --->7007 --->7008 --->7009 --->701 --->7010 --->7011 --->7012 --->7013 --->7014 --->7015 --->7016 --->7017 --->7018 --->7019 --->702 --->7020 --->7021 --->7022 --->7023 --->7024 --->7025 --->7026 --->7027 --->7028 --->7029 --->703 --->7030 --->7031 --->7032 --->7033 --->7034 --->7035 --->7036 --->7037 --->7038 --->7039 --->704 --->7040 --->7041 --->7042 --->7043 --->7044 --->7045 --->7046 --->7047 --->7048 --->7049 --->705 --->7050 --->7051 --->7052 --->7053 --->7054 --->7055 --->7056 --->7057 --->7058 --->7059 --->706 --->7060 --->7061 --->7062 --->7063 --->7064 --->7065 --->7066 --->7067 --->7068 --->7069 --->707 --->7070 --->7071 --->7072 --->7073 --->7074 --->7075 --->7076 --->7077 --->7078 --->7079 --->708 --->7080 --->7081 --->7082 --->7083 --->7084 --->7085 --->7086 --->7087 --->7088 --->7089 --->709 --->7090 --->7091 --->7092 --->7093 --->7094 --->7095 --->7096 --->7097 --->7098 --->7099 --->71 --->710 --->7100 --->7101 --->7102 --->7103 --->7104 --->7105 --->7106 --->7107 --->7108 --->7109 --->711 --->7110 --->7111 --->7112 --->7113 --->7114 --->7115 --->7116 --->7117 --->7118 --->7119 --->712 --->7120 --->7121 --->7122 --->7123 --->7124 --->7125 --->7126 --->7127 --->7128 --->7129 --->713 --->7130 --->7131 --->7132 --->7133 --->7134 --->7135 --->7136 --->7137 --->7138 --->7139 --->714 --->7140 --->7141 --->7142 --->7143 --->7144 --->7145 --->7146 --->7147 --->7148 --->7149 --->715 --->7150 --->7151 --->7152 --->7153 --->7154 --->7155 --->7156 --->7157 --->7158 --->7159 --->716 --->7160 --->7161 --->7162 --->7163 --->7164 --->7165 --->7166 --->7167 --->7168 --->7169 --->717 --->7170 --->7171 --->7172 --->7173 --->7174 --->7175 --->7176 --->7177 --->7178 --->7179 --->718 --->7180 --->7181 --->7182 --->7183 --->7184 --->7185 --->7186 --->7187 --->7188 --->7189 --->719 --->7190 --->7191 --->7192 --->7193 --->7194 --->7195 --->7196 --->7197 --->7198 --->7199 --->72 --->720 --->7200 --->7201 --->7202 --->7203 --->7204 --->7205 --->7206 --->7207 --->7208 --->7209 --->721 --->7210 --->7211 --->7212 --->7213 --->7214 --->7215 --->7216 --->7217 --->7218 --->7219 --->722 --->7220 --->7221 --->7222 --->7223 --->7224 --->7225 --->7226 --->7227 --->7228 --->7229 --->723 --->7230 --->7231 --->7232 --->7233 --->7234 --->7235 --->7236 --->7237 --->7238 --->7239 --->724 --->7240 --->7241 --->7242 --->7243 --->7244 --->7245 --->7246 --->7247 --->7248 --->7249 --->725 --->7250 --->7251 --->7252 --->7253 --->7254 --->7255 --->7256 --->7257 --->7258 --->7259 --->726 --->7260 --->7261 --->7262 --->7263 --->7264 --->7265 --->7266 --->7267 --->7268 --->7269 --->727 --->7270 --->7271 --->7272 --->7273 --->7274 --->7275 --->7276 --->7277 --->7278 --->7279 --->728 --->7280 --->7281 --->7282 --->7283 --->7284 --->7285 --->7286 --->7287 --->7288 --->7289 --->729 --->7290 --->7291 --->7292 --->7293 --->7294 --->7295 --->7296 --->7297 --->7298 --->7299 --->73 --->730 --->7300 --->7301 --->7302 --->7303 --->7304 --->7305 --->7306 --->7307 --->7308 --->7309 --->731 --->7310 --->7311 --->7312 --->7313 --->7314 --->7315 --->7316 --->7317 --->7318 --->7319 --->732 --->7320 --->7321 --->7322 --->7323 --->7324 --->7325 --->7326 --->7327 --->7328 --->7329 --->733 --->7330 --->7331 --->7332 --->7333 --->7334 --->7335 --->7336 --->7337 --->7338 --->7339 --->734 --->7340 --->7341 --->7342 --->7343 --->7344 --->7345 --->7346 --->7347 --->7348 --->7349 --->735 --->7350 --->7351 --->7352 --->7353 --->7354 --->7355 --->7356 --->7357 --->7358 --->7359 --->736 --->7360 --->7361 --->7362 --->7363 --->7364 --->7365 --->7366 --->7367 --->7368 --->7369 --->737 --->7370 --->7371 --->7372 --->7373 --->7374 --->7375 --->7376 --->7377 --->7378 --->7379 --->738 --->7380 --->7381 --->7382 --->7383 --->7384 --->7385 --->7386 --->7387 --->7388 --->7389 --->739 --->7390 --->7391 --->7392 --->7393 --->7394 --->7395 --->7396 --->7397 --->7398 --->7399 --->74 --->740 --->7400 --->7401 --->7402 --->7403 --->7404 --->7405 --->7406 --->7407 --->7408 --->7409 --->741 --->7410 --->7411 --->7412 --->7413 --->7414 --->7415 --->7416 --->7417 --->7418 --->7419 --->742 --->7420 --->7421 --->7422 --->7423 --->7424 --->7425 --->7426 --->7427 --->7428 --->7429 --->743 --->7430 --->7431 --->7432 --->7433 --->7434 --->7435 --->7436 --->7437 --->7438 --->7439 --->744 --->7440 --->7441 --->7442 --->7443 --->7444 --->7445 --->7446 --->7447 --->7448 --->7449 --->745 --->7450 --->7451 --->7452 --->7453 --->7454 --->7455 --->7456 --->7457 --->7458 --->7459 --->746 --->7460 --->7461 --->7462 --->7463 --->7464 --->7465 --->7466 --->7467 --->7468 --->7469 --->747 --->7470 --->7471 --->7472 --->7473 --->7474 --->7475 --->7476 --->7477 --->7478 --->7479 --->748 --->7480 --->7481 --->7482 --->7483 --->7484 --->7485 --->7486 --->7487 --->7488 --->7489 --->749 --->7490 --->7491 --->7492 --->7493 --->7494 --->7495 --->7496 --->7497 --->7498 --->7499 --->75 --->750 --->7500 --->7501 --->7502 --->7503 --->7504 --->7505 --->7506 --->7507 --->7508 --->7509 --->751 --->7510 --->7511 --->7512 --->7513 --->7514 --->7515 --->7516 --->7517 --->7518 --->7519 --->752 --->7520 --->7521 --->7522 --->7523 --->7524 --->7525 --->7526 --->7527 --->7528 --->7529 --->753 --->7530 --->7531 --->7532 --->7533 --->7534 --->7535 --->7536 --->7537 --->7538 --->7539 --->754 --->7540 --->7541 --->7542 --->7543 --->7544 --->7545 --->7546 --->7547 --->7548 --->7549 --->755 --->7550 --->7551 --->7552 --->7553 --->7554 --->7555 --->7556 --->7557 --->7558 --->7559 --->756 --->7560 --->7561 --->7562 --->7563 --->7564 --->7565 --->7566 --->7567 --->7568 --->7569 --->757 --->7570 --->7571 --->7572 --->7573 --->7574 --->7575 --->7576 --->7577 --->7578 --->7579 --->758 --->7580 --->7581 --->7582 --->7583 --->7584 --->7585 --->7586 --->7587 --->7588 --->7589 --->759 --->7590 --->7591 --->7592 --->7593 --->7594 --->7595 --->7596 --->7597 --->7598 --->7599 --->76 --->760 --->7600 --->7601 --->7602 --->7603 --->7604 --->7605 --->7606 --->7607 --->7608 --->7609 --->761 --->7610 --->7611 --->7612 --->7613 --->7614 --->7615 --->7616 --->7617 --->7618 --->7619 --->762 --->7620 --->7621 --->7622 --->7623 --->7624 --->7625 --->7626 --->7627 --->7628 --->7629 --->763 --->7630 --->7631 --->7632 --->7633 --->7634 --->7635 --->7636 --->7637 --->7638 --->7639 --->764 --->7640 --->7641 --->7642 --->7643 --->7644 --->7645 --->7646 --->7647 --->7648 --->7649 --->765 --->7650 --->7651 --->7652 --->7653 --->7654 --->7655 --->7656 --->7657 --->7658 --->7659 --->766 --->7660 --->7661 --->7662 --->7663 --->7664 --->7665 --->7666 --->7667 --->7668 --->7669 --->767 --->7670 --->7671 --->7672 --->7673 --->7674 --->7675 --->7676 --->7677 --->7678 --->7679 --->768 --->7680 --->7681 --->7682 --->7683 --->7684 --->7685 --->7686 --->7687 --->7688 --->7689 --->769 --->7690 --->7691 --->7692 --->7693 --->7694 --->7695 --->7696 --->7697 --->7698 --->7699 --->77 --->770 --->7700 --->7701 --->7702 --->7703 --->7704 --->7705 --->7706 --->7707 --->7708 --->7709 --->771 --->7710 --->7711 --->7712 --->7713 --->7714 --->7715 --->7716 --->7717 --->7718 --->7719 --->772 --->7720 --->7721 --->7722 --->7723 --->7724 --->7725 --->7726 --->7727 --->7728 --->7729 --->773 --->7730 --->7731 --->7732 --->7733 --->7734 --->7735 --->7736 --->7737 --->7738 --->7739 --->774 --->7740 --->7741 --->7742 --->7743 --->7744 --->7745 --->7746 --->7747 --->7748 --->7749 --->775 --->7750 --->7751 --->7752 --->7753 --->7754 --->7755 --->7756 --->7757 --->7758 --->7759 --->776 --->7760 --->7761 --->7762 --->7763 --->7764 --->7765 --->7766 --->7767 --->7768 --->7769 --->777 --->7770 --->7771 --->7772 --->7773 --->7774 --->7775 --->7776 --->7777 --->7778 --->7779 --->778 --->7780 --->7781 --->7782 --->7783 --->7784 --->7785 --->7786 --->7787 --->7788 --->7789 --->779 --->7790 --->7791 --->7792 --->7793 --->7794 --->7795 --->7796 --->7797 --->7798 --->7799 --->78 --->780 --->7800 --->7801 --->7802 --->7803 --->7804 --->7805 --->7806 --->7807 --->7808 --->7809 --->781 --->7810 --->7811 --->7812 --->7813 --->7814 --->7815 --->7816 --->7817 --->7818 --->7819 --->782 --->7820 --->7821 --->7822 --->7823 --->7824 --->7825 --->7826 --->7827 --->7828 --->7829 --->783 --->7830 --->7831 --->7832 --->7833 --->7834 --->7835 --->7836 --->7837 --->7838 --->7839 --->784 --->7840 --->7841 --->7842 --->7843 --->7844 --->7845 --->7846 --->7847 --->7848 --->7849 --->785 --->7850 --->7851 --->7852 --->7853 --->7854 --->7855 --->7856 --->7857 --->7858 --->7859 --->786 --->7860 --->7861 --->7862 --->7863 --->7864 --->7865 --->7866 --->7867 --->7868 --->7869 --->787 --->7870 --->7871 --->7872 --->7873 --->7874 --->7875 --->7876 --->7877 --->7878 --->7879 --->788 --->7880 --->7881 --->7882 --->7883 --->7884 --->7885 --->7886 --->7887 --->7888 --->7889 --->789 --->7890 --->7891 --->7892 --->7893 --->7894 --->7895 --->7896 --->7897 --->7898 --->7899 --->79 --->790 --->7900 --->7901 --->7902 --->7903 --->7904 --->7905 --->7906 --->7907 --->7908 --->7909 --->791 --->7910 --->7911 --->7912 --->7913 --->7914 --->7915 --->7916 --->7917 --->7918 --->7919 --->792 --->7920 --->7921 --->7922 --->7923 --->7924 --->7925 --->7926 --->7927 --->7928 --->7929 --->793 --->7930 --->7931 --->7932 --->7933 --->7934 --->7935 --->7936 --->7937 --->7938 --->7939 --->794 --->7940 --->7941 --->7942 --->7943 --->7944 --->7945 --->7946 --->7947 --->7948 --->7949 --->795 --->7950 --->7951 --->7952 --->7953 --->7954 --->7955 --->7956 --->7957 --->7958 --->7959 --->796 --->7960 --->7961 --->7962 --->7963 --->7964 --->7965 --->7966 --->7967 --->7968 --->7969 --->797 --->7970 --->7971 --->7972 --->7973 --->7974 --->7975 --->7976 --->7977 --->7978 --->7979 --->798 --->7980 --->7981 --->7982 --->7983 --->7984 --->7985 --->7986 --->7987 --->7988 --->7989 --->799 --->7990 --->7991 --->7992 --->7993 --->7994 --->7995 --->7996 --->7997 --->7998 --->7999 --->8 --->80 --->800 --->8000 --->8001 --->8002 --->8003 --->8004 --->8005 --->8006 --->8007 --->8008 --->8009 --->801 --->8010 --->8011 --->8012 --->8013 --->8014 --->8015 --->8016 --->8017 --->8018 --->8019 --->802 --->8020 --->8021 --->8022 --->8023 --->8024 --->8025 --->8026 --->8027 --->8028 --->8029 --->803 --->8030 --->8031 --->8032 --->8033 --->8034 --->8035 --->8036 --->8037 --->8038 --->8039 --->804 --->8040 --->8041 --->8042 --->8043 --->8044 --->8045 --->8046 --->8047 --->8048 --->8049 --->805 --->8050 --->8051 --->8052 --->8053 --->8054 --->8055 --->8056 --->8057 --->8058 --->8059 --->806 --->8060 --->8061 --->8062 --->8063 --->8064 --->8065 --->8066 --->8067 --->8068 --->8069 --->807 --->8070 --->8071 --->8072 --->8073 --->8074 --->8075 --->8076 --->8077 --->8078 --->8079 --->808 --->8080 --->8081 --->8082 --->8083 --->8084 --->8085 --->8086 --->8087 --->8088 --->8089 --->809 --->8090 --->8091 --->8092 --->8093 --->8094 --->8095 --->8096 --->8097 --->8098 --->8099 --->81 --->810 --->8100 --->8101 --->8102 --->8103 --->8104 --->8105 --->8106 --->8107 --->8108 --->8109 --->811 --->8110 --->8111 --->8112 --->8113 --->8114 --->8115 --->8116 --->8117 --->8118 --->8119 --->812 --->8120 --->8121 --->8122 --->8123 --->8124 --->8125 --->8126 --->8127 --->8128 --->8129 --->813 --->8130 --->8131 --->8132 --->8133 --->8134 --->8135 --->8136 --->8137 --->8138 --->8139 --->814 --->8140 --->8141 --->8142 --->8143 --->8144 --->8145 --->8146 --->8147 --->8148 --->8149 --->815 --->8150 --->8151 --->8152 --->8153 --->8154 --->8155 --->8156 --->8157 --->8158 --->8159 --->816 --->8160 --->8161 --->8162 --->8163 --->8164 --->8165 --->8166 --->8167 --->8168 --->8169 --->817 --->8170 --->8171 --->8172 --->8173 --->8174 --->8175 --->8176 --->8177 --->8178 --->8179 --->818 --->8180 --->8181 --->8182 --->8183 --->8184 --->8185 --->8186 --->8187 --->8188 --->8189 --->819 --->8190 --->8191 --->8192 --->8193 --->8194 --->8195 --->8196 --->8197 --->8198 --->8199 --->82 --->820 --->8200 --->8201 --->8202 --->8203 --->8204 --->8205 --->8206 --->8207 --->8208 --->8209 --->821 --->8210 --->8211 --->8212 --->8213 --->8214 --->8215 --->8216 --->8217 --->8218 --->8219 --->822 --->8220 --->8221 --->8222 --->8223 --->8224 --->8225 --->8226 --->8227 --->8228 --->8229 --->823 --->8230 --->8231 --->8232 --->8233 --->8234 --->8235 --->8236 --->8237 --->8238 --->8239 --->824 --->8240 --->8241 --->8242 --->8243 --->8244 --->8245 --->8246 --->8247 --->8248 --->8249 --->825 --->8250 --->8251 --->8252 --->8253 --->8254 --->8255 --->8256 --->8257 --->8258 --->8259 --->826 --->8260 --->8261 --->8262 --->8263 --->8264 --->8265 --->8266 --->8267 --->8268 --->8269 --->827 --->8270 --->8271 --->8272 --->8273 --->8274 --->8275 --->8276 --->8277 --->8278 --->8279 --->828 --->8280 --->8281 --->8282 --->8283 --->8284 --->8285 --->8286 --->8287 --->8288 --->8289 --->829 --->8290 --->8291 --->8292 --->8293 --->8294 --->8295 --->8296 --->8297 --->8298 --->8299 --->83 --->830 --->8300 --->8301 --->8302 --->8303 --->8304 --->8305 --->8306 --->8307 --->8308 --->8309 --->831 --->8310 --->8311 --->8312 --->8313 --->8314 --->8315 --->8316 --->8317 --->8318 --->8319 --->832 --->8320 --->8321 --->8322 --->8323 --->8324 --->8325 --->8326 --->8327 --->8328 --->8329 --->833 --->8330 --->8331 --->8332 --->8333 --->8334 --->8335 --->8336 --->8337 --->8338 --->8339 --->834 --->8340 --->8341 --->8342 --->8343 --->8344 --->8345 --->8346 --->8347 --->8348 --->8349 --->835 --->8350 --->8351 --->8352 --->8353 --->8354 --->8355 --->8356 --->8357 --->8358 --->8359 --->836 --->8360 --->8361 --->8362 --->8363 --->8364 --->8365 --->8366 --->8367 --->8368 --->8369 --->837 --->8370 --->8371 --->8372 --->8373 --->8374 --->8375 --->8376 --->8377 --->8378 --->8379 --->838 --->8380 --->8381 --->8382 --->8383 --->8384 --->8385 --->8386 --->8387 --->8388 --->8389 --->839 --->8390 --->8391 --->8392 --->8393 --->8394 --->8395 --->8396 --->8397 --->8398 --->8399 --->84 --->840 --->8400 --->8401 --->8402 --->8403 --->8404 --->8405 --->8406 --->8407 --->8408 --->8409 --->841 --->8410 --->8411 --->8412 --->8413 --->8414 --->8415 --->8416 --->8417 --->8418 --->8419 --->842 --->8420 --->8421 --->8422 --->8423 --->8424 --->8425 --->8426 --->8427 --->8428 --->8429 --->843 --->8430 --->8431 --->8432 --->8433 --->8434 --->8435 --->8436 --->8437 --->8438 --->8439 --->844 --->8440 --->8441 --->8442 --->8443 --->8444 --->8445 --->8446 --->8447 --->8448 --->8449 --->845 --->8450 --->8451 --->8452 --->8453 --->8454 --->8455 --->8456 --->8457 --->8458 --->8459 --->846 --->8460 --->8461 --->8462 --->8463 --->8464 --->8465 --->8466 --->8467 --->8468 --->8469 --->847 --->8470 --->8471 --->8472 --->8473 --->8474 --->8475 --->8476 --->8477 --->8478 --->8479 --->848 --->8480 --->8481 --->8482 --->8483 --->8484 --->8485 --->8486 --->8487 --->8488 --->8489 --->849 --->8490 --->8491 --->8492 --->8493 --->8494 --->8495 --->8496 --->8497 --->8498 --->8499 --->85 --->850 --->8500 --->8501 --->8502 --->8503 --->8504 --->8505 --->8506 --->8507 --->8508 --->8509 --->851 --->8510 --->8511 --->8512 --->8513 --->8514 --->8515 --->8516 --->8517 --->8518 --->8519 --->852 --->8520 --->8521 --->8522 --->8523 --->8524 --->8525 --->8526 --->8527 --->8528 --->8529 --->853 --->8530 --->8531 --->8532 --->8533 --->8534 --->8535 --->8536 --->8537 --->8538 --->8539 --->854 --->8540 --->8541 --->8542 --->8543 --->8544 --->8545 --->8546 --->8547 --->8548 --->8549 --->855 --->8550 --->8551 --->8552 --->8553 --->8554 --->8555 --->8556 --->8557 --->8558 --->8559 --->856 --->8560 --->8561 --->8562 --->8563 --->8564 --->8565 --->8566 --->8567 --->8568 --->8569 --->857 --->8570 --->8571 --->8572 --->8573 --->8574 --->8575 --->8576 --->8577 --->8578 --->8579 --->858 --->8580 --->8581 --->8582 --->8583 --->8584 --->8585 --->8586 --->8587 --->8588 --->8589 --->859 --->8590 --->8591 --->8592 --->8593 --->8594 --->8595 --->8596 --->8597 --->8598 --->8599 --->86 --->860 --->8600 --->8601 --->8602 --->8603 --->8604 --->8605 --->8606 --->8607 --->8608 --->8609 --->861 --->8610 --->8611 --->8612 --->8613 --->8614 --->8615 --->8616 --->8617 --->8618 --->8619 --->862 --->8620 --->8621 --->8622 --->8623 --->8624 --->8625 --->8626 --->8627 --->8628 --->8629 --->863 --->8630 --->8631 --->8632 --->8633 --->8634 --->8635 --->8636 --->8637 --->8638 --->8639 --->864 --->8640 --->8641 --->8642 --->8643 --->8644 --->8645 --->8646 --->8647 --->8648 --->8649 --->865 --->8650 --->8651 --->8652 --->8653 --->8654 --->8655 --->8656 --->8657 --->8658 --->8659 --->866 --->8660 --->8661 --->8662 --->8663 --->8664 --->8665 --->8666 --->8667 --->8668 --->8669 --->867 --->8670 --->8671 --->8672 --->8673 --->8674 --->8675 --->8676 --->8677 --->8678 --->8679 --->868 --->8680 --->8681 --->8682 --->8683 --->8684 --->8685 --->8686 --->8687 --->8688 --->8689 --->869 --->8690 --->8691 --->8692 --->8693 --->8694 --->8695 --->8696 --->8697 --->8698 --->8699 --->87 --->870 --->8700 --->8701 --->8702 --->8703 --->8704 --->8705 --->8706 --->8707 --->8708 --->8709 --->871 --->8710 --->8711 --->8712 --->8713 --->8714 --->8715 --->8716 --->8717 --->8718 --->8719 --->872 --->8720 --->8721 --->8722 --->8723 --->8724 --->8725 --->8726 --->8727 --->8728 --->8729 --->873 --->8730 --->8731 --->8732 --->8733 --->8734 --->8735 --->8736 --->8737 --->8738 --->8739 --->874 --->8740 --->8741 --->8742 --->8743 --->8744 --->8745 --->8746 --->8747 --->8748 --->8749 --->875 --->8750 --->8751 --->8752 --->8753 --->8754 --->8755 --->8756 --->8757 --->8758 --->8759 --->876 --->8760 --->8761 --->8762 --->8763 --->8764 --->8765 --->8766 --->8767 --->8768 --->8769 --->877 --->8770 --->8771 --->8772 --->8773 --->8774 --->8775 --->8776 --->8777 --->8778 --->8779 --->878 --->8780 --->8781 --->8782 --->8783 --->8784 --->8785 --->8786 --->8787 --->8788 --->8789 --->879 --->8790 --->8791 --->8792 --->8793 --->8794 --->8795 --->8796 --->8797 --->8798 --->8799 --->88 --->880 --->8800 --->8801 --->8802 --->8803 --->8804 --->8805 --->8806 --->8807 --->8808 --->8809 --->881 --->8810 --->8811 --->8812 --->8813 --->8814 --->8815 --->8816 --->8817 --->8818 --->8819 --->882 --->8820 --->8821 --->8822 --->8823 --->8824 --->8825 --->8826 --->8827 --->8828 --->8829 --->883 --->8830 --->8831 --->8832 --->8833 --->8834 --->8835 --->8836 --->8837 --->8838 --->8839 --->884 --->8840 --->8841 --->8842 --->8843 --->8844 --->8845 --->8846 --->8847 --->8848 --->8849 --->885 --->8850 --->8851 --->8852 --->8853 --->8854 --->8855 --->8856 --->8857 --->8858 --->8859 --->886 --->8860 --->8861 --->8862 --->8863 --->8864 --->8865 --->8866 --->8867 --->8868 --->8869 --->887 --->8870 --->8871 --->8872 --->8873 --->8874 --->8875 --->8876 --->8877 --->8878 --->8879 --->888 --->8880 --->8881 --->8882 --->8883 --->8884 --->8885 --->8886 --->8887 --->8888 --->8889 --->889 --->8890 --->8891 --->8892 --->8893 --->8894 --->8895 --->8896 --->8897 --->8898 --->8899 --->89 --->890 --->8900 --->8901 --->8902 --->8903 --->8904 --->8905 --->8906 --->8907 --->8908 --->8909 --->891 --->8910 --->8911 --->8912 --->8913 --->8914 --->8915 --->8916 --->8917 --->8918 --->8919 --->892 --->8920 --->8921 --->8922 --->8923 --->8924 --->8925 --->8926 --->8927 --->8928 --->8929 --->893 --->8930 --->8931 --->8932 --->8933 --->8934 --->8935 --->8936 --->8937 --->8938 --->8939 --->894 --->8940 --->8941 --->8942 --->8943 --->8944 --->8945 --->8946 --->8947 --->8948 --->8949 --->895 --->8950 --->8951 --->8952 --->8953 --->8954 --->8955 --->8956 --->8957 --->8958 --->8959 --->896 --->8960 --->8961 --->8962 --->8963 --->8964 --->8965 --->8966 --->8967 --->8968 --->8969 --->897 --->8970 --->8971 --->8972 --->8973 --->8974 --->8975 --->8976 --->8977 --->8978 --->8979 --->898 --->8980 --->8981 --->8982 --->8983 --->8984 --->8985 --->8986 --->8987 --->8988 --->8989 --->899 --->8990 --->8991 --->8992 --->8993 --->8994 --->8995 --->8996 --->8997 --->8998 --->8999 --->9 --->90 --->900 --->9000 --->9001 --->9002 --->9003 --->9004 --->9005 --->9006 --->9007 --->9008 --->9009 --->901 --->9010 --->9011 --->9012 --->9013 --->9014 --->9015 --->9016 --->9017 --->9018 --->9019 --->902 --->9020 --->9021 --->9022 --->9023 --->9024 --->9025 --->9026 --->9027 --->9028 --->9029 --->903 --->9030 --->9031 --->9032 --->9033 --->9034 --->9035 --->9036 --->9037 --->9038 --->9039 --->904 --->9040 --->9041 --->9042 --->9043 --->9044 --->9045 --->9046 --->9047 --->9048 --->9049 --->905 --->9050 --->9051 --->9052 --->9053 --->9054 --->9055 --->9056 --->9057 --->9058 --->9059 --->906 --->9060 --->9061 --->9062 --->9063 --->9064 --->9065 --->9066 --->9067 --->9068 --->9069 --->907 --->9070 --->9071 --->9072 --->9073 --->9074 --->9075 --->9076 --->9077 --->9078 --->9079 --->908 --->9080 --->9081 --->9082 --->9083 --->9084 --->9085 --->9086 --->9087 --->9088 --->9089 --->909 --->9090 --->9091 --->9092 --->9093 --->9094 --->9095 --->9096 --->9097 --->9098 --->9099 --->91 --->910 --->9100 --->9101 --->9102 --->9103 --->9104 --->9105 --->9106 --->9107 --->9108 --->9109 --->911 --->9110 --->9111 --->9112 --->9113 --->9114 --->9115 --->9116 --->9117 --->9118 --->9119 --->912 --->9120 --->9121 --->9122 --->9123 --->9124 --->9125 --->9126 --->9127 --->9128 --->9129 --->913 --->9130 --->9131 --->9132 --->9133 --->9134 --->9135 --->9136 --->9137 --->9138 --->9139 --->914 --->9140 --->9141 --->9142 --->9143 --->9144 --->9145 --->9146 --->9147 --->9148 --->9149 --->915 --->9150 --->9151 --->9152 --->9153 --->9154 --->9155 --->9156 --->9157 --->9158 --->9159 --->916 --->9160 --->9161 --->9162 --->9163 --->9164 --->9165 --->9166 --->9167 --->9168 --->9169 --->917 --->9170 --->9171 --->9172 --->9173 --->9174 --->9175 --->9176 --->9177 --->9178 --->9179 --->918 --->9180 --->9181 --->9182 --->9183 --->9184 --->9185 --->9186 --->9187 --->9188 --->9189 --->919 --->9190 --->9191 --->9192 --->9193 --->9194 --->9195 --->9196 --->9197 --->9198 --->9199 --->92 --->920 --->9200 --->9201 --->9202 --->9203 --->9204 --->9205 --->9206 --->9207 --->9208 --->9209 --->921 --->9210 --->9211 --->9212 --->9213 --->9214 --->9215 --->9216 --->9217 --->9218 --->9219 --->922 --->9220 --->9221 --->9222 --->9223 --->9224 --->9225 --->9226 --->9227 --->9228 --->9229 --->923 --->9230 --->9231 --->9232 --->9233 --->9234 --->9235 --->9236 --->9237 --->9238 --->9239 --->924 --->9240 --->9241 --->9242 --->9243 --->9244 --->9245 --->9246 --->9247 --->9248 --->9249 --->925 --->9250 --->9251 --->9252 --->9253 --->9254 --->9255 --->9256 --->9257 --->9258 --->9259 --->926 --->9260 --->9261 --->9262 --->9263 --->9264 --->9265 --->9266 --->9267 --->9268 --->9269 --->927 --->9270 --->9271 --->9272 --->9273 --->9274 --->9275 --->9276 --->9277 --->9278 --->9279 --->928 --->9280 --->9281 --->9282 --->9283 --->9284 --->9285 --->9286 --->9287 --->9288 --->9289 --->929 --->9290 --->9291 --->9292 --->9293 --->9294 --->9295 --->9296 --->9297 --->9298 --->9299 --->93 --->930 --->9300 --->9301 --->9302 --->9303 --->9304 --->9305 --->9306 --->9307 --->9308 --->9309 --->931 --->9310 --->9311 --->9312 --->9313 --->9314 --->9315 --->9316 --->9317 --->9318 --->9319 --->932 --->9320 --->9321 --->9322 --->9323 --->9324 --->9325 --->9326 --->9327 --->9328 --->9329 --->933 --->9330 --->9331 --->9332 --->9333 --->9334 --->9335 --->9336 --->9337 --->9338 --->9339 --->934 --->9340 --->9341 --->9342 --->9343 --->9344 --->9345 --->9346 --->9347 --->9348 --->9349 --->935 --->9350 --->9351 --->9352 --->9353 --->9354 --->9355 --->9356 --->9357 --->9358 --->9359 --->936 --->9360 --->9361 --->9362 --->9363 --->9364 --->9365 --->9366 --->9367 --->9368 --->9369 --->937 --->9370 --->9371 --->9372 --->9373 --->9374 --->9375 --->9376 --->9377 --->9378 --->9379 --->938 --->9380 --->9381 --->9382 --->9383 --->9384 --->9385 --->9386 --->9387 --->9388 --->9389 --->939 --->9390 --->9391 --->9392 --->9393 --->9394 --->9395 --->9396 --->9397 --->9398 --->9399 --->94 --->940 --->9400 --->9401 --->9402 --->9403 --->9404 --->9405 --->9406 --->9407 --->9408 --->9409 --->941 --->9410 --->9411 --->9412 --->9413 --->9414 --->9415 --->9416 --->9417 --->9418 --->9419 --->942 --->9420 --->9421 --->9422 --->9423 --->9424 --->9425 --->9426 --->9427 --->9428 --->9429 --->943 --->9430 --->9431 --->9432 --->9433 --->9434 --->9435 --->9436 --->9437 --->9438 --->9439 --->944 --->9440 --->9441 --->9442 --->9443 --->9444 --->9445 --->9446 --->9447 --->9448 --->9449 --->945 --->9450 --->9451 --->9452 --->9453 --->9454 --->9455 --->9456 --->9457 --->9458 --->9459 --->946 --->9460 --->9461 --->9462 --->9463 --->9464 --->9465 --->9466 --->9467 --->9468 --->9469 --->947 --->9470 --->9471 --->9472 --->9473 --->9474 --->9475 --->9476 --->9477 --->9478 --->9479 --->948 --->9480 --->9481 --->9482 --->9483 --->9484 --->9485 --->9486 --->9487 --->9488 --->9489 --->949 --->9490 --->9491 --->9492 --->9493 --->9494 --->9495 --->9496 --->9497 --->9498 --->9499 --->95 --->950 --->9500 --->9501 --->9502 --->9503 --->9504 --->9505 --->9506 --->9507 --->9508 --->9509 --->951 --->9510 --->9511 --->9512 --->9513 --->9514 --->9515 --->9516 --->9517 --->9518 --->9519 --->952 --->9520 --->9521 --->9522 --->9523 --->9524 --->9525 --->9526 --->9527 --->9528 --->9529 --->953 --->9530 --->9531 --->9532 --->9533 --->9534 --->9535 --->9536 --->9537 --->9538 --->9539 --->954 --->9540 --->9541 --->9542 --->9543 --->9544 --->9545 --->9546 --->9547 --->9548 --->9549 --->955 --->9550 --->9551 --->9552 --->9553 --->9554 --->9555 --->9556 --->9557 --->9558 --->9559 --->956 --->9560 --->9561 --->9562 --->9563 --->9564 --->9565 --->9566 --->9567 --->9568 --->9569 --->957 --->9570 --->9571 --->9572 --->9573 --->9574 --->9575 --->9576 --->9577 --->9578 --->9579 --->958 --->9580 --->9581 --->9582 --->9583 --->9584 --->9585 --->9586 --->9587 --->9588 --->9589 --->959 --->9590 --->9591 --->9592 --->9593 --->9594 --->9595 --->9596 --->9597 --->9598 --->9599 --->96 --->960 --->9600 --->9601 --->9602 --->9603 --->9604 --->9605 --->9606 --->9607 --->9608 --->9609 --->961 --->9610 --->9611 --->9612 --->9613 --->9614 --->9615 --->9616 --->9617 --->9618 --->9619 --->962 --->9620 --->9621 --->9622 --->9623 --->9624 --->9625 --->9626 --->9627 --->9628 --->9629 --->963 --->9630 --->9631 --->9632 --->9633 --->9634 --->9635 --->9636 --->9637 --->9638 --->9639 --->964 --->9640 --->9641 --->9642 --->9643 --->9644 --->9645 --->9646 --->9647 --->9648 --->9649 --->965 --->9650 --->9651 --->9652 --->9653 --->9654 --->9655 --->9656 --->9657 --->9658 --->9659 --->966 --->9660 --->9661 --->9662 --->9663 --->9664 --->9665 --->9666 --->9667 --->9668 --->9669 --->967 --->9670 --->9671 --->9672 --->9673 --->9674 --->9675 --->9676 --->9677 --->9678 --->9679 --->968 --->9680 --->9681 --->9682 --->9683 --->9684 --->9685 --->9686 --->9687 --->9688 --->9689 --->969 --->9690 --->9691 --->9692 --->9693 --->9694 --->9695 --->9696 --->9697 --->9698 --->9699 --->97 --->970 --->9700 --->9701 --->9702 --->9703 --->9704 --->9705 --->9706 --->9707 --->9708 --->9709 --->971 --->9710 --->9711 --->9712 --->9713 --->9714 --->9715 --->9716 --->9717 --->9718 --->9719 --->972 --->9720 --->9721 --->9722 --->9723 --->9724 --->9725 --->9726 --->9727 --->9728 --->9729 --->973 --->9730 --->9731 --->9732 --->9733 --->9734 --->9735 --->9736 --->9737 --->9738 --->9739 --->974 --->9740 --->9741 --->9742 --->9743 --->9744 --->9745 --->9746 --->9747 --->9748 --->9749 --->975 --->9750 --->9751 --->9752 --->9753 --->9754 --->9755 --->9756 --->9757 --->9758 --->9759 --->976 --->9760 --->9761 --->9762 --->9763 --->9764 --->9765 --->9766 --->9767 --->9768 --->9769 --->977 --->9770 --->9771 --->9772 --->9773 --->9774 --->9775 --->9776 --->9777 --->9778 --->9779 --->978 --->9780 --->9781 --->9782 --->9783 --->9784 --->9785 --->9786 --->9787 --->9788 --->9789 --->979 --->9790 --->9791 --->9792 --->9793 --->9794 --->9795 --->9796 --->9797 --->9798 --->9799 --->98 --->980 --->9800 --->9801 --->9802 --->9803 --->9804 --->9805 --->9806 --->9807 --->9808 --->9809 --->981 --->9810 --->9811 --->9812 --->9813 --->9814 --->9815 --->9816 --->9817 --->9818 --->9819 --->982 --->9820 --->9821 --->9822 --->9823 --->9824 --->9825 --->9826 --->9827 --->9828 --->9829 --->983 --->9830 --->9831 --->9832 --->9833 --->9834 --->9835 --->9836 --->9837 --->9838 --->9839 --->984 --->9840 --->9841 --->9842 --->9843 --->9844 --->9845 --->9846 --->9847 --->9848 --->9849 --->985 --->9850 --->9851 --->9852 --->9853 --->9854 --->9855 --->9856 --->9857 --->9858 --->9859 --->986 --->9860 --->9861 --->9862 --->9863 --->9864 --->9865 --->9866 --->9867 --->9868 --->9869 --->987 --->9870 --->9871 --->9872 --->9873 --->9874 --->9875 --->9876 --->9877 --->9878 --->9879 --->988 --->9880 --->9881 --->9882 --->9883 --->9884 --->9885 --->9886 --->9887 --->9888 --->9889 --->989 --->9890 --->9891 --->9892 --->9893 --->9894 --->9895 --->9896 --->9897 --->9898 --->9899 --->99 --->990 --->9900 --->9901 --->9902 --->9903 --->9904 --->9905 --->9906 --->9907 --->9908 --->9909 --->991 --->9910 --->9911 --->9912 --->9913 --->9914 --->9915 --->9916 --->9917 --->9918 --->9919 --->992 --->9920 --->9921 --->9922 --->9923 --->9924 --->9925 --->9926 --->9927 --->9928 --->9929 --->993 --->9930 --->9931 --->9932 --->9933 --->9934 --->9935 --->9936 --->9937 --->9938 --->9939 --->994 --->9940 --->9941 --->9942 --->9943 --->9944 --->9945 --->9946 --->9947 --->9948 --->9949 --->995 --->9950 --->9951 --->9952 --->9953 --->9954 --->9955 --->9956 --->9957 --->9958 --->9959 --->996 --->9960 --->9961 --->9962 --->9963 --->9964 --->9965 --->9966 --->9967 --->9968 --->9969 --->997 --->9970 --->9971 --->9972 --->9973 --->9974 --->9975 --->9976 --->9977 --->9978 --->9979 --->998 --->9980 --->9981 --->9982 --->9983 --->9984 --->9985 --->9986 --->9987 --->9988 --->9989 --->999 --->9990 --->9991 --->9992 --->9993 --->9994 --->9995 --->9996 --->9997 --->9998 --->9999 -0--> -1--> -10--> -100--> -1000--> -10000--> -1001--> -1002--> -1003--> -1004--> -1005--> -1006--> -1007--> -1008--> -1009--> -101--> -1010--> -1011--> -1012--> -1013--> -1014--> -1015--> -1016--> -1017--> -1018--> -1019--> -102--> -1020--> -1021--> -1022--> -1023--> -1024--> -1025--> -1026--> -1027--> -1028--> -1029--> -103--> -1030--> -1031--> -1032--> -1033--> -1034--> -1035--> -1036--> -1037--> -1038--> -1039--> -104--> -1040--> -1041--> -1042--> -1043--> -1044--> -1045--> -1046--> -1047--> -1048--> -1049--> -105--> -1050--> -1051--> -1052--> -1053--> -1054--> -1055--> -1056--> -1057--> -1058--> -1059--> -106--> -1060--> -1061--> -1062--> -1063--> -1064--> -1065--> -1066--> -1067--> -1068--> -1069--> -107--> -1070--> -1071--> -1072--> -1073--> -1074--> -1075--> -1076--> -1077--> -1078--> -1079--> -108--> -1080--> -1081--> -1082--> -1083--> -1084--> -1085--> -1086--> -1087--> -1088--> -1089--> -109--> -1090--> -1091--> -1092--> -1093--> -1094--> -1095--> -1096--> -1097--> -1098--> -1099--> -11--> -110--> -1100--> -1101--> -1102--> -1103--> -1104--> -1105--> -1106--> -1107--> -1108--> -1109--> -111--> -1110--> -1111--> -1112--> -1113--> -1114--> -1115--> -1116--> -1117--> -1118--> -1119--> -112--> -1120--> -1121--> -1122--> -1123--> -1124--> -1125--> -1126--> -1127--> -1128--> -1129--> -113--> -1130--> -1131--> -1132--> -1133--> -1134--> -1135--> -1136--> -1137--> -1138--> -1139--> -114--> -1140--> -1141--> -1142--> -1143--> -1144--> -1145--> -1146--> -1147--> -1148--> -1149--> -115--> -1150--> -1151--> -1152--> -1153--> -1154--> -1155--> -1156--> -1157--> -1158--> -1159--> -116--> -1160--> -1161--> -1162--> -1163--> -1164--> -1165--> -1166--> -1167--> -1168--> -1169--> -117--> -1170--> -1171--> -1172--> -1173--> -1174--> -1175--> -1176--> -1177--> -1178--> -1179--> -118--> -1180--> -1181--> -1182--> -1183--> -1184--> -1185--> -1186--> -1187--> -1188--> -1189--> -119--> -1190--> -1191--> -1192--> -1193--> -1194--> -1195--> -1196--> -1197--> -1198--> -1199--> -12--> -120--> -1200--> -1201--> -1202--> -1203--> -1204--> -1205--> -1206--> -1207--> -1208--> -1209--> -121--> -1210--> -1211--> -1212--> -1213--> -1214--> -1215--> -1216--> -1217--> -1218--> -1219--> -122--> -1220--> -1221--> -1222--> -1223--> -1224--> -1225--> -1226--> -1227--> -1228--> -1229--> -123--> -1230--> -1231--> -1232--> -1233--> -1234--> -1235--> -1236--> -1237--> -1238--> -1239--> -124--> -1240--> -1241--> -1242--> -1243--> -1244--> -1245--> -1246--> -1247--> -1248--> -1249--> -125--> -1250--> -1251--> -1252--> -1253--> -1254--> -1255--> -1256--> -1257--> -1258--> -1259--> -126--> -1260--> -1261--> -1262--> -1263--> -1264--> -1265--> -1266--> -1267--> -1268--> -1269--> -127--> -1270--> -1271--> -1272--> -1273--> -1274--> -1275--> -1276--> -1277--> -1278--> -1279--> -128--> -1280--> -1281--> -1282--> -1283--> -1284--> -1285--> -1286--> -1287--> -1288--> -1289--> -129--> -1290--> -1291--> -1292--> -1293--> -1294--> -1295--> -1296--> -1297--> -1298--> -1299--> -13--> -130--> -1300--> -1301--> -1302--> -1303--> -1304--> -1305--> -1306--> -1307--> -1308--> -1309--> -131--> -1310--> -1311--> -1312--> -1313--> -1314--> -1315--> -1316--> -1317--> -1318--> -1319--> -132--> -1320--> -1321--> -1322--> -1323--> -1324--> -1325--> -1326--> -1327--> -1328--> -1329--> -133--> -1330--> -1331--> -1332--> -1333--> -1334--> -1335--> -1336--> -1337--> -1338--> -1339--> -134--> -1340--> -1341--> -1342--> -1343--> -1344--> -1345--> -1346--> -1347--> -1348--> -1349--> -135--> -1350--> -1351--> -1352--> -1353--> -1354--> -1355--> -1356--> -1357--> -1358--> -1359--> -136--> -1360--> -1361--> -1362--> -1363--> -1364--> -1365--> -1366--> -1367--> -1368--> -1369--> -137--> -1370--> -1371--> -1372--> -1373--> -1374--> -1375--> -1376--> -1377--> -1378--> -1379--> -138--> -1380--> -1381--> -1382--> -1383--> -1384--> -1385--> -1386--> -1387--> -1388--> -1389--> -139--> -1390--> -1391--> -1392--> -1393--> -1394--> -1395--> -1396--> -1397--> -1398--> -1399--> -14--> -140--> -1400--> -1401--> -1402--> -1403--> -1404--> -1405--> -1406--> -1407--> -1408--> -1409--> -141--> -1410--> -1411--> -1412--> -1413--> -1414--> -1415--> -1416--> -1417--> -1418--> -1419--> -142--> -1420--> -1421--> -1422--> -1423--> -1424--> -1425--> -1426--> -1427--> -1428--> -1429--> -143--> -1430--> -1431--> -1432--> -1433--> -1434--> -1435--> -1436--> -1437--> -1438--> -1439--> -144--> -1440--> -1441--> -1442--> -1443--> -1444--> -1445--> -1446--> -1447--> -1448--> -1449--> -145--> -1450--> -1451--> -1452--> -1453--> -1454--> -1455--> -1456--> -1457--> -1458--> -1459--> -146--> -1460--> -1461--> -1462--> -1463--> -1464--> -1465--> -1466--> -1467--> -1468--> -1469--> -147--> -1470--> -1471--> -1472--> -1473--> -1474--> -1475--> -1476--> -1477--> -1478--> -1479--> -148--> -1480--> -1481--> -1482--> -1483--> -1484--> -1485--> -1486--> -1487--> -1488--> -1489--> -149--> -1490--> -1491--> -1492--> -1493--> -1494--> -1495--> -1496--> -1497--> -1498--> -1499--> -15--> -150--> -1500--> -1501--> -1502--> -1503--> -1504--> -1505--> -1506--> -1507--> -1508--> -1509--> -151--> -1510--> -1511--> -1512--> -1513--> -1514--> -1515--> -1516--> -1517--> -1518--> -1519--> -152--> -1520--> -1521--> -1522--> -1523--> -1524--> -1525--> -1526--> -1527--> -1528--> -1529--> -153--> -1530--> -1531--> -1532--> -1533--> -1534--> -1535--> -1536--> -1537--> -1538--> -1539--> -154--> -1540--> -1541--> -1542--> -1543--> -1544--> -1545--> -1546--> -1547--> -1548--> -1549--> -155--> -1550--> -1551--> -1552--> -1553--> -1554--> -1555--> -1556--> -1557--> -1558--> -1559--> -156--> -1560--> -1561--> -1562--> -1563--> -1564--> -1565--> -1566--> -1567--> -1568--> -1569--> -157--> -1570--> -1571--> -1572--> -1573--> -1574--> -1575--> -1576--> -1577--> -1578--> -1579--> -158--> -1580--> -1581--> -1582--> -1583--> -1584--> -1585--> -1586--> -1587--> -1588--> -1589--> -159--> -1590--> -1591--> -1592--> -1593--> -1594--> -1595--> -1596--> -1597--> -1598--> -1599--> -16--> -160--> -1600--> -1601--> -1602--> -1603--> -1604--> -1605--> -1606--> -1607--> -1608--> -1609--> -161--> -1610--> -1611--> -1612--> -1613--> -1614--> -1615--> -1616--> -1617--> -1618--> -1619--> -162--> -1620--> -1621--> -1622--> -1623--> -1624--> -1625--> -1626--> -1627--> -1628--> -1629--> -163--> -1630--> -1631--> -1632--> -1633--> -1634--> -1635--> -1636--> -1637--> -1638--> -1639--> -164--> -1640--> -1641--> -1642--> -1643--> -1644--> -1645--> -1646--> -1647--> -1648--> -1649--> -165--> -1650--> -1651--> -1652--> -1653--> -1654--> -1655--> -1656--> -1657--> -1658--> -1659--> -166--> -1660--> -1661--> -1662--> -1663--> -1664--> -1665--> -1666--> -1667--> -1668--> -1669--> -167--> -1670--> -1671--> -1672--> -1673--> -1674--> -1675--> -1676--> -1677--> -1678--> -1679--> -168--> -1680--> -1681--> -1682--> -1683--> -1684--> -1685--> -1686--> -1687--> -1688--> -1689--> -169--> -1690--> -1691--> -1692--> -1693--> -1694--> -1695--> -1696--> -1697--> -1698--> -1699--> -17--> -170--> -1700--> -1701--> -1702--> -1703--> -1704--> -1705--> -1706--> -1707--> -1708--> -1709--> -171--> -1710--> -1711--> -1712--> -1713--> -1714--> -1715--> -1716--> -1717--> -1718--> -1719--> -172--> -1720--> -1721--> -1722--> -1723--> -1724--> -1725--> -1726--> -1727--> -1728--> -1729--> -173--> -1730--> -1731--> -1732--> -1733--> -1734--> -1735--> -1736--> -1737--> -1738--> -1739--> -174--> -1740--> -1741--> -1742--> -1743--> -1744--> -1745--> -1746--> -1747--> -1748--> -1749--> -175--> -1750--> -1751--> -1752--> -1753--> -1754--> -1755--> -1756--> -1757--> -1758--> -1759--> -176--> -1760--> -1761--> -1762--> -1763--> -1764--> -1765--> -1766--> -1767--> -1768--> -1769--> -177--> -1770--> -1771--> -1772--> -1773--> -1774--> -1775--> -1776--> -1777--> -1778--> -1779--> -178--> -1780--> -1781--> -1782--> -1783--> -1784--> -1785--> -1786--> -1787--> -1788--> -1789--> -179--> -1790--> -1791--> -1792--> -1793--> -1794--> -1795--> -1796--> -1797--> -1798--> -1799--> -18--> -180--> -1800--> -1801--> -1802--> -1803--> -1804--> -1805--> -1806--> -1807--> -1808--> -1809--> -181--> -1810--> -1811--> -1812--> -1813--> -1814--> -1815--> -1816--> -1817--> -1818--> -1819--> -182--> -1820--> -1821--> -1822--> -1823--> -1824--> -1825--> -1826--> -1827--> -1828--> -1829--> -183--> -1830--> -1831--> -1832--> -1833--> -1834--> -1835--> -1836--> -1837--> -1838--> -1839--> -184--> -1840--> -1841--> -1842--> -1843--> -1844--> -1845--> -1846--> -1847--> -1848--> -1849--> -185--> -1850--> -1851--> -1852--> -1853--> -1854--> -1855--> -1856--> -1857--> -1858--> -1859--> -186--> -1860--> -1861--> -1862--> -1863--> -1864--> -1865--> -1866--> -1867--> -1868--> -1869--> -187--> -1870--> -1871--> -1872--> -1873--> -1874--> -1875--> -1876--> -1877--> -1878--> -1879--> -188--> -1880--> -1881--> -1882--> -1883--> -1884--> -1885--> -1886--> -1887--> -1888--> -1889--> -189--> -1890--> -1891--> -1892--> -1893--> -1894--> -1895--> -1896--> -1897--> -1898--> -1899--> -19--> -190--> -1900--> -1901--> -1902--> -1903--> -1904--> -1905--> -1906--> -1907--> -1908--> -1909--> -191--> -1910--> -1911--> -1912--> -1913--> -1914--> -1915--> -1916--> -1917--> -1918--> -1919--> -192--> -1920--> -1921--> -1922--> -1923--> -1924--> -1925--> -1926--> -1927--> -1928--> -1929--> -193--> -1930--> -1931--> -1932--> -1933--> -1934--> -1935--> -1936--> -1937--> -1938--> -1939--> -194--> -1940--> -1941--> -1942--> -1943--> -1944--> -1945--> -1946--> -1947--> -1948--> -1949--> -195--> -1950--> -1951--> -1952--> -1953--> -1954--> -1955--> -1956--> -1957--> -1958--> -1959--> -196--> -1960--> -1961--> -1962--> -1963--> -1964--> -1965--> -1966--> -1967--> -1968--> -1969--> -197--> -1970--> -1971--> -1972--> -1973--> -1974--> -1975--> -1976--> -1977--> -1978--> -1979--> -198--> -1980--> -1981--> -1982--> -1983--> -1984--> -1985--> -1986--> -1987--> -1988--> -1989--> -199--> -1990--> -1991--> -1992--> -1993--> -1994--> -1995--> -1996--> -1997--> -1998--> -1999--> -2--> -20--> -200--> -2000--> -2001--> -2002--> -2003--> -2004--> -2005--> -2006--> -2007--> -2008--> -2009--> -201--> -2010--> -2011--> -2012--> -2013--> -2014--> -2015--> -2016--> -2017--> -2018--> -2019--> -202--> -2020--> -2021--> -2022--> -2023--> -2024--> -2025--> -2026--> -2027--> -2028--> -2029--> -203--> -2030--> -2031--> -2032--> -2033--> -2034--> -2035--> -2036--> -2037--> -2038--> -2039--> -204--> -2040--> -2041--> -2042--> -2043--> -2044--> -2045--> -2046--> -2047--> -2048--> -2049--> -205--> -2050--> -2051--> -2052--> -2053--> -2054--> -2055--> -2056--> -2057--> -2058--> -2059--> -206--> -2060--> -2061--> -2062--> -2063--> -2064--> -2065--> -2066--> -2067--> -2068--> -2069--> -207--> -2070--> -2071--> -2072--> -2073--> -2074--> -2075--> -2076--> -2077--> -2078--> -2079--> -208--> -2080--> -2081--> -2082--> -2083--> -2084--> -2085--> -2086--> -2087--> -2088--> -2089--> -209--> -2090--> -2091--> -2092--> -2093--> -2094--> -2095--> -2096--> -2097--> -2098--> -2099--> -21--> -210--> -2100--> -2101--> -2102--> -2103--> -2104--> -2105--> -2106--> -2107--> -2108--> -2109--> -211--> -2110--> -2111--> -2112--> -2113--> -2114--> -2115--> -2116--> -2117--> -2118--> -2119--> -212--> -2120--> -2121--> -2122--> -2123--> -2124--> -2125--> -2126--> -2127--> -2128--> -2129--> -213--> -2130--> -2131--> -2132--> -2133--> -2134--> -2135--> -2136--> -2137--> -2138--> -2139--> -214--> -2140--> -2141--> -2142--> -2143--> -2144--> -2145--> -2146--> -2147--> -2148--> -2149--> -215--> -2150--> -2151--> -2152--> -2153--> -2154--> -2155--> -2156--> -2157--> -2158--> -2159--> -216--> -2160--> -2161--> -2162--> -2163--> -2164--> -2165--> -2166--> -2167--> -2168--> -2169--> -217--> -2170--> -2171--> -2172--> -2173--> -2174--> -2175--> -2176--> -2177--> -2178--> -2179--> -218--> -2180--> -2181--> -2182--> -2183--> -2184--> -2185--> -2186--> -2187--> -2188--> -2189--> -219--> -2190--> -2191--> -2192--> -2193--> -2194--> -2195--> -2196--> -2197--> -2198--> -2199--> -22--> -220--> -2200--> -2201--> -2202--> -2203--> -2204--> -2205--> -2206--> -2207--> -2208--> -2209--> -221--> -2210--> -2211--> -2212--> -2213--> -2214--> -2215--> -2216--> -2217--> -2218--> -2219--> -222--> -2220--> -2221--> -2222--> -2223--> -2224--> -2225--> -2226--> -2227--> -2228--> -2229--> -223--> -2230--> -2231--> -2232--> -2233--> -2234--> -2235--> -2236--> -2237--> -2238--> -2239--> -224--> -2240--> -2241--> -2242--> -2243--> -2244--> -2245--> -2246--> -2247--> -2248--> -2249--> -225--> -2250--> -2251--> -2252--> -2253--> -2254--> -2255--> -2256--> -2257--> -2258--> -2259--> -226--> -2260--> -2261--> -2262--> -2263--> -2264--> -2265--> -2266--> -2267--> -2268--> -2269--> -227--> -2270--> -2271--> -2272--> -2273--> -2274--> -2275--> -2276--> -2277--> -2278--> -2279--> -228--> -2280--> -2281--> -2282--> -2283--> -2284--> -2285--> -2286--> -2287--> -2288--> -2289--> -229--> -2290--> -2291--> -2292--> -2293--> -2294--> -2295--> -2296--> -2297--> -2298--> -2299--> -23--> -230--> -2300--> -2301--> -2302--> -2303--> -2304--> -2305--> -2306--> -2307--> -2308--> -2309--> -231--> -2310--> -2311--> -2312--> -2313--> -2314--> -2315--> -2316--> -2317--> -2318--> -2319--> -232--> -2320--> -2321--> -2322--> -2323--> -2324--> -2325--> -2326--> -2327--> -2328--> -2329--> -233--> -2330--> -2331--> -2332--> -2333--> -2334--> -2335--> -2336--> -2337--> -2338--> -2339--> -234--> -2340--> -2341--> -2342--> -2343--> -2344--> -2345--> -2346--> -2347--> -2348--> -2349--> -235--> -2350--> -2351--> -2352--> -2353--> -2354--> -2355--> -2356--> -2357--> -2358--> -2359--> -236--> -2360--> -2361--> -2362--> -2363--> -2364--> -2365--> -2366--> -2367--> -2368--> -2369--> -237--> -2370--> -2371--> -2372--> -2373--> -2374--> -2375--> -2376--> -2377--> -2378--> -2379--> -238--> -2380--> -2381--> -2382--> -2383--> -2384--> -2385--> -2386--> -2387--> -2388--> -2389--> -239--> -2390--> -2391--> -2392--> -2393--> -2394--> -2395--> -2396--> -2397--> -2398--> -2399--> -24--> -240--> -2400--> -2401--> -2402--> -2403--> -2404--> -2405--> -2406--> -2407--> -2408--> -2409--> -241--> -2410--> -2411--> -2412--> -2413--> -2414--> -2415--> -2416--> -2417--> -2418--> -2419--> -242--> -2420--> -2421--> -2422--> -2423--> -2424--> -2425--> -2426--> -2427--> -2428--> -2429--> -243--> -2430--> -2431--> -2432--> -2433--> -2434--> -2435--> -2436--> -2437--> -2438--> -2439--> -244--> -2440--> -2441--> -2442--> -2443--> -2444--> -2445--> -2446--> -2447--> -2448--> -2449--> -245--> -2450--> -2451--> -2452--> -2453--> -2454--> -2455--> -2456--> -2457--> -2458--> -2459--> -246--> -2460--> -2461--> -2462--> -2463--> -2464--> -2465--> -2466--> -2467--> -2468--> -2469--> -247--> -2470--> -2471--> -2472--> -2473--> -2474--> -2475--> -2476--> -2477--> -2478--> -2479--> -248--> -2480--> -2481--> -2482--> -2483--> -2484--> -2485--> -2486--> -2487--> -2488--> -2489--> -249--> -2490--> -2491--> -2492--> -2493--> -2494--> -2495--> -2496--> -2497--> -2498--> -2499--> -25--> -250--> -2500--> -2501--> -2502--> -2503--> -2504--> -2505--> -2506--> -2507--> -2508--> -2509--> -251--> -2510--> -2511--> -2512--> -2513--> -2514--> -2515--> -2516--> -2517--> -2518--> -2519--> -252--> -2520--> -2521--> -2522--> -2523--> -2524--> -2525--> -2526--> -2527--> -2528--> -2529--> -253--> -2530--> -2531--> -2532--> -2533--> -2534--> -2535--> -2536--> -2537--> -2538--> -2539--> -254--> -2540--> -2541--> -2542--> -2543--> -2544--> -2545--> -2546--> -2547--> -2548--> -2549--> -255--> -2550--> -2551--> -2552--> -2553--> -2554--> -2555--> -2556--> -2557--> -2558--> -2559--> -256--> -2560--> -2561--> -2562--> -2563--> -2564--> -2565--> -2566--> -2567--> -2568--> -2569--> -257--> -2570--> -2571--> -2572--> -2573--> -2574--> -2575--> -2576--> -2577--> -2578--> -2579--> -258--> -2580--> -2581--> -2582--> -2583--> -2584--> -2585--> -2586--> -2587--> -2588--> -2589--> -259--> -2590--> -2591--> -2592--> -2593--> -2594--> -2595--> -2596--> -2597--> -2598--> -2599--> -26--> -260--> -2600--> -2601--> -2602--> -2603--> -2604--> -2605--> -2606--> -2607--> -2608--> -2609--> -261--> -2610--> -2611--> -2612--> -2613--> -2614--> -2615--> -2616--> -2617--> -2618--> -2619--> -262--> -2620--> -2621--> -2622--> -2623--> -2624--> -2625--> -2626--> -2627--> -2628--> -2629--> -263--> -2630--> -2631--> -2632--> -2633--> -2634--> -2635--> -2636--> -2637--> -2638--> -2639--> -264--> -2640--> -2641--> -2642--> -2643--> -2644--> -2645--> -2646--> -2647--> -2648--> -2649--> -265--> -2650--> -2651--> -2652--> -2653--> -2654--> -2655--> -2656--> -2657--> -2658--> -2659--> -266--> -2660--> -2661--> -2662--> -2663--> -2664--> -2665--> -2666--> -2667--> -2668--> -2669--> -267--> -2670--> -2671--> -2672--> -2673--> -2674--> -2675--> -2676--> -2677--> -2678--> -2679--> -268--> -2680--> -2681--> -2682--> -2683--> -2684--> -2685--> -2686--> -2687--> -2688--> -2689--> -269--> -2690--> -2691--> -2692--> -2693--> -2694--> -2695--> -2696--> -2697--> -2698--> -2699--> -27--> -270--> -2700--> -2701--> -2702--> -2703--> -2704--> -2705--> -2706--> -2707--> -2708--> -2709--> -271--> -2710--> -2711--> -2712--> -2713--> -2714--> -2715--> -2716--> -2717--> -2718--> -2719--> -272--> -2720--> -2721--> -2722--> -2723--> -2724--> -2725--> -2726--> -2727--> -2728--> -2729--> -273--> -2730--> -2731--> -2732--> -2733--> -2734--> -2735--> -2736--> -2737--> -2738--> -2739--> -274--> -2740--> -2741--> -2742--> -2743--> -2744--> -2745--> -2746--> -2747--> -2748--> -2749--> -275--> -2750--> -2751--> -2752--> -2753--> -2754--> -2755--> -2756--> -2757--> -2758--> -2759--> -276--> -2760--> -2761--> -2762--> -2763--> -2764--> -2765--> -2766--> -2767--> -2768--> -2769--> -277--> -2770--> -2771--> -2772--> -2773--> -2774--> -2775--> -2776--> -2777--> -2778--> -2779--> -278--> -2780--> -2781--> -2782--> -2783--> -2784--> -2785--> -2786--> -2787--> -2788--> -2789--> -279--> -2790--> -2791--> -2792--> -2793--> -2794--> -2795--> -2796--> -2797--> -2798--> -2799--> -28--> -280--> -2800--> -2801--> -2802--> -2803--> -2804--> -2805--> -2806--> -2807--> -2808--> -2809--> -281--> -2810--> -2811--> -2812--> -2813--> -2814--> -2815--> -2816--> -2817--> -2818--> -2819--> -282--> -2820--> -2821--> -2822--> -2823--> -2824--> -2825--> -2826--> -2827--> -2828--> -2829--> -283--> -2830--> -2831--> -2832--> -2833--> -2834--> -2835--> -2836--> -2837--> -2838--> -2839--> -284--> -2840--> -2841--> -2842--> -2843--> -2844--> -2845--> -2846--> -2847--> -2848--> -2849--> -285--> -2850--> -2851--> -2852--> -2853--> -2854--> -2855--> -2856--> -2857--> -2858--> -2859--> -286--> -2860--> -2861--> -2862--> -2863--> -2864--> -2865--> -2866--> -2867--> -2868--> -2869--> -287--> -2870--> -2871--> -2872--> -2873--> -2874--> -2875--> -2876--> -2877--> -2878--> -2879--> -288--> -2880--> -2881--> -2882--> -2883--> -2884--> -2885--> -2886--> -2887--> -2888--> -2889--> -289--> -2890--> -2891--> -2892--> -2893--> -2894--> -2895--> -2896--> -2897--> -2898--> -2899--> -29--> -290--> -2900--> -2901--> -2902--> -2903--> -2904--> -2905--> -2906--> -2907--> -2908--> -2909--> -291--> -2910--> -2911--> -2912--> -2913--> -2914--> -2915--> -2916--> -2917--> -2918--> -2919--> -292--> -2920--> -2921--> -2922--> -2923--> -2924--> -2925--> -2926--> -2927--> -2928--> -2929--> -293--> -2930--> -2931--> -2932--> -2933--> -2934--> -2935--> -2936--> -2937--> -2938--> -2939--> -294--> -2940--> -2941--> -2942--> -2943--> -2944--> -2945--> -2946--> -2947--> -2948--> -2949--> -295--> -2950--> -2951--> -2952--> -2953--> -2954--> -2955--> -2956--> -2957--> -2958--> -2959--> -296--> -2960--> -2961--> -2962--> -2963--> -2964--> -2965--> -2966--> -2967--> -2968--> -2969--> -297--> -2970--> -2971--> -2972--> -2973--> -2974--> -2975--> -2976--> -2977--> -2978--> -2979--> -298--> -2980--> -2981--> -2982--> -2983--> -2984--> -2985--> -2986--> -2987--> -2988--> -2989--> -299--> -2990--> -2991--> -2992--> -2993--> -2994--> -2995--> -2996--> -2997--> -2998--> -2999--> -3--> -30--> -300--> -3000--> -3001--> -3002--> -3003--> -3004--> -3005--> -3006--> -3007--> -3008--> -3009--> -301--> -3010--> -3011--> -3012--> -3013--> -3014--> -3015--> -3016--> -3017--> -3018--> -3019--> -302--> -3020--> -3021--> -3022--> -3023--> -3024--> -3025--> -3026--> -3027--> -3028--> -3029--> -303--> -3030--> -3031--> -3032--> -3033--> -3034--> -3035--> -3036--> -3037--> -3038--> -3039--> -304--> -3040--> -3041--> -3042--> -3043--> -3044--> -3045--> -3046--> -3047--> -3048--> -3049--> -305--> -3050--> -3051--> -3052--> -3053--> -3054--> -3055--> -3056--> -3057--> -3058--> -3059--> -306--> -3060--> -3061--> -3062--> -3063--> -3064--> -3065--> -3066--> -3067--> -3068--> -3069--> -307--> -3070--> -3071--> -3072--> -3073--> -3074--> -3075--> -3076--> -3077--> -3078--> -3079--> -308--> -3080--> -3081--> -3082--> -3083--> -3084--> -3085--> -3086--> -3087--> -3088--> -3089--> -309--> -3090--> -3091--> -3092--> -3093--> -3094--> -3095--> -3096--> -3097--> -3098--> -3099--> -31--> -310--> -3100--> -3101--> -3102--> -3103--> -3104--> -3105--> -3106--> -3107--> -3108--> -3109--> -311--> -3110--> -3111--> -3112--> -3113--> -3114--> -3115--> -3116--> -3117--> -3118--> -3119--> -312--> -3120--> -3121--> -3122--> -3123--> -3124--> -3125--> -3126--> -3127--> -3128--> -3129--> -313--> -3130--> -3131--> -3132--> -3133--> -3134--> -3135--> -3136--> -3137--> -3138--> -3139--> -314--> -3140--> -3141--> -3142--> -3143--> -3144--> -3145--> -3146--> -3147--> -3148--> -3149--> -315--> -3150--> -3151--> -3152--> -3153--> -3154--> -3155--> -3156--> -3157--> -3158--> -3159--> -316--> -3160--> -3161--> -3162--> -3163--> -3164--> -3165--> -3166--> -3167--> -3168--> -3169--> -317--> -3170--> -3171--> -3172--> -3173--> -3174--> -3175--> -3176--> -3177--> -3178--> -3179--> -318--> -3180--> -3181--> -3182--> -3183--> -3184--> -3185--> -3186--> -3187--> -3188--> -3189--> -319--> -3190--> -3191--> -3192--> -3193--> -3194--> -3195--> -3196--> -3197--> -3198--> -3199--> -32--> -320--> -3200--> -3201--> -3202--> -3203--> -3204--> -3205--> -3206--> -3207--> -3208--> -3209--> -321--> -3210--> -3211--> -3212--> -3213--> -3214--> -3215--> -3216--> -3217--> -3218--> -3219--> -322--> -3220--> -3221--> -3222--> -3223--> -3224--> -3225--> -3226--> -3227--> -3228--> -3229--> -323--> -3230--> -3231--> -3232--> -3233--> -3234--> -3235--> -3236--> -3237--> -3238--> -3239--> -324--> -3240--> -3241--> -3242--> -3243--> -3244--> -3245--> -3246--> -3247--> -3248--> -3249--> -325--> -3250--> -3251--> -3252--> -3253--> -3254--> -3255--> -3256--> -3257--> -3258--> -3259--> -326--> -3260--> -3261--> -3262--> -3263--> -3264--> -3265--> -3266--> -3267--> -3268--> -3269--> -327--> -3270--> -3271--> -3272--> -3273--> -3274--> -3275--> -3276--> -3277--> -3278--> -3279--> -328--> -3280--> -3281--> -3282--> -3283--> -3284--> -3285--> -3286--> -3287--> -3288--> -3289--> -329--> -3290--> -3291--> -3292--> -3293--> -3294--> -3295--> -3296--> -3297--> -3298--> -3299--> -33--> -330--> -3300--> -3301--> -3302--> -3303--> -3304--> -3305--> -3306--> -3307--> -3308--> -3309--> -331--> -3310--> -3311--> -3312--> -3313--> -3314--> -3315--> -3316--> -3317--> -3318--> -3319--> -332--> -3320--> -3321--> -3322--> -3323--> -3324--> -3325--> -3326--> -3327--> -3328--> -3329--> -333--> -3330--> -3331--> -3332--> -3333--> -3334--> -3335--> -3336--> -3337--> -3338--> -3339--> -334--> -3340--> -3341--> -3342--> -3343--> -3344--> -3345--> -3346--> -3347--> -3348--> -3349--> -335--> -3350--> -3351--> -3352--> -3353--> -3354--> -3355--> -3356--> -3357--> -3358--> -3359--> -336--> -3360--> -3361--> -3362--> -3363--> -3364--> -3365--> -3366--> -3367--> -3368--> -3369--> -337--> -3370--> -3371--> -3372--> -3373--> -3374--> -3375--> -3376--> -3377--> -3378--> -3379--> -338--> -3380--> -3381--> -3382--> -3383--> -3384--> -3385--> -3386--> -3387--> -3388--> -3389--> -339--> -3390--> -3391--> -3392--> -3393--> -3394--> -3395--> -3396--> -3397--> -3398--> -3399--> -34--> -340--> -3400--> -3401--> -3402--> -3403--> -3404--> -3405--> -3406--> -3407--> -3408--> -3409--> -341--> -3410--> -3411--> -3412--> -3413--> -3414--> -3415--> -3416--> -3417--> -3418--> -3419--> -342--> -3420--> -3421--> -3422--> -3423--> -3424--> -3425--> -3426--> -3427--> -3428--> -3429--> -343--> -3430--> -3431--> -3432--> -3433--> -3434--> -3435--> -3436--> -3437--> -3438--> -3439--> -344--> -3440--> -3441--> -3442--> -3443--> -3444--> -3445--> -3446--> -3447--> -3448--> -3449--> -345--> -3450--> -3451--> -3452--> -3453--> -3454--> -3455--> -3456--> -3457--> -3458--> -3459--> -346--> -3460--> -3461--> -3462--> -3463--> -3464--> -3465--> -3466--> -3467--> -3468--> -3469--> -347--> -3470--> -3471--> -3472--> -3473--> -3474--> -3475--> -3476--> -3477--> -3478--> -3479--> -348--> -3480--> -3481--> -3482--> -3483--> -3484--> -3485--> -3486--> -3487--> -3488--> -3489--> -349--> -3490--> -3491--> -3492--> -3493--> -3494--> -3495--> -3496--> -3497--> -3498--> -3499--> -35--> -350--> -3500--> -3501--> -3502--> -3503--> -3504--> -3505--> -3506--> -3507--> -3508--> -3509--> -351--> -3510--> -3511--> -3512--> -3513--> -3514--> -3515--> -3516--> -3517--> -3518--> -3519--> -352--> -3520--> -3521--> -3522--> -3523--> -3524--> -3525--> -3526--> -3527--> -3528--> -3529--> -353--> -3530--> -3531--> -3532--> -3533--> -3534--> -3535--> -3536--> -3537--> -3538--> -3539--> -354--> -3540--> -3541--> -3542--> -3543--> -3544--> -3545--> -3546--> -3547--> -3548--> -3549--> -355--> -3550--> -3551--> -3552--> -3553--> -3554--> -3555--> -3556--> -3557--> -3558--> -3559--> -356--> -3560--> -3561--> -3562--> -3563--> -3564--> -3565--> -3566--> -3567--> -3568--> -3569--> -357--> -3570--> -3571--> -3572--> -3573--> -3574--> -3575--> -3576--> -3577--> -3578--> -3579--> -358--> -3580--> -3581--> -3582--> -3583--> -3584--> -3585--> -3586--> -3587--> -3588--> -3589--> -359--> -3590--> -3591--> -3592--> -3593--> -3594--> -3595--> -3596--> -3597--> -3598--> -3599--> -36--> -360--> -3600--> -3601--> -3602--> -3603--> -3604--> -3605--> -3606--> -3607--> -3608--> -3609--> -361--> -3610--> -3611--> -3612--> -3613--> -3614--> -3615--> -3616--> -3617--> -3618--> -3619--> -362--> -3620--> -3621--> -3622--> -3623--> -3624--> -3625--> -3626--> -3627--> -3628--> -3629--> -363--> -3630--> -3631--> -3632--> -3633--> -3634--> -3635--> -3636--> -3637--> -3638--> -3639--> -364--> -3640--> -3641--> -3642--> -3643--> -3644--> -3645--> -3646--> -3647--> -3648--> -3649--> -365--> -3650--> -3651--> -3652--> -3653--> -3654--> -3655--> -3656--> -3657--> -3658--> -3659--> -366--> -3660--> -3661--> -3662--> -3663--> -3664--> -3665--> -3666--> -3667--> -3668--> -3669--> -367--> -3670--> -3671--> -3672--> -3673--> -3674--> -3675--> -3676--> -3677--> -3678--> -3679--> -368--> -3680--> -3681--> -3682--> -3683--> -3684--> -3685--> -3686--> -3687--> -3688--> -3689--> -369--> -3690--> -3691--> -3692--> -3693--> -3694--> -3695--> -3696--> -3697--> -3698--> -3699--> -37--> -370--> -3700--> -3701--> -3702--> -3703--> -3704--> -3705--> -3706--> -3707--> -3708--> -3709--> -371--> -3710--> -3711--> -3712--> -3713--> -3714--> -3715--> -3716--> -3717--> -3718--> -3719--> -372--> -3720--> -3721--> -3722--> -3723--> -3724--> -3725--> -3726--> -3727--> -3728--> -3729--> -373--> -3730--> -3731--> -3732--> -3733--> -3734--> -3735--> -3736--> -3737--> -3738--> -3739--> -374--> -3740--> -3741--> -3742--> -3743--> -3744--> -3745--> -3746--> -3747--> -3748--> -3749--> -375--> -3750--> -3751--> -3752--> -3753--> -3754--> -3755--> -3756--> -3757--> -3758--> -3759--> -376--> -3760--> -3761--> -3762--> -3763--> -3764--> -3765--> -3766--> -3767--> -3768--> -3769--> -377--> -3770--> -3771--> -3772--> -3773--> -3774--> -3775--> -3776--> -3777--> -3778--> -3779--> -378--> -3780--> -3781--> -3782--> -3783--> -3784--> -3785--> -3786--> -3787--> -3788--> -3789--> -379--> -3790--> -3791--> -3792--> -3793--> -3794--> -3795--> -3796--> -3797--> -3798--> -3799--> -38--> -380--> -3800--> -3801--> -3802--> -3803--> -3804--> -3805--> -3806--> -3807--> -3808--> -3809--> -381--> -3810--> -3811--> -3812--> -3813--> -3814--> -3815--> -3816--> -3817--> -3818--> -3819--> -382--> -3820--> -3821--> -3822--> -3823--> -3824--> -3825--> -3826--> -3827--> -3828--> -3829--> -383--> -3830--> -3831--> -3832--> -3833--> -3834--> -3835--> -3836--> -3837--> -3838--> -3839--> -384--> -3840--> -3841--> -3842--> -3843--> -3844--> -3845--> -3846--> -3847--> -3848--> -3849--> -385--> -3850--> -3851--> -3852--> -3853--> -3854--> -3855--> -3856--> -3857--> -3858--> -3859--> -386--> -3860--> -3861--> -3862--> -3863--> -3864--> -3865--> -3866--> -3867--> -3868--> -3869--> -387--> -3870--> -3871--> -3872--> -3873--> -3874--> -3875--> -3876--> -3877--> -3878--> -3879--> -388--> -3880--> -3881--> -3882--> -3883--> -3884--> -3885--> -3886--> -3887--> -3888--> -3889--> -389--> -3890--> -3891--> -3892--> -3893--> -3894--> -3895--> -3896--> -3897--> -3898--> -3899--> -39--> -390--> -3900--> -3901--> -3902--> -3903--> -3904--> -3905--> -3906--> -3907--> -3908--> -3909--> -391--> -3910--> -3911--> -3912--> -3913--> -3914--> -3915--> -3916--> -3917--> -3918--> -3919--> -392--> -3920--> -3921--> -3922--> -3923--> -3924--> -3925--> -3926--> -3927--> -3928--> -3929--> -393--> -3930--> -3931--> -3932--> -3933--> -3934--> -3935--> -3936--> -3937--> -3938--> -3939--> -394--> -3940--> -3941--> -3942--> -3943--> -3944--> -3945--> -3946--> -3947--> -3948--> -3949--> -395--> -3950--> -3951--> -3952--> -3953--> -3954--> -3955--> -3956--> -3957--> -3958--> -3959--> -396--> -3960--> -3961--> -3962--> -3963--> -3964--> -3965--> -3966--> -3967--> -3968--> -3969--> -397--> -3970--> -3971--> -3972--> -3973--> -3974--> -3975--> -3976--> -3977--> -3978--> -3979--> -398--> -3980--> -3981--> -3982--> -3983--> -3984--> -3985--> -3986--> -3987--> -3988--> -3989--> -399--> -3990--> -3991--> -3992--> -3993--> -3994--> -3995--> -3996--> -3997--> -3998--> -3999--> -4--> -40--> -400--> -4000--> -4001--> -4002--> -4003--> -4004--> -4005--> -4006--> -4007--> -4008--> -4009--> -401--> -4010--> -4011--> -4012--> -4013--> -4014--> -4015--> -4016--> -4017--> -4018--> -4019--> -402--> -4020--> -4021--> -4022--> -4023--> -4024--> -4025--> -4026--> -4027--> -4028--> -4029--> -403--> -4030--> -4031--> -4032--> -4033--> -4034--> -4035--> -4036--> -4037--> -4038--> -4039--> -404--> -4040--> -4041--> -4042--> -4043--> -4044--> -4045--> -4046--> -4047--> -4048--> -4049--> -405--> -4050--> -4051--> -4052--> -4053--> -4054--> -4055--> -4056--> -4057--> -4058--> -4059--> -406--> -4060--> -4061--> -4062--> -4063--> -4064--> -4065--> -4066--> -4067--> -4068--> -4069--> -407--> -4070--> -4071--> -4072--> -4073--> -4074--> -4075--> -4076--> -4077--> -4078--> -4079--> -408--> -4080--> -4081--> -4082--> -4083--> -4084--> -4085--> -4086--> -4087--> -4088--> -4089--> -409--> -4090--> -4091--> -4092--> -4093--> -4094--> -4095--> -4096--> -4097--> -4098--> -4099--> -41--> -410--> -4100--> -4101--> -4102--> -4103--> -4104--> -4105--> -4106--> -4107--> -4108--> -4109--> -411--> -4110--> -4111--> -4112--> -4113--> -4114--> -4115--> -4116--> -4117--> -4118--> -4119--> -412--> -4120--> -4121--> -4122--> -4123--> -4124--> -4125--> -4126--> -4127--> -4128--> -4129--> -413--> -4130--> -4131--> -4132--> -4133--> -4134--> -4135--> -4136--> -4137--> -4138--> -4139--> -414--> -4140--> -4141--> -4142--> -4143--> -4144--> -4145--> -4146--> -4147--> -4148--> -4149--> -415--> -4150--> -4151--> -4152--> -4153--> -4154--> -4155--> -4156--> -4157--> -4158--> -4159--> -416--> -4160--> -4161--> -4162--> -4163--> -4164--> -4165--> -4166--> -4167--> -4168--> -4169--> -417--> -4170--> -4171--> -4172--> -4173--> -4174--> -4175--> -4176--> -4177--> -4178--> -4179--> -418--> -4180--> -4181--> -4182--> -4183--> -4184--> -4185--> -4186--> -4187--> -4188--> -4189--> -419--> -4190--> -4191--> -4192--> -4193--> -4194--> -4195--> -4196--> -4197--> -4198--> -4199--> -42--> -420--> -4200--> -4201--> -4202--> -4203--> -4204--> -4205--> -4206--> -4207--> -4208--> -4209--> -421--> -4210--> -4211--> -4212--> -4213--> -4214--> -4215--> -4216--> -4217--> -4218--> -4219--> -422--> -4220--> -4221--> -4222--> -4223--> -4224--> -4225--> -4226--> -4227--> -4228--> -4229--> -423--> -4230--> -4231--> -4232--> -4233--> -4234--> -4235--> -4236--> -4237--> -4238--> -4239--> -424--> -4240--> -4241--> -4242--> -4243--> -4244--> -4245--> -4246--> -4247--> -4248--> -4249--> -425--> -4250--> -4251--> -4252--> -4253--> -4254--> -4255--> -4256--> -4257--> -4258--> -4259--> -426--> -4260--> -4261--> -4262--> -4263--> -4264--> -4265--> -4266--> -4267--> -4268--> -4269--> -427--> -4270--> -4271--> -4272--> -4273--> -4274--> -4275--> -4276--> -4277--> -4278--> -4279--> -428--> -4280--> -4281--> -4282--> -4283--> -4284--> -4285--> -4286--> -4287--> -4288--> -4289--> -429--> -4290--> -4291--> -4292--> -4293--> -4294--> -4295--> -4296--> -4297--> -4298--> -4299--> -43--> -430--> -4300--> -4301--> -4302--> -4303--> -4304--> -4305--> -4306--> -4307--> -4308--> -4309--> -431--> -4310--> -4311--> -4312--> -4313--> -4314--> -4315--> -4316--> -4317--> -4318--> -4319--> -432--> -4320--> -4321--> -4322--> -4323--> -4324--> -4325--> -4326--> -4327--> -4328--> -4329--> -433--> -4330--> -4331--> -4332--> -4333--> -4334--> -4335--> -4336--> -4337--> -4338--> -4339--> -434--> -4340--> -4341--> -4342--> -4343--> -4344--> -4345--> -4346--> -4347--> -4348--> -4349--> -435--> -4350--> -4351--> -4352--> -4353--> -4354--> -4355--> -4356--> -4357--> -4358--> -4359--> -436--> -4360--> -4361--> -4362--> -4363--> -4364--> -4365--> -4366--> -4367--> -4368--> -4369--> -437--> -4370--> -4371--> -4372--> -4373--> -4374--> -4375--> -4376--> -4377--> -4378--> -4379--> -438--> -4380--> -4381--> -4382--> -4383--> -4384--> -4385--> -4386--> -4387--> -4388--> -4389--> -439--> -4390--> -4391--> -4392--> -4393--> -4394--> -4395--> -4396--> -4397--> -4398--> -4399--> -44--> -440--> -4400--> -4401--> -4402--> -4403--> -4404--> -4405--> -4406--> -4407--> -4408--> -4409--> -441--> -4410--> -4411--> -4412--> -4413--> -4414--> -4415--> -4416--> -4417--> -4418--> -4419--> -442--> -4420--> -4421--> -4422--> -4423--> -4424--> -4425--> -4426--> -4427--> -4428--> -4429--> -443--> -4430--> -4431--> -4432--> -4433--> -4434--> -4435--> -4436--> -4437--> -4438--> -4439--> -444--> -4440--> -4441--> -4442--> -4443--> -4444--> -4445--> -4446--> -4447--> -4448--> -4449--> -445--> -4450--> -4451--> -4452--> -4453--> -4454--> -4455--> -4456--> -4457--> -4458--> -4459--> -446--> -4460--> -4461--> -4462--> -4463--> -4464--> -4465--> -4466--> -4467--> -4468--> -4469--> -447--> -4470--> -4471--> -4472--> -4473--> -4474--> -4475--> -4476--> -4477--> -4478--> -4479--> -448--> -4480--> -4481--> -4482--> -4483--> -4484--> -4485--> -4486--> -4487--> -4488--> -4489--> -449--> -4490--> -4491--> -4492--> -4493--> -4494--> -4495--> -4496--> -4497--> -4498--> -4499--> -45--> -450--> -4500--> -4501--> -4502--> -4503--> -4504--> -4505--> -4506--> -4507--> -4508--> -4509--> -451--> -4510--> -4511--> -4512--> -4513--> -4514--> -4515--> -4516--> -4517--> -4518--> -4519--> -452--> -4520--> -4521--> -4522--> -4523--> -4524--> -4525--> -4526--> -4527--> -4528--> -4529--> -453--> -4530--> -4531--> -4532--> -4533--> -4534--> -4535--> -4536--> -4537--> -4538--> -4539--> -454--> -4540--> -4541--> -4542--> -4543--> -4544--> -4545--> -4546--> -4547--> -4548--> -4549--> -455--> -4550--> -4551--> -4552--> -4553--> -4554--> -4555--> -4556--> -4557--> -4558--> -4559--> -456--> -4560--> -4561--> -4562--> -4563--> -4564--> -4565--> -4566--> -4567--> -4568--> -4569--> -457--> -4570--> -4571--> -4572--> -4573--> -4574--> -4575--> -4576--> -4577--> -4578--> -4579--> -458--> -4580--> -4581--> -4582--> -4583--> -4584--> -4585--> -4586--> -4587--> -4588--> -4589--> -459--> -4590--> -4591--> -4592--> -4593--> -4594--> -4595--> -4596--> -4597--> -4598--> -4599--> -46--> -460--> -4600--> -4601--> -4602--> -4603--> -4604--> -4605--> -4606--> -4607--> -4608--> -4609--> -461--> -4610--> -4611--> -4612--> -4613--> -4614--> -4615--> -4616--> -4617--> -4618--> -4619--> -462--> -4620--> -4621--> -4622--> -4623--> -4624--> -4625--> -4626--> -4627--> -4628--> -4629--> -463--> -4630--> -4631--> -4632--> -4633--> -4634--> -4635--> -4636--> -4637--> -4638--> -4639--> -464--> -4640--> -4641--> -4642--> -4643--> -4644--> -4645--> -4646--> -4647--> -4648--> -4649--> -465--> -4650--> -4651--> -4652--> -4653--> -4654--> -4655--> -4656--> -4657--> -4658--> -4659--> -466--> -4660--> -4661--> -4662--> -4663--> -4664--> -4665--> -4666--> -4667--> -4668--> -4669--> -467--> -4670--> -4671--> -4672--> -4673--> -4674--> -4675--> -4676--> -4677--> -4678--> -4679--> -468--> -4680--> -4681--> -4682--> -4683--> -4684--> -4685--> -4686--> -4687--> -4688--> -4689--> -469--> -4690--> -4691--> -4692--> -4693--> -4694--> -4695--> -4696--> -4697--> -4698--> -4699--> -47--> -470--> -4700--> -4701--> -4702--> -4703--> -4704--> -4705--> -4706--> -4707--> -4708--> -4709--> -471--> -4710--> -4711--> -4712--> -4713--> -4714--> -4715--> -4716--> -4717--> -4718--> -4719--> -472--> -4720--> -4721--> -4722--> -4723--> -4724--> -4725--> -4726--> -4727--> -4728--> -4729--> -473--> -4730--> -4731--> -4732--> -4733--> -4734--> -4735--> -4736--> -4737--> -4738--> -4739--> -474--> -4740--> -4741--> -4742--> -4743--> -4744--> -4745--> -4746--> -4747--> -4748--> -4749--> -475--> -4750--> -4751--> -4752--> -4753--> -4754--> -4755--> -4756--> -4757--> -4758--> -4759--> -476--> -4760--> -4761--> -4762--> -4763--> -4764--> -4765--> -4766--> -4767--> -4768--> -4769--> -477--> -4770--> -4771--> -4772--> -4773--> -4774--> -4775--> -4776--> -4777--> -4778--> -4779--> -478--> -4780--> -4781--> -4782--> -4783--> -4784--> -4785--> -4786--> -4787--> -4788--> -4789--> -479--> -4790--> -4791--> -4792--> -4793--> -4794--> -4795--> -4796--> -4797--> -4798--> -4799--> -48--> -480--> -4800--> -4801--> -4802--> -4803--> -4804--> -4805--> -4806--> -4807--> -4808--> -4809--> -481--> -4810--> -4811--> -4812--> -4813--> -4814--> -4815--> -4816--> -4817--> -4818--> -4819--> -482--> -4820--> -4821--> -4822--> -4823--> -4824--> -4825--> -4826--> -4827--> -4828--> -4829--> -483--> -4830--> -4831--> -4832--> -4833--> -4834--> -4835--> -4836--> -4837--> -4838--> -4839--> -484--> -4840--> -4841--> -4842--> -4843--> -4844--> -4845--> -4846--> -4847--> -4848--> -4849--> -485--> -4850--> -4851--> -4852--> -4853--> -4854--> -4855--> -4856--> -4857--> -4858--> -4859--> -486--> -4860--> -4861--> -4862--> -4863--> -4864--> -4865--> -4866--> -4867--> -4868--> -4869--> -487--> -4870--> -4871--> -4872--> -4873--> -4874--> -4875--> -4876--> -4877--> -4878--> -4879--> -488--> -4880--> -4881--> -4882--> -4883--> -4884--> -4885--> -4886--> -4887--> -4888--> -4889--> -489--> -4890--> -4891--> -4892--> -4893--> -4894--> -4895--> -4896--> -4897--> -4898--> -4899--> -49--> -490--> -4900--> -4901--> -4902--> -4903--> -4904--> -4905--> -4906--> -4907--> -4908--> -4909--> -491--> -4910--> -4911--> -4912--> -4913--> -4914--> -4915--> -4916--> -4917--> -4918--> -4919--> -492--> -4920--> -4921--> -4922--> -4923--> -4924--> -4925--> -4926--> -4927--> -4928--> -4929--> -493--> -4930--> -4931--> -4932--> -4933--> -4934--> -4935--> -4936--> -4937--> -4938--> -4939--> -494--> -4940--> -4941--> -4942--> -4943--> -4944--> -4945--> -4946--> -4947--> -4948--> -4949--> -495--> -4950--> -4951--> -4952--> -4953--> -4954--> -4955--> -4956--> -4957--> -4958--> -4959--> -496--> -4960--> -4961--> -4962--> -4963--> -4964--> -4965--> -4966--> -4967--> -4968--> -4969--> -497--> -4970--> -4971--> -4972--> -4973--> -4974--> -4975--> -4976--> -4977--> -4978--> -4979--> -498--> -4980--> -4981--> -4982--> -4983--> -4984--> -4985--> -4986--> -4987--> -4988--> -4989--> -499--> -4990--> -4991--> -4992--> -4993--> -4994--> -4995--> -4996--> -4997--> -4998--> -4999--> -5--> -50--> -500--> -5000--> -5001--> -5002--> -5003--> -5004--> -5005--> -5006--> -5007--> -5008--> -5009--> -501--> -5010--> -5011--> -5012--> -5013--> -5014--> -5015--> -5016--> -5017--> -5018--> -5019--> -502--> -5020--> -5021--> -5022--> -5023--> -5024--> -5025--> -5026--> -5027--> -5028--> -5029--> -503--> -5030--> -5031--> -5032--> -5033--> -5034--> -5035--> -5036--> -5037--> -5038--> -5039--> -504--> -5040--> -5041--> -5042--> -5043--> -5044--> -5045--> -5046--> -5047--> -5048--> -5049--> -505--> -5050--> -5051--> -5052--> -5053--> -5054--> -5055--> -5056--> -5057--> -5058--> -5059--> -506--> -5060--> -5061--> -5062--> -5063--> -5064--> -5065--> -5066--> -5067--> -5068--> -5069--> -507--> -5070--> -5071--> -5072--> -5073--> -5074--> -5075--> -5076--> -5077--> -5078--> -5079--> -508--> -5080--> -5081--> -5082--> -5083--> -5084--> -5085--> -5086--> -5087--> -5088--> -5089--> -509--> -5090--> -5091--> -5092--> -5093--> -5094--> -5095--> -5096--> -5097--> -5098--> -5099--> -51--> -510--> -5100--> -5101--> -5102--> -5103--> -5104--> -5105--> -5106--> -5107--> -5108--> -5109--> -511--> -5110--> -5111--> -5112--> -5113--> -5114--> -5115--> -5116--> -5117--> -5118--> -5119--> -512--> -5120--> -5121--> -5122--> -5123--> -5124--> -5125--> -5126--> -5127--> -5128--> -5129--> -513--> -5130--> -5131--> -5132--> -5133--> -5134--> -5135--> -5136--> -5137--> -5138--> -5139--> -514--> -5140--> -5141--> -5142--> -5143--> -5144--> -5145--> -5146--> -5147--> -5148--> -5149--> -515--> -5150--> -5151--> -5152--> -5153--> -5154--> -5155--> -5156--> -5157--> -5158--> -5159--> -516--> -5160--> -5161--> -5162--> -5163--> -5164--> -5165--> -5166--> -5167--> -5168--> -5169--> -517--> -5170--> -5171--> -5172--> -5173--> -5174--> -5175--> -5176--> -5177--> -5178--> -5179--> -518--> -5180--> -5181--> -5182--> -5183--> -5184--> -5185--> -5186--> -5187--> -5188--> -5189--> -519--> -5190--> -5191--> -5192--> -5193--> -5194--> -5195--> -5196--> -5197--> -5198--> -5199--> -52--> -520--> -5200--> -5201--> -5202--> -5203--> -5204--> -5205--> -5206--> -5207--> -5208--> -5209--> -521--> -5210--> -5211--> -5212--> -5213--> -5214--> -5215--> -5216--> -5217--> -5218--> -5219--> -522--> -5220--> -5221--> -5222--> -5223--> -5224--> -5225--> -5226--> -5227--> -5228--> -5229--> -523--> -5230--> -5231--> -5232--> -5233--> -5234--> -5235--> -5236--> -5237--> -5238--> -5239--> -524--> -5240--> -5241--> -5242--> -5243--> -5244--> -5245--> -5246--> -5247--> -5248--> -5249--> -525--> -5250--> -5251--> -5252--> -5253--> -5254--> -5255--> -5256--> -5257--> -5258--> -5259--> -526--> -5260--> -5261--> -5262--> -5263--> -5264--> -5265--> -5266--> -5267--> -5268--> -5269--> -527--> -5270--> -5271--> -5272--> -5273--> -5274--> -5275--> -5276--> -5277--> -5278--> -5279--> -528--> -5280--> -5281--> -5282--> -5283--> -5284--> -5285--> -5286--> -5287--> -5288--> -5289--> -529--> -5290--> -5291--> -5292--> -5293--> -5294--> -5295--> -5296--> -5297--> -5298--> -5299--> -53--> -530--> -5300--> -5301--> -5302--> -5303--> -5304--> -5305--> -5306--> -5307--> -5308--> -5309--> -531--> -5310--> -5311--> -5312--> -5313--> -5314--> -5315--> -5316--> -5317--> -5318--> -5319--> -532--> -5320--> -5321--> -5322--> -5323--> -5324--> -5325--> -5326--> -5327--> -5328--> -5329--> -533--> -5330--> -5331--> -5332--> -5333--> -5334--> -5335--> -5336--> -5337--> -5338--> -5339--> -534--> -5340--> -5341--> -5342--> -5343--> -5344--> -5345--> -5346--> -5347--> -5348--> -5349--> -535--> -5350--> -5351--> -5352--> -5353--> -5354--> -5355--> -5356--> -5357--> -5358--> -5359--> -536--> -5360--> -5361--> -5362--> -5363--> -5364--> -5365--> -5366--> -5367--> -5368--> -5369--> -537--> -5370--> -5371--> -5372--> -5373--> -5374--> -5375--> -5376--> -5377--> -5378--> -5379--> -538--> -5380--> -5381--> -5382--> -5383--> -5384--> -5385--> -5386--> -5387--> -5388--> -5389--> -539--> -5390--> -5391--> -5392--> -5393--> -5394--> -5395--> -5396--> -5397--> -5398--> -5399--> -54--> -540--> -5400--> -5401--> -5402--> -5403--> -5404--> -5405--> -5406--> -5407--> -5408--> -5409--> -541--> -5410--> -5411--> -5412--> -5413--> -5414--> -5415--> -5416--> -5417--> -5418--> -5419--> -542--> -5420--> -5421--> -5422--> -5423--> -5424--> -5425--> -5426--> -5427--> -5428--> -5429--> -543--> -5430--> -5431--> -5432--> -5433--> -5434--> -5435--> -5436--> -5437--> -5438--> -5439--> -544--> -5440--> -5441--> -5442--> -5443--> -5444--> -5445--> -5446--> -5447--> -5448--> -5449--> -545--> -5450--> -5451--> -5452--> -5453--> -5454--> -5455--> -5456--> -5457--> -5458--> -5459--> -546--> -5460--> -5461--> -5462--> -5463--> -5464--> -5465--> -5466--> -5467--> -5468--> -5469--> -547--> -5470--> -5471--> -5472--> -5473--> -5474--> -5475--> -5476--> -5477--> -5478--> -5479--> -548--> -5480--> -5481--> -5482--> -5483--> -5484--> -5485--> -5486--> -5487--> -5488--> -5489--> -549--> -5490--> -5491--> -5492--> -5493--> -5494--> -5495--> -5496--> -5497--> -5498--> -5499--> -55--> -550--> -5500--> -5501--> -5502--> -5503--> -5504--> -5505--> -5506--> -5507--> -5508--> -5509--> -551--> -5510--> -5511--> -5512--> -5513--> -5514--> -5515--> -5516--> -5517--> -5518--> -5519--> -552--> -5520--> -5521--> -5522--> -5523--> -5524--> -5525--> -5526--> -5527--> -5528--> -5529--> -553--> -5530--> -5531--> -5532--> -5533--> -5534--> -5535--> -5536--> -5537--> -5538--> -5539--> -554--> -5540--> -5541--> -5542--> -5543--> -5544--> -5545--> -5546--> -5547--> -5548--> -5549--> -555--> -5550--> -5551--> -5552--> -5553--> -5554--> -5555--> -5556--> -5557--> -5558--> -5559--> -556--> -5560--> -5561--> -5562--> -5563--> -5564--> -5565--> -5566--> -5567--> -5568--> -5569--> -557--> -5570--> -5571--> -5572--> -5573--> -5574--> -5575--> -5576--> -5577--> -5578--> -5579--> -558--> -5580--> -5581--> -5582--> -5583--> -5584--> -5585--> -5586--> -5587--> -5588--> -5589--> -559--> -5590--> -5591--> -5592--> -5593--> -5594--> -5595--> -5596--> -5597--> -5598--> -5599--> -56--> -560--> -5600--> -5601--> -5602--> -5603--> -5604--> -5605--> -5606--> -5607--> -5608--> -5609--> -561--> -5610--> -5611--> -5612--> -5613--> -5614--> -5615--> -5616--> -5617--> -5618--> -5619--> -562--> -5620--> -5621--> -5622--> -5623--> -5624--> -5625--> -5626--> -5627--> -5628--> -5629--> -563--> -5630--> -5631--> -5632--> -5633--> -5634--> -5635--> -5636--> -5637--> -5638--> -5639--> -564--> -5640--> -5641--> -5642--> -5643--> -5644--> -5645--> -5646--> -5647--> -5648--> -5649--> -565--> -5650--> -5651--> -5652--> -5653--> -5654--> -5655--> -5656--> -5657--> -5658--> -5659--> -566--> -5660--> -5661--> -5662--> -5663--> -5664--> -5665--> -5666--> -5667--> -5668--> -5669--> -567--> -5670--> -5671--> -5672--> -5673--> -5674--> -5675--> -5676--> -5677--> -5678--> -5679--> -568--> -5680--> -5681--> -5682--> -5683--> -5684--> -5685--> -5686--> -5687--> -5688--> -5689--> -569--> -5690--> -5691--> -5692--> -5693--> -5694--> -5695--> -5696--> -5697--> -5698--> -5699--> -57--> -570--> -5700--> -5701--> -5702--> -5703--> -5704--> -5705--> -5706--> -5707--> -5708--> -5709--> -571--> -5710--> -5711--> -5712--> -5713--> -5714--> -5715--> -5716--> -5717--> -5718--> -5719--> -572--> -5720--> -5721--> -5722--> -5723--> -5724--> -5725--> -5726--> -5727--> -5728--> -5729--> -573--> -5730--> -5731--> -5732--> -5733--> -5734--> -5735--> -5736--> -5737--> -5738--> -5739--> -574--> -5740--> -5741--> -5742--> -5743--> -5744--> -5745--> -5746--> -5747--> -5748--> -5749--> -575--> -5750--> -5751--> -5752--> -5753--> -5754--> -5755--> -5756--> -5757--> -5758--> -5759--> -576--> -5760--> -5761--> -5762--> -5763--> -5764--> -5765--> -5766--> -5767--> -5768--> -5769--> -577--> -5770--> -5771--> -5772--> -5773--> -5774--> -5775--> -5776--> -5777--> -5778--> -5779--> -578--> -5780--> -5781--> -5782--> -5783--> -5784--> -5785--> -5786--> -5787--> -5788--> -5789--> -579--> -5790--> -5791--> -5792--> -5793--> -5794--> -5795--> -5796--> -5797--> -5798--> -5799--> -58--> -580--> -5800--> -5801--> -5802--> -5803--> -5804--> -5805--> -5806--> -5807--> -5808--> -5809--> -581--> -5810--> -5811--> -5812--> -5813--> -5814--> -5815--> -5816--> -5817--> -5818--> -5819--> -582--> -5820--> -5821--> -5822--> -5823--> -5824--> -5825--> -5826--> -5827--> -5828--> -5829--> -583--> -5830--> -5831--> -5832--> -5833--> -5834--> -5835--> -5836--> -5837--> -5838--> -5839--> -584--> -5840--> -5841--> -5842--> -5843--> -5844--> -5845--> -5846--> -5847--> -5848--> -5849--> -585--> -5850--> -5851--> -5852--> -5853--> -5854--> -5855--> -5856--> -5857--> -5858--> -5859--> -586--> -5860--> -5861--> -5862--> -5863--> -5864--> -5865--> -5866--> -5867--> -5868--> -5869--> -587--> -5870--> -5871--> -5872--> -5873--> -5874--> -5875--> -5876--> -5877--> -5878--> -5879--> -588--> -5880--> -5881--> -5882--> -5883--> -5884--> -5885--> -5886--> -5887--> -5888--> -5889--> -589--> -5890--> -5891--> -5892--> -5893--> -5894--> -5895--> -5896--> -5897--> -5898--> -5899--> -59--> -590--> -5900--> -5901--> -5902--> -5903--> -5904--> -5905--> -5906--> -5907--> -5908--> -5909--> -591--> -5910--> -5911--> -5912--> -5913--> -5914--> -5915--> -5916--> -5917--> -5918--> -5919--> -592--> -5920--> -5921--> -5922--> -5923--> -5924--> -5925--> -5926--> -5927--> -5928--> -5929--> -593--> -5930--> -5931--> -5932--> -5933--> -5934--> -5935--> -5936--> -5937--> -5938--> -5939--> -594--> -5940--> -5941--> -5942--> -5943--> -5944--> -5945--> -5946--> -5947--> -5948--> -5949--> -595--> -5950--> -5951--> -5952--> -5953--> -5954--> -5955--> -5956--> -5957--> -5958--> -5959--> -596--> -5960--> -5961--> -5962--> -5963--> -5964--> -5965--> -5966--> -5967--> -5968--> -5969--> -597--> -5970--> -5971--> -5972--> -5973--> -5974--> -5975--> -5976--> -5977--> -5978--> -5979--> -598--> -5980--> -5981--> -5982--> -5983--> -5984--> -5985--> -5986--> -5987--> -5988--> -5989--> -599--> -5990--> -5991--> -5992--> -5993--> -5994--> -5995--> -5996--> -5997--> -5998--> -5999--> -6--> -60--> -600--> -6000--> -6001--> -6002--> -6003--> -6004--> -6005--> -6006--> -6007--> -6008--> -6009--> -601--> -6010--> -6011--> -6012--> -6013--> -6014--> -6015--> -6016--> -6017--> -6018--> -6019--> -602--> -6020--> -6021--> -6022--> -6023--> -6024--> -6025--> -6026--> -6027--> -6028--> -6029--> -603--> -6030--> -6031--> -6032--> -6033--> -6034--> -6035--> -6036--> -6037--> -6038--> -6039--> -604--> -6040--> -6041--> -6042--> -6043--> -6044--> -6045--> -6046--> -6047--> -6048--> -6049--> -605--> -6050--> -6051--> -6052--> -6053--> -6054--> -6055--> -6056--> -6057--> -6058--> -6059--> -606--> -6060--> -6061--> -6062--> -6063--> -6064--> -6065--> -6066--> -6067--> -6068--> -6069--> -607--> -6070--> -6071--> -6072--> -6073--> -6074--> -6075--> -6076--> -6077--> -6078--> -6079--> -608--> -6080--> -6081--> -6082--> -6083--> -6084--> -6085--> -6086--> -6087--> -6088--> -6089--> -609--> -6090--> -6091--> -6092--> -6093--> -6094--> -6095--> -6096--> -6097--> -6098--> -6099--> -61--> -610--> -6100--> -6101--> -6102--> -6103--> -6104--> -6105--> -6106--> -6107--> -6108--> -6109--> -611--> -6110--> -6111--> -6112--> -6113--> -6114--> -6115--> -6116--> -6117--> -6118--> -6119--> -612--> -6120--> -6121--> -6122--> -6123--> -6124--> -6125--> -6126--> -6127--> -6128--> -6129--> -613--> -6130--> -6131--> -6132--> -6133--> -6134--> -6135--> -6136--> -6137--> -6138--> -6139--> -614--> -6140--> -6141--> -6142--> -6143--> -6144--> -6145--> -6146--> -6147--> -6148--> -6149--> -615--> -6150--> -6151--> -6152--> -6153--> -6154--> -6155--> -6156--> -6157--> -6158--> -6159--> -616--> -6160--> -6161--> -6162--> -6163--> -6164--> -6165--> -6166--> -6167--> -6168--> -6169--> -617--> -6170--> -6171--> -6172--> -6173--> -6174--> -6175--> -6176--> -6177--> -6178--> -6179--> -618--> -6180--> -6181--> -6182--> -6183--> -6184--> -6185--> -6186--> -6187--> -6188--> -6189--> -619--> -6190--> -6191--> -6192--> -6193--> -6194--> -6195--> -6196--> -6197--> -6198--> -6199--> -62--> -620--> -6200--> -6201--> -6202--> -6203--> -6204--> -6205--> -6206--> -6207--> -6208--> -6209--> -621--> -6210--> -6211--> -6212--> -6213--> -6214--> -6215--> -6216--> -6217--> -6218--> -6219--> -622--> -6220--> -6221--> -6222--> -6223--> -6224--> -6225--> -6226--> -6227--> -6228--> -6229--> -623--> -6230--> -6231--> -6232--> -6233--> -6234--> -6235--> -6236--> -6237--> -6238--> -6239--> -624--> -6240--> -6241--> -6242--> -6243--> -6244--> -6245--> -6246--> -6247--> -6248--> -6249--> -625--> -6250--> -6251--> -6252--> -6253--> -6254--> -6255--> -6256--> -6257--> -6258--> -6259--> -626--> -6260--> -6261--> -6262--> -6263--> -6264--> -6265--> -6266--> -6267--> -6268--> -6269--> -627--> -6270--> -6271--> -6272--> -6273--> -6274--> -6275--> -6276--> -6277--> -6278--> -6279--> -628--> -6280--> -6281--> -6282--> -6283--> -6284--> -6285--> -6286--> -6287--> -6288--> -6289--> -629--> -6290--> -6291--> -6292--> -6293--> -6294--> -6295--> -6296--> -6297--> -6298--> -6299--> -63--> -630--> -6300--> -6301--> -6302--> -6303--> -6304--> -6305--> -6306--> -6307--> -6308--> -6309--> -631--> -6310--> -6311--> -6312--> -6313--> -6314--> -6315--> -6316--> -6317--> -6318--> -6319--> -632--> -6320--> -6321--> -6322--> -6323--> -6324--> -6325--> -6326--> -6327--> -6328--> -6329--> -633--> -6330--> -6331--> -6332--> -6333--> -6334--> -6335--> -6336--> -6337--> -6338--> -6339--> -634--> -6340--> -6341--> -6342--> -6343--> -6344--> -6345--> -6346--> -6347--> -6348--> -6349--> -635--> -6350--> -6351--> -6352--> -6353--> -6354--> -6355--> -6356--> -6357--> -6358--> -6359--> -636--> -6360--> -6361--> -6362--> -6363--> -6364--> -6365--> -6366--> -6367--> -6368--> -6369--> -637--> -6370--> -6371--> -6372--> -6373--> -6374--> -6375--> -6376--> -6377--> -6378--> -6379--> -638--> -6380--> -6381--> -6382--> -6383--> -6384--> -6385--> -6386--> -6387--> -6388--> -6389--> -639--> -6390--> -6391--> -6392--> -6393--> -6394--> -6395--> -6396--> -6397--> -6398--> -6399--> -64--> -640--> -6400--> -6401--> -6402--> -6403--> -6404--> -6405--> -6406--> -6407--> -6408--> -6409--> -641--> -6410--> -6411--> -6412--> -6413--> -6414--> -6415--> -6416--> -6417--> -6418--> -6419--> -642--> -6420--> -6421--> -6422--> -6423--> -6424--> -6425--> -6426--> -6427--> -6428--> -6429--> -643--> -6430--> -6431--> -6432--> -6433--> -6434--> -6435--> -6436--> -6437--> -6438--> -6439--> -644--> -6440--> -6441--> -6442--> -6443--> -6444--> -6445--> -6446--> -6447--> -6448--> -6449--> -645--> -6450--> -6451--> -6452--> -6453--> -6454--> -6455--> -6456--> -6457--> -6458--> -6459--> -646--> -6460--> -6461--> -6462--> -6463--> -6464--> -6465--> -6466--> -6467--> -6468--> -6469--> -647--> -6470--> -6471--> -6472--> -6473--> -6474--> -6475--> -6476--> -6477--> -6478--> -6479--> -648--> -6480--> -6481--> -6482--> -6483--> -6484--> -6485--> -6486--> -6487--> -6488--> -6489--> -649--> -6490--> -6491--> -6492--> -6493--> -6494--> -6495--> -6496--> -6497--> -6498--> -6499--> -65--> -650--> -6500--> -6501--> -6502--> -6503--> -6504--> -6505--> -6506--> -6507--> -6508--> -6509--> -651--> -6510--> -6511--> -6512--> -6513--> -6514--> -6515--> -6516--> -6517--> -6518--> -6519--> -652--> -6520--> -6521--> -6522--> -6523--> -6524--> -6525--> -6526--> -6527--> -6528--> -6529--> -653--> -6530--> -6531--> -6532--> -6533--> -6534--> -6535--> -6536--> -6537--> -6538--> -6539--> -654--> -6540--> -6541--> -6542--> -6543--> -6544--> -6545--> -6546--> -6547--> -6548--> -6549--> -655--> -6550--> -6551--> -6552--> -6553--> -6554--> -6555--> -6556--> -6557--> -6558--> -6559--> -656--> -6560--> -6561--> -6562--> -6563--> -6564--> -6565--> -6566--> -6567--> -6568--> -6569--> -657--> -6570--> -6571--> -6572--> -6573--> -6574--> -6575--> -6576--> -6577--> -6578--> -6579--> -658--> -6580--> -6581--> -6582--> -6583--> -6584--> -6585--> -6586--> -6587--> -6588--> -6589--> -659--> -6590--> -6591--> -6592--> -6593--> -6594--> -6595--> -6596--> -6597--> -6598--> -6599--> -66--> -660--> -6600--> -6601--> -6602--> -6603--> -6604--> -6605--> -6606--> -6607--> -6608--> -6609--> -661--> -6610--> -6611--> -6612--> -6613--> -6614--> -6615--> -6616--> -6617--> -6618--> -6619--> -662--> -6620--> -6621--> -6622--> -6623--> -6624--> -6625--> -6626--> -6627--> -6628--> -6629--> -663--> -6630--> -6631--> -6632--> -6633--> -6634--> -6635--> -6636--> -6637--> -6638--> -6639--> -664--> -6640--> -6641--> -6642--> -6643--> -6644--> -6645--> -6646--> -6647--> -6648--> -6649--> -665--> -6650--> -6651--> -6652--> -6653--> -6654--> -6655--> -6656--> -6657--> -6658--> -6659--> -666--> -6660--> -6661--> -6662--> -6663--> -6664--> -6665--> -6666--> -6667--> -6668--> -6669--> -667--> -6670--> -6671--> -6672--> -6673--> -6674--> -6675--> -6676--> -6677--> -6678--> -6679--> -668--> -6680--> -6681--> -6682--> -6683--> -6684--> -6685--> -6686--> -6687--> -6688--> -6689--> -669--> -6690--> -6691--> -6692--> -6693--> -6694--> -6695--> -6696--> -6697--> -6698--> -6699--> -67--> -670--> -6700--> -6701--> -6702--> -6703--> -6704--> -6705--> -6706--> -6707--> -6708--> -6709--> -671--> -6710--> -6711--> -6712--> -6713--> -6714--> -6715--> -6716--> -6717--> -6718--> -6719--> -672--> -6720--> -6721--> -6722--> -6723--> -6724--> -6725--> -6726--> -6727--> -6728--> -6729--> -673--> -6730--> -6731--> -6732--> -6733--> -6734--> -6735--> -6736--> -6737--> -6738--> -6739--> -674--> -6740--> -6741--> -6742--> -6743--> -6744--> -6745--> -6746--> -6747--> -6748--> -6749--> -675--> -6750--> -6751--> -6752--> -6753--> -6754--> -6755--> -6756--> -6757--> -6758--> -6759--> -676--> -6760--> -6761--> -6762--> -6763--> -6764--> -6765--> -6766--> -6767--> -6768--> -6769--> -677--> -6770--> -6771--> -6772--> -6773--> -6774--> -6775--> -6776--> -6777--> -6778--> -6779--> -678--> -6780--> -6781--> -6782--> -6783--> -6784--> -6785--> -6786--> -6787--> -6788--> -6789--> -679--> -6790--> -6791--> -6792--> -6793--> -6794--> -6795--> -6796--> -6797--> -6798--> -6799--> -68--> -680--> -6800--> -6801--> -6802--> -6803--> -6804--> -6805--> -6806--> -6807--> -6808--> -6809--> -681--> -6810--> -6811--> -6812--> -6813--> -6814--> -6815--> -6816--> -6817--> -6818--> -6819--> -682--> -6820--> -6821--> -6822--> -6823--> -6824--> -6825--> -6826--> -6827--> -6828--> -6829--> -683--> -6830--> -6831--> -6832--> -6833--> -6834--> -6835--> -6836--> -6837--> -6838--> -6839--> -684--> -6840--> -6841--> -6842--> -6843--> -6844--> -6845--> -6846--> -6847--> -6848--> -6849--> -685--> -6850--> -6851--> -6852--> -6853--> -6854--> -6855--> -6856--> -6857--> -6858--> -6859--> -686--> -6860--> -6861--> -6862--> -6863--> -6864--> -6865--> -6866--> -6867--> -6868--> -6869--> -687--> -6870--> -6871--> -6872--> -6873--> -6874--> -6875--> -6876--> -6877--> -6878--> -6879--> -688--> -6880--> -6881--> -6882--> -6883--> -6884--> -6885--> -6886--> -6887--> -6888--> -6889--> -689--> -6890--> -6891--> -6892--> -6893--> -6894--> -6895--> -6896--> -6897--> -6898--> -6899--> -69--> -690--> -6900--> -6901--> -6902--> -6903--> -6904--> -6905--> -6906--> -6907--> -6908--> -6909--> -691--> -6910--> -6911--> -6912--> -6913--> -6914--> -6915--> -6916--> -6917--> -6918--> -6919--> -692--> -6920--> -6921--> -6922--> -6923--> -6924--> -6925--> -6926--> -6927--> -6928--> -6929--> -693--> -6930--> -6931--> -6932--> -6933--> -6934--> -6935--> -6936--> -6937--> -6938--> -6939--> -694--> -6940--> -6941--> -6942--> -6943--> -6944--> -6945--> -6946--> -6947--> -6948--> -6949--> -695--> -6950--> -6951--> -6952--> -6953--> -6954--> -6955--> -6956--> -6957--> -6958--> -6959--> -696--> -6960--> -6961--> -6962--> -6963--> -6964--> -6965--> -6966--> -6967--> -6968--> -6969--> -697--> -6970--> -6971--> -6972--> -6973--> -6974--> -6975--> -6976--> -6977--> -6978--> -6979--> -698--> -6980--> -6981--> -6982--> -6983--> -6984--> -6985--> -6986--> -6987--> -6988--> -6989--> -699--> -6990--> -6991--> -6992--> -6993--> -6994--> -6995--> -6996--> -6997--> -6998--> -6999--> -7--> -70--> -700--> -7000--> -7001--> -7002--> -7003--> -7004--> -7005--> -7006--> -7007--> -7008--> -7009--> -701--> -7010--> -7011--> -7012--> -7013--> -7014--> -7015--> -7016--> -7017--> -7018--> -7019--> -702--> -7020--> -7021--> -7022--> -7023--> -7024--> -7025--> -7026--> -7027--> -7028--> -7029--> -703--> -7030--> -7031--> -7032--> -7033--> -7034--> -7035--> -7036--> -7037--> -7038--> -7039--> -704--> -7040--> -7041--> -7042--> -7043--> -7044--> -7045--> -7046--> -7047--> -7048--> -7049--> -705--> -7050--> -7051--> -7052--> -7053--> -7054--> -7055--> -7056--> -7057--> -7058--> -7059--> -706--> -7060--> -7061--> -7062--> -7063--> -7064--> -7065--> -7066--> -7067--> -7068--> -7069--> -707--> -7070--> -7071--> -7072--> -7073--> -7074--> -7075--> -7076--> -7077--> -7078--> -7079--> -708--> -7080--> -7081--> -7082--> -7083--> -7084--> -7085--> -7086--> -7087--> -7088--> -7089--> -709--> -7090--> -7091--> -7092--> -7093--> -7094--> -7095--> -7096--> -7097--> -7098--> -7099--> -71--> -710--> -7100--> -7101--> -7102--> -7103--> -7104--> -7105--> -7106--> -7107--> -7108--> -7109--> -711--> -7110--> -7111--> -7112--> -7113--> -7114--> -7115--> -7116--> -7117--> -7118--> -7119--> -712--> -7120--> -7121--> -7122--> -7123--> -7124--> -7125--> -7126--> -7127--> -7128--> -7129--> -713--> -7130--> -7131--> -7132--> -7133--> -7134--> -7135--> -7136--> -7137--> -7138--> -7139--> -714--> -7140--> -7141--> -7142--> -7143--> -7144--> -7145--> -7146--> -7147--> -7148--> -7149--> -715--> -7150--> -7151--> -7152--> -7153--> -7154--> -7155--> -7156--> -7157--> -7158--> -7159--> -716--> -7160--> -7161--> -7162--> -7163--> -7164--> -7165--> -7166--> -7167--> -7168--> -7169--> -717--> -7170--> -7171--> -7172--> -7173--> -7174--> -7175--> -7176--> -7177--> -7178--> -7179--> -718--> -7180--> -7181--> -7182--> -7183--> -7184--> -7185--> -7186--> -7187--> -7188--> -7189--> -719--> -7190--> -7191--> -7192--> -7193--> -7194--> -7195--> -7196--> -7197--> -7198--> -7199--> -72--> -720--> -7200--> -7201--> -7202--> -7203--> -7204--> -7205--> -7206--> -7207--> -7208--> -7209--> -721--> -7210--> -7211--> -7212--> -7213--> -7214--> -7215--> -7216--> -7217--> -7218--> -7219--> -722--> -7220--> -7221--> -7222--> -7223--> -7224--> -7225--> -7226--> -7227--> -7228--> -7229--> -723--> -7230--> -7231--> -7232--> -7233--> -7234--> -7235--> -7236--> -7237--> -7238--> -7239--> -724--> -7240--> -7241--> -7242--> -7243--> -7244--> -7245--> -7246--> -7247--> -7248--> -7249--> -725--> -7250--> -7251--> -7252--> -7253--> -7254--> -7255--> -7256--> -7257--> -7258--> -7259--> -726--> -7260--> -7261--> -7262--> -7263--> -7264--> -7265--> -7266--> -7267--> -7268--> -7269--> -727--> -7270--> -7271--> -7272--> -7273--> -7274--> -7275--> -7276--> -7277--> -7278--> -7279--> -728--> -7280--> -7281--> -7282--> -7283--> -7284--> -7285--> -7286--> -7287--> -7288--> -7289--> -729--> -7290--> -7291--> -7292--> -7293--> -7294--> -7295--> -7296--> -7297--> -7298--> -7299--> -73--> -730--> -7300--> -7301--> -7302--> -7303--> -7304--> -7305--> -7306--> -7307--> -7308--> -7309--> -731--> -7310--> -7311--> -7312--> -7313--> -7314--> -7315--> -7316--> -7317--> -7318--> -7319--> -732--> -7320--> -7321--> -7322--> -7323--> -7324--> -7325--> -7326--> -7327--> -7328--> -7329--> -733--> -7330--> -7331--> -7332--> -7333--> -7334--> -7335--> -7336--> -7337--> -7338--> -7339--> -734--> -7340--> -7341--> -7342--> -7343--> -7344--> -7345--> -7346--> -7347--> -7348--> -7349--> -735--> -7350--> -7351--> -7352--> -7353--> -7354--> -7355--> -7356--> -7357--> -7358--> -7359--> -736--> -7360--> -7361--> -7362--> -7363--> -7364--> -7365--> -7366--> -7367--> -7368--> -7369--> -737--> -7370--> -7371--> -7372--> -7373--> -7374--> -7375--> -7376--> -7377--> -7378--> -7379--> -738--> -7380--> -7381--> -7382--> -7383--> -7384--> -7385--> -7386--> -7387--> -7388--> -7389--> -739--> -7390--> -7391--> -7392--> -7393--> -7394--> -7395--> -7396--> -7397--> -7398--> -7399--> -74--> -740--> -7400--> -7401--> -7402--> -7403--> -7404--> -7405--> -7406--> -7407--> -7408--> -7409--> -741--> -7410--> -7411--> -7412--> -7413--> -7414--> -7415--> -7416--> -7417--> -7418--> -7419--> -742--> -7420--> -7421--> -7422--> -7423--> -7424--> -7425--> -7426--> -7427--> -7428--> -7429--> -743--> -7430--> -7431--> -7432--> -7433--> -7434--> -7435--> -7436--> -7437--> -7438--> -7439--> -744--> -7440--> -7441--> -7442--> -7443--> -7444--> -7445--> -7446--> -7447--> -7448--> -7449--> -745--> -7450--> -7451--> -7452--> -7453--> -7454--> -7455--> -7456--> -7457--> -7458--> -7459--> -746--> -7460--> -7461--> -7462--> -7463--> -7464--> -7465--> -7466--> -7467--> -7468--> -7469--> -747--> -7470--> -7471--> -7472--> -7473--> -7474--> -7475--> -7476--> -7477--> -7478--> -7479--> -748--> -7480--> -7481--> -7482--> -7483--> -7484--> -7485--> -7486--> -7487--> -7488--> -7489--> -749--> -7490--> -7491--> -7492--> -7493--> -7494--> -7495--> -7496--> -7497--> -7498--> -7499--> -75--> -750--> -7500--> -7501--> -7502--> -7503--> -7504--> -7505--> -7506--> -7507--> -7508--> -7509--> -751--> -7510--> -7511--> -7512--> -7513--> -7514--> -7515--> -7516--> -7517--> -7518--> -7519--> -752--> -7520--> -7521--> -7522--> -7523--> -7524--> -7525--> -7526--> -7527--> -7528--> -7529--> -753--> -7530--> -7531--> -7532--> -7533--> -7534--> -7535--> -7536--> -7537--> -7538--> -7539--> -754--> -7540--> -7541--> -7542--> -7543--> -7544--> -7545--> -7546--> -7547--> -7548--> -7549--> -755--> -7550--> -7551--> -7552--> -7553--> -7554--> -7555--> -7556--> -7557--> -7558--> -7559--> -756--> -7560--> -7561--> -7562--> -7563--> -7564--> -7565--> -7566--> -7567--> -7568--> -7569--> -757--> -7570--> -7571--> -7572--> -7573--> -7574--> -7575--> -7576--> -7577--> -7578--> -7579--> -758--> -7580--> -7581--> -7582--> -7583--> -7584--> -7585--> -7586--> -7587--> -7588--> -7589--> -759--> -7590--> -7591--> -7592--> -7593--> -7594--> -7595--> -7596--> -7597--> -7598--> -7599--> -76--> -760--> -7600--> -7601--> -7602--> -7603--> -7604--> -7605--> -7606--> -7607--> -7608--> -7609--> -761--> -7610--> -7611--> -7612--> -7613--> -7614--> -7615--> -7616--> -7617--> -7618--> -7619--> -762--> -7620--> -7621--> -7622--> -7623--> -7624--> -7625--> -7626--> -7627--> -7628--> -7629--> -763--> -7630--> -7631--> -7632--> -7633--> -7634--> -7635--> -7636--> -7637--> -7638--> -7639--> -764--> -7640--> -7641--> -7642--> -7643--> -7644--> -7645--> -7646--> -7647--> -7648--> -7649--> -765--> -7650--> -7651--> -7652--> -7653--> -7654--> -7655--> -7656--> -7657--> -7658--> -7659--> -766--> -7660--> -7661--> -7662--> -7663--> -7664--> -7665--> -7666--> -7667--> -7668--> -7669--> -767--> -7670--> -7671--> -7672--> -7673--> -7674--> -7675--> -7676--> -7677--> -7678--> -7679--> -768--> -7680--> -7681--> -7682--> -7683--> -7684--> -7685--> -7686--> -7687--> -7688--> -7689--> -769--> -7690--> -7691--> -7692--> -7693--> -7694--> -7695--> -7696--> -7697--> -7698--> -7699--> -77--> -770--> -7700--> -7701--> -7702--> -7703--> -7704--> -7705--> -7706--> -7707--> -7708--> -7709--> -771--> -7710--> -7711--> -7712--> -7713--> -7714--> -7715--> -7716--> -7717--> -7718--> -7719--> -772--> -7720--> -7721--> -7722--> -7723--> -7724--> -7725--> -7726--> -7727--> -7728--> -7729--> -773--> -7730--> -7731--> -7732--> -7733--> -7734--> -7735--> -7736--> -7737--> -7738--> -7739--> -774--> -7740--> -7741--> -7742--> -7743--> -7744--> -7745--> -7746--> -7747--> -7748--> -7749--> -775--> -7750--> -7751--> -7752--> -7753--> -7754--> -7755--> -7756--> -7757--> -7758--> -7759--> -776--> -7760--> -7761--> -7762--> -7763--> -7764--> -7765--> -7766--> -7767--> -7768--> -7769--> -777--> -7770--> -7771--> -7772--> -7773--> -7774--> -7775--> -7776--> -7777--> -7778--> -7779--> -778--> -7780--> -7781--> -7782--> -7783--> -7784--> -7785--> -7786--> -7787--> -7788--> -7789--> -779--> -7790--> -7791--> -7792--> -7793--> -7794--> -7795--> -7796--> -7797--> -7798--> -7799--> -78--> -780--> -7800--> -7801--> -7802--> -7803--> -7804--> -7805--> -7806--> -7807--> -7808--> -7809--> -781--> -7810--> -7811--> -7812--> -7813--> -7814--> -7815--> -7816--> -7817--> -7818--> -7819--> -782--> -7820--> -7821--> -7822--> -7823--> -7824--> -7825--> -7826--> -7827--> -7828--> -7829--> -783--> -7830--> -7831--> -7832--> -7833--> -7834--> -7835--> -7836--> -7837--> -7838--> -7839--> -784--> -7840--> -7841--> -7842--> -7843--> -7844--> -7845--> -7846--> -7847--> -7848--> -7849--> -785--> -7850--> -7851--> -7852--> -7853--> -7854--> -7855--> -7856--> -7857--> -7858--> -7859--> -786--> -7860--> -7861--> -7862--> -7863--> -7864--> -7865--> -7866--> -7867--> -7868--> -7869--> -787--> -7870--> -7871--> -7872--> -7873--> -7874--> -7875--> -7876--> -7877--> -7878--> -7879--> -788--> -7880--> -7881--> -7882--> -7883--> -7884--> -7885--> -7886--> -7887--> -7888--> -7889--> -789--> -7890--> -7891--> -7892--> -7893--> -7894--> -7895--> -7896--> -7897--> -7898--> -7899--> -79--> -790--> -7900--> -7901--> -7902--> -7903--> -7904--> -7905--> -7906--> -7907--> -7908--> -7909--> -791--> -7910--> -7911--> -7912--> -7913--> -7914--> -7915--> -7916--> -7917--> -7918--> -7919--> -792--> -7920--> -7921--> -7922--> -7923--> -7924--> -7925--> -7926--> -7927--> -7928--> -7929--> -793--> -7930--> -7931--> -7932--> -7933--> -7934--> -7935--> -7936--> -7937--> -7938--> -7939--> -794--> -7940--> -7941--> -7942--> -7943--> -7944--> -7945--> -7946--> -7947--> -7948--> -7949--> -795--> -7950--> -7951--> -7952--> -7953--> -7954--> -7955--> -7956--> -7957--> -7958--> -7959--> -796--> -7960--> -7961--> -7962--> -7963--> -7964--> -7965--> -7966--> -7967--> -7968--> -7969--> -797--> -7970--> -7971--> -7972--> -7973--> -7974--> -7975--> -7976--> -7977--> -7978--> -7979--> -798--> -7980--> -7981--> -7982--> -7983--> -7984--> -7985--> -7986--> -7987--> -7988--> -7989--> -799--> -7990--> -7991--> -7992--> -7993--> -7994--> -7995--> -7996--> -7997--> -7998--> -7999--> -8--> -80--> -800--> -8000--> -8001--> -8002--> -8003--> -8004--> -8005--> -8006--> -8007--> -8008--> -8009--> -801--> -8010--> -8011--> -8012--> -8013--> -8014--> -8015--> -8016--> -8017--> -8018--> -8019--> -802--> -8020--> -8021--> -8022--> -8023--> -8024--> -8025--> -8026--> -8027--> -8028--> -8029--> -803--> -8030--> -8031--> -8032--> -8033--> -8034--> -8035--> -8036--> -8037--> -8038--> -8039--> -804--> -8040--> -8041--> -8042--> -8043--> -8044--> -8045--> -8046--> -8047--> -8048--> -8049--> -805--> -8050--> -8051--> -8052--> -8053--> -8054--> -8055--> -8056--> -8057--> -8058--> -8059--> -806--> -8060--> -8061--> -8062--> -8063--> -8064--> -8065--> -8066--> -8067--> -8068--> -8069--> -807--> -8070--> -8071--> -8072--> -8073--> -8074--> -8075--> -8076--> -8077--> -8078--> -8079--> -808--> -8080--> -8081--> -8082--> -8083--> -8084--> -8085--> -8086--> -8087--> -8088--> -8089--> -809--> -8090--> -8091--> -8092--> -8093--> -8094--> -8095--> -8096--> -8097--> -8098--> -8099--> -81--> -810--> -8100--> -8101--> -8102--> -8103--> -8104--> -8105--> -8106--> -8107--> -8108--> -8109--> -811--> -8110--> -8111--> -8112--> -8113--> -8114--> -8115--> -8116--> -8117--> -8118--> -8119--> -812--> -8120--> -8121--> -8122--> -8123--> -8124--> -8125--> -8126--> -8127--> -8128--> -8129--> -813--> -8130--> -8131--> -8132--> -8133--> -8134--> -8135--> -8136--> -8137--> -8138--> -8139--> -814--> -8140--> -8141--> -8142--> -8143--> -8144--> -8145--> -8146--> -8147--> -8148--> -8149--> -815--> -8150--> -8151--> -8152--> -8153--> -8154--> -8155--> -8156--> -8157--> -8158--> -8159--> -816--> -8160--> -8161--> -8162--> -8163--> -8164--> -8165--> -8166--> -8167--> -8168--> -8169--> -817--> -8170--> -8171--> -8172--> -8173--> -8174--> -8175--> -8176--> -8177--> -8178--> -8179--> -818--> -8180--> -8181--> -8182--> -8183--> -8184--> -8185--> -8186--> -8187--> -8188--> -8189--> -819--> -8190--> -8191--> -8192--> -8193--> -8194--> -8195--> -8196--> -8197--> -8198--> -8199--> -82--> -820--> -8200--> -8201--> -8202--> -8203--> -8204--> -8205--> -8206--> -8207--> -8208--> -8209--> -821--> -8210--> -8211--> -8212--> -8213--> -8214--> -8215--> -8216--> -8217--> -8218--> -8219--> -822--> -8220--> -8221--> -8222--> -8223--> -8224--> -8225--> -8226--> -8227--> -8228--> -8229--> -823--> -8230--> -8231--> -8232--> -8233--> -8234--> -8235--> -8236--> -8237--> -8238--> -8239--> -824--> -8240--> -8241--> -8242--> -8243--> -8244--> -8245--> -8246--> -8247--> -8248--> -8249--> -825--> -8250--> -8251--> -8252--> -8253--> -8254--> -8255--> -8256--> -8257--> -8258--> -8259--> -826--> -8260--> -8261--> -8262--> -8263--> -8264--> -8265--> -8266--> -8267--> -8268--> -8269--> -827--> -8270--> -8271--> -8272--> -8273--> -8274--> -8275--> -8276--> -8277--> -8278--> -8279--> -828--> -8280--> -8281--> -8282--> -8283--> -8284--> -8285--> -8286--> -8287--> -8288--> -8289--> -829--> -8290--> -8291--> -8292--> -8293--> -8294--> -8295--> -8296--> -8297--> -8298--> -8299--> -83--> -830--> -8300--> -8301--> -8302--> -8303--> -8304--> -8305--> -8306--> -8307--> -8308--> -8309--> -831--> -8310--> -8311--> -8312--> -8313--> -8314--> -8315--> -8316--> -8317--> -8318--> -8319--> -832--> -8320--> -8321--> -8322--> -8323--> -8324--> -8325--> -8326--> -8327--> -8328--> -8329--> -833--> -8330--> -8331--> -8332--> -8333--> -8334--> -8335--> -8336--> -8337--> -8338--> -8339--> -834--> -8340--> -8341--> -8342--> -8343--> -8344--> -8345--> -8346--> -8347--> -8348--> -8349--> -835--> -8350--> -8351--> -8352--> -8353--> -8354--> -8355--> -8356--> -8357--> -8358--> -8359--> -836--> -8360--> -8361--> -8362--> -8363--> -8364--> -8365--> -8366--> -8367--> -8368--> -8369--> -837--> -8370--> -8371--> -8372--> -8373--> -8374--> -8375--> -8376--> -8377--> -8378--> -8379--> -838--> -8380--> -8381--> -8382--> -8383--> -8384--> -8385--> -8386--> -8387--> -8388--> -8389--> -839--> -8390--> -8391--> -8392--> -8393--> -8394--> -8395--> -8396--> -8397--> -8398--> -8399--> -84--> -840--> -8400--> -8401--> -8402--> -8403--> -8404--> -8405--> -8406--> -8407--> -8408--> -8409--> -841--> -8410--> -8411--> -8412--> -8413--> -8414--> -8415--> -8416--> -8417--> -8418--> -8419--> -842--> -8420--> -8421--> -8422--> -8423--> -8424--> -8425--> -8426--> -8427--> -8428--> -8429--> -843--> -8430--> -8431--> -8432--> -8433--> -8434--> -8435--> -8436--> -8437--> -8438--> -8439--> -844--> -8440--> -8441--> -8442--> -8443--> -8444--> -8445--> -8446--> -8447--> -8448--> -8449--> -845--> -8450--> -8451--> -8452--> -8453--> -8454--> -8455--> -8456--> -8457--> -8458--> -8459--> -846--> -8460--> -8461--> -8462--> -8463--> -8464--> -8465--> -8466--> -8467--> -8468--> -8469--> -847--> -8470--> -8471--> -8472--> -8473--> -8474--> -8475--> -8476--> -8477--> -8478--> -8479--> -848--> -8480--> -8481--> -8482--> -8483--> -8484--> -8485--> -8486--> -8487--> -8488--> -8489--> -849--> -8490--> -8491--> -8492--> -8493--> -8494--> -8495--> -8496--> -8497--> -8498--> -8499--> -85--> -850--> -8500--> -8501--> -8502--> -8503--> -8504--> -8505--> -8506--> -8507--> -8508--> -8509--> -851--> -8510--> -8511--> -8512--> -8513--> -8514--> -8515--> -8516--> -8517--> -8518--> -8519--> -852--> -8520--> -8521--> -8522--> -8523--> -8524--> -8525--> -8526--> -8527--> -8528--> -8529--> -853--> -8530--> -8531--> -8532--> -8533--> -8534--> -8535--> -8536--> -8537--> -8538--> -8539--> -854--> -8540--> -8541--> -8542--> -8543--> -8544--> -8545--> -8546--> -8547--> -8548--> -8549--> -855--> -8550--> -8551--> -8552--> -8553--> -8554--> -8555--> -8556--> -8557--> -8558--> -8559--> -856--> -8560--> -8561--> -8562--> -8563--> -8564--> -8565--> -8566--> -8567--> -8568--> -8569--> -857--> -8570--> -8571--> -8572--> -8573--> -8574--> -8575--> -8576--> -8577--> -8578--> -8579--> -858--> -8580--> -8581--> -8582--> -8583--> -8584--> -8585--> -8586--> -8587--> -8588--> -8589--> -859--> -8590--> -8591--> -8592--> -8593--> -8594--> -8595--> -8596--> -8597--> -8598--> -8599--> -86--> -860--> -8600--> -8601--> -8602--> -8603--> -8604--> -8605--> -8606--> -8607--> -8608--> -8609--> -861--> -8610--> -8611--> -8612--> -8613--> -8614--> -8615--> -8616--> -8617--> -8618--> -8619--> -862--> -8620--> -8621--> -8622--> -8623--> -8624--> -8625--> -8626--> -8627--> -8628--> -8629--> -863--> -8630--> -8631--> -8632--> -8633--> -8634--> -8635--> -8636--> -8637--> -8638--> -8639--> -864--> -8640--> -8641--> -8642--> -8643--> -8644--> -8645--> -8646--> -8647--> -8648--> -8649--> -865--> -8650--> -8651--> -8652--> -8653--> -8654--> -8655--> -8656--> -8657--> -8658--> -8659--> -866--> -8660--> -8661--> -8662--> -8663--> -8664--> -8665--> -8666--> -8667--> -8668--> -8669--> -867--> -8670--> -8671--> -8672--> -8673--> -8674--> -8675--> -8676--> -8677--> -8678--> -8679--> -868--> -8680--> -8681--> -8682--> -8683--> -8684--> -8685--> -8686--> -8687--> -8688--> -8689--> -869--> -8690--> -8691--> -8692--> -8693--> -8694--> -8695--> -8696--> -8697--> -8698--> -8699--> -87--> -870--> -8700--> -8701--> -8702--> -8703--> -8704--> -8705--> -8706--> -8707--> -8708--> -8709--> -871--> -8710--> -8711--> -8712--> -8713--> -8714--> -8715--> -8716--> -8717--> -8718--> -8719--> -872--> -8720--> -8721--> -8722--> -8723--> -8724--> -8725--> -8726--> -8727--> -8728--> -8729--> -873--> -8730--> -8731--> -8732--> -8733--> -8734--> -8735--> -8736--> -8737--> -8738--> -8739--> -874--> -8740--> -8741--> -8742--> -8743--> -8744--> -8745--> -8746--> -8747--> -8748--> -8749--> -875--> -8750--> -8751--> -8752--> -8753--> -8754--> -8755--> -8756--> -8757--> -8758--> -8759--> -876--> -8760--> -8761--> -8762--> -8763--> -8764--> -8765--> -8766--> -8767--> -8768--> -8769--> -877--> -8770--> -8771--> -8772--> -8773--> -8774--> -8775--> -8776--> -8777--> -8778--> -8779--> -878--> -8780--> -8781--> -8782--> -8783--> -8784--> -8785--> -8786--> -8787--> -8788--> -8789--> -879--> -8790--> -8791--> -8792--> -8793--> -8794--> -8795--> -8796--> -8797--> -8798--> -8799--> -88--> -880--> -8800--> -8801--> -8802--> -8803--> -8804--> -8805--> -8806--> -8807--> -8808--> -8809--> -881--> -8810--> -8811--> -8812--> -8813--> -8814--> -8815--> -8816--> -8817--> -8818--> -8819--> -882--> -8820--> -8821--> -8822--> -8823--> -8824--> -8825--> -8826--> -8827--> -8828--> -8829--> -883--> -8830--> -8831--> -8832--> -8833--> -8834--> -8835--> -8836--> -8837--> -8838--> -8839--> -884--> -8840--> -8841--> -8842--> -8843--> -8844--> -8845--> -8846--> -8847--> -8848--> -8849--> -885--> -8850--> -8851--> -8852--> -8853--> -8854--> -8855--> -8856--> -8857--> -8858--> -8859--> -886--> -8860--> -8861--> -8862--> -8863--> -8864--> -8865--> -8866--> -8867--> -8868--> -8869--> -887--> -8870--> -8871--> -8872--> -8873--> -8874--> -8875--> -8876--> -8877--> -8878--> -8879--> -888--> -8880--> -8881--> -8882--> -8883--> -8884--> -8885--> -8886--> -8887--> -8888--> -8889--> -889--> -8890--> -8891--> -8892--> -8893--> -8894--> -8895--> -8896--> -8897--> -8898--> -8899--> -89--> -890--> -8900--> -8901--> -8902--> -8903--> -8904--> -8905--> -8906--> -8907--> -8908--> -8909--> -891--> -8910--> -8911--> -8912--> -8913--> -8914--> -8915--> -8916--> -8917--> -8918--> -8919--> -892--> -8920--> -8921--> -8922--> -8923--> -8924--> -8925--> -8926--> -8927--> -8928--> -8929--> -893--> -8930--> -8931--> -8932--> -8933--> -8934--> -8935--> -8936--> -8937--> -8938--> -8939--> -894--> -8940--> -8941--> -8942--> -8943--> -8944--> -8945--> -8946--> -8947--> -8948--> -8949--> -895--> -8950--> -8951--> -8952--> -8953--> -8954--> -8955--> -8956--> -8957--> -8958--> -8959--> -896--> -8960--> -8961--> -8962--> -8963--> -8964--> -8965--> -8966--> -8967--> -8968--> -8969--> -897--> -8970--> -8971--> -8972--> -8973--> -8974--> -8975--> -8976--> -8977--> -8978--> -8979--> -898--> -8980--> -8981--> -8982--> -8983--> -8984--> -8985--> -8986--> -8987--> -8988--> -8989--> -899--> -8990--> -8991--> -8992--> -8993--> -8994--> -8995--> -8996--> -8997--> -8998--> -8999--> -9--> -90--> -900--> -9000--> -9001--> -9002--> -9003--> -9004--> -9005--> -9006--> -9007--> -9008--> -9009--> -901--> -9010--> -9011--> -9012--> -9013--> -9014--> -9015--> -9016--> -9017--> -9018--> -9019--> -902--> -9020--> -9021--> -9022--> -9023--> -9024--> -9025--> -9026--> -9027--> -9028--> -9029--> -903--> -9030--> -9031--> -9032--> -9033--> -9034--> -9035--> -9036--> -9037--> -9038--> -9039--> -904--> -9040--> -9041--> -9042--> -9043--> -9044--> -9045--> -9046--> -9047--> -9048--> -9049--> -905--> -9050--> -9051--> -9052--> -9053--> -9054--> -9055--> -9056--> -9057--> -9058--> -9059--> -906--> -9060--> -9061--> -9062--> -9063--> -9064--> -9065--> -9066--> -9067--> -9068--> -9069--> -907--> -9070--> -9071--> -9072--> -9073--> -9074--> -9075--> -9076--> -9077--> -9078--> -9079--> -908--> -9080--> -9081--> -9082--> -9083--> -9084--> -9085--> -9086--> -9087--> -9088--> -9089--> -909--> -9090--> -9091--> -9092--> -9093--> -9094--> -9095--> -9096--> -9097--> -9098--> -9099--> -91--> -910--> -9100--> -9101--> -9102--> -9103--> -9104--> -9105--> -9106--> -9107--> -9108--> -9109--> -911--> -9110--> -9111--> -9112--> -9113--> -9114--> -9115--> -9116--> -9117--> -9118--> -9119--> -912--> -9120--> -9121--> -9122--> -9123--> -9124--> -9125--> -9126--> -9127--> -9128--> -9129--> -913--> -9130--> -9131--> -9132--> -9133--> -9134--> -9135--> -9136--> -9137--> -9138--> -9139--> -914--> -9140--> -9141--> -9142--> -9143--> -9144--> -9145--> -9146--> -9147--> -9148--> -9149--> -915--> -9150--> -9151--> -9152--> -9153--> -9154--> -9155--> -9156--> -9157--> -9158--> -9159--> -916--> -9160--> -9161--> -9162--> -9163--> -9164--> -9165--> -9166--> -9167--> -9168--> -9169--> -917--> -9170--> -9171--> -9172--> -9173--> -9174--> -9175--> -9176--> -9177--> -9178--> -9179--> -918--> -9180--> -9181--> -9182--> -9183--> -9184--> -9185--> -9186--> -9187--> -9188--> -9189--> -919--> -9190--> -9191--> -9192--> -9193--> -9194--> -9195--> -9196--> -9197--> -9198--> -9199--> -92--> -920--> -9200--> -9201--> -9202--> -9203--> -9204--> -9205--> -9206--> -9207--> -9208--> -9209--> -921--> -9210--> -9211--> -9212--> -9213--> -9214--> -9215--> -9216--> -9217--> -9218--> -9219--> -922--> -9220--> -9221--> -9222--> -9223--> -9224--> -9225--> -9226--> -9227--> -9228--> -9229--> -923--> -9230--> -9231--> -9232--> -9233--> -9234--> -9235--> -9236--> -9237--> -9238--> -9239--> -924--> -9240--> -9241--> -9242--> -9243--> -9244--> -9245--> -9246--> -9247--> -9248--> -9249--> -925--> -9250--> -9251--> -9252--> -9253--> -9254--> -9255--> -9256--> -9257--> -9258--> -9259--> -926--> -9260--> -9261--> -9262--> -9263--> -9264--> -9265--> -9266--> -9267--> -9268--> -9269--> -927--> -9270--> -9271--> -9272--> -9273--> -9274--> -9275--> -9276--> -9277--> -9278--> -9279--> -928--> -9280--> -9281--> -9282--> -9283--> -9284--> -9285--> -9286--> -9287--> -9288--> -9289--> -929--> -9290--> -9291--> -9292--> -9293--> -9294--> -9295--> -9296--> -9297--> -9298--> -9299--> -93--> -930--> -9300--> -9301--> -9302--> -9303--> -9304--> -9305--> -9306--> -9307--> -9308--> -9309--> -931--> -9310--> -9311--> -9312--> -9313--> -9314--> -9315--> -9316--> -9317--> -9318--> -9319--> -932--> -9320--> -9321--> -9322--> -9323--> -9324--> -9325--> -9326--> -9327--> -9328--> -9329--> -933--> -9330--> -9331--> -9332--> -9333--> -9334--> -9335--> -9336--> -9337--> -9338--> -9339--> -934--> -9340--> -9341--> -9342--> -9343--> -9344--> -9345--> -9346--> -9347--> -9348--> -9349--> -935--> -9350--> -9351--> -9352--> -9353--> -9354--> -9355--> -9356--> -9357--> -9358--> -9359--> -936--> -9360--> -9361--> -9362--> -9363--> -9364--> -9365--> -9366--> -9367--> -9368--> -9369--> -937--> -9370--> -9371--> -9372--> -9373--> -9374--> -9375--> -9376--> -9377--> -9378--> -9379--> -938--> -9380--> -9381--> -9382--> -9383--> -9384--> -9385--> -9386--> -9387--> -9388--> -9389--> -939--> -9390--> -9391--> -9392--> -9393--> -9394--> -9395--> -9396--> -9397--> -9398--> -9399--> -94--> -940--> -9400--> -9401--> -9402--> -9403--> -9404--> -9405--> -9406--> -9407--> -9408--> -9409--> -941--> -9410--> -9411--> -9412--> -9413--> -9414--> -9415--> -9416--> -9417--> -9418--> -9419--> -942--> -9420--> -9421--> -9422--> -9423--> -9424--> -9425--> -9426--> -9427--> -9428--> -9429--> -943--> -9430--> -9431--> -9432--> -9433--> -9434--> -9435--> -9436--> -9437--> -9438--> -9439--> -944--> -9440--> -9441--> -9442--> -9443--> -9444--> -9445--> -9446--> -9447--> -9448--> -9449--> -945--> -9450--> -9451--> -9452--> -9453--> -9454--> -9455--> -9456--> -9457--> -9458--> -9459--> -946--> -9460--> -9461--> -9462--> -9463--> -9464--> -9465--> -9466--> -9467--> -9468--> -9469--> -947--> -9470--> -9471--> -9472--> -9473--> -9474--> -9475--> -9476--> -9477--> -9478--> -9479--> -948--> -9480--> -9481--> -9482--> -9483--> -9484--> -9485--> -9486--> -9487--> -9488--> -9489--> -949--> -9490--> -9491--> -9492--> -9493--> -9494--> -9495--> -9496--> -9497--> -9498--> -9499--> -95--> -950--> -9500--> -9501--> -9502--> -9503--> -9504--> -9505--> -9506--> -9507--> -9508--> -9509--> -951--> -9510--> -9511--> -9512--> -9513--> -9514--> -9515--> -9516--> -9517--> -9518--> -9519--> -952--> -9520--> -9521--> -9522--> -9523--> -9524--> -9525--> -9526--> -9527--> -9528--> -9529--> -953--> -9530--> -9531--> -9532--> -9533--> -9534--> -9535--> -9536--> -9537--> -9538--> -9539--> -954--> -9540--> -9541--> -9542--> -9543--> -9544--> -9545--> -9546--> -9547--> -9548--> -9549--> -955--> -9550--> -9551--> -9552--> -9553--> -9554--> -9555--> -9556--> -9557--> -9558--> -9559--> -956--> -9560--> -9561--> -9562--> -9563--> -9564--> -9565--> -9566--> -9567--> -9568--> -9569--> -957--> -9570--> -9571--> -9572--> -9573--> -9574--> -9575--> -9576--> -9577--> -9578--> -9579--> -958--> -9580--> -9581--> -9582--> -9583--> -9584--> -9585--> -9586--> -9587--> -9588--> -9589--> -959--> -9590--> -9591--> -9592--> -9593--> -9594--> -9595--> -9596--> -9597--> -9598--> -9599--> -96--> -960--> -9600--> -9601--> -9602--> -9603--> -9604--> -9605--> -9606--> -9607--> -9608--> -9609--> -961--> -9610--> -9611--> -9612--> -9613--> -9614--> -9615--> -9616--> -9617--> -9618--> -9619--> -962--> -9620--> -9621--> -9622--> -9623--> -9624--> -9625--> -9626--> -9627--> -9628--> -9629--> -963--> -9630--> -9631--> -9632--> -9633--> -9634--> -9635--> -9636--> -9637--> -9638--> -9639--> -964--> -9640--> -9641--> -9642--> -9643--> -9644--> -9645--> -9646--> -9647--> -9648--> -9649--> -965--> -9650--> -9651--> -9652--> -9653--> -9654--> -9655--> -9656--> -9657--> -9658--> -9659--> -966--> -9660--> -9661--> -9662--> -9663--> -9664--> -9665--> -9666--> -9667--> -9668--> -9669--> -967--> -9670--> -9671--> -9672--> -9673--> -9674--> -9675--> -9676--> -9677--> -9678--> -9679--> -968--> -9680--> -9681--> -9682--> -9683--> -9684--> -9685--> -9686--> -9687--> -9688--> -9689--> -969--> -9690--> -9691--> -9692--> -9693--> -9694--> -9695--> -9696--> -9697--> -9698--> -9699--> -97--> -970--> -9700--> -9701--> -9702--> -9703--> -9704--> -9705--> -9706--> -9707--> -9708--> -9709--> -971--> -9710--> -9711--> -9712--> -9713--> -9714--> -9715--> -9716--> -9717--> -9718--> -9719--> -972--> -9720--> -9721--> -9722--> -9723--> -9724--> -9725--> -9726--> -9727--> -9728--> -9729--> -973--> -9730--> -9731--> -9732--> -9733--> -9734--> -9735--> -9736--> -9737--> -9738--> -9739--> -974--> -9740--> -9741--> -9742--> -9743--> -9744--> -9745--> -9746--> -9747--> -9748--> -9749--> -975--> -9750--> -9751--> -9752--> -9753--> -9754--> -9755--> -9756--> -9757--> -9758--> -9759--> -976--> -9760--> -9761--> -9762--> -9763--> -9764--> -9765--> -9766--> -9767--> -9768--> -9769--> -977--> -9770--> -9771--> -9772--> -9773--> -9774--> -9775--> -9776--> -9777--> -9778--> -9779--> -978--> -9780--> -9781--> -9782--> -9783--> -9784--> -9785--> -9786--> -9787--> -9788--> -9789--> -979--> -9790--> -9791--> -9792--> -9793--> -9794--> -9795--> -9796--> -9797--> -9798--> -9799--> -98--> -980--> -9800--> -9801--> -9802--> -9803--> -9804--> -9805--> -9806--> -9807--> -9808--> -9809--> -981--> -9810--> -9811--> -9812--> -9813--> -9814--> -9815--> -9816--> -9817--> -9818--> -9819--> -982--> -9820--> -9821--> -9822--> -9823--> -9824--> -9825--> -9826--> -9827--> -9828--> -9829--> -983--> -9830--> -9831--> -9832--> -9833--> -9834--> -9835--> -9836--> -9837--> -9838--> -9839--> -984--> -9840--> -9841--> -9842--> -9843--> -9844--> -9845--> -9846--> -9847--> -9848--> -9849--> -985--> -9850--> -9851--> -9852--> -9853--> -9854--> -9855--> -9856--> -9857--> -9858--> -9859--> -986--> -9860--> -9861--> -9862--> -9863--> -9864--> -9865--> -9866--> -9867--> -9868--> -9869--> -987--> -9870--> -9871--> -9872--> -9873--> -9874--> -9875--> -9876--> -9877--> -9878--> -9879--> -988--> -9880--> -9881--> -9882--> -9883--> -9884--> -9885--> -9886--> -9887--> -9888--> -9889--> -989--> -9890--> -9891--> -9892--> -9893--> -9894--> -9895--> -9896--> -9897--> -9898--> -9899--> -99--> -990--> -9900--> -9901--> -9902--> -9903--> -9904--> -9905--> -9906--> -9907--> -9908--> -9909--> -991--> -9910--> -9911--> -9912--> -9913--> -9914--> -9915--> -9916--> -9917--> -9918--> -9919--> -992--> -9920--> -9921--> -9922--> -9923--> -9924--> -9925--> -9926--> -9927--> -9928--> -9929--> -993--> -9930--> -9931--> -9932--> -9933--> -9934--> -9935--> -9936--> -9937--> -9938--> -9939--> -994--> -9940--> -9941--> -9942--> -9943--> -9944--> -9945--> -9946--> -9947--> -9948--> -9949--> -995--> -9950--> -9951--> -9952--> -9953--> -9954--> -9955--> -9956--> -9957--> -9958--> -9959--> -996--> -9960--> -9961--> -9962--> -9963--> -9964--> -9965--> -9966--> -9967--> -9968--> -9969--> -997--> -9970--> -9971--> -9972--> -9973--> -9974--> -9975--> -9976--> -9977--> -9978--> -9979--> -998--> -9980--> -9981--> -9982--> -9983--> -9984--> -9985--> -9986--> -9987--> -9988--> -9989--> -999--> -9990--> -9991--> -9992--> -9993--> -9994--> -9995--> -9996--> -9997--> -9998--> -9999--> diff --git a/testsuite/tests/lib-threads/test2.checker b/testsuite/tests/lib-threads/test2.checker deleted file mode 100644 index 75f6cf56..00000000 --- a/testsuite/tests/lib-threads/test2.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -sed -e 1q test2.result | grep -q '^[ab]*' diff --git a/testsuite/tests/lib-threads/test2.ml b/testsuite/tests/lib-threads/test2.ml deleted file mode 100644 index 85a5e65a..00000000 --- a/testsuite/tests/lib-threads/test2.ml +++ /dev/null @@ -1,27 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 yield = ref false - -let print_message c = - for i = 1 to 10000 do - print_char c; flush stdout; - if !yield then Thread.yield() - done - -let _ = yield := (Array.length Sys.argv > 1) -let t1 = Thread.create print_message 'a' -let t2 = Thread.create print_message 'b' -let _ = Thread.join t1 -let _ = Thread.join t2 - -;; diff --git a/testsuite/tests/lib-threads/test3.checker b/testsuite/tests/lib-threads/test3.checker deleted file mode 100644 index 88fa4934..00000000 --- a/testsuite/tests/lib-threads/test3.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -sed -e 1q test3.result | grep -q '^[ab]*' diff --git a/testsuite/tests/lib-threads/test3.ml b/testsuite/tests/lib-threads/test3.ml deleted file mode 100644 index 1540363c..00000000 --- a/testsuite/tests/lib-threads/test3.ml +++ /dev/null @@ -1,20 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 print_message delay c = - while true do - print_char c; flush stdout; Thread.delay delay - done - -let _ = - Thread.create (print_message 0.6666666666) 'a'; - print_message 1.0 'b' diff --git a/testsuite/tests/lib-threads/test3.precheck b/testsuite/tests/lib-threads/test3.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/test3.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/test3.runner b/testsuite/tests/lib-threads/test3.runner deleted file mode 100644 index dc04062a..00000000 --- a/testsuite/tests/lib-threads/test3.runner +++ /dev/null @@ -1,16 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program >test3.result & -pid=$! -sleep 5 -kill -9 $pid diff --git a/testsuite/tests/lib-threads/test4.checker b/testsuite/tests/lib-threads/test4.checker deleted file mode 100644 index 38cc6186..00000000 --- a/testsuite/tests/lib-threads/test4.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -LC_ALL=C $SORT -u test4.result | $DIFF test4.reference - diff --git a/testsuite/tests/lib-threads/test4.data b/testsuite/tests/lib-threads/test4.data deleted file mode 100644 index 8edb37e3..00000000 --- a/testsuite/tests/lib-threads/test4.data +++ /dev/null @@ -1,3 +0,0 @@ -abc -def -ghi diff --git a/testsuite/tests/lib-threads/test4.ml b/testsuite/tests/lib-threads/test4.ml deleted file mode 100644 index 7fb789c7..00000000 --- a/testsuite/tests/lib-threads/test4.ml +++ /dev/null @@ -1,33 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 output_lock = Mutex.create() - -let rec fib n = if n <= 2 then 1 else fib(n-1) + fib(n-2) - -let fibtask n = - while true do - let res = fib n in - Mutex.lock output_lock; - print_int res; print_newline(); - Mutex.unlock output_lock - done - -let _ = - Thread.create fibtask 28; - Thread.delay 1.0; - while true do - let l = read_line () in - Mutex.lock output_lock; - print_string ">> "; print_string l; print_newline(); - Mutex.unlock output_lock - done diff --git a/testsuite/tests/lib-threads/test4.reference b/testsuite/tests/lib-threads/test4.reference deleted file mode 100644 index dfcd2b52..00000000 --- a/testsuite/tests/lib-threads/test4.reference +++ /dev/null @@ -1,4 +0,0 @@ -317811 ->> abc ->> def ->> ghi diff --git a/testsuite/tests/lib-threads/test4.runner b/testsuite/tests/lib-threads/test4.runner deleted file mode 100644 index 43ac5632..00000000 --- a/testsuite/tests/lib-threads/test4.runner +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program test4.result 2>/dev/null || true diff --git a/testsuite/tests/lib-threads/test5.checker b/testsuite/tests/lib-threads/test5.checker deleted file mode 100644 index 5eef50b1..00000000 --- a/testsuite/tests/lib-threads/test5.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -LC_ALL=C $SORT -u test5.result | $DIFF test5.reference - diff --git a/testsuite/tests/lib-threads/test5.ml b/testsuite/tests/lib-threads/test5.ml deleted file mode 100644 index 24591919..00000000 --- a/testsuite/tests/lib-threads/test5.ml +++ /dev/null @@ -1,31 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -open Event - -let ch = (new_channel() : string channel) - -let rec sender msg = - sync (send ch msg); - sender msg - -let rec receiver name = - print_string (name ^ ": " ^ sync (receive ch) ^ "\n"); - flush stdout; - receiver name - -let _ = - Thread.create sender "hello"; - Thread.create sender "world"; - Thread.create receiver "A"; - receiver "B"; - exit 0 diff --git a/testsuite/tests/lib-threads/test5.precheck b/testsuite/tests/lib-threads/test5.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/test5.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/test5.reference b/testsuite/tests/lib-threads/test5.reference deleted file mode 100644 index a66a57b2..00000000 --- a/testsuite/tests/lib-threads/test5.reference +++ /dev/null @@ -1,4 +0,0 @@ -A: hello -A: world -B: hello -B: world diff --git a/testsuite/tests/lib-threads/test5.runner b/testsuite/tests/lib-threads/test5.runner deleted file mode 100644 index 80dfe37e..00000000 --- a/testsuite/tests/lib-threads/test5.runner +++ /dev/null @@ -1,16 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program >test5.result & -pid=$! -sleep 3 -kill -9 $pid diff --git a/testsuite/tests/lib-threads/test6.checker b/testsuite/tests/lib-threads/test6.checker deleted file mode 100644 index cc00a631..00000000 --- a/testsuite/tests/lib-threads/test6.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -LC_ALL=C $SORT -u test6.result | $DIFF test6.reference - diff --git a/testsuite/tests/lib-threads/test6.ml b/testsuite/tests/lib-threads/test6.ml deleted file mode 100644 index 1db9911d..00000000 --- a/testsuite/tests/lib-threads/test6.ml +++ /dev/null @@ -1,27 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -open Event - -let ch = (new_channel() : string channel) - -let rec f tag msg = - select [ - send ch msg; - wrap (receive ch) (fun x -> print_string(tag ^ ": " ^ x); print_newline()) - ]; - f tag msg - -let _ = - Thread.create (f "A") "hello"; - f "B" "world"; - exit 0 diff --git a/testsuite/tests/lib-threads/test6.precheck b/testsuite/tests/lib-threads/test6.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/test6.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/test6.reference b/testsuite/tests/lib-threads/test6.reference deleted file mode 100644 index e4a14898..00000000 --- a/testsuite/tests/lib-threads/test6.reference +++ /dev/null @@ -1,2 +0,0 @@ -A: world -B: hello diff --git a/testsuite/tests/lib-threads/test6.runner b/testsuite/tests/lib-threads/test6.runner deleted file mode 100644 index 50f88d8c..00000000 --- a/testsuite/tests/lib-threads/test6.runner +++ /dev/null @@ -1,16 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program >test6.result & -pid=$! -sleep 1 -kill -9 $pid diff --git a/testsuite/tests/lib-threads/test7.checker b/testsuite/tests/lib-threads/test7.checker deleted file mode 100644 index 4c4b2b4d..00000000 --- a/testsuite/tests/lib-threads/test7.checker +++ /dev/null @@ -1,14 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -test `grep -E '^-?[0123456789]+$' test7.result | wc -l` \ - = `cat test7.result | wc -l` diff --git a/testsuite/tests/lib-threads/test7.ml b/testsuite/tests/lib-threads/test7.ml deleted file mode 100644 index 9dae688f..00000000 --- a/testsuite/tests/lib-threads/test7.ml +++ /dev/null @@ -1,38 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -open Event - -let add_ch = new_channel() -let sub_ch = new_channel() -let read_ch = new_channel() - -let rec accu n = - select [ - wrap (receive add_ch) (fun x -> accu (n+x)); - wrap (receive sub_ch) (fun x -> accu (n-x)); - wrap (send read_ch n) (fun () -> accu n) - ] - -let rec sender chan value = - sync(send chan value); sender chan value - -let read () = - print_int(sync(receive read_ch)); print_newline() - -let main () = - Thread.create accu 0; - Thread.create (sender add_ch) 1; - Thread.create (sender sub_ch) 1; - while true do read() done - -let _ = Printexc.catch main () diff --git a/testsuite/tests/lib-threads/test7.precheck b/testsuite/tests/lib-threads/test7.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/test7.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/test7.runner b/testsuite/tests/lib-threads/test7.runner deleted file mode 100644 index ccd56a31..00000000 --- a/testsuite/tests/lib-threads/test7.runner +++ /dev/null @@ -1,16 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program >test7.result & -pid=$! -sleep 1 -kill -9 $pid diff --git a/testsuite/tests/lib-threads/test8.ml b/testsuite/tests/lib-threads/test8.ml deleted file mode 100644 index b3d1025d..00000000 --- a/testsuite/tests/lib-threads/test8.ml +++ /dev/null @@ -1,63 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -open Event - -type 'a buffer_channel = { - input: 'a channel; - output: 'a channel; - thread: Thread.t; -} - -let new_buffer_channel() = - let ic = new_channel() in - let oc = new_channel() in - let rec buffer_process front rear = - match (front, rear) with - | (["EOF"], []) -> Thread.exit () - | ([], []) -> buffer_process [sync(receive ic)] [] - | (hd::tl, _) -> - select [ - wrap (receive ic) (fun x -> buffer_process front (x::rear)); - wrap (send oc hd) (fun () -> buffer_process tl rear) - ] - | ([], _) -> buffer_process (List.rev rear) [] in - let t = Thread.create (buffer_process []) [] in - { input = ic; output = oc; thread = t } - -let buffer_send bc data = - sync(send bc.input data) - -let buffer_receive bc = - receive bc.output - -(* Test *) - -let box = new_buffer_channel() -let ch = new_channel() - -let f () = - buffer_send box "un"; - buffer_send box "deux"; - sync (send ch 3) - -let g () = - print_int (sync(receive ch)); print_newline(); - print_string (sync(buffer_receive box)); print_newline(); - print_string (sync(buffer_receive box)); print_newline() - -let _ = - let t = Thread.create f () in - g(); - buffer_send box "EOF"; - Thread.join box.thread; - Thread.join t diff --git a/testsuite/tests/lib-threads/test8.precheck b/testsuite/tests/lib-threads/test8.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/test8.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/test9.checker b/testsuite/tests/lib-threads/test9.checker deleted file mode 100644 index 09dd0e25..00000000 --- a/testsuite/tests/lib-threads/test9.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -LC_ALL=C $SORT test9.result | $DIFF test9.reference - diff --git a/testsuite/tests/lib-threads/test9.ml b/testsuite/tests/lib-threads/test9.ml deleted file mode 100644 index 16d61e04..00000000 --- a/testsuite/tests/lib-threads/test9.ml +++ /dev/null @@ -1,38 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -open Event - -type 'a swap_chan = ('a * 'a channel) channel - -let swap msg_out ch = - guard (fun () -> - let ic = new_channel() in - choose [ - wrap (receive ch) (fun (msg_in, oc) -> sync (send oc msg_out); msg_in); - wrap (send ch (msg_out, ic)) (fun () -> sync (receive ic)) - ]) - -let ch = new_channel() - -let f () = - let res = sync (swap "F" ch) in - print_string "f "; print_string res; print_newline() - -let g () = - let res = sync (swap "G" ch) in - print_string "g "; print_string res; print_newline() - -let _ = - let id = Thread.create f () in - g (); - Thread.join id diff --git a/testsuite/tests/lib-threads/test9.precheck b/testsuite/tests/lib-threads/test9.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/test9.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/testA.checker b/testsuite/tests/lib-threads/testA.checker deleted file mode 100644 index 00fdfb7a..00000000 --- a/testsuite/tests/lib-threads/testA.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -LC_ALL=C $SORT testA.result | $DIFF testA.reference - diff --git a/testsuite/tests/lib-threads/testA.ml b/testsuite/tests/lib-threads/testA.ml deleted file mode 100644 index 30efd6d3..00000000 --- a/testsuite/tests/lib-threads/testA.ml +++ /dev/null @@ -1,38 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 private_data = (Hashtbl.create 17 : (Thread.t, string) Hashtbl.t) -let private_data_lock = Mutex.create() -let output_lock = Mutex.create() - -let set_private_data data = - Mutex.lock private_data_lock; - Hashtbl.add private_data (Thread.self()) data; - Mutex.unlock private_data_lock - -let get_private_data () = - Hashtbl.find private_data (Thread.self()) - -let process id data = - set_private_data data; - Mutex.lock output_lock; - print_int id; print_string " --> "; print_string(get_private_data()); - print_newline(); - Mutex.unlock output_lock - -let _ = - let t1 = Thread.create (process 1) "un" in - let t2 = Thread.create (process 2) "deux" in - let t3 = Thread.create (process 3) "trois" in - let t4 = Thread.create (process 4) "quatre" in - let t5 = Thread.create (process 5) "cinq" in - List.iter Thread.join [t1;t2;t3;t4;t5] diff --git a/testsuite/tests/lib-threads/testexit.checker b/testsuite/tests/lib-threads/testexit.checker deleted file mode 100644 index 55dcd7ba..00000000 --- a/testsuite/tests/lib-threads/testexit.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -LC_ALL=C $SORT testexit.result | $DIFF testexit.reference - diff --git a/testsuite/tests/lib-threads/testexit.ml b/testsuite/tests/lib-threads/testexit.ml deleted file mode 100644 index b0cb80d6..00000000 --- a/testsuite/tests/lib-threads/testexit.ml +++ /dev/null @@ -1,33 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -(* Test Thread.exit *) - -let somethread (name, limit, last) = - let counter = ref 0 in - while true do - incr counter; - if !counter >= limit then begin - print_string (name ^ " exiting\n"); - flush stdout; - if last then exit 0 else Thread.exit() - end; - print_string (name ^ ": " ^ string_of_int !counter ^ "\n"); - flush stdout; - Thread.delay 0.5 - done - -let _ = - let _ = Thread.create somethread ("A", 5, false) in - let _ = Thread.create somethread ("B", 8, false) in - let _ = Thread.create somethread ("C", 11, true) in - somethread ("Main", 3, false) diff --git a/testsuite/tests/lib-threads/testexit.reference b/testsuite/tests/lib-threads/testexit.reference deleted file mode 100644 index 46ee7622..00000000 --- a/testsuite/tests/lib-threads/testexit.reference +++ /dev/null @@ -1,27 +0,0 @@ -A exiting -A: 1 -A: 2 -A: 3 -A: 4 -B exiting -B: 1 -B: 2 -B: 3 -B: 4 -B: 5 -B: 6 -B: 7 -C exiting -C: 1 -C: 10 -C: 2 -C: 3 -C: 4 -C: 5 -C: 6 -C: 7 -C: 8 -C: 9 -Main exiting -Main: 1 -Main: 2 diff --git a/testsuite/tests/lib-threads/testio.ml b/testsuite/tests/lib-threads/testio.ml deleted file mode 100644 index de0e4136..00000000 --- a/testsuite/tests/lib-threads/testio.ml +++ /dev/null @@ -1,132 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -(* Test a file copy function *) - -let test msg producer consumer src dst = - print_string msg; print_newline(); - let ic = open_in_bin src in - let oc = open_out_bin dst in - let (in_fd, out_fd) = Unix.pipe() in - let ipipe = Unix.in_channel_of_descr in_fd in - let opipe = Unix.out_channel_of_descr out_fd in - let prod = Thread.create producer (ic, opipe) in - let cons = Thread.create consumer (ipipe, oc) in - Thread.join prod; - Thread.join cons; - if Unix.system ("cmp " ^ src ^ " " ^ dst) = Unix.WEXITED 0 - then print_string "passed" - else print_string "FAILED"; - print_newline() - -(* File copy with constant-sized chunks *) - -let copy_file sz (ic, oc) = - let buffer = String.create sz in - let rec copy () = - let n = input ic buffer 0 sz in - if n = 0 then () else begin - output oc buffer 0 n; - copy () - end in - copy(); - close_in ic; - close_out oc - -(* File copy with random-sized chunks *) - -let copy_random sz (ic, oc) = - let buffer = String.create sz in - let rec copy () = - let s = 1 + Random.int sz in - let n = input ic buffer 0 s in - if n = 0 then () else begin - output oc buffer 0 n; - copy () - end in - copy(); - close_in ic; - close_out oc - -(* File copy line per line *) - -let copy_line (ic, oc) = - try - while true do - output_string oc (input_line ic); output_char oc '\n' - done - with End_of_file -> - close_in ic; - close_out oc - -(* Create long lines of text *) - -let make_lines ofile = - let oc = open_out ofile in - for i = 1 to 256 do - output_string oc (String.make (i*16) '.'); output_char oc '\n' - done; - close_out oc - -(* Test input_line on truncated lines *) - -let test_trunc_line ofile = - print_string "truncated line"; print_newline(); - let oc = open_out ofile in - output_string oc "A line without newline!"; - close_out oc; - try - let ic = open_in ofile in - let s = input_line ic in - close_in ic; - if s = "A line without newline!" - then print_string "passed" - else print_string "FAILED"; - print_newline() - with End_of_file -> - print_string "FAILED"; print_newline() - -(* The test *) - -let main() = - let ifile = try Sys.argv.(1) with _ -> "testio.ml" in - let ofile = Filename.temp_file "testio" "" in - test "256-byte chunks, 256-byte chunks" - (copy_file 256) (copy_file 256) ifile ofile; - test "4096-byte chunks, 4096-byte chunks" - (copy_file 4096) (copy_file 4096) ifile ofile; - test "65536-byte chunks, 65536-byte chunks" - (copy_file 65536) (copy_file 65536) ifile ofile; - test "256-byte chunks, 4096-byte chunks" - (copy_file 256) (copy_file 4096) ifile ofile; - test "4096-byte chunks, 256-byte chunks" - (copy_file 4096) (copy_file 256) ifile ofile; - test "4096-byte chunks, 65536-byte chunks" - (copy_file 4096) (copy_file 65536) ifile ofile; - test "263-byte chunks, 4011-byte chunks" - (copy_file 263) (copy_file 4011) ifile ofile; - test "613-byte chunks, 1027-byte chunks" - (copy_file 613) (copy_file 1027) ifile ofile; - test "0...8192 byte chunks" - (copy_random 8192) (copy_random 8192) ifile ofile; - test "line per line, short lines" - copy_line copy_line "test-file-short-lines" ofile; - let linesfile = Filename.temp_file "lines" "" in - make_lines linesfile; - test "line per line, short and long lines" - copy_line copy_line linesfile ofile; - test_trunc_line ofile; - Sys.remove linesfile; - Sys.remove ofile; - exit 0 - -let _ = Unix.handle_unix_error main (); exit 0 diff --git a/testsuite/tests/lib-threads/testio.reference b/testsuite/tests/lib-threads/testio.reference deleted file mode 100644 index 26de848f..00000000 --- a/testsuite/tests/lib-threads/testio.reference +++ /dev/null @@ -1,24 +0,0 @@ -256-byte chunks, 256-byte chunks -passed -4096-byte chunks, 4096-byte chunks -passed -65536-byte chunks, 65536-byte chunks -passed -256-byte chunks, 4096-byte chunks -passed -4096-byte chunks, 256-byte chunks -passed -4096-byte chunks, 65536-byte chunks -passed -263-byte chunks, 4011-byte chunks -passed -613-byte chunks, 1027-byte chunks -passed -0...8192 byte chunks -passed -line per line, short lines -passed -line per line, short and long lines -passed -truncated line -passed diff --git a/testsuite/tests/lib-threads/testsieve.ml b/testsuite/tests/lib-threads/testsieve.ml deleted file mode 100644 index 6979f803..00000000 --- a/testsuite/tests/lib-threads/testsieve.ml +++ /dev/null @@ -1,54 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 sieve primes= - Event.sync (Event.send primes 0); - Event.sync (Event.send primes 1); - Event.sync (Event.send primes 2); - let integers = Event.new_channel () in - let rec enumerate n= - Event.sync (Event.send integers n); - enumerate (n + 2) - and filter inpout = - let n = Event.sync (Event.receive inpout) - (* On prepare le terrain pour l'appel recursif *) - and output = Event.new_channel () in - (* Celui qui etait en tete du crible est premier *) - Event.sync (Event.send primes n); - Thread.create filter output; - (* On elimine de la sortie ceux qui sont des multiples de n *) - while true do - let m = Event.sync (Event.receive inpout) in - (* print_int n; print_string ": "; print_int m; print_newline(); *) - if (m mod n) = 0 - then () - else ((Event.sync (Event.send output m));()) - done in - Thread.create filter integers; - Thread.create enumerate 3 - -let premiers = Event.new_channel () - -let main _ = - Thread.create sieve premiers; - while true do - for i = 1 to 100 do - let n = Event.sync (Event.receive premiers) in - print_int n; print_newline() - done; - exit 0 - done - - -let _ = - try main () - with _ -> exit 0;; diff --git a/testsuite/tests/lib-threads/testsieve.reference b/testsuite/tests/lib-threads/testsieve.reference deleted file mode 100644 index b6b8c06e..00000000 --- a/testsuite/tests/lib-threads/testsieve.reference +++ /dev/null @@ -1,100 +0,0 @@ -0 -1 -2 -3 -5 -7 -11 -13 -17 -19 -23 -29 -31 -37 -41 -43 -47 -53 -59 -61 -67 -71 -73 -79 -83 -89 -97 -101 -103 -107 -109 -113 -127 -131 -137 -139 -149 -151 -157 -163 -167 -173 -179 -181 -191 -193 -197 -199 -211 -223 -227 -229 -233 -239 -241 -251 -257 -263 -269 -271 -277 -281 -283 -293 -307 -311 -313 -317 -331 -337 -347 -349 -353 -359 -367 -373 -379 -383 -389 -397 -401 -409 -419 -421 -431 -433 -439 -443 -449 -457 -461 -463 -467 -479 -487 -491 -499 -503 -509 -521 diff --git a/testsuite/tests/lib-threads/testsignal.checker b/testsuite/tests/lib-threads/testsignal.checker deleted file mode 100644 index 3febbff4..00000000 --- a/testsuite/tests/lib-threads/testsignal.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -sed -e 1q testsignal.result | grep -q '^[ab]*Got ctrl-C, exiting...$' diff --git a/testsuite/tests/lib-threads/testsignal.ml b/testsuite/tests/lib-threads/testsignal.ml deleted file mode 100644 index 67fa75f7..00000000 --- a/testsuite/tests/lib-threads/testsignal.ml +++ /dev/null @@ -1,25 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 sighandler _ = - print_string "Got ctrl-C, exiting..."; print_newline(); - exit 0 - -let print_message delay c = - while true do - print_char c; flush stdout; Thread.delay delay - done - -let _ = - Sys.signal Sys.sigint (Sys.Signal_handle sighandler); - Thread.create (print_message 0.6666666666) 'a'; - print_message 1.0 'b' diff --git a/testsuite/tests/lib-threads/testsignal.precheck b/testsuite/tests/lib-threads/testsignal.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/testsignal.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/testsignal.runner b/testsuite/tests/lib-threads/testsignal.runner deleted file mode 100644 index ed4e9279..00000000 --- a/testsuite/tests/lib-threads/testsignal.runner +++ /dev/null @@ -1,16 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program >testsignal.result & -pid=$! -sleep 3 -kill -INT $pid diff --git a/testsuite/tests/lib-threads/testsignal2.checker b/testsuite/tests/lib-threads/testsignal2.checker deleted file mode 100644 index 47ede358..00000000 --- a/testsuite/tests/lib-threads/testsignal2.checker +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -sed -e 1q testsignal2.result | grep -q '^[ab]*' diff --git a/testsuite/tests/lib-threads/testsignal2.ml b/testsuite/tests/lib-threads/testsignal2.ml deleted file mode 100644 index e59a8557..00000000 --- a/testsuite/tests/lib-threads/testsignal2.ml +++ /dev/null @@ -1,23 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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 print_message delay c = - while true do - print_char c; flush stdout; Thread.delay delay - done - -let _ = - Thread.sigmask Unix.SIG_BLOCK [Sys.sigint; Sys.sigterm]; - let th1 = Thread.create (print_message 0.6666666666) 'a' in - let th2 = Thread.create (print_message 1.0) 'b' in - let s = Thread.wait_signal [Sys.sigint; Sys.sigterm] in - Printf.printf "Got signal %d, exiting...\n" s diff --git a/testsuite/tests/lib-threads/testsignal2.precheck b/testsuite/tests/lib-threads/testsignal2.precheck deleted file mode 100644 index aa357092..00000000 --- a/testsuite/tests/lib-threads/testsignal2.precheck +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - -$CANKILL diff --git a/testsuite/tests/lib-threads/testsignal2.runner b/testsuite/tests/lib-threads/testsignal2.runner deleted file mode 100644 index 19a3942f..00000000 --- a/testsuite/tests/lib-threads/testsignal2.runner +++ /dev/null @@ -1,18 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program >testsignal2.result & -pid=$! -sleep 3 -kill -INT $pid -sleep 1 -kill -9 $pid 2>&- || true diff --git a/testsuite/tests/lib-threads/testsocket.ml b/testsuite/tests/lib-threads/testsocket.ml deleted file mode 100644 index 6b2b0b04..00000000 --- a/testsuite/tests/lib-threads/testsocket.ml +++ /dev/null @@ -1,48 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -open Unix - -let engine verbose number address = - print_int number; print_string "> connecting"; print_newline(); - let (ic, oc) = open_connection (ADDR_INET(address, 80)) in - print_int number; print_string "> connected"; print_newline(); - output_string oc "GET / HTTP1.0\r\n\r\n"; flush oc; - try - while true do - let s = input_line ic in - if verbose then begin - print_int number; print_string ">"; print_string s; print_newline() - end - done; - with End_of_file -> - close_out oc; - print_int number; print_string "> data retrieved"; print_newline() - -let main() = - let verbose, argv = - match Sys.argv with - | [| _ |] -> false, [| Sys.argv.(0); "caml.inria.fr" |] - | _ -> true, Sys.argv in - let addresses = Array.make (Array.length argv - 1) inet_addr_any in - for i = 1 to Array.length argv - 1 do - addresses.(i - 1) <- (gethostbyname argv.(i)).h_addr_list.(0) - done; - let processes = Array.make (Array.length addresses) (Thread.self()) in - for i = 0 to Array.length addresses - 1 do - processes.(i) <- Thread.create (engine verbose i) addresses.(i) - done; - for i = 0 to Array.length processes - 1 do - Thread.join processes.(i) - done - -let _ = Printexc.catch main (); exit 0 diff --git a/testsuite/tests/lib-threads/testsocket.precheck b/testsuite/tests/lib-threads/testsocket.precheck deleted file mode 100644 index 6d41158e..00000000 --- a/testsuite/tests/lib-threads/testsocket.precheck +++ /dev/null @@ -1,23 +0,0 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### - - -########################################## -########################################## -#### TEMPORARY #### -########################################## -########################################## - -# disable this test on Windows non-cygwin ports until we decide -# how to fix PR#5325 and PR#5578 - -$CANKILL diff --git a/testsuite/tests/lib-threads/testsocket.reference b/testsuite/tests/lib-threads/testsocket.reference deleted file mode 100644 index ce521418..00000000 --- a/testsuite/tests/lib-threads/testsocket.reference +++ /dev/null @@ -1,3 +0,0 @@ -0> connecting -0> connected -0> data retrieved diff --git a/testsuite/tests/lib-threads/tls.checker b/testsuite/tests/lib-threads/tls.checker new file mode 100644 index 00000000..b1d036b0 --- /dev/null +++ b/testsuite/tests/lib-threads/tls.checker @@ -0,0 +1,16 @@ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +LC_ALL=C $SORT tls.result | $DIFF tls.reference - diff --git a/testsuite/tests/lib-threads/tls.ml b/testsuite/tests/lib-threads/tls.ml new file mode 100644 index 00000000..0f51b9d5 --- /dev/null +++ b/testsuite/tests/lib-threads/tls.ml @@ -0,0 +1,41 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +let private_data = (Hashtbl.create 17 : (Thread.t, string) Hashtbl.t) +let private_data_lock = Mutex.create() +let output_lock = Mutex.create() + +let set_private_data data = + Mutex.lock private_data_lock; + Hashtbl.add private_data (Thread.self()) data; + Mutex.unlock private_data_lock + +let get_private_data () = + Hashtbl.find private_data (Thread.self()) + +let process id data = + set_private_data data; + Mutex.lock output_lock; + print_int id; print_string " --> "; print_string(get_private_data()); + print_newline(); + Mutex.unlock output_lock + +let _ = + let t1 = Thread.create (process 1) "un" in + let t2 = Thread.create (process 2) "deux" in + let t3 = Thread.create (process 3) "trois" in + let t4 = Thread.create (process 4) "quatre" in + let t5 = Thread.create (process 5) "cinq" in + List.iter Thread.join [t1;t2;t3;t4;t5] diff --git a/testsuite/tests/lib-threads/testA.reference b/testsuite/tests/lib-threads/tls.reference similarity index 100% rename from testsuite/tests/lib-threads/testA.reference rename to testsuite/tests/lib-threads/tls.reference diff --git a/testsuite/tests/lib-threads/token1.ml b/testsuite/tests/lib-threads/token1.ml deleted file mode 100644 index d0a7528b..00000000 --- a/testsuite/tests/lib-threads/token1.ml +++ /dev/null @@ -1,48 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -(* Performance test for mutexes and conditions *) - -let mut = Mutex.create() - -let niter = ref 0 - -let token = ref 0 - -let process (n, conds, nprocs) = - while true do - Mutex.lock mut; - while !token <> n do - (* Printf.printf "Thread %d waiting (token = %d)\n" n !token; *) - Condition.wait conds.(n) mut - done; - (* Printf.printf "Thread %d got token %d\n" n !token; *) - incr token; - if !token >= nprocs then token := 0; - if n = 0 then begin - decr niter; - if !niter <= 0 then exit 0 - end; - Condition.signal conds.(!token); - Mutex.unlock mut - done - -let main() = - let nprocs = try int_of_string Sys.argv.(1) with _ -> 100 in - let iter = try int_of_string Sys.argv.(2) with _ -> 1000 in - let conds = Array.make nprocs (Condition.create()) in - for i = 1 to nprocs - 1 do conds.(i) <- Condition.create() done; - niter := iter; - for i = 0 to nprocs - 1 do Thread.create process (i, conds, nprocs) done; - Thread.delay 3600. - -let _ = main() diff --git a/testsuite/tests/lib-threads/token2.ml b/testsuite/tests/lib-threads/token2.ml deleted file mode 100644 index c3548fb0..00000000 --- a/testsuite/tests/lib-threads/token2.ml +++ /dev/null @@ -1,51 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -(* Performance test for I/O scheduling *) - -let mut = Mutex.create() - -let niter = ref 0 - -let token = ref 0 - -let process (n, ins, outs, nprocs) = - let buf = String.make 1 '.' in - while buf <> "-" do - Unix.read ins.(n) buf 0 1; - (* Printf.printf "Thread %d got the token\n" n; *) - if n = 0 then begin - decr niter; - if !niter <= 0 then buf.[0] <- '-'; - end; - let next = if n + 1 >= nprocs then 0 else n + 1 in - (* Printf.printf "Thread %d sending token to thread %d\n" n next; *) - Unix.write outs.(next) buf 0 1 - done - -let main() = - let nprocs = try int_of_string Sys.argv.(1) with _ -> 100 in - let iter = try int_of_string Sys.argv.(2) with _ -> 1000 in - let ins = Array.make nprocs Unix.stdin in - let outs = Array.make nprocs Unix.stdout in - let threads = Array.make nprocs (Thread.self ()) in - for n = 0 to nprocs - 1 do - let (i, o) = Unix.pipe() in ins.(n) <- i; outs.(n) <- o - done; - niter := iter; - for i = 0 to nprocs - 1 do - threads.(i) <- Thread.create process (i, ins, outs, nprocs) - done; - Unix.write outs.(0) "X" 0 1; - for i = 0 to nprocs - 1 do Thread.join threads.(i) done - -let _ = main() diff --git a/testsuite/tests/lib-threads/torture.data b/testsuite/tests/lib-threads/torture.data deleted file mode 100644 index 8edb37e3..00000000 --- a/testsuite/tests/lib-threads/torture.data +++ /dev/null @@ -1,3 +0,0 @@ -abc -def -ghi diff --git a/testsuite/tests/lib-threads/torture.ml b/testsuite/tests/lib-threads/torture.ml index 0c1a3a3a..82908d24 100644 --- a/testsuite/tests/lib-threads/torture.ml +++ b/testsuite/tests/lib-threads/torture.ml @@ -1,18 +1,21 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) - -(* Torture test - lots of GC *) - -let finished = ref false;; +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) + +(* Torture test - I/O interspersed with lots of GC *) + +let finished = ref false let gc_thread () = while not !finished do @@ -21,35 +24,28 @@ let gc_thread () = Thread.yield() done -let stdin_thread () = - while not !finished do - print_string ">"; flush stdout; - let s = read_line() in - print_string " >>> "; print_string s; print_newline() - done - let writer_thread (oc, size) = while not !finished do (* print_string "writer "; print_int size; print_newline(); *) let buff = String.make size 'a' in - Unix.write oc buff 0 size + ignore(Unix.write oc buff 0 size) done; let buff = String.make size 'b' in - Unix.write oc buff 0 size + ignore (Unix.write oc buff 0 size) let reader_thread (ic, size) = while true do (* print_string "reader "; print_int size; print_newline(); *) - let buff = String.create size in + let buff = String.make size ' ' in let n = Unix.read ic buff 0 size in (* print_string "reader "; print_int n; print_newline(); *) for i = 0 to n-1 do - if buff.[i] = 'b' then raise Exit - else if buff.[i] <> 'a' then prerr_endline "error in reader_thread" + if buff.[i] = 'b' then Thread.exit() + else if buff.[i] <> 'a' then print_string "error in reader_thread\n" done done -let main() = +let _ = let t1 = Thread.create gc_thread () in let (out1, in1) = Unix.pipe() in let t2 = Thread.create writer_thread (in1, 4096) in @@ -57,10 +53,7 @@ let main() = let (out2, in2) = Unix.pipe() in let t4 = Thread.create writer_thread (in2, 16) in let t5 = Thread.create reader_thread (out2, 16) in - try - stdin_thread() - with _ -> - finished := true; - List.iter Thread.join [t1; t2; t3; t4; t5] - -let _ = main() + Thread.delay 3.0; + finished := true; + List.iter Thread.join [t1; t2; t3; t4; t5]; + print_string "passed\n" diff --git a/testsuite/tests/lib-threads/torture.reference b/testsuite/tests/lib-threads/torture.reference index f726cc46..b0aad4de 100644 --- a/testsuite/tests/lib-threads/torture.reference +++ b/testsuite/tests/lib-threads/torture.reference @@ -1,4 +1 @@ -> >>> abc -> >>> def -> >>> ghi -> \ No newline at end of file +passed diff --git a/testsuite/tests/lib-threads/torture.runner b/testsuite/tests/lib-threads/torture.runner deleted file mode 100644 index fc1ed387..00000000 --- a/testsuite/tests/lib-threads/torture.runner +++ /dev/null @@ -1,13 +0,0 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### - -$RUNTIME ./program torture.result 2>/dev/null || true diff --git a/testsuite/tests/lib-uchar/Makefile b/testsuite/tests/lib-uchar/Makefile new file mode 100644 index 00000000..c11a415f --- /dev/null +++ b/testsuite/tests/lib-uchar/Makefile @@ -0,0 +1,18 @@ +#************************************************************************** +#* * +#* 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=../.. +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/lib-uchar/test.ml b/testsuite/tests/lib-uchar/test.ml new file mode 100644 index 00000000..f7e37725 --- /dev/null +++ b/testsuite/tests/lib-uchar/test.ml @@ -0,0 +1,111 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Daniel C. Buenzli *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + + +let assert_raise_invalid_argument f v = + assert (try ignore (f v); false with Invalid_argument _ -> true) + +let test_constants () = + assert (Uchar.(to_int min) = 0x0000); + assert (Uchar.(to_int max) = 0x10FFFF); + () + +let test_succ () = + assert (Uchar.(to_int (succ min)) = 0x0001); + assert (Uchar.(to_int (succ (of_int 0xD7FF))) = 0xE000); + assert (Uchar.(to_int (succ (of_int 0xE000))) = 0xE001); + assert_raise_invalid_argument Uchar.succ Uchar.max; + () + +let test_pred () = + assert_raise_invalid_argument Uchar.pred Uchar.min; + assert (Uchar.(to_int (pred (of_int 0xD7FF))) = 0xD7FE); + assert (Uchar.(to_int (pred (of_int 0xE000))) = 0xD7FF); + assert (Uchar.(to_int (pred max)) = 0x10FFFE); + () + +let test_is_valid () = + assert (not (Uchar.is_valid (-1))); + assert (Uchar.is_valid 0x0000); + assert (Uchar.is_valid 0xD7FF); + assert (not (Uchar.is_valid 0xD800)); + assert (not (Uchar.is_valid 0xDFFF)); + assert (Uchar.is_valid 0xE000); + assert (Uchar.is_valid 0x10FFFF); + assert (not (Uchar.is_valid 0x110000)); + assert (not (Uchar.is_valid min_int)); + assert (not (Uchar.is_valid max_int)); + () + +let char_max = Uchar.of_int 0x00FF + +let test_is_char () = + assert (Uchar.(is_char Uchar.min)); + assert (Uchar.(is_char char_max)); + assert (Uchar.(not (is_char (of_int 0x0100)))); + assert (not (Uchar.is_char Uchar.max)); + () + +let test_of_char () = + assert (Uchar.(equal (of_char '\xFF') char_max)); + assert (Uchar.(equal (of_char '\x00') min)); + () + +let test_to_char () = + assert (Uchar.(to_char min) = '\x00'); + assert (Uchar.(to_char char_max) = '\xFF'); + assert_raise_invalid_argument Uchar.to_char (Uchar.succ char_max); + assert_raise_invalid_argument Uchar.to_char Uchar.max; + () + +let test_equal () = + assert (Uchar.(equal min min)); + assert (Uchar.(equal max max)); + assert (not Uchar.(equal min max)); + () + +let test_compare () = + assert (Uchar.(compare min min) = 0); + assert (Uchar.(compare max max) = 0); + assert (Uchar.(compare min max) = (-1)); + 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 (); + test_pred (); + test_is_valid (); + test_is_char (); + test_of_char (); + test_to_char (); + test_equal (); + test_compare (); + test_dump (); + () + +let () = + tests (); + print_endline "OK" diff --git a/testsuite/tests/lib-uchar/test.reference b/testsuite/tests/lib-uchar/test.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/lib-uchar/test.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/link-test/Makefile b/testsuite/tests/link-test/Makefile new file mode 100644 index 00000000..d1ee0c24 --- /dev/null +++ b/testsuite/tests/link-test/Makefile @@ -0,0 +1,36 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Thomas Refis, Jane Street Europe * +#* * +#* Copyright 2010 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* 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. * +#* * +#************************************************************************** + +default: + printf " ... testing 'test.reference':" + @$(OCAMLOPT) -c submodule.ml + @$(OCAMLOPT) -c aliases.ml + @$(OCAMLOPT) -c test.ml + @$(OCAMLOPT) -a submodule.cmx aliases.cmx -o mylib.cmxa + @$(OCAMLOPT) mylib.cmxa test.cmx -o test.native + @./test.native > test.result + @$(DIFF) test.result test.reference >/dev/null \ + && echo " => passed" || echo " => failed" + +promote: defaultpromote + +clean: defaultclean + @rm -f *.result + @rm -f test.native + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common +COMPFLAGS = -no-alias-deps diff --git a/testsuite/tests/link-test/aliases.ml b/testsuite/tests/link-test/aliases.ml new file mode 100644 index 00000000..65fbc19f --- /dev/null +++ b/testsuite/tests/link-test/aliases.ml @@ -0,0 +1 @@ +module Submodule = Submodule diff --git a/testsuite/tests/link-test/submodule.ml b/testsuite/tests/link-test/submodule.ml new file mode 100644 index 00000000..b315f202 --- /dev/null +++ b/testsuite/tests/link-test/submodule.ml @@ -0,0 +1,2 @@ +let () = print_endline "linked"; flush stdout +module M = struct end diff --git a/testsuite/tests/link-test/test.ml b/testsuite/tests/link-test/test.ml new file mode 100644 index 00000000..80190b83 --- /dev/null +++ b/testsuite/tests/link-test/test.ml @@ -0,0 +1 @@ +include Aliases.Submodule.M diff --git a/testsuite/tests/link-test/test.reference b/testsuite/tests/link-test/test.reference new file mode 100644 index 00000000..1fb9bdd6 --- /dev/null +++ b/testsuite/tests/link-test/test.reference @@ -0,0 +1 @@ +linked diff --git a/testsuite/tests/match-exception-warnings/Makefile b/testsuite/tests/match-exception-warnings/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/match-exception-warnings/Makefile +++ b/testsuite/tests/match-exception-warnings/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/match-exception/Makefile b/testsuite/tests/match-exception/Makefile index 299656b2..c11a415f 100644 --- a/testsuite/tests/match-exception/Makefile +++ b/testsuite/tests/match-exception/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.several diff --git a/testsuite/tests/match-exception/allocation.ml b/testsuite/tests/match-exception/allocation.ml index fa943ffa..72055c3a 100644 --- a/testsuite/tests/match-exception/allocation.ml +++ b/testsuite/tests/match-exception/allocation.ml @@ -15,7 +15,8 @@ let test_multiple_match_does_not_allocate = let allocated_bytes'' = Gc.allocated_bytes () in let _ = f a b in let allocated_bytes''' = Gc.allocated_bytes () in - if allocated_bytes' -. allocated_bytes = allocated_bytes''' -. allocated_bytes'' + if allocated_bytes' -. allocated_bytes + = allocated_bytes''' -. allocated_bytes'' then Printf.printf "no allocations for multiple-value match\n" else diff --git a/testsuite/tests/match-exception/exception_propagation.ml b/testsuite/tests/match-exception/exception_propagation.ml index 38d2cfd6..eedde784 100644 --- a/testsuite/tests/match-exception/exception_propagation.ml +++ b/testsuite/tests/match-exception/exception_propagation.ml @@ -3,7 +3,7 @@ *) let () = try - match + match (let _ = raise Not_found in assert false) with diff --git a/testsuite/tests/match-exception/match_failure.ml b/testsuite/tests/match-exception/match_failure.ml index c6149bf3..40c60595 100644 --- a/testsuite/tests/match-exception/match_failure.ml +++ b/testsuite/tests/match-exception/match_failure.ml @@ -5,8 +5,8 @@ let return_some_3 () = Some (1 + 2) ;; let test_match_partial_match = - try - let _ = (match return_some_3 () with + try + let _ = (match return_some_3 () with | Some x when x < 3 -> "Some x" | exception Failure _ -> "failure" | exception Invalid_argument _ -> "invalid argument" diff --git a/testsuite/tests/match-exception/nested_handlers.ml b/testsuite/tests/match-exception/nested_handlers.ml index 0314cb10..7f2a6514 100644 --- a/testsuite/tests/match-exception/nested_handlers.ml +++ b/testsuite/tests/match-exception/nested_handlers.ml @@ -7,8 +7,8 @@ let test_multiple_handlers = let collect v = trace := v :: !trace in let _ = match - begin - match + begin + match begin collect "one"; failwith "two" @@ -17,14 +17,14 @@ let test_multiple_handlers = () -> collect "failure one" | exception (Failure x) -> collect x; - failwith "three" + failwith "three" end with - () -> + () -> collect "failure two"; | exception (Failure x) -> collect x; - match + match begin collect "four"; failwith "five" diff --git a/testsuite/tests/match-exception/streams.ml b/testsuite/tests/match-exception/streams.ml index 42e9a5f1..43a31510 100644 --- a/testsuite/tests/match-exception/streams.ml +++ b/testsuite/tests/match-exception/streams.ml @@ -17,7 +17,7 @@ let make_stream_up_to n = let stream_get (Stream (x, s)) = (x, Lazy.force s) ;; -let rec iter_stream_match f s = +let rec iter_stream_match f s = match stream_get s with exception End_of_stream -> () | (x, s') -> @@ -26,7 +26,7 @@ let rec iter_stream_match f s = iter_stream_match f s' end ;; - + let test_iter_stream = let limit = 10000000 in try diff --git a/testsuite/tests/misc-kb/Makefile b/testsuite/tests/misc-kb/Makefile index 98bcd7c5..1ce51aca 100644 --- a/testsuite/tests/misc-kb/Makefile +++ b/testsuite/tests/misc-kb/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=terms equations orderings kb diff --git a/testsuite/tests/misc-kb/equations.ml b/testsuite/tests/misc-kb/equations.ml index 0ea3bb11..6e28aa08 100644 --- a/testsuite/tests/misc-kb/equations.ml +++ b/testsuite/tests/misc-kb/equations.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (****************** Equation manipulations *************) diff --git a/testsuite/tests/misc-kb/equations.mli b/testsuite/tests/misc-kb/equations.mli index db80f481..81a6ec45 100644 --- a/testsuite/tests/misc-kb/equations.mli +++ b/testsuite/tests/misc-kb/equations.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Terms diff --git a/testsuite/tests/misc-kb/kb.ml b/testsuite/tests/misc-kb/kb.ml index 0892a90c..bb0e4391 100644 --- a/testsuite/tests/misc-kb/kb.ml +++ b/testsuite/tests/misc-kb/kb.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Terms open Equations diff --git a/testsuite/tests/misc-kb/kb.mli b/testsuite/tests/misc-kb/kb.mli index 246bc819..78bbba5c 100644 --- a/testsuite/tests/misc-kb/kb.mli +++ b/testsuite/tests/misc-kb/kb.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Terms open Equations diff --git a/testsuite/tests/misc-kb/kbmain.ml b/testsuite/tests/misc-kb/kbmain.ml index 753f7353..b8aff7ce 100644 --- a/testsuite/tests/misc-kb/kbmain.ml +++ b/testsuite/tests/misc-kb/kbmain.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Terms open Equations @@ -76,4 +79,4 @@ let greater pair = match group_order pair with Greater -> true | _ -> false let _ = - for i = 1 to 20 do kb_complete greater [] geom_rules done + kb_complete greater [] geom_rules diff --git a/testsuite/tests/misc-kb/kbmain.reference b/testsuite/tests/misc-kb/kbmain.reference index 2789a669..758a0b4d 100644 --- a/testsuite/tests/misc-kb/kbmain.reference +++ b/testsuite/tests/misc-kb/kbmain.reference @@ -271,5190 +271,3 @@ Canonical set found : 134 : A*(I(B)*v1) = I(B)*(A*v1) 135 : C*I(B) = I(B)*C 136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*I(C)) -7 : C*(B*I(C)) = B -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -11 : C*(A*(I(C)*A)) = U -12 : C*(B*(I(C)*v1)) = B*v1 -13 : I(U)*v1 = v1 -14 : I(I(v1))*U = v1 -15 : I(v3*v2)*(v3*(v2*v1)) = v1 -16 : C*(A*(I(C)*(B*A))) = B -17 : I(C)*U = C -18 : C*(A*(I(C)*(A*v1))) = v1 -19 : I(C)*B = B*I(C) -20 : I(I(v2))*v1 = v2*v1 -Rule 14 deleted -21 : v1*U = v1 -Rule 17 deleted -22 : I(C) = C -Rule 19 deleted -Rule 18 deleted -Rule 16 deleted -Rule 12 deleted -Rule 11 deleted -Rule 7 deleted -23 : C*B = B*C -24 : C*(A*(C*(A*v1))) = v1 -25 : C*(A*(C*(B*A))) = B -26 : C*(B*(C*v1)) = B*v1 -27 : C*(A*(C*A)) = U -28 : C*(B*C) = B -29 : C*(A*(C*(B*(A*v1)))) = B*v1 -30 : I(I(v2*v1)*v2) = v1 -31 : I(v2*I(v1))*v2 = v1 -32 : I(v4*(v3*v2))*(v4*(v3*(v2*v1))) = v1 -33 : I(v1*A)*(v1*(B*A)) = B -34 : I(v1*C)*v1 = C -35 : I(v3*I(v2))*(v3*v1) = v2*v1 -36 : I(v2*A)*(v2*(B*(A*v1))) = B*v1 -37 : I(v2*C)*(v2*v1) = C*v1 -38 : v1*I(v1) = U -39 : I(C*(A*C))*v1 = A*v1 -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -Rule 13 deleted -42 : I(I(v1)) = v1 -Rule 20 deleted -43 : C*(B*v1) = B*(C*v1) -Rule 29 deleted -Rule 28 deleted -Rule 26 deleted -Rule 25 deleted -44 : A*(C*(A*v1)) = C*v1 -Rule 24 deleted -45 : A*(C*A) = C -Rule 27 deleted -46 : v2*(I(v1*v2)*v1) = U -47 : I(I(v3*(v2*v1))*(v3*v2)) = v1 -48 : I(I(B*A)*A) = B -49 : v3*(I(v2*v3)*(v2*v1)) = v1 -50 : I(I(v1)*I(v2)) = v2*v1 -51 : I(I(B*(A*v1))*A) = B*v1 -52 : I(I(v1)*C) = C*v1 -53 : I(v2*I(v1*v2)) = v1 -54 : I(v3*(v2*I(v1)))*(v3*v2) = v1 -55 : I(v1*(C*(A*C)))*v1 = A -56 : v2*I(I(v1)*v2) = v1 -57 : I(v2*(I(v3*v1)*v3))*v2 = v1 -58 : I(v5*(v4*(v3*v2)))*(v5*(v4*(v3*(v2*v1)))) = v1 -59 : I(v2*(v1*A))*(v2*(v1*(B*A))) = B -60 : I(v2*(v1*C))*(v2*v1) = C -61 : I(v4*(v3*I(v2)))*(v4*(v3*v1)) = v2*v1 -62 : I(v3*(v2*A))*(v3*(v2*(B*(A*v1)))) = B*v1 -63 : I(v3*(v2*C))*(v3*(v2*v1)) = C*v1 -64 : I(v3*(I(v4*v2)*v4))*(v3*v1) = v2*v1 -65 : v4*(I(v3*(v2*v4))*(v3*(v2*v1))) = v1 -66 : I(I(B)*A)*A = B -67 : I(A*A)*(B*(A*A)) = B -68 : v1*(I(A*v1)*(B*A)) = B -69 : I(I(v1*A)*(v1*B))*B = A -70 : v1*I(C*v1) = C -71 : I(A*I(v1))*(B*A) = v1*B -72 : I(C*I(v1)) = v1*C -73 : I(v2*(C*(A*C)))*(v2*v1) = A*v1 -74 : I(A*I(v2))*(B*(A*v1)) = v2*(B*v1) -75 : v3*(I(I(v2)*v3)*v1) = v2*v1 -76 : I(I(B*I(v1))*A)*(v1*A) = B -77 : I(v1*A)*(v1*(B*(B*A))) = B*B -78 : I(I(B)*A)*(A*v1) = B*v1 -79 : I(A*A)*(B*(A*(A*v1))) = B*v1 -80 : I(v2*A)*(v2*(B*(B*(A*v1)))) = B*(B*v1) -81 : v2*(I(A*v2)*(B*(A*v1))) = B*v1 -82 : I(I(v2*A)*(v2*B))*(B*v1) = A*v1 -83 : I(I(B*I(v2))*A)*(v2*(A*v1)) = B*v1 -84 : I(A*C)*(B*A) = B*C -85 : I(A*C)*(B*(A*v1)) = B*(C*v1) -86 : v2*(I(C*v2)*v1) = C*v1 -87 : I(I(B*C)*A)*(C*A) = B -88 : I(I(B*C)*A)*(C*(A*v1)) = B*v1 -89 : v2*(v1*I(v2*v1)) = U -90 : B*(A*I(B)) = A -91 : I(v2*v1)*v2 = I(v1) -Rule 64 deleted -Rule 57 deleted -Rule 55 deleted -Rule 46 deleted -Rule 34 deleted -Rule 31 deleted -Rule 30 deleted -92 : I(C*(A*C)) = A -Rule 39 deleted -93 : I(v3*(v2*v1))*(v3*v2) = I(v1) -Rule 60 deleted -Rule 54 deleted -Rule 47 deleted -94 : I(v1*I(v2)) = v2*I(v1) -Rule 83 deleted -Rule 76 deleted -Rule 74 deleted -Rule 72 deleted -Rule 71 deleted -Rule 53 deleted -Rule 50 deleted -Rule 35 deleted -95 : I(v2*(I(B)*A))*(v2*(A*v1)) = B*v1 -96 : I(v1*(I(B)*A))*(v1*A) = B -97 : I(v1*A)*(v1*B) = B*(C*(A*C)) -Rule 82 deleted -Rule 69 deleted -98 : I(v1*C) = C*I(v1) -Rule 88 deleted -Rule 87 deleted -Rule 85 deleted -Rule 84 deleted -Rule 52 deleted -Rule 37 deleted -99 : v3*(v2*(I(v3*v2)*v1)) = v1 -100 : B*(A*(I(B)*v1)) = A*v1 -101 : I(v3*v2)*(v3*v1) = I(v2)*v1 -Rule 97 deleted -Rule 96 deleted -Rule 95 deleted -Rule 93 deleted -Rule 80 deleted -Rule 77 deleted -Rule 73 deleted -Rule 65 deleted -Rule 63 deleted -Rule 62 deleted -Rule 61 deleted -Rule 59 deleted -Rule 58 deleted -Rule 49 deleted -Rule 36 deleted -Rule 33 deleted -Rule 32 deleted -Rule 15 deleted -102 : B*(C*I(B)) = C -103 : B*(C*(I(B)*v1)) = C*v1 -104 : B*(I(B*A)*A) = U -105 : B*(I(B*A)*(A*v1)) = v1 -106 : I(B*A)*A = I(B) -Rule 104 deleted -Rule 48 deleted -107 : B*(v1*(I(B*(A*v1))*A)) = U -108 : I(I(B*(B*A))*A) = B*B -109 : B*(v2*(I(B*(A*v2))*(A*v1))) = v1 -110 : I(I(B*(B*(A*v1)))*A) = B*(B*v1) -111 : I(I(B)*A) = B*(C*(A*C)) -Rule 78 deleted -Rule 66 deleted -112 : I(I(B*v1)*A) = B*(C*(A*(C*v1))) -Rule 110 deleted -Rule 108 deleted -Rule 51 deleted -113 : v3*(v2*I(I(v1)*(v3*v2))) = v1 -114 : v1*I(C*(A*(C*v1))) = A -115 : I(I(v1)*v2) = I(v2)*v1 -Rule 113 deleted -Rule 112 deleted -Rule 111 deleted -Rule 75 deleted -Rule 56 deleted -116 : v2*(v1*(I(A*(v2*v1))*(B*A))) = B -117 : I(A*v1)*(B*A) = I(v1)*B -Rule 116 deleted -Rule 68 deleted -118 : v2*(v1*I(C*(v2*v1))) = C -119 : I(C*v1) = I(v1)*C -Rule 118 deleted -Rule 114 deleted -Rule 92 deleted -Rule 86 deleted -Rule 70 deleted -120 : v1*(I(A*(C*v1))*C) = A -121 : I(A*A)*(B*(B*(A*A))) = B*B -122 : I(A*A)*(B*(B*(A*(A*v1)))) = B*(B*v1) -123 : I(A*A)*(B*(A*v1)) = B*(C*(A*(C*v1))) -Rule 79 deleted -Rule 67 deleted -124 : v3*(v2*(I(A*(v3*v2))*(B*(A*v1)))) = B*v1 -125 : v1*(I(A*v1)*(B*(B*A))) = B*B -126 : I(A*v2)*(B*(A*v1)) = I(v2)*(B*v1) -Rule 124 deleted -Rule 123 deleted -Rule 81 deleted -127 : v3*(v2*(v1*I(v3*(v2*v1)))) = U -128 : v2*I(v1*v2) = I(v1) -Rule 89 deleted -129 : A*I(B) = I(B)*A -Rule 90 deleted -130 : I(v1*v2) = I(v2)*I(v1) -Rule 128 deleted -Rule 127 deleted -Rule 126 deleted -Rule 125 deleted -Rule 122 deleted -Rule 121 deleted -Rule 120 deleted -Rule 119 deleted -Rule 117 deleted -Rule 115 deleted -Rule 109 deleted -Rule 107 deleted -Rule 106 deleted -Rule 105 deleted -Rule 101 deleted -Rule 99 deleted -Rule 98 deleted -Rule 94 deleted -Rule 91 deleted -131 : B*(C*(A*(C*(I(B)*(A*v1))))) = v1 -132 : B*(C*(A*(C*(I(B)*A)))) = U -133 : C*(A*(C*(I(B)*A))) = I(B) -Rule 132 deleted -134 : A*(I(B)*v1) = I(B)*(A*v1) -Rule 100 deleted -135 : C*I(B) = I(B)*C -Rule 102 deleted -136 : C*(I(B)*v1) = I(B)*(C*v1) -Rule 133 deleted -Rule 131 deleted -Rule 103 deleted -Canonical set found : -1 : U*v1 = v1 -2 : I(v1)*v1 = U -3 : (v3*v2)*v1 = v3*(v2*v1) -4 : A*B = B*A -5 : C*C = U -6 : I(A) = C*(A*C) -8 : I(v2)*(v2*v1) = v1 -9 : A*(B*v1) = B*(A*v1) -10 : C*(C*v1) = v1 -21 : v1*U = v1 -22 : I(C) = C -23 : C*B = B*C -38 : v1*I(v1) = U -40 : v2*(I(v2)*v1) = v1 -41 : I(U) = U -42 : I(I(v1)) = v1 -43 : C*(B*v1) = B*(C*v1) -44 : A*(C*(A*v1)) = C*v1 -45 : A*(C*A) = C -129 : A*I(B) = I(B)*A -130 : I(v1*v2) = I(v2)*I(v1) -134 : A*(I(B)*v1) = I(B)*(A*v1) -135 : C*I(B) = I(B)*C -136 : C*(I(B)*v1) = I(B)*(C*v1) diff --git a/testsuite/tests/misc-kb/orderings.ml b/testsuite/tests/misc-kb/orderings.ml index 488f8703..2646e835 100644 --- a/testsuite/tests/misc-kb/orderings.ml +++ b/testsuite/tests/misc-kb/orderings.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (*********************** Recursive Path Ordering ****************************) diff --git a/testsuite/tests/misc-kb/orderings.mli b/testsuite/tests/misc-kb/orderings.mli index d67e3796..2bc41e96 100644 --- a/testsuite/tests/misc-kb/orderings.mli +++ b/testsuite/tests/misc-kb/orderings.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Terms diff --git a/testsuite/tests/misc-kb/terms.ml b/testsuite/tests/misc-kb/terms.ml index b490c81f..b1e95311 100644 --- a/testsuite/tests/misc-kb/terms.ml +++ b/testsuite/tests/misc-kb/terms.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (****************** Term manipulations *****************) diff --git a/testsuite/tests/misc-kb/terms.mli b/testsuite/tests/misc-kb/terms.mli index aa1dd2cd..90da1a8c 100644 --- a/testsuite/tests/misc-kb/terms.mli +++ b/testsuite/tests/misc-kb/terms.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 term = Var of int diff --git a/testsuite/tests/misc-unsafe/Makefile b/testsuite/tests/misc-unsafe/Makefile index 4a70866f..2afaa5d2 100644 --- a/testsuite/tests/misc-unsafe/Makefile +++ b/testsuite/tests/misc-unsafe/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. UNSAFE=ON diff --git a/testsuite/tests/misc-unsafe/almabench.ml b/testsuite/tests/misc-unsafe/almabench.ml index e5cdf36c..54fc3108 100644 --- a/testsuite/tests/misc-unsafe/almabench.ml +++ b/testsuite/tests/misc-unsafe/almabench.ml @@ -47,7 +47,8 @@ and test_length = 36525 and sineps = 0.3977771559319137 and coseps = 0.9174820620691818 -and amas = [| 6023600.0; 408523.5; 328900.5; 3098710.0; 1047.355; 3498.5; 22869.0; 19314.0 |] +and amas = [| 6023600.0; 408523.5; 328900.5; 3098710.0; + 1047.355; 3498.5; 22869.0; 19314.0 |] (* * tables giving the mean keplerian elements, limited to t**2 terms: @@ -311,6 +312,7 @@ let _ = Printf.printf "%d %.2f %.2f\n%!" p position.(0) position.(1) done; (* Benchmark *) +(** for i = 0 to test_loops - 1 do jd.(0) <- j2000; jd.(1) <- 0.0; @@ -322,3 +324,4 @@ let _ = done done done +**) diff --git a/testsuite/tests/misc-unsafe/fft.ml b/testsuite/tests/misc-unsafe/fft.ml index 7e2442b0..3e3024ee 100644 --- a/testsuite/tests/misc-unsafe/fft.ml +++ b/testsuite/tests/misc-unsafe/fft.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let pi = 3.14159265358979323846 @@ -183,4 +186,4 @@ let test np = print_newline() let _ = - let np = ref 16 in for i = 1 to 16 do test !np; np := !np*2 done + let np = ref 16 in for i = 1 to 15 do test !np; np := !np*2 done diff --git a/testsuite/tests/misc-unsafe/fft.reference b/testsuite/tests/misc-unsafe/fft.reference index b0f1238b..ce6544e9 100644 --- a/testsuite/tests/misc-unsafe/fft.reference +++ b/testsuite/tests/misc-unsafe/fft.reference @@ -13,4 +13,3 @@ 65536... ok 131072... ok 262144... ok -524288... ok diff --git a/testsuite/tests/misc-unsafe/quicksort.ml b/testsuite/tests/misc-unsafe/quicksort.ml index 8879d952..9835d699 100644 --- a/testsuite/tests/misc-unsafe/quicksort.ml +++ b/testsuite/tests/misc-unsafe/quicksort.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Good test for loops. Best compiled with -unsafe. *) @@ -84,7 +87,7 @@ let test_sort sort_fun size = let main () = - test_sort qsort 500000; - test_sort qsort2 500000 + test_sort qsort 50000; + test_sort qsort2 50000 let _ = main(); exit 0 diff --git a/testsuite/tests/misc-unsafe/soli.ml b/testsuite/tests/misc-unsafe/soli.ml index e4aa7215..bdf1e1ed 100644 --- a/testsuite/tests/misc-unsafe/soli.ml +++ b/testsuite/tests/misc-unsafe/soli.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 peg = Out | Empty | Peg diff --git a/testsuite/tests/misc/Makefile b/testsuite/tests/misc/Makefile index 299656b2..c11a415f 100644 --- a/testsuite/tests/misc/Makefile +++ b/testsuite/tests/misc/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.several diff --git a/testsuite/tests/misc/bdd.ml b/testsuite/tests/misc/bdd.ml index 297eb68e..684202ad 100644 --- a/testsuite/tests/misc/bdd.ml +++ b/testsuite/tests/misc/bdd.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Translated to OCaml by Xavier Leroy *) (* Original code written in SML by ... *) @@ -213,9 +216,9 @@ let test_hwb bdd vars = let main () = let n = - if Array.length Sys.argv >= 2 then int_of_string Sys.argv.(1) else 22 in + if Array.length Sys.argv >= 2 then int_of_string Sys.argv.(1) else 20 in let ntests = - if Array.length Sys.argv >= 3 then int_of_string Sys.argv.(2) else 100 in + if Array.length Sys.argv >= 3 then int_of_string Sys.argv.(2) else 10 in let bdd = hwb n in let succeeded = ref true in for i = 1 to ntests do diff --git a/testsuite/tests/misc/boyer.ml b/testsuite/tests/misc/boyer.ml index 09bfd649..257cdea8 100644 --- a/testsuite/tests/misc/boyer.ml +++ b/testsuite/tests/misc/boyer.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Manipulations over terms *) @@ -880,7 +883,7 @@ let term = cterm_to_term( let _ = let ok = ref true in - for i = 1 to 50 do + for i = 1 to 10 do if not (tautp (apply_subst subst term)) then ok := false done; if !ok then @@ -888,22 +891,3 @@ let _ = else print_string "Cannot prove!\n"; exit 0 - -(********* -with - failure s -> - print_string "Exception failure("; print_string s; print_string ")\n" - | Unify -> - print_string "Exception Unify\n" - | match_failure(file,start,stop) -> - print_string "Exception match_failure("; - print_string file; - print_string ","; - print_int start; - print_string ","; - print_int stop; - print_string ")\n" - | _ -> - print_string "Exception ?\n" - -**********) diff --git a/testsuite/tests/misc/ephetest.ml b/testsuite/tests/misc/ephetest.ml new file mode 100644 index 00000000..6aa9ca01 --- /dev/null +++ b/testsuite/tests/misc/ephetest.ml @@ -0,0 +1,180 @@ +(*************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2008 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 debug = false + +open Printf +open Ephemeron + +let is_true test s b = printf "%s %s: %s\n" test s (if b then "OK" else "FAIL") +let is_false test s b = is_true test s (not b) + +let is_data_value test eph (v:int) = + match K1.get_data_copy eph with + | Some x -> + if !x = v + then printf "%s data set: OK\n" test + else printf "%s data set: FAIL(bad value %i)\n" test (!x) + | None -> printf "%s data set: FAIL\n" test + +let is_key_value test eph (v:int) = + match K1.get_key_copy eph with + | Some x -> + if !x = v + then printf "%s key set: OK\n" test + else printf "%s key set: FAIL(bad value %i)\n" test (!x) + | None -> printf "%s key unset: FAIL\n" test + +let is_key_unset test eph = + is_false test "key unset" (K1.check_key eph) + +let is_data_unset test eph = + is_false test "data unset" (K1.check_data eph) + +let make_ra () = ref (ref 1) [@@inline never] +let make_rb () = ref (ref (ref 2)) [@@inline never] +let ra = make_ra () +let rb = make_rb () + +(** test: key alive data dangling *) +let test1 () = + let test = "test1" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + K1.set_key eph (!ra); + K1.set_data eph (ref 42); + is_key_value test eph 1; + is_data_value test eph 42; + Gc.minor (); + is_key_value test eph 1; + is_data_value test eph 42; + Gc.full_major (); + is_key_value test eph 1; + is_data_value test eph 42; + ra := ref 12; + Gc.full_major (); + is_key_unset test eph; + is_data_unset test eph +let () = (test1 [@inlined never]) () + +(** test: key dangling data dangling *) +let test2 () = + let test = "test2" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + K1.set_key eph (ref 125); + K1.set_data eph (ref 42); + is_key_value test eph 125; + is_data_value test eph 42; + ra := ref 13; + Gc.minor (); + is_key_unset test eph; + is_data_unset test eph +let () = (test2 [@inlined never]) () + +(** test: key dangling data alive *) +let test3 () = + let test = "test3" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + K1.set_key eph (ref 125); + K1.set_data eph (!ra); + is_key_value test eph 125; + is_data_value test eph 13; + ra := ref 14; + Gc.minor (); + is_key_unset test eph; + is_data_unset test eph +let () = (test3 [@inlined never]) () + +(** test: key alive but one away, data dangling *) +let test4 () = + let test = "test4" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + rb := ref (ref 3); + K1.set_key eph (!(!rb)); + K1.set_data eph (ref 43); + is_key_value test eph 3; + is_data_value test eph 43; + Gc.minor (); + Gc.minor (); + is_key_value test eph 3; + is_data_value test eph 43 +let () = (test4 [@inlined never]) () + +(** test: key dangling but one away, data dangling *) +let test5 () = + let test = "test5" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + rb := ref (ref 3); + K1.set_key eph (!(!rb)); + K1.set_data eph (ref 43); + is_key_value test eph 3; + is_data_value test eph 43; + !rb := ref 4; + Gc.minor (); + Gc.minor (); + is_key_unset test eph; + is_data_unset test eph +let () = (test5 [@inlined never]) () + +(** test: key accessible from data but all dangling *) +let test6 () = + let test = "test6" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref ref) K1.t = K1.create () in + rb := ref (ref 3); + K1.set_key eph (!(!rb)); + K1.set_data eph (ref (!(!rb))); + Gc.minor (); + is_key_value test eph 3; + !rb := ref 4; + Gc.full_major (); + is_key_unset test eph; + is_data_unset test eph +let () = (test6 [@inlined never]) () + +(** test: ephemeron accessible from data but they are dangling *) +type t = + | No + | Ephe of (int ref, t) K1.t + +let rc = ref No + +let test7 () = + let test = "test7" in + Gc.minor (); + Gc.full_major (); + ra := ref 42; + let weak : t Weak.t = Weak.create 1 in + let eph : (int ref, t) K1.t ref = ref (K1.create ()) in + rc := Ephe !eph; + Weak.set weak 0 (Some !rc); + K1.set_key !eph !ra; + K1.set_data !eph !rc; + Gc.minor (); + is_true test "before" (Weak.check weak 0); + eph := K1.create (); + rc := No; + Gc.full_major (); + Gc.full_major (); + Gc.full_major (); + is_false test "after" (Weak.check weak 0) +let () = (test7 [@inlined never]) () diff --git a/testsuite/tests/misc/ephetest.reference b/testsuite/tests/misc/ephetest.reference new file mode 100644 index 00000000..2699fdf7 --- /dev/null +++ b/testsuite/tests/misc/ephetest.reference @@ -0,0 +1,29 @@ +test1 key set: OK +test1 data set: OK +test1 key set: OK +test1 data set: OK +test1 key set: OK +test1 data set: OK +test1 key unset: OK +test1 data unset: OK +test2 key set: OK +test2 data set: OK +test2 key unset: OK +test2 data unset: OK +test3 key set: OK +test3 data set: OK +test3 key unset: OK +test3 data unset: OK +test4 key set: OK +test4 data set: OK +test4 key set: OK +test4 data set: OK +test5 key set: OK +test5 data set: OK +test5 key unset: OK +test5 data unset: OK +test6 key set: OK +test6 key unset: OK +test6 data unset: OK +test7 before: OK +test7 after: OK diff --git a/testsuite/tests/misc/ephetest2.ml b/testsuite/tests/misc/ephetest2.ml new file mode 100644 index 00000000..d1da4486 --- /dev/null +++ b/testsuite/tests/misc/ephetest2.ml @@ -0,0 +1,161 @@ +(*************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2008 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. *) +(* *) +(*************************************************************************) + +(*** + This test evaluate boolean formula composed by conjunction and + disjunction using ephemeron: + - true == alive, false == garbage collected + - and == an n-ephemeron, or == many 1-ephemeron + +*) + +let nb_test = 4 +let max_level = 10 + (** probability that a branch is not linked to a previous one *) +let proba_no_shared = 0.2 +let arity_max = 4 + +let proba_new = proba_no_shared ** (1./.(float_of_int max_level)) + +open Format +open Ephemeron + +let is_true test s b = printf "%s %s: %s\n" test s (if b then "OK" else "FAIL") +let is_false test s b = is_true test s (not b) + +type varephe = int ref +type ephe = (varephe,varephe) Kn.t + +type formula = + | Constant of bool + | And of var array + | Or of var array + +and var = { + form: formula; + value: bool; + ephe: varephe Weak.t; +} + +let print_short_bool fmt b = + if b + then pp_print_string fmt "t" + else pp_print_string fmt "f" + +let rec pp_form fmt = function + | Constant b -> + fprintf fmt "%b" b + | And a -> + fprintf fmt "And[@[%a@]]" (fun fmt -> Array.iter (pp_var fmt)) a + | Or a -> + fprintf fmt "Or[@[%a@]]" (fun fmt -> Array.iter (pp_var fmt)) a + +and pp_var fmt v = + fprintf fmt "%a%a:%a;@ " + print_short_bool v.value + print_short_bool (Weak.check v.ephe 0) + pp_form v.form + +type env = { + (** resizeable array for cheap *) + vars : (int,var) Hashtbl.t; + (** the ephemerons must be alive *) + ephes : ephe Stack.t; + (** keep alive the true constant *) + varephe_true : varephe Stack.t; +(** keep temporarily alive the false constant *) + varephe_false : varephe Stack.t; +} + +let new_env () = { + vars = Hashtbl.create 100; + ephes = Stack.create (); + varephe_true = Stack.create (); + varephe_false = Stack.create (); +} + +let evaluate = function + | Constant b -> b + | And a -> Array.fold_left (fun acc e -> acc && e.value) true a + | Or a -> Array.fold_left (fun acc e -> acc || e.value) false a + +let get_ephe v = + match Weak.get v.ephe 0 with + | None -> + invalid_arg "Error: weak dead but nothing have been released" + | Some r -> r + +(** create a variable and its definition in the boolean world and + ephemerons world *) +let rec create env rem_level (** remaining level *) = + let varephe = ref 1 in + let form = + if rem_level = 0 then (** Constant *) + if Random.bool () + then (Stack.push varephe env.varephe_true ; Constant true ) + else (Stack.push varephe env.varephe_false; Constant false) + else + let size = (Random.int (arity_max - 1)) + 2 in + let new_link _ = + if (Hashtbl.length env.vars) = 0 || Random.float 1. < proba_new + then create env (rem_level -1) + else Hashtbl.find env.vars (Random.int (Hashtbl.length env.vars)) + in + let args = Array.init size new_link in + if Random.bool () + then begin (** Or *) + Array.iter (fun v -> + let r = get_ephe v in + let e = Kn.create 1 in + Kn.set_key e 0 r; + Kn.set_data e varephe; + Stack.push e env.ephes + ) args; Or args + end + else begin (** And *) + let e = Kn.create (Array.length args) in + for i=0 to Array.length args - 1 do + Kn.set_key e i (get_ephe args.(i)); + done; + Kn.set_data e varephe; + Stack.push e env.ephes; + And args + end + in + let create_weak e = + let w = Weak.create 1 in + Weak.set w 0 (Some e); + w + in + let v = {form; value = evaluate form; + ephe = create_weak varephe; + } in + Hashtbl.add env.vars (Hashtbl.length env.vars) v; + v + + +let check_var v = v.value = Weak.check v.ephe 0 + +let run test init = + Random.init init; + let env = new_env () in + let _top = create env max_level in + (** release false ref *) + Stack.clear env.varephe_false; + Gc.full_major (); + let res = Hashtbl.fold (fun _ v acc -> acc && check_var v) env.vars true in + is_true test "check" res + +let () = + for i = 0 to nb_test do + run ("test"^(string_of_int i)) i; + done diff --git a/testsuite/tests/misc/ephetest2.reference b/testsuite/tests/misc/ephetest2.reference new file mode 100644 index 00000000..db17cd7a --- /dev/null +++ b/testsuite/tests/misc/ephetest2.reference @@ -0,0 +1,5 @@ +test0 check: OK +test1 check: OK +test2 check: OK +test3 check: OK +test4 check: OK diff --git a/testsuite/tests/misc/ephetest3.ml b/testsuite/tests/misc/ephetest3.ml new file mode 100644 index 00000000..3c49b47f --- /dev/null +++ b/testsuite/tests/misc/ephetest3.ml @@ -0,0 +1,133 @@ +(*************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2008 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. *) +(* *) +(*************************************************************************) + +(** This test weak table by application to the memoization of collatz + (also known as syracuse) algorithm suite computation *) + +(** We use Int64 because they are boxed *) + +(** number of element of the suite to compute (more are computed) *) +let n = 1000 + +let two = Int64.of_int 2 +let three = Int64.of_int 3 + +let collatz x = + if Int64.equal (Int64.rem x two) Int64.zero + then Int64.div x two + else Int64.succ (Int64.mul x three) + +module S = struct + include Int64 + let hash (x:t) = Hashtbl.hash x +end + +let pp = Int64.to_string + +module HW = Ephemeron.K1.Make(S) +module SW = Weak.Make(S) + + +let sw = SW.create n +let hashcons x = SW.merge sw x + +let hw = HW.create n + +let rec fill_hw x = + if not (HW.mem hw x) then begin + let y = hashcons (collatz x) in + HW.add hw x y; + fill_hw y + end + +exception InvariantBroken of string +let test b = Printf.ksprintf (fun s -> if not b then raise (InvariantBroken s)) + +let rec check_hw_aux cache x = + (** We use int so that the cache doesn't make x alive *) + if not (Hashtbl.mem cache (Int64.to_int x)) then begin + test (HW.mem hw x) "missing %s%!" (pp x); + let y = + try HW.find hw x + with Not_found -> + test (not (HW.mem hw x)) "key in the table but data missing %s!%!" + (pp x); + test false "missing %s%!" (pp x); + assert false + in + let y' = collatz x in + test (Int64.equal y y') "bad result for %s: %s instead of %s%!" + (pp x) (pp y) (pp y'); + let y'' = hashcons y' in + test (y == y'') "bad result for %s: not physically equal%!" (pp x); + Hashtbl.add cache (Int64.to_int x) (); + check_hw_aux cache y + end + +let check_hw iter = + let cache = Hashtbl.create n in + iter (fun x -> check_hw_aux cache x) + +(** tests *) + +let run ~next ~check = + HW.reset hw; + SW.clear sw; + (* Gc.full_major (); *) + for x=0 to n do + let x' = next x in + fill_hw x'; + check x; + done; + Gc.full_major (); + HW.clean hw; + Printf.printf "length: %i\n%!" (HW.length hw) + +let print_stats () = + let print_stats name stats = + Printf.printf "%s (%3i,%3i,%3i): %!" + name + stats.Hashtbl.num_bindings + stats.Hashtbl.num_buckets + stats.Hashtbl.max_bucket_length; + Array.iteri (fun i n -> Printf.printf "%i: %i, %!" i n) + stats.Hashtbl.bucket_histogram; + Printf.printf "\n%!"; + in + print_stats "stats : " (HW.stats hw); + print_stats "stats_alive: " (HW.stats_alive hw) + +let test_keep_last d d' = + Printf.printf "## Keep last %i alive, check each %i ##\n%!" (n/d) (n/d'); + let keep_alive = Array.create (n/d) Int64.zero in + let next x = + let x' = hashcons (Int64.of_int x) in + Array.set keep_alive (x mod (n/d)) x'; + x' + in + let check x = + if x mod (n/d') = 0 || x = n then begin + check_hw (fun f -> Array.iter f keep_alive) + end + in + run ~next ~check; + (** keep the array alive until the end *) + let s = + Array.fold_left (fun acc x -> Int64.add x acc) Int64.zero keep_alive in + Printf.printf "sum of kept alive %s\n%!" (pp s); + print_stats (); + Printf.printf "\n%!" + +let () = + test_keep_last 1 10; + test_keep_last 50 10; + test_keep_last 100 2 diff --git a/testsuite/tests/misc/ephetest3.reference b/testsuite/tests/misc/ephetest3.reference new file mode 100644 index 00000000..4fd03fb9 --- /dev/null +++ b/testsuite/tests/misc/ephetest3.reference @@ -0,0 +1,18 @@ +## Keep last 1000 alive, check each 100 ## +length: 2228 +sum of kept alive 500500 +stats : (2228,2048, 6): 0: 658, 1: 791, 2: 413, 3: 143, 4: 34, 5: 8, 6: 1, +stats_alive: (2228,2048, 6): 0: 658, 1: 791, 2: 413, 3: 143, 4: 34, 5: 8, 6: 1, + +## Keep last 20 alive, check each 100 ## +length: 458 +sum of kept alive 19810 +stats : (458,2048, 3): 0: 1636, 1: 370, 2: 38, 3: 4, +stats_alive: (458,2048, 3): 0: 1636, 1: 370, 2: 38, 3: 4, + +## Keep last 10 alive, check each 500 ## +length: 339 +sum of kept alive 9955 +stats : (339,2048, 3): 0: 1740, 1: 279, 2: 27, 3: 2, +stats_alive: (339,2048, 3): 0: 1740, 1: 279, 2: 27, 3: 2, + diff --git a/testsuite/tests/misc/fib.ml b/testsuite/tests/misc/fib.ml index adaf5488..5c7c9dc2 100644 --- a/testsuite/tests/misc/fib.ml +++ b/testsuite/tests/misc/fib.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let rec fib n = if n < 2 then 1 else fib(n-1) + fib(n-2) @@ -17,5 +20,5 @@ let _ = let n = if Array.length Sys.argv >= 2 then int_of_string Sys.argv.(1) - else 40 in + else 30 in print_int(fib n); print_newline(); exit 0 diff --git a/testsuite/tests/misc/fib.reference b/testsuite/tests/misc/fib.reference index 1d7ca9c6..08c2ab3e 100644 --- a/testsuite/tests/misc/fib.reference +++ b/testsuite/tests/misc/fib.reference @@ -1 +1 @@ -165580141 +1346269 diff --git a/testsuite/tests/misc/hamming.ml b/testsuite/tests/misc/hamming.ml index 7c49c2b4..885d2752 100644 --- a/testsuite/tests/misc/hamming.ml +++ b/testsuite/tests/misc/hamming.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) (* We cannot use bignums because we don't do custom runtimes, but int64 is a bit short, so we roll our own 37-digit numbers... diff --git a/testsuite/tests/misc/nucleic.ml b/testsuite/tests/misc/nucleic.ml index 6b5b196f..55647e15 100644 --- a/testsuite/tests/misc/nucleic.ml +++ b/testsuite/tests/misc/nucleic.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Use floating-point arithmetic *) @@ -3230,7 +3233,6 @@ let run () = most_distant_atom (pseudoknot ()) let main () = - for i = 1 to 50 do ignore(run()) done; Printf.printf "%.4f" (run ()); print_newline() let _ = main () diff --git a/testsuite/tests/misc/pr7168.ml b/testsuite/tests/misc/pr7168.ml new file mode 100644 index 00000000..fb0ef7d2 --- /dev/null +++ b/testsuite/tests/misc/pr7168.ml @@ -0,0 +1,77 @@ +let rec f x = + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in let x = x+x in let x = x+x in let x = x+x in + let x = x+x in + let _ = f x in + () + +let _ = + if (Gc.get ()).Gc.stack_limit = 0 then begin + (* We are in native code. Skip the test because some platforms cannot + reliably detect stack overflow. *) + Printf.printf "OK\n" + end else begin + try f 1 + with Stack_overflow -> Printf.printf "OK\n" + end diff --git a/testsuite/tests/misc/pr7168.reference b/testsuite/tests/misc/pr7168.reference new file mode 100644 index 00000000..d86bac9d --- /dev/null +++ b/testsuite/tests/misc/pr7168.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/misc/sieve.ml b/testsuite/tests/misc/sieve.ml index 7d8d21bd..54df6e28 100644 --- a/testsuite/tests/misc/sieve.ml +++ b/testsuite/tests/misc/sieve.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Eratosthene's sieve *) diff --git a/testsuite/tests/misc/sorts.ml b/testsuite/tests/misc/sorts.ml index db9ecae5..40a0fbb2 100644 --- a/testsuite/tests/misc/sorts.ml +++ b/testsuite/tests/misc/sorts.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) +(* *) +(* Copyright 2000 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. *) +(* *) +(**************************************************************************) (* Test bench for sorting algorithms. *) @@ -20,11 +23,11 @@ open Printf;; (* - Criteres: - 0. overhead en pile: doit etre logn au maximum. - 1. stable ou non. - 2. overhead en espace. - 3. vitesse. + Criteria: + 0. stack overhead: at most log n. + 1. stable or not. + 2. space overhead. + 3. speed. *) (************************************************************************) @@ -193,9 +196,8 @@ let chklex b rstate n a = chkgen (mkrec1 b) cmplex rstate n a;; let lens = [ 0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 28; - 100; 127; 128; 129; 191; 192; 193; 506; - 1000; 1023; 1024; 1025; 1535; 1536; 1537; 2323; - 4000; 4094; 4096; 4098; 5123; + 100; 127; 128; 129; 193; 506; + 1000; 1025; 1535; 2323; ];; type ('a, 'b, 'c, 'd) aux = { @@ -468,8 +470,8 @@ let bench3c limit name f aux = (* merge sort on lists *) (* FIXME to do: cutoff - to do: cascader les pattern-matchings (enlever les paires) - to do: fermeture intermediaire pour merge + to do: cascade pattern-matchings (delete pairs) + to do: intermediary closure for merge *) let (@@) = List.rev_append;; @@ -1713,11 +1715,11 @@ let amerge_1j cmp a = end; ;; -(* FIXME a essayer: *) -(* list->array->list direct et array->list->array direct *) +(* FIXME try: *) +(* list->array->list direct and array->list->array direct *) (* overhead = 1/3, 1/4, etc. *) (* overhead = sqrt (n) *) -(* overhead = n/3 jusqu'a 30k, 30k jusqu'a 900M, sqrt (n) au-dela *) +(* overhead = n/3 up to 30k, 30k up to 900M, sqrt (n) beyond *) (************************************************************************) (* merge sort on arrays, merge with loop *) @@ -2268,7 +2270,7 @@ let amerge_3j cmp a = end; ;; -(* FIXME essayer bottom-up merge on arrays ? *) +(* FIXME try bottom-up merge on arrays? *) (************************************************************************) (* Shell sort on arrays *) @@ -3929,8 +3931,8 @@ let aheap_1 cmp a = (************************************************************************) (* Heap sort on arrays (top-down, binary) *) -(* FIXME essayer application partielle de trickledown (merge avec down) *) -(* FIXME essayer expanser maxson dans trickledown; supprimer l'exception. *) +(* FIXME try partial application of trickledown (merge with down) *) +(* FIXME try to expand maxson in trickledown; delete the exception. *) let aheap_2 cmp a = let maxson l i e = @@ -4152,7 +4154,7 @@ let aheap_6 cmp a = if l > 1 then (let e = a.(1) in a.(1) <- a.(0); a.(0) <- e); ;; -(* FIXME essayer cutoff pour heapsort *) +(* FIXME try cutoff for heapsort *) (************************************************************************) (* Insertion sort with dichotomic search *) diff --git a/testsuite/tests/misc/sorts.reference b/testsuite/tests/misc/sorts.reference index fa0cc048..d311fcdd 100644 --- a/testsuite/tests/misc/sorts.reference +++ b/testsuite/tests/misc/sorts.reference @@ -2,197 +2,197 @@ Command line arguments are: Testing List.sort... List.sort with constant ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with reverse-sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with random ints (many dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with random ints (few dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with records (str) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with records (int[1]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with records (int[10]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with records (int[100]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.sort with records (int[1000]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Testing List.stable_sort... List.stable_sort with constant ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with reverse-sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with random ints (many dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with random ints (few dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (str) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[1]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[10]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[100]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[1000]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[1]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[10]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[100]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. List.stable_sort with records (int[1000]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Testing Array.sort... Array.sort with constant ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with reverse-sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with random ints (many dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with random ints (few dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with records (str) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with records (int[1]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with records (int[10]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with records (int[100]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.sort with records (int[1000]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Testing Array.stable_sort... Array.stable_sort with constant ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with reverse-sorted ints 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with random ints (many dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with random ints (few dups) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (str) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[1]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[10]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[100]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[1000]) 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[1]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[10]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[100]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Array.stable_sort with records (int[1000]) [stable] 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. - 12. 13. 28. 100. 127. 128. 129. 191. 192. 193. 506. 1000. - 1023. 1024. 1025. 1535. 1536. 1537. 2323. 4000. 4094. 4096. 4098. 5123. + 12. 13. 28. 100. 127. 128. 129. 193. 506. 1000. 1025. 1535. + 2323. Number of tests failed: 0 diff --git a/testsuite/tests/misc/takc.ml b/testsuite/tests/misc/takc.ml index 667ff5a7..8fec8984 100644 --- a/testsuite/tests/misc/takc.ml +++ b/testsuite/tests/misc/takc.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let rec tak x y z = if x > y then tak (tak (x-1) y z) (tak (y-1) z x) (tak (z-1) x y) @@ -17,4 +20,4 @@ let rec tak x y z = let rec repeat n = if n <= 0 then 0 else tak 18 12 6 + repeat(n-1) -let _ = print_int (repeat 2000); print_newline(); exit 0 +let _ = print_int (repeat 200); print_newline(); exit 0 diff --git a/testsuite/tests/misc/takc.reference b/testsuite/tests/misc/takc.reference index bfed8193..50989ffe 100644 --- a/testsuite/tests/misc/takc.reference +++ b/testsuite/tests/misc/takc.reference @@ -1 +1 @@ -14000 +1400 diff --git a/testsuite/tests/misc/taku.ml b/testsuite/tests/misc/taku.ml index 47d94c88..647266c8 100644 --- a/testsuite/tests/misc/taku.ml +++ b/testsuite/tests/misc/taku.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let rec tak (x, y, z) = if x > y then tak(tak (x-1, y, z), tak (y-1, z, x), tak (z-1, x, y)) @@ -17,4 +20,4 @@ let rec tak (x, y, z) = let rec repeat n = if n <= 0 then 0 else tak(18,12,6) + repeat(n-1) -let _ = print_int (repeat 2000); print_newline(); exit 0 +let _ = print_int (repeat 200); print_newline(); exit 0 diff --git a/testsuite/tests/misc/taku.reference b/testsuite/tests/misc/taku.reference index bfed8193..50989ffe 100644 --- a/testsuite/tests/misc/taku.reference +++ b/testsuite/tests/misc/taku.reference @@ -1 +1 @@ -14000 +1400 diff --git a/testsuite/tests/misc/weaklifetime2.ml b/testsuite/tests/misc/weaklifetime2.ml new file mode 100644 index 00000000..4e18640e --- /dev/null +++ b/testsuite/tests/misc/weaklifetime2.ml @@ -0,0 +1,69 @@ +(*************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, Jane Street Group, LLC *) +(* *) +(* Copyright 2015 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 n = 500 +let loop = 2 + +let alive = ref (Array.init n (fun _ -> Array.make 10 0)) + +let create_weaks () = + Array.init n (fun i -> + let w = Weak.create 1 in + Weak.set w 0 (Some (!alive.(i))); + w + ) + +(** We are trying to keep the weak pointer of weak2 set when the + weak pointer of weak1 and weak3 are wrongly unset. + [weak1], [weak2] and [weak3] are identical. + *) + +let weak1 = create_weaks () +let weak2 = create_weaks () +let weak3 = create_weaks () + +(** put the weak pointers in the major heap *) +let () = + let dummy = ref [||] in + for l=0 to 10 do + dummy := Array.make 300 0 + done + +let gccount () = (Gc.quick_stat ()).Gc.major_collections;; + +let () = + for _l=1 to loop do + let bad = ref 0 in + for i=0 to n-1 do + (** make *this* weak key alive *) + for _j=0 to n*10 do + ignore (Weak.get weak2.(i) 0); + done; + (** Check that if it is alive in weak2 it is alive in weak1 *) + if Weak.check weak2.(i) 0 && + not (Weak.check weak1.(i) 0) && + Weak.check weak2.(i) 0 + then incr bad; + (** Check that if it is alive in weak2 it is alive in weak3 + This case was failing before the addition of the clean phase in the gc + *) + if Weak.check weak2.(i) 0 && + not (Weak.check weak3.(i) 0) && + Weak.check weak2.(i) 0 + then incr bad; + !alive.(i) <- Array.make 10 0; + done; + (* Printf.printf "bad: %i\ gccount:%i\n%!" !bad (gccount ()); *) + if !bad > 0 + then Printf.printf "failing\n%!" + else Printf.printf "success\n%!" + done diff --git a/testsuite/tests/misc/weaklifetime2.reference b/testsuite/tests/misc/weaklifetime2.reference new file mode 100644 index 00000000..cfb2161c --- /dev/null +++ b/testsuite/tests/misc/weaklifetime2.reference @@ -0,0 +1,2 @@ +success +success diff --git a/testsuite/tests/no-alias-deps/Makefile b/testsuite/tests/no-alias-deps/Makefile new file mode 100644 index 00000000..d80c2ea5 --- /dev/null +++ b/testsuite/tests/no-alias-deps/Makefile @@ -0,0 +1,37 @@ +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** + +default: b.cmi c.cmi d.cmi aliases.ml + @$(OCAMLC) -c aliases.ml > aliases.ml.result 2>&1 || true + @$(OBJINFO) aliases.cmo | \ + sed -e "s/[a-f0-9]\{32\}/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/g" \ + > aliases.cmo.result 2>&1 || true + @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 + +b.cmi: b.cmi.pre + @cp b.cmi.pre b.cmi + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common +COMPFLAGS = -no-alias-deps diff --git a/testsuite/tests/no-alias-deps/aliases.cmo.reference b/testsuite/tests/no-alias-deps/aliases.cmo.reference new file mode 100644 index 00000000..dd190714 --- /dev/null +++ b/testsuite/tests/no-alias-deps/aliases.cmo.reference @@ -0,0 +1,12 @@ +File aliases.cmo +Unit name: Aliases +Interfaces imported: + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Pervasives + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa D + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa CamlinternalFormatBasics + -------------------------------- C + -------------------------------- B + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aliases + -------------------------------- A +Uses unsafe features: no +Force link: no diff --git a/testsuite/tests/no-alias-deps/aliases.ml b/testsuite/tests/no-alias-deps/aliases.ml new file mode 100644 index 00000000..c74dcae6 --- /dev/null +++ b/testsuite/tests/no-alias-deps/aliases.ml @@ -0,0 +1,5 @@ +module A' = A (* missing a.cmi *) +module B' = B (* broken b.cmi *) +module C' = C (* valid c.cmi *) +module D' = D (* valid d.cmi *) +let () = print_int D'.something diff --git a/testsuite/tests/no-alias-deps/aliases.ml.reference b/testsuite/tests/no-alias-deps/aliases.ml.reference new file mode 100644 index 00000000..ce6a3d1b --- /dev/null +++ b/testsuite/tests/no-alias-deps/aliases.ml.reference @@ -0,0 +1,5 @@ +File "_none_", line 1: +Warning 49: no cmi file was found in path for module A +File "_none_", line 1: +Warning 49: no valid cmi file was found in path for module B. b.cmi +is not a compiled interface diff --git a/testsuite/tests/no-alias-deps/b.cmi.pre b/testsuite/tests/no-alias-deps/b.cmi.pre new file mode 100644 index 00000000..b0aedf1b --- /dev/null +++ b/testsuite/tests/no-alias-deps/b.cmi.pre @@ -0,0 +1 @@ +Not a valid cmi file diff --git a/testsuite/tests/no-alias-deps/c.mli b/testsuite/tests/no-alias-deps/c.mli new file mode 100644 index 00000000..5d27914b --- /dev/null +++ b/testsuite/tests/no-alias-deps/c.mli @@ -0,0 +1 @@ +val something : int diff --git a/testsuite/tests/no-alias-deps/d.mli b/testsuite/tests/no-alias-deps/d.mli new file mode 100644 index 00000000..5d27914b --- /dev/null +++ b/testsuite/tests/no-alias-deps/d.mli @@ -0,0 +1 @@ +val something : int diff --git a/testsuite/tests/opaque/Makefile b/testsuite/tests/opaque/Makefile new file mode 100644 index 00000000..247ee8ce --- /dev/null +++ b/testsuite/tests/opaque/Makefile @@ -0,0 +1,75 @@ +#************************************************************************** +#* * +#* 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 'test' with ordinary compilation => skipped" + @echo " ... testing 'test' with change to opaque interface => skipped" + @echo " ... testing 'test' with change to opaque implementation \ + => skipped" + @echo " ... testing 'test' with change to non-opaque implementation \ + => skipped" + +.PHONY: compile +compile: + @$(OCAMLOPT) -I intf -opaque -c intf/opaque_intf.mli + @$(OCAMLOPT) -I intf -c intf/opaque_impl.mli + @$(OCAMLOPT) -I intf -c intf/regular.mli + @cp intf/*.mli intf/*.cmi fst + @cp intf/*.mli intf/*.cmi snd + @$(OCAMLOPT) -I fst -c fst/opaque_intf.ml + @$(OCAMLOPT) -I fst -opaque -c fst/opaque_impl.ml + @$(OCAMLOPT) -I fst -c fst/regular.ml + @$(OCAMLOPT) -I snd -c snd/opaque_intf.ml + @$(OCAMLOPT) -I snd -opaque -c snd/opaque_impl.ml + @$(OCAMLOPT) -I snd -c snd/regular.ml + @$(OCAMLOPT) -I fst -c test.ml + @ + @printf " ... testing 'test' with ordinary compilation"; \ + $(OCAMLOPT) fst/opaque_intf.cmx fst/opaque_impl.cmx \ + fst/regular.cmx test.cmx 2>/dev/null \ + && echo " => passed" || echo " => failed"; \ + printf " ... testing 'test' with change to opaque interface"; \ + $(OCAMLOPT) snd/opaque_intf.cmx fst/opaque_impl.cmx \ + fst/regular.cmx test.cmx 2>/dev/null \ + && echo " => passed" || echo " => failed"; \ + printf " ... testing 'test' with change to opaque implementation"; \ + $(OCAMLOPT) fst/opaque_intf.cmx snd/opaque_impl.cmx \ + fst/regular.cmx test.cmx 2>/dev/null \ + && echo " => passed" || echo " => failed"; \ + printf " ... testing 'test' with change to non-opaque implementation";\ + $(OCAMLOPT) fst/opaque_intf.cmx fst/opaque_impl.cmx \ + snd/regular.cmx test.cmx 2>/dev/null \ + && echo " => failed" || echo " => passed"; \ + +.PHONY: promote +promote: + +.PHONY: clean +clean: defaultclean + @rm -f *.cmi *.cmx *.$(O) a.out camlprog.exe + @rm -f intf/*.cmi + @rm -f fst/*.cmi fst/*.cmx fst/*.$(O) fst/*.mli + @rm -f snd/*.cmi snd/*.cmx snd/*.$(O) snd/*.mli + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/opaque/fst/opaque_impl.ml b/testsuite/tests/opaque/fst/opaque_impl.ml new file mode 100644 index 00000000..932c0d35 --- /dev/null +++ b/testsuite/tests/opaque/fst/opaque_impl.ml @@ -0,0 +1,2 @@ + +let choose x y = x diff --git a/testsuite/tests/opaque/fst/opaque_intf.ml b/testsuite/tests/opaque/fst/opaque_intf.ml new file mode 100644 index 00000000..932c0d35 --- /dev/null +++ b/testsuite/tests/opaque/fst/opaque_intf.ml @@ -0,0 +1,2 @@ + +let choose x y = x diff --git a/testsuite/tests/opaque/fst/regular.ml b/testsuite/tests/opaque/fst/regular.ml new file mode 100644 index 00000000..932c0d35 --- /dev/null +++ b/testsuite/tests/opaque/fst/regular.ml @@ -0,0 +1,2 @@ + +let choose x y = x diff --git a/testsuite/tests/opaque/intf/opaque_impl.mli b/testsuite/tests/opaque/intf/opaque_impl.mli new file mode 100644 index 00000000..59d0a4c3 --- /dev/null +++ b/testsuite/tests/opaque/intf/opaque_impl.mli @@ -0,0 +1,2 @@ + +val choose : 'a -> 'a -> 'a diff --git a/testsuite/tests/opaque/intf/opaque_intf.mli b/testsuite/tests/opaque/intf/opaque_intf.mli new file mode 100644 index 00000000..59d0a4c3 --- /dev/null +++ b/testsuite/tests/opaque/intf/opaque_intf.mli @@ -0,0 +1,2 @@ + +val choose : 'a -> 'a -> 'a diff --git a/testsuite/tests/opaque/intf/regular.mli b/testsuite/tests/opaque/intf/regular.mli new file mode 100644 index 00000000..59d0a4c3 --- /dev/null +++ b/testsuite/tests/opaque/intf/regular.mli @@ -0,0 +1,2 @@ + +val choose : 'a -> 'a -> 'a diff --git a/testsuite/tests/opaque/snd/opaque_impl.ml b/testsuite/tests/opaque/snd/opaque_impl.ml new file mode 100644 index 00000000..df8c0130 --- /dev/null +++ b/testsuite/tests/opaque/snd/opaque_impl.ml @@ -0,0 +1,2 @@ + +let choose x y = y diff --git a/testsuite/tests/opaque/snd/opaque_intf.ml b/testsuite/tests/opaque/snd/opaque_intf.ml new file mode 100644 index 00000000..df8c0130 --- /dev/null +++ b/testsuite/tests/opaque/snd/opaque_intf.ml @@ -0,0 +1,2 @@ + +let choose x y = y diff --git a/testsuite/tests/opaque/snd/regular.ml b/testsuite/tests/opaque/snd/regular.ml new file mode 100644 index 00000000..df8c0130 --- /dev/null +++ b/testsuite/tests/opaque/snd/regular.ml @@ -0,0 +1,2 @@ + +let choose x y = y diff --git a/testsuite/tests/opaque/test.ml b/testsuite/tests/opaque/test.ml new file mode 100644 index 00000000..020c1385 --- /dev/null +++ b/testsuite/tests/opaque/test.ml @@ -0,0 +1,9 @@ + +let () = + print_endline (Opaque_intf.choose "Opaque_intf: First" "Opaque_intf: Second") + +let () = + print_endline (Opaque_impl.choose "Opaque_impl: First" "Opaque_impl: Second") + +let () = + print_endline (Regular.choose "Regular: First" "Regular: Second") diff --git a/testsuite/tests/parsing/Makefile b/testsuite/tests/parsing/Makefile new file mode 100644 index 00000000..eac3f246 --- /dev/null +++ b/testsuite/tests/parsing/Makefile @@ -0,0 +1,19 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Jeremie Dimino, Jane Street Europe * +#* * +#* 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=../.. +TOPFLAGS+=-dparsetree +include $(BASEDIR)/makefiles/Makefile.dparsetree +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/parsing/attributes.ml b/testsuite/tests/parsing/attributes.ml new file mode 100644 index 00000000..8276380e --- /dev/null +++ b/testsuite/tests/parsing/attributes.ml @@ -0,0 +1,34 @@ +[@@@foo] + +let (x[@foo]) : unit [@foo] = ()[@foo] + [@@foo] + +type t = + | Foo of (t[@foo]) [@foo] +[@@foo] + +[@@@foo] + + +module M = struct + type t = { + l : (t [@foo]) [@foo] + } + [@@foo] + [@@foo] + + [@@@foo] +end[@foo] +[@@foo] + +module type S = sig + + include (module type of (M[@foo]))[@foo] with type t := M.t[@foo] + [@@foo] + + [@@@foo] + +end[@foo] +[@@foo] + +[@@@foo] diff --git a/testsuite/tests/parsing/attributes.ml.reference b/testsuite/tests/parsing/attributes.ml.reference new file mode 100644 index 00000000..c6e8ad8d --- /dev/null +++ b/testsuite/tests/parsing/attributes.ml.reference @@ -0,0 +1,153 @@ +[ + structure_item (attributes.ml[1,0+0]..[1,0+8]) + Pstr_attribute "foo" + [] + structure_item (attributes.ml[3,10+0]..[4,49+9]) + Pstr_value Nonrec + [ + + attribute "foo" + [] + pattern (attributes.ml[3,10+4]..[3,10+38]) ghost + Ppat_constraint + pattern (attributes.ml[3,10+4]..[3,10+13]) + attribute "foo" + [] + Ppat_var "x" (attributes.ml[3,10+5]..[3,10+6]) + core_type (attributes.ml[3,10+16]..[3,10+20]) + attribute "foo" + [] + Ptyp_constr "unit" (attributes.ml[3,10+16]..[3,10+20]) + [] + expression (attributes.ml[3,10+30]..[3,10+32]) + attribute "foo" + [] + Pexp_construct "()" (attributes.ml[3,10+30]..[3,10+32]) + None + ] + structure_item (attributes.ml[6,60+0]..[8,97+7]) + Pstr_type Rec + [ + type_declaration "t" (attributes.ml[6,60+5]..[6,60+6]) (attributes.ml[6,60+0]..[8,97+7]) + attribute "foo" + [] + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_variant + [ + (attributes.ml[7,69+2]..[7,69+27]) + "Foo" (attributes.ml[7,69+4]..[7,69+7]) + attribute "foo" + [] + [ + core_type (attributes.ml[7,69+12]..[7,69+13]) + attribute "foo" + [] + Ptyp_constr "t" (attributes.ml[7,69+12]..[7,69+13]) + [] + ] + None + ] + ptype_private = Public + ptype_manifest = + None + ] + structure_item (attributes.ml[10,106+0]..[10,106+8]) + Pstr_attribute "foo" + [] + structure_item (attributes.ml[13,117+0]..[22,224+7]) + Pstr_module + "M" (attributes.ml[13,117+7]..[13,117+8]) + attribute "foo" + [] + module_expr (attributes.ml[13,117+11]..[21,214+3]) + attribute "foo" + [] + Pmod_structure + [ + structure_item (attributes.ml[14,135+2]..[18,190+11]) + Pstr_type Rec + [ + type_declaration "t" (attributes.ml[14,135+7]..[14,135+8]) (attributes.ml[14,135+2]..[18,190+11]) + attribute "foo" + [] + attribute "foo" + [] + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_record + [ + (attributes.ml[15,148+4]..[15,148+25]) + attribute "foo" + [] + Immutable + "l" (attributes.ml[15,148+4]..[15,148+5]) core_type (attributes.ml[15,148+9]..[15,148+10]) + attribute "foo" + [] + Ptyp_constr "t" (attributes.ml[15,148+9]..[15,148+10]) + [] + ] + ptype_private = Public + ptype_manifest = + None + ] + structure_item (attributes.ml[20,203+2]..[20,203+10]) + Pstr_attribute "foo" + [] + ] + structure_item (attributes.ml[24,233+0]..[32,357+7]) + Pstr_modtype "S" (attributes.ml[24,233+12]..[24,233+13]) + attribute "foo" + [] + module_type (attributes.ml[24,233+16]..[31,347+3]) + attribute "foo" + [] + Pmty_signature + [ + signature_item (attributes.ml[26,254+2]..[27,322+11]) + Psig_include + module_type (attributes.ml[26,254+10]..[26,254+61]) + attribute "foo" + [] + Pmty_with + module_type (attributes.ml[26,254+11]..[26,254+35]) + attribute "foo" + [] + Pmty_typeof + module_expr (attributes.ml[26,254+27]..[26,254+28]) + attribute "foo" + [] + Pmod_ident "M" (attributes.ml[26,254+27]..[26,254+28]) + [ + Pwith_typesubst + type_declaration "t" (attributes.ml[26,254+53]..[26,254+54]) (attributes.ml[26,254+48]..[26,254+61]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (attributes.ml[26,254+58]..[26,254+61]) + Ptyp_constr "M.t" (attributes.ml[26,254+58]..[26,254+61]) + [] + ] + attribute "foo" + [] + signature_item (attributes.ml[29,335+2]..[29,335+10]) + Psig_attribute "foo" + [] + ] + structure_item (attributes.ml[34,366+0]..[34,366+8]) + Pstr_attribute "foo" + [] +] + diff --git a/testsuite/tests/parsing/docstrings.ml b/testsuite/tests/parsing/docstrings.ml new file mode 100644 index 00000000..ea847113 --- /dev/null +++ b/testsuite/tests/parsing/docstrings.ml @@ -0,0 +1,16 @@ +type 'a with_default + = ?size:int (** default [42] *) + -> ?resizable:bool (** default [true] *) + -> 'a + +type obj = < + meth1 : int -> int; + (** method 1 *) + + meth2: unit -> float (** method 2 *); +> + +type var = [ + | `Foo (** foo *) + | `Bar of int * string (** bar *) +] diff --git a/testsuite/tests/parsing/docstrings.ml.reference b/testsuite/tests/parsing/docstrings.ml.reference new file mode 100644 index 00000000..da40ede7 --- /dev/null +++ b/testsuite/tests/parsing/docstrings.ml.reference @@ -0,0 +1,146 @@ +[ + structure_item (docstrings.ml[1,0+0]..[4,105+7]) + Pstr_type Rec + [ + type_declaration "with_default" (docstrings.ml[1,0+8]..[1,0+20]) (docstrings.ml[1,0+0]..[4,105+7]) + ptype_params = + [ + core_type (docstrings.ml[1,0+5]..[1,0+7]) + Ptyp_var a + ] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (docstrings.ml[2,21+5]..[4,105+7]) + Ptyp_arrow + Optional "size" + core_type (docstrings.ml[2,21+11]..[2,21+14]) + attribute "ocaml.doc" + [ + structure_item (docstrings.ml[2,21+21]..[2,21+40]) + Pstr_eval + expression (docstrings.ml[2,21+21]..[2,21+40]) + Pexp_constant PConst_string(" default [42] ",None) + ] + Ptyp_constr "int" (docstrings.ml[2,21+11]..[2,21+14]) + [] + core_type (docstrings.ml[3,62+5]..[4,105+7]) + Ptyp_arrow + Optional "resizable" + core_type (docstrings.ml[3,62+16]..[3,62+20]) + attribute "ocaml.doc" + [ + structure_item (docstrings.ml[3,62+21]..[3,62+42]) + Pstr_eval + expression (docstrings.ml[3,62+21]..[3,62+42]) + Pexp_constant PConst_string(" default [true] ",None) + ] + Ptyp_constr "bool" (docstrings.ml[3,62+16]..[3,62+20]) + [] + core_type (docstrings.ml[4,105+5]..[4,105+7]) + Ptyp_var a + ] + structure_item (docstrings.ml[6,114+0]..[11,208+1]) + Pstr_type Rec + [ + type_declaration "obj" (docstrings.ml[6,114+5]..[6,114+8]) (docstrings.ml[6,114+0]..[11,208+1]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (docstrings.ml[6,114+11]..[11,208+1]) + Ptyp_object Closed + method meth1 + attribute "ocaml.doc" + [ + structure_item (docstrings.ml[8,149+2]..[8,149+17]) + Pstr_eval + expression (docstrings.ml[8,149+2]..[8,149+17]) + Pexp_constant PConst_string(" method 1 ",None) + ] + core_type (docstrings.ml[7,127+10]..[7,127+20]) + Ptyp_arrow + Nolabel + core_type (docstrings.ml[7,127+10]..[7,127+13]) + Ptyp_constr "int" (docstrings.ml[7,127+10]..[7,127+13]) + [] + core_type (docstrings.ml[7,127+17]..[7,127+20]) + Ptyp_constr "int" (docstrings.ml[7,127+17]..[7,127+20]) + [] + method meth2 + attribute "ocaml.doc" + [ + structure_item (docstrings.ml[10,168+23]..[10,168+38]) + Pstr_eval + expression (docstrings.ml[10,168+23]..[10,168+38]) + Pexp_constant PConst_string(" method 2 ",None) + ] + core_type (docstrings.ml[10,168+9]..[10,168+22]) + Ptyp_arrow + Nolabel + core_type (docstrings.ml[10,168+9]..[10,168+13]) + Ptyp_constr "unit" (docstrings.ml[10,168+9]..[10,168+13]) + [] + core_type (docstrings.ml[10,168+17]..[10,168+22]) + Ptyp_constr "float" (docstrings.ml[10,168+17]..[10,168+22]) + [] + ] + structure_item (docstrings.ml[13,211+0]..[16,280+1]) + Pstr_type Rec + [ + type_declaration "var" (docstrings.ml[13,211+5]..[13,211+8]) (docstrings.ml[13,211+0]..[16,280+1]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (docstrings.ml[13,211+11]..[16,280+1]) + Ptyp_variant closed=Closed + [ + Rtag "Foo" true + attribute "ocaml.doc" + [ + structure_item (docstrings.ml[14,224+9]..[14,224+19]) + Pstr_eval + expression (docstrings.ml[14,224+9]..[14,224+19]) + Pexp_constant PConst_string(" foo ",None) + ] + [] + Rtag "Bar" false + attribute "ocaml.doc" + [ + structure_item (docstrings.ml[15,244+25]..[15,244+35]) + Pstr_eval + expression (docstrings.ml[15,244+25]..[15,244+35]) + Pexp_constant PConst_string(" bar ",None) + ] + [ + core_type (docstrings.ml[15,244+12]..[15,244+24]) + Ptyp_tuple + [ + core_type (docstrings.ml[15,244+12]..[15,244+15]) + Ptyp_constr "int" (docstrings.ml[15,244+12]..[15,244+15]) + [] + core_type (docstrings.ml[15,244+18]..[15,244+24]) + Ptyp_constr "string" (docstrings.ml[15,244+18]..[15,244+24]) + [] + ] + ] + ] + None + ] +] + diff --git a/testsuite/tests/parsing/extensions.ml b/testsuite/tests/parsing/extensions.ml new file mode 100644 index 00000000..e0feab8b --- /dev/null +++ b/testsuite/tests/parsing/extensions.ml @@ -0,0 +1,18 @@ + +[%%foo let x = 1 in x] +let [%foo 2+1] : [%foo bar.baz] = [%foo "foo"] + +[%%foo module M = [%bar] ] +let [%foo let () = () ] : [%foo type t = t ] = [%foo class c = object end] + +[%%foo: 'a list] +let [%foo: [`Foo] ] : [%foo: t -> t ] = [%foo: < foo : t > ] + +[%%foo? _ ] +[%%foo? Some y when y > 0] +let [%foo? (Bar x | Baz x) ] : [%foo? #bar ] = [%foo? { x }] + +[%%foo: module M : [%baz]] +let [%foo: include S with type t = t ] + : [%foo: val x : t val y : t] + = [%foo: type t = t ] diff --git a/testsuite/tests/parsing/extensions.ml.reference b/testsuite/tests/parsing/extensions.ml.reference new file mode 100644 index 00000000..bd14c5d3 --- /dev/null +++ b/testsuite/tests/parsing/extensions.ml.reference @@ -0,0 +1,326 @@ +[ + structure_item (extensions.ml[2,1+0]..[2,1+22]) + Pstr_extension "foo" + [ + structure_item (extensions.ml[2,1+7]..[2,1+21]) + Pstr_eval + expression (extensions.ml[2,1+7]..[2,1+21]) + Pexp_let Nonrec + [ + + pattern (extensions.ml[2,1+11]..[2,1+12]) + Ppat_var "x" (extensions.ml[2,1+11]..[2,1+12]) + expression (extensions.ml[2,1+15]..[2,1+16]) + Pexp_constant PConst_int (1,None) + ] + expression (extensions.ml[2,1+20]..[2,1+21]) + Pexp_ident "x" (extensions.ml[2,1+20]..[2,1+21]) + ] + structure_item (extensions.ml[3,24+0]..[3,24+46]) + Pstr_value Nonrec + [ + + pattern (extensions.ml[3,24+4]..[3,24+46]) ghost + Ppat_constraint + pattern (extensions.ml[3,24+4]..[3,24+14]) + Ppat_extension "foo" + [ + structure_item (extensions.ml[3,24+10]..[3,24+13]) + Pstr_eval + expression (extensions.ml[3,24+10]..[3,24+13]) + Pexp_apply + expression (extensions.ml[3,24+11]..[3,24+12]) + Pexp_ident "+" (extensions.ml[3,24+11]..[3,24+12]) + [ + + Nolabel + expression (extensions.ml[3,24+10]..[3,24+11]) + Pexp_constant PConst_int (2,None) + + Nolabel + expression (extensions.ml[3,24+12]..[3,24+13]) + Pexp_constant PConst_int (1,None) + ] + ] + core_type (extensions.ml[3,24+17]..[3,24+31]) + Ptyp_extension "foo" + [ + structure_item (extensions.ml[3,24+23]..[3,24+30]) + Pstr_eval + expression (extensions.ml[3,24+23]..[3,24+30]) + Pexp_field + expression (extensions.ml[3,24+23]..[3,24+26]) + Pexp_ident "bar" (extensions.ml[3,24+23]..[3,24+26]) + "baz" (extensions.ml[3,24+27]..[3,24+30]) + ] + expression (extensions.ml[3,24+34]..[3,24+46]) + Pexp_extension "foo" + [ + structure_item (extensions.ml[3,24+40]..[3,24+45]) + Pstr_eval + expression (extensions.ml[3,24+40]..[3,24+45]) + Pexp_constant PConst_string("foo",None) + ] + ] + structure_item (extensions.ml[5,72+0]..[5,72+26]) + Pstr_extension "foo" + [ + structure_item (extensions.ml[5,72+7]..[5,72+24]) + Pstr_module + "M" (extensions.ml[5,72+14]..[5,72+15]) + module_expr (extensions.ml[5,72+18]..[5,72+24]) + Pmod_extension "bar" + [] + ] + structure_item (extensions.ml[6,99+0]..[6,99+74]) + Pstr_value Nonrec + [ + + pattern (extensions.ml[6,99+4]..[6,99+74]) ghost + Ppat_constraint + pattern (extensions.ml[6,99+4]..[6,99+23]) + Ppat_extension "foo" + [ + structure_item (extensions.ml[6,99+10]..[6,99+21]) + Pstr_value Nonrec + [ + + pattern (extensions.ml[6,99+14]..[6,99+16]) + Ppat_construct "()" (extensions.ml[6,99+14]..[6,99+16]) + None + expression (extensions.ml[6,99+19]..[6,99+21]) + Pexp_construct "()" (extensions.ml[6,99+19]..[6,99+21]) + None + ] + ] + core_type (extensions.ml[6,99+26]..[6,99+44]) + Ptyp_extension "foo" + [ + structure_item (extensions.ml[6,99+32]..[6,99+42]) + Pstr_type Rec + [ + type_declaration "t" (extensions.ml[6,99+37]..[6,99+38]) (extensions.ml[6,99+32]..[6,99+42]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (extensions.ml[6,99+41]..[6,99+42]) + Ptyp_constr "t" (extensions.ml[6,99+41]..[6,99+42]) + [] + ] + ] + expression (extensions.ml[6,99+47]..[6,99+74]) + Pexp_extension "foo" + [ + structure_item (extensions.ml[6,99+53]..[6,99+73]) + Pstr_class + [ + class_declaration (extensions.ml[6,99+53]..[6,99+73]) + pci_virt = Concrete + pci_params = + [] + pci_name = "c" (extensions.ml[6,99+59]..[6,99+60]) + pci_expr = + class_expr (extensions.ml[6,99+63]..[6,99+73]) + Pcl_structure + class_structure + pattern (extensions.ml[6,99+69]..[6,99+69]) ghost + Ppat_any + [] + ] + ] + ] + structure_item (extensions.ml[8,175+0]..[8,175+16]) + Pstr_extension "foo" + core_type (extensions.ml[8,175+8]..[8,175+15]) + Ptyp_constr "list" (extensions.ml[8,175+11]..[8,175+15]) + [ + core_type (extensions.ml[8,175+8]..[8,175+10]) + Ptyp_var a + ] + structure_item (extensions.ml[9,192+0]..[9,192+60]) + Pstr_value Nonrec + [ + + pattern (extensions.ml[9,192+4]..[9,192+60]) ghost + Ppat_constraint + pattern (extensions.ml[9,192+4]..[9,192+19]) + Ppat_extension "foo" + core_type (extensions.ml[9,192+11]..[9,192+17]) + Ptyp_variant closed=Closed + [ + Rtag "Foo" true + [] + ] + None + core_type (extensions.ml[9,192+22]..[9,192+37]) + Ptyp_extension "foo" + core_type (extensions.ml[9,192+29]..[9,192+35]) + Ptyp_arrow + Nolabel + core_type (extensions.ml[9,192+29]..[9,192+30]) + Ptyp_constr "t" (extensions.ml[9,192+29]..[9,192+30]) + [] + core_type (extensions.ml[9,192+34]..[9,192+35]) + Ptyp_constr "t" (extensions.ml[9,192+34]..[9,192+35]) + [] + expression (extensions.ml[9,192+40]..[9,192+60]) + Pexp_extension "foo" + core_type (extensions.ml[9,192+47]..[9,192+58]) + Ptyp_object Closed + method foo + core_type (extensions.ml[9,192+55]..[9,192+56]) + Ptyp_constr "t" (extensions.ml[9,192+55]..[9,192+56]) + [] + ] + structure_item (extensions.ml[11,254+0]..[11,254+11]) + Pstr_extension "foo" + pattern (extensions.ml[11,254+8]..[11,254+9]) + Ppat_any + structure_item (extensions.ml[12,266+0]..[12,266+26]) + Pstr_extension "foo" + pattern (extensions.ml[12,266+8]..[12,266+14]) + Ppat_construct "Some" (extensions.ml[12,266+8]..[12,266+12]) + Some + pattern (extensions.ml[12,266+13]..[12,266+14]) + Ppat_var "y" (extensions.ml[12,266+13]..[12,266+14]) + + expression (extensions.ml[12,266+20]..[12,266+25]) + Pexp_apply + expression (extensions.ml[12,266+22]..[12,266+23]) + Pexp_ident ">" (extensions.ml[12,266+22]..[12,266+23]) + [ + + Nolabel + expression (extensions.ml[12,266+20]..[12,266+21]) + Pexp_ident "y" (extensions.ml[12,266+20]..[12,266+21]) + + Nolabel + expression (extensions.ml[12,266+24]..[12,266+25]) + Pexp_constant PConst_int (0,None) + ] + structure_item (extensions.ml[13,293+0]..[13,293+60]) + Pstr_value Nonrec + [ + + pattern (extensions.ml[13,293+4]..[13,293+60]) ghost + Ppat_constraint + pattern (extensions.ml[13,293+4]..[13,293+28]) + Ppat_extension "foo" + pattern (extensions.ml[13,293+11]..[13,293+26]) + Ppat_or + pattern (extensions.ml[13,293+12]..[13,293+17]) + Ppat_construct "Bar" (extensions.ml[13,293+12]..[13,293+15]) + Some + pattern (extensions.ml[13,293+16]..[13,293+17]) + Ppat_var "x" (extensions.ml[13,293+16]..[13,293+17]) + pattern (extensions.ml[13,293+20]..[13,293+25]) + Ppat_construct "Baz" (extensions.ml[13,293+20]..[13,293+23]) + Some + pattern (extensions.ml[13,293+24]..[13,293+25]) + Ppat_var "x" (extensions.ml[13,293+24]..[13,293+25]) + core_type (extensions.ml[13,293+31]..[13,293+44]) + Ptyp_extension "foo" + pattern (extensions.ml[13,293+38]..[13,293+42]) + Ppat_type + "bar" (extensions.ml[13,293+39]..[13,293+42]) + expression (extensions.ml[13,293+47]..[13,293+60]) + Pexp_extension "foo" + pattern (extensions.ml[13,293+54]..[13,293+59]) + Ppat_record Closed + [ + "x" (extensions.ml[13,293+56]..[13,293+57]) + pattern (extensions.ml[13,293+56]..[13,293+57]) + Ppat_var "x" (extensions.ml[13,293+56]..[13,293+57]) + ] + ] + structure_item (extensions.ml[15,355+0]..[15,355+26]) + Pstr_extension "foo" + [ + signature_item (extensions.ml[15,355+8]..[15,355+25]) + Psig_module "M" (extensions.ml[15,355+15]..[15,355+16]) + module_type (extensions.ml[15,355+19]..[15,355+25]) + Pmod_extension "baz" + [] + ] + structure_item (extensions.ml[16,382+0]..[18,454+23]) + Pstr_value Nonrec + [ + + pattern (extensions.ml[16,382+4]..[18,454+23]) ghost + Ppat_constraint + pattern (extensions.ml[16,382+4]..[16,382+38]) + Ppat_extension "foo" + [ + signature_item (extensions.ml[16,382+11]..[16,382+36]) + Psig_include + module_type (extensions.ml[16,382+19]..[16,382+36]) + Pmty_with + module_type (extensions.ml[16,382+19]..[16,382+20]) + Pmty_ident "S" (extensions.ml[16,382+19]..[16,382+20]) + [ + Pwith_type "t" (extensions.ml[16,382+31]..[16,382+32]) + type_declaration "t" (extensions.ml[16,382+31]..[16,382+32]) (extensions.ml[16,382+26]..[16,382+36]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (extensions.ml[16,382+35]..[16,382+36]) + Ptyp_constr "t" (extensions.ml[16,382+35]..[16,382+36]) + [] + ] + ] + core_type (extensions.ml[17,421+4]..[17,421+32]) + Ptyp_extension "foo" + [ + signature_item (extensions.ml[17,421+11]..[17,421+20]) + Psig_value + value_description "x" (extensions.ml[17,421+15]..[17,421+16]) (extensions.ml[17,421+11]..[17,421+20]) + core_type (extensions.ml[17,421+19]..[17,421+20]) + Ptyp_constr "t" (extensions.ml[17,421+19]..[17,421+20]) + [] + [] + signature_item (extensions.ml[17,421+22]..[17,421+31]) + Psig_value + value_description "y" (extensions.ml[17,421+26]..[17,421+27]) (extensions.ml[17,421+22]..[17,421+31]) + core_type (extensions.ml[17,421+30]..[17,421+31]) + Ptyp_constr "t" (extensions.ml[17,421+30]..[17,421+31]) + [] + [] + ] + expression (extensions.ml[18,454+4]..[18,454+23]) + Pexp_extension "foo" + [ + signature_item (extensions.ml[18,454+11]..[18,454+21]) + Psig_type Rec + [ + type_declaration "t" (extensions.ml[18,454+16]..[18,454+17]) (extensions.ml[18,454+11]..[18,454+21]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (extensions.ml[18,454+20]..[18,454+21]) + Ptyp_constr "t" (extensions.ml[18,454+20]..[18,454+21]) + [] + ] + ] + ] +] + +File "extensions.ml", line 2, characters 3-6: +Uninterpreted extension 'foo'. diff --git a/testsuite/tests/parsing/int_and_float_with_modifier.ml b/testsuite/tests/parsing/int_and_float_with_modifier.ml new file mode 100644 index 00000000..06384257 --- /dev/null +++ b/testsuite/tests/parsing/int_and_float_with_modifier.ml @@ -0,0 +1,14 @@ +let int_with_custom_modifier = + 1234567890_1234567890_1234567890_1234567890_1234567890z +let float_with_custom_modifier = + 1234567890_1234567890_1234567890_1234567890_1234567890.z + +let int32 = 1234l +let int64 = 1234L +let nativeint = 1234n + +let hex_without_modifier = 0x32f +let hex_with_modifier = 0x32g + +let float_without_modifer = 1.2e3 +let float_with_modifer = 1.2g diff --git a/testsuite/tests/parsing/int_and_float_with_modifier.ml.reference b/testsuite/tests/parsing/int_and_float_with_modifier.ml.reference new file mode 100644 index 00000000..fd3bee0e --- /dev/null +++ b/testsuite/tests/parsing/int_and_float_with_modifier.ml.reference @@ -0,0 +1,86 @@ +[ + structure_item (int_and_float_with_modifier.ml[1,0+0]..[2,31+57]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[1,0+4]..[1,0+28]) + Ppat_var "int_with_custom_modifier" (int_and_float_with_modifier.ml[1,0+4]..[1,0+28]) + expression (int_and_float_with_modifier.ml[2,31+2]..[2,31+57]) + Pexp_constant PConst_int (1234567890_1234567890_1234567890_1234567890_1234567890,Some z) + ] + structure_item (int_and_float_with_modifier.ml[3,89+0]..[4,122+58]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[3,89+4]..[3,89+30]) + Ppat_var "float_with_custom_modifier" (int_and_float_with_modifier.ml[3,89+4]..[3,89+30]) + expression (int_and_float_with_modifier.ml[4,122+2]..[4,122+58]) + Pexp_constant PConst_float (1234567890_1234567890_1234567890_1234567890_1234567890.,Some z) + ] + structure_item (int_and_float_with_modifier.ml[6,182+0]..[6,182+21]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[6,182+4]..[6,182+9]) + Ppat_var "int32" (int_and_float_with_modifier.ml[6,182+4]..[6,182+9]) + expression (int_and_float_with_modifier.ml[6,182+16]..[6,182+21]) + Pexp_constant PConst_int (1234,Some l) + ] + structure_item (int_and_float_with_modifier.ml[7,204+0]..[7,204+21]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[7,204+4]..[7,204+9]) + Ppat_var "int64" (int_and_float_with_modifier.ml[7,204+4]..[7,204+9]) + expression (int_and_float_with_modifier.ml[7,204+16]..[7,204+21]) + Pexp_constant PConst_int (1234,Some L) + ] + structure_item (int_and_float_with_modifier.ml[8,226+0]..[8,226+21]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[8,226+4]..[8,226+13]) + Ppat_var "nativeint" (int_and_float_with_modifier.ml[8,226+4]..[8,226+13]) + expression (int_and_float_with_modifier.ml[8,226+16]..[8,226+21]) + Pexp_constant PConst_int (1234,Some n) + ] + structure_item (int_and_float_with_modifier.ml[10,249+0]..[10,249+32]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[10,249+4]..[10,249+24]) + Ppat_var "hex_without_modifier" (int_and_float_with_modifier.ml[10,249+4]..[10,249+24]) + expression (int_and_float_with_modifier.ml[10,249+27]..[10,249+32]) + Pexp_constant PConst_int (0x32f,None) + ] + structure_item (int_and_float_with_modifier.ml[11,282+0]..[11,282+32]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[11,282+4]..[11,282+21]) + Ppat_var "hex_with_modifier" (int_and_float_with_modifier.ml[11,282+4]..[11,282+21]) + expression (int_and_float_with_modifier.ml[11,282+27]..[11,282+32]) + Pexp_constant PConst_int (0x32,Some g) + ] + structure_item (int_and_float_with_modifier.ml[13,316+0]..[13,316+33]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[13,316+4]..[13,316+25]) + Ppat_var "float_without_modifer" (int_and_float_with_modifier.ml[13,316+4]..[13,316+25]) + expression (int_and_float_with_modifier.ml[13,316+28]..[13,316+33]) + Pexp_constant PConst_float (1.2e3,None) + ] + structure_item (int_and_float_with_modifier.ml[14,350+0]..[14,350+32]) + Pstr_value Nonrec + [ + + pattern (int_and_float_with_modifier.ml[14,350+4]..[14,350+22]) + Ppat_var "float_with_modifer" (int_and_float_with_modifier.ml[14,350+4]..[14,350+22]) + expression (int_and_float_with_modifier.ml[14,350+28]..[14,350+32]) + Pexp_constant PConst_float (1.2,Some g) + ] +] + +File "int_and_float_with_modifier.ml", line 2, characters 2-57: +Error: Unknown modifier 'z' for literal 1234567890_1234567890_1234567890_1234567890_1234567890z diff --git a/testsuite/tests/parsing/pr6865.ml b/testsuite/tests/parsing/pr6865.ml new file mode 100644 index 00000000..78cd602f --- /dev/null +++ b/testsuite/tests/parsing/pr6865.ml @@ -0,0 +1,3 @@ +let%foo x = 42 +let%foo _ = () and _ = () +let%foo _ = () diff --git a/testsuite/tests/parsing/pr6865.ml.reference b/testsuite/tests/parsing/pr6865.ml.reference new file mode 100644 index 00000000..55a541fb --- /dev/null +++ b/testsuite/tests/parsing/pr6865.ml.reference @@ -0,0 +1,52 @@ +[ + structure_item (pr6865.ml[1,0+0]..[1,0+14]) ghost + Pstr_extension "foo" + [ + structure_item (pr6865.ml[1,0+0]..[1,0+14]) + Pstr_value Nonrec + [ + + pattern (pr6865.ml[1,0+8]..[1,0+9]) + Ppat_var "x" (pr6865.ml[1,0+8]..[1,0+9]) + expression (pr6865.ml[1,0+12]..[1,0+14]) + Pexp_constant PConst_int (42,None) + ] + ] + structure_item (pr6865.ml[2,15+0]..[2,15+25]) ghost + Pstr_extension "foo" + [ + structure_item (pr6865.ml[2,15+0]..[2,15+25]) + Pstr_value Nonrec + [ + + pattern (pr6865.ml[2,15+8]..[2,15+9]) + Ppat_any + expression (pr6865.ml[2,15+12]..[2,15+14]) + Pexp_construct "()" (pr6865.ml[2,15+12]..[2,15+14]) + None + + pattern (pr6865.ml[2,15+19]..[2,15+20]) + Ppat_any + expression (pr6865.ml[2,15+23]..[2,15+25]) + Pexp_construct "()" (pr6865.ml[2,15+23]..[2,15+25]) + None + ] + ] + structure_item (pr6865.ml[3,41+0]..[3,41+14]) ghost + Pstr_extension "foo" + [ + structure_item (pr6865.ml[3,41+0]..[3,41+14]) + Pstr_value Nonrec + [ + + pattern (pr6865.ml[3,41+8]..[3,41+9]) + Ppat_any + expression (pr6865.ml[3,41+12]..[3,41+14]) + Pexp_construct "()" (pr6865.ml[3,41+12]..[3,41+14]) + None + ] + ] +] + +File "pr6865.ml", line 1, characters 4-7: +Uninterpreted extension 'foo'. diff --git a/testsuite/tests/parsing/shortcut_ext_attr.ml b/testsuite/tests/parsing/shortcut_ext_attr.ml new file mode 100644 index 00000000..e65a663c --- /dev/null +++ b/testsuite/tests/parsing/shortcut_ext_attr.ml @@ -0,0 +1,113 @@ + +(* Expressions *) +let () = + let%foo[@foo] x = 3 + and[@foo] y = 4 in + (let module%foo[@foo] M = M in ()) ; + (let open%foo[@foo] M in ()) ; + (fun%foo[@foo] x -> ()) ; + (function%foo[@foo] x -> ()) ; + (try%foo[@foo] () with _ -> ()) ; + (if%foo[@foo] () then () else ()) ; + while%foo[@foo] () do () done ; + for%foo[@foo] x = () to () do () done ; + assert%foo[@foo] true ; + lazy%foo[@foo] x ; + object%foo[@foo] end ; + begin%foo[@foo] 3 end ; + new%foo[@foo] x ; + + match%foo[@foo] () with + (* Pattern expressions *) + | lazy%foo[@foo] x -> () + | exception%foo[@foo] x -> () + + +(* Class expressions *) +class x = + fun[@foo] x -> + let[@foo] x = 3 in + object[@foo] + inherit[@foo] x + val[@foo] x = 3 + val[@foo] virtual x : t + val![@foo] mutable x = 3 + method[@foo] x = 3 + method[@foo] virtual x : t + method![@foo] private x = 3 + initializer[@foo] x + end + +(* Class type expressions *) +class type t = + object[@foo] + inherit[@foo] t + val[@foo] x : t + val[@foo] mutable x : t + method[@foo] x : t + method[@foo] private x : t + constraint[@foo] t = t' + end + +(* Type expressions *) +type t = + (module%foo[@foo] M) + +(* Module expressions *) +module M = + functor[@foo] (M : S) -> + (val[@foo] x) + (struct[@foo] end) + +(* Module type expression *) +module type S = + functor[@foo] (M:S) -> + (module type of[@foo] M) -> + (sig[@foo] end) + +(* Structure items *) +let%foo[@foo] x = 4 +and[@foo] y = x + +type%foo[@foo] t = int +and[@foo] t = int +type%foo[@foo] t += T + +class%foo[@foo] x = x +class type%foo[@foo] x = x +external%foo[@foo] x : _ = "" +exception%foo[@foo] X + +module%foo[@foo] M = M +module%foo[@foo] rec M : S = M +and[@foo] M : S = M +module type%foo[@foo] S = S + +include%foo[@foo] M +open%foo[@foo] M + +(* Signature items *) +module type S = sig + val%foo[@foo] x : t + external%foo[@foo] x : t = "" + + type%foo[@foo] t = int + and[@foo] t' = int + type%foo[@foo] t += T + + exception%foo[@foo] X + + module%foo[@foo] M : S + module%foo[@foo] rec M : S + and[@foo] M : S + module%foo[@foo] M = M + + module type%foo[@foo] S = S + + include%foo[@foo] M + open%foo[@foo] M + + class%foo[@foo] x : t + class type%foo[@foo] x = x + +end diff --git a/testsuite/tests/parsing/shortcut_ext_attr.ml.reference b/testsuite/tests/parsing/shortcut_ext_attr.ml.reference new file mode 100644 index 00000000..27c32e16 --- /dev/null +++ b/testsuite/tests/parsing/shortcut_ext_attr.ml.reference @@ -0,0 +1,962 @@ +[ + structure_item (shortcut_ext_attr.ml[3,19+0]..[23,554+31]) + Pstr_value Nonrec + [ + + pattern (shortcut_ext_attr.ml[3,19+4]..[3,19+6]) + Ppat_construct "()" (shortcut_ext_attr.ml[3,19+4]..[3,19+6]) + None + expression (shortcut_ext_attr.ml[4,28+2]..[23,554+31]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[4,28+2]..[23,554+31]) + Pstr_eval + expression (shortcut_ext_attr.ml[4,28+2]..[23,554+31]) + Pexp_let Nonrec + [ + + attribute "foo" + [] + pattern (shortcut_ext_attr.ml[4,28+16]..[4,28+17]) + Ppat_var "x" (shortcut_ext_attr.ml[4,28+16]..[4,28+17]) + expression (shortcut_ext_attr.ml[4,28+20]..[4,28+21]) + Pexp_constant PConst_int (3,None) + + attribute "foo" + [] + pattern (shortcut_ext_attr.ml[5,50+12]..[5,50+13]) + Ppat_var "y" (shortcut_ext_attr.ml[5,50+12]..[5,50+13]) + expression (shortcut_ext_attr.ml[5,50+16]..[5,50+17]) + Pexp_constant PConst_int (4,None) + ] + expression (shortcut_ext_attr.ml[6,71+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[6,71+2]..[6,71+36]) + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[6,71+3]..[6,71+35]) + Pstr_eval + expression (shortcut_ext_attr.ml[6,71+3]..[6,71+35]) + attribute "foo" + [] + Pexp_letmodule "M" (shortcut_ext_attr.ml[6,71+24]..[6,71+25]) + module_expr (shortcut_ext_attr.ml[6,71+28]..[6,71+29]) + Pmod_ident "M" (shortcut_ext_attr.ml[6,71+28]..[6,71+29]) + expression (shortcut_ext_attr.ml[6,71+33]..[6,71+35]) + Pexp_construct "()" (shortcut_ext_attr.ml[6,71+33]..[6,71+35]) + None + ] + expression (shortcut_ext_attr.ml[7,110+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[7,110+2]..[7,110+30]) + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[7,110+3]..[7,110+29]) + Pstr_eval + expression (shortcut_ext_attr.ml[7,110+3]..[7,110+29]) + attribute "foo" + [] + Pexp_open Fresh ""M" (shortcut_ext_attr.ml[7,110+22]..[7,110+23])" + expression (shortcut_ext_attr.ml[7,110+27]..[7,110+29]) + Pexp_construct "()" (shortcut_ext_attr.ml[7,110+27]..[7,110+29]) + None + ] + expression (shortcut_ext_attr.ml[8,143+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[8,143+2]..[8,143+25]) + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[8,143+3]..[8,143+24]) + Pstr_eval + expression (shortcut_ext_attr.ml[8,143+3]..[8,143+24]) + attribute "foo" + [] + Pexp_fun + Nolabel + None + pattern (shortcut_ext_attr.ml[8,143+17]..[8,143+18]) + Ppat_var "x" (shortcut_ext_attr.ml[8,143+17]..[8,143+18]) + expression (shortcut_ext_attr.ml[8,143+22]..[8,143+24]) + Pexp_construct "()" (shortcut_ext_attr.ml[8,143+22]..[8,143+24]) + None + ] + expression (shortcut_ext_attr.ml[9,171+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[9,171+2]..[9,171+30]) + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[9,171+3]..[9,171+29]) + Pstr_eval + expression (shortcut_ext_attr.ml[9,171+3]..[9,171+29]) + attribute "foo" + [] + Pexp_function + [ + + pattern (shortcut_ext_attr.ml[9,171+22]..[9,171+23]) + Ppat_var "x" (shortcut_ext_attr.ml[9,171+22]..[9,171+23]) + expression (shortcut_ext_attr.ml[9,171+27]..[9,171+29]) + Pexp_construct "()" (shortcut_ext_attr.ml[9,171+27]..[9,171+29]) + None + ] + ] + expression (shortcut_ext_attr.ml[10,204+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[10,204+2]..[10,204+33]) + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[10,204+3]..[10,204+32]) + Pstr_eval + expression (shortcut_ext_attr.ml[10,204+3]..[10,204+32]) + attribute "foo" + [] + Pexp_try + expression (shortcut_ext_attr.ml[10,204+17]..[10,204+19]) + Pexp_construct "()" (shortcut_ext_attr.ml[10,204+17]..[10,204+19]) + None + [ + + pattern (shortcut_ext_attr.ml[10,204+25]..[10,204+26]) + Ppat_any + expression (shortcut_ext_attr.ml[10,204+30]..[10,204+32]) + Pexp_construct "()" (shortcut_ext_attr.ml[10,204+30]..[10,204+32]) + None + ] + ] + expression (shortcut_ext_attr.ml[11,240+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[11,240+2]..[11,240+35]) + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[11,240+3]..[11,240+34]) + Pstr_eval + expression (shortcut_ext_attr.ml[11,240+3]..[11,240+34]) + attribute "foo" + [] + Pexp_ifthenelse + expression (shortcut_ext_attr.ml[11,240+16]..[11,240+18]) + Pexp_construct "()" (shortcut_ext_attr.ml[11,240+16]..[11,240+18]) + None + expression (shortcut_ext_attr.ml[11,240+24]..[11,240+26]) + Pexp_construct "()" (shortcut_ext_attr.ml[11,240+24]..[11,240+26]) + None + Some + expression (shortcut_ext_attr.ml[11,240+32]..[11,240+34]) + Pexp_construct "()" (shortcut_ext_attr.ml[11,240+32]..[11,240+34]) + None + ] + expression (shortcut_ext_attr.ml[12,278+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[12,278+2]..[12,278+31]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[12,278+2]..[12,278+31]) + Pstr_eval + expression (shortcut_ext_attr.ml[12,278+2]..[12,278+31]) + attribute "foo" + [] + Pexp_while + expression (shortcut_ext_attr.ml[12,278+18]..[12,278+20]) + Pexp_construct "()" (shortcut_ext_attr.ml[12,278+18]..[12,278+20]) + None + expression (shortcut_ext_attr.ml[12,278+24]..[12,278+26]) + Pexp_construct "()" (shortcut_ext_attr.ml[12,278+24]..[12,278+26]) + None + ] + expression (shortcut_ext_attr.ml[13,312+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[13,312+2]..[13,312+39]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[13,312+2]..[13,312+39]) + Pstr_eval + expression (shortcut_ext_attr.ml[13,312+2]..[13,312+39]) + attribute "foo" + [] + Pexp_for Up + pattern (shortcut_ext_attr.ml[13,312+16]..[13,312+17]) + Ppat_var "x" (shortcut_ext_attr.ml[13,312+16]..[13,312+17]) + expression (shortcut_ext_attr.ml[13,312+20]..[13,312+22]) + Pexp_construct "()" (shortcut_ext_attr.ml[13,312+20]..[13,312+22]) + None + expression (shortcut_ext_attr.ml[13,312+26]..[13,312+28]) + Pexp_construct "()" (shortcut_ext_attr.ml[13,312+26]..[13,312+28]) + None + expression (shortcut_ext_attr.ml[13,312+32]..[13,312+34]) + Pexp_construct "()" (shortcut_ext_attr.ml[13,312+32]..[13,312+34]) + None + ] + expression (shortcut_ext_attr.ml[14,354+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[14,354+2]..[14,354+23]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[14,354+2]..[14,354+23]) + Pstr_eval + expression (shortcut_ext_attr.ml[14,354+2]..[14,354+23]) + attribute "foo" + [] + Pexp_assert + expression (shortcut_ext_attr.ml[14,354+19]..[14,354+23]) + Pexp_construct "true" (shortcut_ext_attr.ml[14,354+19]..[14,354+23]) + None + ] + expression (shortcut_ext_attr.ml[15,380+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[15,380+2]..[15,380+18]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[15,380+2]..[15,380+18]) + Pstr_eval + expression (shortcut_ext_attr.ml[15,380+2]..[15,380+18]) + attribute "foo" + [] + Pexp_lazy + expression (shortcut_ext_attr.ml[15,380+17]..[15,380+18]) + Pexp_ident "x" (shortcut_ext_attr.ml[15,380+17]..[15,380+18]) + ] + expression (shortcut_ext_attr.ml[16,401+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[16,401+2]..[16,401+22]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[16,401+2]..[16,401+22]) + Pstr_eval + expression (shortcut_ext_attr.ml[16,401+2]..[16,401+22]) + attribute "foo" + [] + Pexp_object + class_structure + pattern (shortcut_ext_attr.ml[16,401+18]..[16,401+18]) ghost + Ppat_any + [] + ] + expression (shortcut_ext_attr.ml[17,426+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[17,426+2]..[17,426+23]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[17,426+2]..[17,426+23]) + Pstr_eval + expression (shortcut_ext_attr.ml[17,426+2]..[17,426+23]) + attribute "foo" + [] + Pexp_constant PConst_int (3,None) + ] + expression (shortcut_ext_attr.ml[18,452+2]..[23,554+31]) + Pexp_sequence + expression (shortcut_ext_attr.ml[18,452+2]..[18,452+17]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[18,452+2]..[18,452+17]) + Pstr_eval + expression (shortcut_ext_attr.ml[18,452+2]..[18,452+17]) + attribute "foo" + [] + Pexp_new "x" (shortcut_ext_attr.ml[18,452+16]..[18,452+17]) + ] + expression (shortcut_ext_attr.ml[20,473+2]..[23,554+31]) ghost + Pexp_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[20,473+2]..[23,554+31]) + Pstr_eval + expression (shortcut_ext_attr.ml[20,473+2]..[23,554+31]) + attribute "foo" + [] + Pexp_match + expression (shortcut_ext_attr.ml[20,473+18]..[20,473+20]) + Pexp_construct "()" (shortcut_ext_attr.ml[20,473+18]..[20,473+20]) + None + [ + + pattern (shortcut_ext_attr.ml[22,527+4]..[22,527+20]) ghost + Ppat_extension "foo" + pattern (shortcut_ext_attr.ml[22,527+4]..[22,527+20]) + attribute "foo" + [] + Ppat_lazy + pattern (shortcut_ext_attr.ml[22,527+19]..[22,527+20]) + Ppat_var "x" (shortcut_ext_attr.ml[22,527+19]..[22,527+20]) + expression (shortcut_ext_attr.ml[22,527+24]..[22,527+26]) + Pexp_construct "()" (shortcut_ext_attr.ml[22,527+24]..[22,527+26]) + None + + pattern (shortcut_ext_attr.ml[23,554+4]..[23,554+25]) ghost + Ppat_extension "foo" + pattern (shortcut_ext_attr.ml[23,554+4]..[23,554+25]) + attribute "foo" + [] + Ppat_exception + pattern (shortcut_ext_attr.ml[23,554+24]..[23,554+25]) + Ppat_var "x" (shortcut_ext_attr.ml[23,554+24]..[23,554+25]) + expression (shortcut_ext_attr.ml[23,554+29]..[23,554+31]) + Pexp_construct "()" (shortcut_ext_attr.ml[23,554+29]..[23,554+31]) + None + ] + ] + ] + ] + structure_item (shortcut_ext_attr.ml[27,612+0]..[39,882+5]) + Pstr_class + [ + class_declaration (shortcut_ext_attr.ml[27,612+0]..[39,882+5]) + pci_virt = Concrete + pci_params = + [] + pci_name = "x" (shortcut_ext_attr.ml[27,612+6]..[27,612+7]) + pci_expr = + class_expr (shortcut_ext_attr.ml[28,622+12]..[39,882+5]) + attribute "foo" + [] + Pcl_fun + Nolabel + None + pattern (shortcut_ext_attr.ml[28,622+12]..[28,622+13]) + Ppat_var "x" (shortcut_ext_attr.ml[28,622+12]..[28,622+13]) + class_expr (shortcut_ext_attr.ml[29,639+2]..[39,882+5]) + Pcl_let Nonrec + [ + + attribute "foo" + [] + pattern (shortcut_ext_attr.ml[29,639+12]..[29,639+13]) + Ppat_var "x" (shortcut_ext_attr.ml[29,639+12]..[29,639+13]) + expression (shortcut_ext_attr.ml[29,639+16]..[29,639+17]) + Pexp_constant PConst_int (3,None) + ] + class_expr (shortcut_ext_attr.ml[30,660+2]..[39,882+5]) + attribute "foo" + [] + Pcl_structure + class_structure + pattern (shortcut_ext_attr.ml[30,660+14]..[30,660+14]) ghost + Ppat_any + [ + class_field (shortcut_ext_attr.ml[31,675+4]..[31,675+19]) + attribute "foo" + [] + Pcf_inherit Fresh + class_expr (shortcut_ext_attr.ml[31,675+18]..[31,675+19]) + Pcl_constr "x" (shortcut_ext_attr.ml[31,675+18]..[31,675+19]) + [] + None + class_field (shortcut_ext_attr.ml[32,695+4]..[32,695+19]) + attribute "foo" + [] + Pcf_val Immutable + "x" (shortcut_ext_attr.ml[32,695+14]..[32,695+15]) + Concrete Fresh + expression (shortcut_ext_attr.ml[32,695+18]..[32,695+19]) + Pexp_constant PConst_int (3,None) + class_field (shortcut_ext_attr.ml[33,715+4]..[33,715+27]) + attribute "foo" + [] + Pcf_val Immutable + "x" (shortcut_ext_attr.ml[33,715+22]..[33,715+23]) + Virtual + core_type (shortcut_ext_attr.ml[33,715+26]..[33,715+27]) + Ptyp_constr "t" (shortcut_ext_attr.ml[33,715+26]..[33,715+27]) + [] + class_field (shortcut_ext_attr.ml[34,743+4]..[34,743+28]) + attribute "foo" + [] + Pcf_val Mutable + "x" (shortcut_ext_attr.ml[34,743+23]..[34,743+24]) + Concrete Override + expression (shortcut_ext_attr.ml[34,743+27]..[34,743+28]) + Pexp_constant PConst_int (3,None) + class_field (shortcut_ext_attr.ml[35,772+4]..[35,772+22]) + attribute "foo" + [] + Pcf_method Public + "x" (shortcut_ext_attr.ml[35,772+17]..[35,772+18]) + Concrete Fresh + expression (shortcut_ext_attr.ml[35,772+10]..[35,772+22]) ghost + Pexp_poly + expression (shortcut_ext_attr.ml[35,772+21]..[35,772+22]) + Pexp_constant PConst_int (3,None) + None + class_field (shortcut_ext_attr.ml[36,795+4]..[36,795+30]) + attribute "foo" + [] + Pcf_method Public + "x" (shortcut_ext_attr.ml[36,795+25]..[36,795+26]) + Virtual + core_type (shortcut_ext_attr.ml[36,795+29]..[36,795+30]) + Ptyp_constr "t" (shortcut_ext_attr.ml[36,795+29]..[36,795+30]) + [] + class_field (shortcut_ext_attr.ml[37,826+4]..[37,826+31]) + attribute "foo" + [] + Pcf_method Private + "x" (shortcut_ext_attr.ml[37,826+26]..[37,826+27]) + Concrete Override + expression (shortcut_ext_attr.ml[37,826+10]..[37,826+31]) ghost + Pexp_poly + expression (shortcut_ext_attr.ml[37,826+30]..[37,826+31]) + Pexp_constant PConst_int (3,None) + None + class_field (shortcut_ext_attr.ml[38,858+4]..[38,858+23]) + attribute "foo" + [] + Pcf_initializer + expression (shortcut_ext_attr.ml[38,858+22]..[38,858+23]) + Pexp_ident "x" (shortcut_ext_attr.ml[38,858+22]..[38,858+23]) + ] + ] + structure_item (shortcut_ext_attr.ml[42,918+0]..[50,1098+5]) + Pstr_class_type + [ + class_type_declaration (shortcut_ext_attr.ml[42,918+0]..[50,1098+5]) + pci_virt = Concrete + pci_params = + [] + pci_name = "t" (shortcut_ext_attr.ml[42,918+11]..[42,918+12]) + pci_expr = + class_type (shortcut_ext_attr.ml[43,933+2]..[50,1098+5]) + attribute "foo" + [] + Pcty_signature + class_signature + core_type (shortcut_ext_attr.ml[43,933+14]..[43,933+14]) + Ptyp_any + [ + class_type_field (shortcut_ext_attr.ml[44,948+4]..[44,948+19]) + attribute "foo" + [] + Pctf_inherit + class_type (shortcut_ext_attr.ml[44,948+18]..[44,948+19]) + Pcty_constr "t" (shortcut_ext_attr.ml[44,948+18]..[44,948+19]) + [] + class_type_field (shortcut_ext_attr.ml[45,968+4]..[45,968+19]) + attribute "foo" + [] + Pctf_val "x" Immutable Concrete + core_type (shortcut_ext_attr.ml[45,968+18]..[45,968+19]) + Ptyp_constr "t" (shortcut_ext_attr.ml[45,968+18]..[45,968+19]) + [] + class_type_field (shortcut_ext_attr.ml[46,988+4]..[46,988+27]) + attribute "foo" + [] + Pctf_val "x" Mutable Concrete + core_type (shortcut_ext_attr.ml[46,988+26]..[46,988+27]) + Ptyp_constr "t" (shortcut_ext_attr.ml[46,988+26]..[46,988+27]) + [] + class_type_field (shortcut_ext_attr.ml[47,1016+4]..[47,1016+22]) + attribute "foo" + [] + Pctf_method "x" Public Concrete + core_type (shortcut_ext_attr.ml[47,1016+21]..[47,1016+22]) + Ptyp_constr "t" (shortcut_ext_attr.ml[47,1016+21]..[47,1016+22]) + [] + class_type_field (shortcut_ext_attr.ml[48,1039+4]..[48,1039+30]) + attribute "foo" + [] + Pctf_method "x" Private Concrete + core_type (shortcut_ext_attr.ml[48,1039+29]..[48,1039+30]) + Ptyp_constr "t" (shortcut_ext_attr.ml[48,1039+29]..[48,1039+30]) + [] + class_type_field (shortcut_ext_attr.ml[49,1070+4]..[49,1070+27]) + attribute "foo" + [] + Pctf_constraint + core_type (shortcut_ext_attr.ml[49,1070+21]..[49,1070+22]) + Ptyp_constr "t" (shortcut_ext_attr.ml[49,1070+21]..[49,1070+22]) + [] + core_type (shortcut_ext_attr.ml[49,1070+25]..[49,1070+27]) + Ptyp_constr "t'" (shortcut_ext_attr.ml[49,1070+25]..[49,1070+27]) + [] + ] + ] + structure_item (shortcut_ext_attr.ml[53,1128+0]..[54,1137+22]) + Pstr_type Rec + [ + type_declaration "t" (shortcut_ext_attr.ml[53,1128+5]..[53,1128+6]) (shortcut_ext_attr.ml[53,1128+0]..[54,1137+22]) + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (shortcut_ext_attr.ml[54,1137+2]..[54,1137+22]) ghost + Ptyp_extension "foo" + core_type (shortcut_ext_attr.ml[54,1137+2]..[54,1137+22]) + attribute "foo" + [] + Ptyp_package "M" (shortcut_ext_attr.ml[54,1137+20]..[54,1137+21]) + [] + ] + structure_item (shortcut_ext_attr.ml[57,1186+0]..[60,1242+22]) + Pstr_module + "M" (shortcut_ext_attr.ml[57,1186+7]..[57,1186+8]) + module_expr (shortcut_ext_attr.ml[58,1197+2]..[60,1242+22]) + attribute "foo" + [] + Pmod_functor "M" (shortcut_ext_attr.ml[58,1197+17]..[58,1197+18]) + module_type (shortcut_ext_attr.ml[58,1197+21]..[58,1197+22]) + Pmty_ident "S" (shortcut_ext_attr.ml[58,1197+21]..[58,1197+22]) + module_expr (shortcut_ext_attr.ml[59,1224+4]..[60,1242+22]) + Pmod_apply + module_expr (shortcut_ext_attr.ml[59,1224+4]..[59,1224+17]) + attribute "foo" + [] + Pmod_unpack + expression (shortcut_ext_attr.ml[59,1224+15]..[59,1224+16]) + Pexp_ident "x" (shortcut_ext_attr.ml[59,1224+15]..[59,1224+16]) + module_expr (shortcut_ext_attr.ml[60,1242+5]..[60,1242+21]) + attribute "foo" + [] + Pmod_structure + [] + structure_item (shortcut_ext_attr.ml[63,1295+0]..[66,1368+19]) + Pstr_modtype "S" (shortcut_ext_attr.ml[63,1295+12]..[63,1295+13]) + module_type (shortcut_ext_attr.ml[64,1311+2]..[66,1368+19]) + attribute "foo" + [] + Pmty_functor "M" (shortcut_ext_attr.ml[64,1311+17]..[64,1311+18]) + module_type (shortcut_ext_attr.ml[64,1311+19]..[64,1311+20]) + Pmty_ident "S" (shortcut_ext_attr.ml[64,1311+19]..[64,1311+20]) + module_type (shortcut_ext_attr.ml[65,1336+4]..[66,1368+19]) + Pmty_functor "_" (_none_[1,0+-1]..[1,0+-1]) ghost + module_type (shortcut_ext_attr.ml[65,1336+5]..[65,1336+27]) + attribute "foo" + [] + Pmty_typeof + module_expr (shortcut_ext_attr.ml[65,1336+26]..[65,1336+27]) + Pmod_ident "M" (shortcut_ext_attr.ml[65,1336+26]..[65,1336+27]) + module_type (shortcut_ext_attr.ml[66,1368+5]..[66,1368+18]) + attribute "foo" + [] + Pmty_signature + [] + structure_item (shortcut_ext_attr.ml[69,1411+0]..[70,1431+15]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[69,1411+0]..[70,1431+15]) + Pstr_value Nonrec + [ + + attribute "foo" + [] + pattern (shortcut_ext_attr.ml[69,1411+14]..[69,1411+15]) + Ppat_var "x" (shortcut_ext_attr.ml[69,1411+14]..[69,1411+15]) + expression (shortcut_ext_attr.ml[69,1411+18]..[69,1411+19]) + Pexp_constant PConst_int (4,None) + + attribute "foo" + [] + pattern (shortcut_ext_attr.ml[70,1431+10]..[70,1431+11]) + Ppat_var "y" (shortcut_ext_attr.ml[70,1431+10]..[70,1431+11]) + expression (shortcut_ext_attr.ml[70,1431+14]..[70,1431+15]) + Pexp_ident "x" (shortcut_ext_attr.ml[70,1431+14]..[70,1431+15]) + ] + ] + structure_item (shortcut_ext_attr.ml[72,1448+0]..[73,1471+17]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[72,1448+0]..[73,1471+17]) + Pstr_type Rec + [ + type_declaration "t" (shortcut_ext_attr.ml[72,1448+15]..[72,1448+16]) (shortcut_ext_attr.ml[72,1448+0]..[72,1448+22]) + attribute "foo" + [] + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (shortcut_ext_attr.ml[72,1448+19]..[72,1448+22]) + Ptyp_constr "int" (shortcut_ext_attr.ml[72,1448+19]..[72,1448+22]) + [] + type_declaration "t" (shortcut_ext_attr.ml[73,1471+10]..[73,1471+11]) (shortcut_ext_attr.ml[73,1471+0]..[73,1471+17]) + attribute "foo" + [] + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (shortcut_ext_attr.ml[73,1471+14]..[73,1471+17]) + Ptyp_constr "int" (shortcut_ext_attr.ml[73,1471+14]..[73,1471+17]) + [] + ] + ] + structure_item (shortcut_ext_attr.ml[74,1489+0]..[74,1489+21]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[74,1489+0]..[74,1489+21]) + Pstr_typext + type_extension + attribute "foo" + [] + ptyext_path = "t" (shortcut_ext_attr.ml[74,1489+15]..[74,1489+16]) + ptyext_params = + [] + ptyext_constructors = + [ + extension_constructor (shortcut_ext_attr.ml[74,1489+20]..[74,1489+21]) + pext_name = "T" + pext_kind = + Pext_decl + [] + None + ] + ptyext_private = Public + ] + structure_item (shortcut_ext_attr.ml[76,1512+0]..[76,1512+21]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[76,1512+0]..[76,1512+21]) + Pstr_class + [ + class_declaration (shortcut_ext_attr.ml[76,1512+0]..[76,1512+21]) + attribute "foo" + [] + pci_virt = Concrete + pci_params = + [] + pci_name = "x" (shortcut_ext_attr.ml[76,1512+16]..[76,1512+17]) + pci_expr = + class_expr (shortcut_ext_attr.ml[76,1512+20]..[76,1512+21]) + Pcl_constr "x" (shortcut_ext_attr.ml[76,1512+20]..[76,1512+21]) + [] + ] + ] + structure_item (shortcut_ext_attr.ml[77,1534+0]..[77,1534+26]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[77,1534+0]..[77,1534+26]) + Pstr_class_type + [ + class_type_declaration (shortcut_ext_attr.ml[77,1534+0]..[77,1534+26]) + attribute "foo" + [] + pci_virt = Concrete + pci_params = + [] + pci_name = "x" (shortcut_ext_attr.ml[77,1534+21]..[77,1534+22]) + pci_expr = + class_type (shortcut_ext_attr.ml[77,1534+25]..[77,1534+26]) + Pcty_constr "x" (shortcut_ext_attr.ml[77,1534+25]..[77,1534+26]) + [] + ] + ] + structure_item (shortcut_ext_attr.ml[78,1561+0]..[78,1561+30]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[78,1561+0]..[78,1561+30]) + Pstr_primitive + value_description "x" (shortcut_ext_attr.ml[78,1561+19]..[78,1561+20]) (shortcut_ext_attr.ml[78,1561+0]..[78,1561+30]) + attribute "foo" + [] + core_type (shortcut_ext_attr.ml[78,1561+23]..[78,1561+24]) + Ptyp_any + [ + "" + ] + ] + structure_item (shortcut_ext_attr.ml[79,1592+0]..[79,1592+21]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[79,1592+0]..[79,1592+21]) + Pstr_exception + extension_constructor (shortcut_ext_attr.ml[79,1592+0]..[79,1592+21]) + attribute "foo" + [] + pext_name = "X" + pext_kind = + Pext_decl + [] + None + ] + structure_item (shortcut_ext_attr.ml[81,1615+0]..[81,1615+22]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[81,1615+0]..[81,1615+22]) + Pstr_module + "M" (shortcut_ext_attr.ml[81,1615+17]..[81,1615+18]) + attribute "foo" + [] + module_expr (shortcut_ext_attr.ml[81,1615+21]..[81,1615+22]) + Pmod_ident "M" (shortcut_ext_attr.ml[81,1615+21]..[81,1615+22]) + ] + structure_item (shortcut_ext_attr.ml[82,1638+0]..[83,1669+19]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[82,1638+0]..[83,1669+19]) + Pstr_recmodule + [ + "M" (shortcut_ext_attr.ml[82,1638+21]..[82,1638+22]) + attribute "foo" + [] + module_expr (shortcut_ext_attr.ml[82,1638+23]..[82,1638+30]) + Pmod_constraint + module_expr (shortcut_ext_attr.ml[82,1638+29]..[82,1638+30]) + Pmod_ident "M" (shortcut_ext_attr.ml[82,1638+29]..[82,1638+30]) + module_type (shortcut_ext_attr.ml[82,1638+25]..[82,1638+26]) + Pmty_ident "S" (shortcut_ext_attr.ml[82,1638+25]..[82,1638+26]) + "M" (shortcut_ext_attr.ml[83,1669+10]..[83,1669+11]) + attribute "foo" + [] + module_expr (shortcut_ext_attr.ml[83,1669+12]..[83,1669+19]) + Pmod_constraint + module_expr (shortcut_ext_attr.ml[83,1669+18]..[83,1669+19]) + Pmod_ident "M" (shortcut_ext_attr.ml[83,1669+18]..[83,1669+19]) + module_type (shortcut_ext_attr.ml[83,1669+14]..[83,1669+15]) + Pmty_ident "S" (shortcut_ext_attr.ml[83,1669+14]..[83,1669+15]) + ] + ] + structure_item (shortcut_ext_attr.ml[84,1689+0]..[84,1689+27]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[84,1689+0]..[84,1689+27]) + Pstr_modtype "S" (shortcut_ext_attr.ml[84,1689+22]..[84,1689+23]) + attribute "foo" + [] + module_type (shortcut_ext_attr.ml[84,1689+26]..[84,1689+27]) + Pmty_ident "S" (shortcut_ext_attr.ml[84,1689+26]..[84,1689+27]) + ] + structure_item (shortcut_ext_attr.ml[86,1718+0]..[86,1718+19]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[86,1718+0]..[86,1718+19]) + Pstr_include attribute "foo" + [] + module_expr (shortcut_ext_attr.ml[86,1718+18]..[86,1718+19]) + Pmod_ident "M" (shortcut_ext_attr.ml[86,1718+18]..[86,1718+19]) + ] + structure_item (shortcut_ext_attr.ml[87,1738+0]..[87,1738+16]) ghost + Pstr_extension "foo" + [ + structure_item (shortcut_ext_attr.ml[87,1738+0]..[87,1738+16]) + Pstr_open Fresh "M" (shortcut_ext_attr.ml[87,1738+15]..[87,1738+16]) + attribute "foo" + [] + ] + structure_item (shortcut_ext_attr.ml[90,1778+0]..[113,2174+3]) + Pstr_modtype "S" (shortcut_ext_attr.ml[90,1778+12]..[90,1778+13]) + module_type (shortcut_ext_attr.ml[90,1778+16]..[113,2174+3]) + Pmty_signature + [ + signature_item (shortcut_ext_attr.ml[91,1798+2]..[91,1798+21]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[91,1798+2]..[91,1798+21]) + Psig_value + value_description "x" (shortcut_ext_attr.ml[91,1798+16]..[91,1798+17]) (shortcut_ext_attr.ml[91,1798+2]..[91,1798+21]) + attribute "foo" + [] + core_type (shortcut_ext_attr.ml[91,1798+20]..[91,1798+21]) + Ptyp_constr "t" (shortcut_ext_attr.ml[91,1798+20]..[91,1798+21]) + [] + [] + ] + signature_item (shortcut_ext_attr.ml[92,1820+2]..[92,1820+31]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[92,1820+2]..[92,1820+31]) + Psig_value + value_description "x" (shortcut_ext_attr.ml[92,1820+21]..[92,1820+22]) (shortcut_ext_attr.ml[92,1820+2]..[92,1820+31]) + attribute "foo" + [] + core_type (shortcut_ext_attr.ml[92,1820+25]..[92,1820+26]) + Ptyp_constr "t" (shortcut_ext_attr.ml[92,1820+25]..[92,1820+26]) + [] + [ + "" + ] + ] + signature_item (shortcut_ext_attr.ml[94,1853+2]..[95,1878+20]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[94,1853+2]..[95,1878+20]) + Psig_type Rec + [ + type_declaration "t" (shortcut_ext_attr.ml[94,1853+17]..[94,1853+18]) (shortcut_ext_attr.ml[94,1853+2]..[94,1853+24]) + attribute "foo" + [] + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (shortcut_ext_attr.ml[94,1853+21]..[94,1853+24]) + Ptyp_constr "int" (shortcut_ext_attr.ml[94,1853+21]..[94,1853+24]) + [] + type_declaration "t'" (shortcut_ext_attr.ml[95,1878+12]..[95,1878+14]) (shortcut_ext_attr.ml[95,1878+2]..[95,1878+20]) + attribute "foo" + [] + ptype_params = + [] + ptype_cstrs = + [] + ptype_kind = + Ptype_abstract + ptype_private = Public + ptype_manifest = + Some + core_type (shortcut_ext_attr.ml[95,1878+17]..[95,1878+20]) + Ptyp_constr "int" (shortcut_ext_attr.ml[95,1878+17]..[95,1878+20]) + [] + ] + ] + signature_item (shortcut_ext_attr.ml[96,1899+2]..[96,1899+23]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[96,1899+2]..[96,1899+23]) + Psig_typext + type_extension + attribute "foo" + [] + ptyext_path = "t" (shortcut_ext_attr.ml[96,1899+17]..[96,1899+18]) + ptyext_params = + [] + ptyext_constructors = + [ + extension_constructor (shortcut_ext_attr.ml[96,1899+22]..[96,1899+23]) + pext_name = "T" + pext_kind = + Pext_decl + [] + None + ] + ptyext_private = Public + ] + signature_item (shortcut_ext_attr.ml[98,1924+2]..[98,1924+23]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[98,1924+2]..[98,1924+23]) + Psig_exception + extension_constructor (shortcut_ext_attr.ml[98,1924+2]..[98,1924+23]) + attribute "foo" + [] + pext_name = "X" + pext_kind = + Pext_decl + [] + None + ] + signature_item (shortcut_ext_attr.ml[100,1949+2]..[100,1949+24]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[100,1949+2]..[100,1949+24]) + Psig_module "M" (shortcut_ext_attr.ml[100,1949+19]..[100,1949+20]) + attribute "foo" + [] + module_type (shortcut_ext_attr.ml[100,1949+23]..[100,1949+24]) + Pmty_ident "S" (shortcut_ext_attr.ml[100,1949+23]..[100,1949+24]) + ] + signature_item (shortcut_ext_attr.ml[101,1974+2]..[102,2003+17]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[101,1974+2]..[102,2003+17]) + Psig_recmodule + [ + "M" (shortcut_ext_attr.ml[101,1974+23]..[101,1974+24]) + attribute "foo" + [] + module_type (shortcut_ext_attr.ml[101,1974+27]..[101,1974+28]) + Pmty_ident "S" (shortcut_ext_attr.ml[101,1974+27]..[101,1974+28]) + "M" (shortcut_ext_attr.ml[102,2003+12]..[102,2003+13]) + attribute "foo" + [] + module_type (shortcut_ext_attr.ml[102,2003+16]..[102,2003+17]) + Pmty_ident "S" (shortcut_ext_attr.ml[102,2003+16]..[102,2003+17]) + ] + ] + signature_item (shortcut_ext_attr.ml[103,2021+2]..[103,2021+24]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[103,2021+2]..[103,2021+24]) + Psig_module "M" (shortcut_ext_attr.ml[103,2021+19]..[103,2021+20]) + attribute "foo" + [] + module_type (shortcut_ext_attr.ml[103,2021+23]..[103,2021+24]) + Pmty_alias "M" (shortcut_ext_attr.ml[103,2021+23]..[103,2021+24]) + ] + signature_item (shortcut_ext_attr.ml[105,2047+2]..[105,2047+29]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[105,2047+2]..[105,2047+29]) + Psig_modtype "S" (shortcut_ext_attr.ml[105,2047+24]..[105,2047+25]) + attribute "foo" + [] + module_type (shortcut_ext_attr.ml[105,2047+28]..[105,2047+29]) + Pmty_ident "S" (shortcut_ext_attr.ml[105,2047+28]..[105,2047+29]) + ] + signature_item (shortcut_ext_attr.ml[107,2078+2]..[107,2078+21]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[107,2078+2]..[107,2078+21]) + Psig_include + module_type (shortcut_ext_attr.ml[107,2078+20]..[107,2078+21]) + Pmty_ident "M" (shortcut_ext_attr.ml[107,2078+20]..[107,2078+21]) + attribute "foo" + [] + ] + signature_item (shortcut_ext_attr.ml[108,2100+2]..[108,2100+18]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[108,2100+2]..[108,2100+18]) + Psig_open Fresh "M" (shortcut_ext_attr.ml[108,2100+17]..[108,2100+18]) + attribute "foo" + [] + ] + signature_item (shortcut_ext_attr.ml[110,2120+2]..[110,2120+23]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[110,2120+2]..[110,2120+23]) + Psig_class + [ + class_description (shortcut_ext_attr.ml[110,2120+2]..[110,2120+23]) + attribute "foo" + [] + pci_virt = Concrete + pci_params = + [] + pci_name = "x" (shortcut_ext_attr.ml[110,2120+18]..[110,2120+19]) + pci_expr = + class_type (shortcut_ext_attr.ml[110,2120+22]..[110,2120+23]) + Pcty_constr "t" (shortcut_ext_attr.ml[110,2120+22]..[110,2120+23]) + [] + ] + ] + signature_item (shortcut_ext_attr.ml[111,2144+2]..[111,2144+28]) ghost + Psig_extension "foo" + [ + signature_item (shortcut_ext_attr.ml[111,2144+2]..[111,2144+28]) + Psig_class_type + [ + class_type_declaration (shortcut_ext_attr.ml[111,2144+2]..[111,2144+28]) + attribute "foo" + [] + pci_virt = Concrete + pci_params = + [] + pci_name = "x" (shortcut_ext_attr.ml[111,2144+23]..[111,2144+24]) + pci_expr = + class_type (shortcut_ext_attr.ml[111,2144+27]..[111,2144+28]) + Pcty_constr "x" (shortcut_ext_attr.ml[111,2144+27]..[111,2144+28]) + [] + ] + ] + ] +] + +File "shortcut_ext_attr.ml", line 4, characters 6-9: +Uninterpreted extension 'foo'. diff --git a/testsuite/tests/ppx-attributes/Makefile b/testsuite/tests/ppx-attributes/Makefile new file mode 100644 index 00000000..bf9c06cf --- /dev/null +++ b/testsuite/tests/ppx-attributes/Makefile @@ -0,0 +1,18 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Peter Zotov * +#* * +#* Copyright 2014 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=../.. +include $(BASEDIR)/makefiles/Makefile.several +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/ppx-attributes/warning.ml b/testsuite/tests/ppx-attributes/warning.ml new file mode 100644 index 00000000..f50c3d60 --- /dev/null +++ b/testsuite/tests/ppx-attributes/warning.ml @@ -0,0 +1,47 @@ +[@@@ocaml.warning "@A"] + +(* Fixture *) + +module type DEPRECATED = sig end +[@@ocaml.deprecated] + +module T = struct + type deprecated + [@@ocaml.deprecated] +end + +(* Structure items *) + +let _ = let x = 1 in () +[@@ocaml.warning "-26"] + +include (struct let _ = let x = 1 in () end) +[@@ocaml.warning "-26"] + +module A = struct let _ = let x = 1 in () end +[@@ocaml.warning "-26"] + +module rec B : sig type t end = struct type t = T.deprecated end +[@@ocaml.warning "-3"] + +module type T = sig type t = T.deprecated end +[@@ocaml.warning "-3"] + +(* Signature items *) + +module type S = sig + val x : T.deprecated + [@@ocaml.warning "-3"] + + module AA : sig type t = T.deprecated end + [@@ocaml.warning "-3"] + + module rec BB : sig type t = T.deprecated end + [@@ocaml.warning "-3"] + + module type T = sig type t = T.deprecated end + [@@ocaml.warning "-3"] + + include DEPRECATED + [@@ocaml.warning "-3"] +end diff --git a/testsuite/tests/ppx-attributes/warning.reference b/testsuite/tests/ppx-attributes/warning.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/prim-revapply/Makefile b/testsuite/tests/prim-revapply/Makefile index 6e8d01ff..ef0afea5 100644 --- a/testsuite/tests/prim-revapply/Makefile +++ b/testsuite/tests/prim-revapply/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. diff --git a/testsuite/tests/prim-revapply/apply.ml b/testsuite/tests/prim-revapply/apply.ml index e873c484..ad17edea 100644 --- a/testsuite/tests/prim-revapply/apply.ml +++ b/testsuite/tests/prim-revapply/apply.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply" diff --git a/testsuite/tests/prim-revapply/revapply.ml b/testsuite/tests/prim-revapply/revapply.ml index d869163e..c8055004 100644 --- a/testsuite/tests/prim-revapply/revapply.ml +++ b/testsuite/tests/prim-revapply/revapply.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" diff --git a/testsuite/tests/regression/pr3612/Makefile b/testsuite/tests/regression/pr3612/Makefile new file mode 100644 index 00000000..866927b3 --- /dev/null +++ b/testsuite/tests/regression/pr3612/Makefile @@ -0,0 +1,21 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Pierre Chambart, OCamlPro * +#* * +#* Copyright 2014 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. * +#* * +#************************************************************************** + +MAIN_MODULE=pr3612 +C_FILES=custom_finalize + +BASEDIR=../../.. +include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/regression/pr3612/custom_finalize.c b/testsuite/tests/regression/pr3612/custom_finalize.c new file mode 100644 index 00000000..d09fc6d9 --- /dev/null +++ b/testsuite/tests/regression/pr3612/custom_finalize.c @@ -0,0 +1,65 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Pierre Chambart, OCamlPro */ +/* */ +/* Copyright 2014 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 +#include + +static int free_counter = 0; +static int alloc_counter = 0; + +static void caml_test_finalize(value v) +{ + free_counter++; +} + +static void caml_test_serialize(value v, + uintnat * wsize_32, + uintnat * wsize_64) +{ + *wsize_32 = 0; + *wsize_64 = 0; +} + +uintnat caml_test_deserialize(void * dst) +{ + alloc_counter++; + return 0; +} + +static struct custom_operations caml_test_ops = { + "_test", + caml_test_finalize, + custom_compare_default, + custom_hash_default, + caml_test_serialize, + caml_test_deserialize, + custom_compare_ext_default +}; + +value caml_test_pr3612_alloc(value unit) +{ + return caml_alloc_custom(&caml_test_ops, 0, 0, 1); +} + +value caml_test_pr3612_counter(value unit) +{ + return Val_int(alloc_counter-free_counter); +} + +CAMLprim value caml_test_pr3612_init(value unit) +{ + caml_register_custom_operations(&caml_test_ops); + return Val_unit; +} diff --git a/testsuite/tests/regression/pr3612/pr3612.ml b/testsuite/tests/regression/pr3612/pr3612.ml new file mode 100644 index 00000000..6ae495f8 --- /dev/null +++ b/testsuite/tests/regression/pr3612/pr3612.ml @@ -0,0 +1,36 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Pierre Chambart, OCamlPro *) +(* *) +(* Copyright 2014 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 t + +external test_alloc : unit -> t = "caml_test_pr3612_alloc" +external get_counter : unit -> int = "caml_test_pr3612_counter" +(* The number of deserialized blocs minus the number of freed blocs *) + +external init : unit -> unit = "caml_test_pr3612_init" + +let test s = + for i = 0 to 1_000_000 do + ignore (Marshal.from_string s 0) + done + +let f () = + init (); + let s = Marshal.to_string (test_alloc ()) [] in + test s; + Gc.full_major (); + print_int (get_counter ()); + print_newline () +let () = (f [@inlined never]) () diff --git a/testsuite/tests/regression/pr3612/pr3612.reference b/testsuite/tests/regression/pr3612/pr3612.reference new file mode 100644 index 00000000..3a2e3f49 --- /dev/null +++ b/testsuite/tests/regression/pr3612/pr3612.reference @@ -0,0 +1 @@ +-1 diff --git a/testsuite/tests/regression/pr5080-notes/Makefile b/testsuite/tests/regression/pr5080-notes/Makefile index 8079539b..57f971c1 100644 --- a/testsuite/tests/regression/pr5080-notes/Makefile +++ b/testsuite/tests/regression/pr5080-notes/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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 = -pp 'camlp4o pa_macro.cmo' MAIN_MODULE = pr5080_notes_ok diff --git a/testsuite/tests/regression/pr5080-notes/pr5080_notes_ok.ml b/testsuite/tests/regression/pr5080-notes/pr5080_notes_ok.ml index f043f397..6bde667c 100644 --- a/testsuite/tests/regression/pr5080-notes/pr5080_notes_ok.ml +++ b/testsuite/tests/regression/pr5080-notes/pr5080_notes_ok.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2011 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2011 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. *) +(* *) +(**************************************************************************) let marshal_int f = match [] with diff --git a/testsuite/tests/regression/pr5233/Makefile b/testsuite/tests/regression/pr5233/Makefile index 7c875051..46dd3025 100644 --- a/testsuite/tests/regression/pr5233/Makefile +++ b/testsuite/tests/regression/pr5233/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** MAIN_MODULE=pr5233 diff --git a/testsuite/tests/regression/pr5233/pr5233.ml b/testsuite/tests/regression/pr5233/pr5233.ml index 75aec4f9..15d3dd9e 100644 --- a/testsuite/tests/regression/pr5233/pr5233.ml +++ b/testsuite/tests/regression/pr5233/pr5233.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) open Printf;; @@ -45,18 +48,21 @@ let check o = printf " ok\n"; ;; -Weak.set !smuggle 0 (Some (String.make size ' '));; +let f () = + Weak.set !smuggle 0 (Some (String.make size ' ')); -(* Check the data just to make sure. *) -check (Weak.get !smuggle 0);; + (* Check the data just to make sure. *) + check (Weak.get !smuggle 0); -(* Get a dangling pointer in W. *) -Gc.full_major ();; + (* Get a dangling pointer in W. *) + Gc.full_major (); + + (* Fill the heap with other stuff. *) + let rec fill n accu = if n = 0 then accu else fill (n-1) (123 :: accu) in + let _r : int list = fill ((Gc.stat ()).Gc.heap_words / 3) [] in + Gc.minor (); -(* Fill the heap with other stuff. *) -let rec fill n accu = if n = 0 then accu else fill (n-1) (123 :: accu);; -let r = fill ((Gc.stat ()).Gc.heap_words / 3) [];; -Gc.minor ();; + (* Now follow the dangling pointer and exhibit the problem. *) + check (Weak.get !smuggle 0) -(* Now follow the dangling pointer and exhibit the problem. *) -check (Weak.get !smuggle 0);; +let () = (f [@inlined never]) () diff --git a/testsuite/tests/regression/pr5757/Makefile b/testsuite/tests/regression/pr5757/Makefile index d0eb0542..7c03bb00 100644 --- a/testsuite/tests/regression/pr5757/Makefile +++ b/testsuite/tests/regression/pr5757/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** MAIN_MODULE=pr5757 diff --git a/testsuite/tests/regression/pr5757/pr5757.ml b/testsuite/tests/regression/pr5757/pr5757.ml index 3a40bb51..ddc4b693 100644 --- a/testsuite/tests/regression/pr5757/pr5757.ml +++ b/testsuite/tests/regression/pr5757/pr5757.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) Random.init 3;; for i = 0 to 100_000 do diff --git a/testsuite/tests/regression/pr6024/Makefile b/testsuite/tests/regression/pr6024/Makefile index 3426801f..c6ff3e5f 100644 --- a/testsuite/tests/regression/pr6024/Makefile +++ b/testsuite/tests/regression/pr6024/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** MAIN_MODULE=pr6024 diff --git a/testsuite/tests/regression/pr6024/pr6024.ml b/testsuite/tests/regression/pr6024/pr6024.ml index b440cb2d..0134f3bd 100644 --- a/testsuite/tests/regression/pr6024/pr6024.ml +++ b/testsuite/tests/regression/pr6024/pr6024.ml @@ -1,13 +1,16 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2013 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2013 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. *) +(* *) +(**************************************************************************) Format.printf "@[%@-@@-@]@.";; diff --git a/testsuite/tests/regression/pr7042/Makefile b/testsuite/tests/regression/pr7042/Makefile new file mode 100644 index 00000000..97995415 --- /dev/null +++ b/testsuite/tests/regression/pr7042/Makefile @@ -0,0 +1,20 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** + +MAIN_MODULE=pr7042 + +BASEDIR=../../.. +include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/regression/pr7042/pr7042.ml b/testsuite/tests/regression/pr7042/pr7042.ml new file mode 100644 index 00000000..eeb7ea91 --- /dev/null +++ b/testsuite/tests/regression/pr7042/pr7042.ml @@ -0,0 +1,19 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Paris-Rocquencourt *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +let _ = + let a = [| 0.0; -. 0.0 |] in + Printf.printf "%Lx %Lx\n" + (Int64.bits_of_float a.(0)) (Int64.bits_of_float a.(1)) diff --git a/testsuite/tests/regression/pr7042/pr7042.reference b/testsuite/tests/regression/pr7042/pr7042.reference new file mode 100644 index 00000000..c6a412a4 --- /dev/null +++ b/testsuite/tests/regression/pr7042/pr7042.reference @@ -0,0 +1 @@ +0 8000000000000000 diff --git a/testsuite/tests/required-external/Makefile b/testsuite/tests/required-external/Makefile new file mode 100644 index 00000000..0285e743 --- /dev/null +++ b/testsuite/tests/required-external/Makefile @@ -0,0 +1,18 @@ +# Ensure that calling an external C primite forces linking +# the module that defines it + +MAIN_MODULE = main +LIBRARIES = lib + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.common + +main.cmo: lib.cma +main.cmx: lib.cmxa + +lib.cma: file.cmo + @$(OCAMLC) -a -o $@ $< + +lib.cmxa: file.cmx + @$(OCAMLOPT) -a -o $@ $< diff --git a/testsuite/tests/required-external/file.ml b/testsuite/tests/required-external/file.ml new file mode 100644 index 00000000..f90910a8 --- /dev/null +++ b/testsuite/tests/required-external/file.ml @@ -0,0 +1,7 @@ +external getcwd : unit -> string = "caml_sys_getcwd" + +let f () = () + +let () = + print_endline "Module `File' is linked"; + flush stdout diff --git a/testsuite/tests/required-external/main.ml b/testsuite/tests/required-external/main.ml new file mode 100644 index 00000000..32d16576 --- /dev/null +++ b/testsuite/tests/required-external/main.ml @@ -0,0 +1,2 @@ +let () = + ignore (File.getcwd ()) diff --git a/testsuite/tests/required-external/main.reference b/testsuite/tests/required-external/main.reference new file mode 100644 index 00000000..12971896 --- /dev/null +++ b/testsuite/tests/required-external/main.reference @@ -0,0 +1 @@ +Module `File' is linked diff --git a/testsuite/tests/runtime-errors/.ignore b/testsuite/tests/runtime-errors/.ignore deleted file mode 100644 index fa628eaa..00000000 --- a/testsuite/tests/runtime-errors/.ignore +++ /dev/null @@ -1 +0,0 @@ -*.bytecode diff --git a/testsuite/tests/runtime-errors/Makefile b/testsuite/tests/runtime-errors/Makefile index 2c0bed9b..cee8ca8c 100644 --- a/testsuite/tests/runtime-errors/Makefile +++ b/testsuite/tests/runtime-errors/Makefile @@ -1,21 +1,24 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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: - $(MAKE) compile - $(MAKE) run + @$(MAKE) compile + @$(MAKE) run .PHONY: compile compile: @@ -30,20 +33,39 @@ compile: @grep -q HAS_STACK_OVERFLOW_DETECTION $(TOPDIR)/config/s.h \ || rm -f stackoverflow.native$(EXE) +# Cygwin doesn't allow the stack limit to be changed - the 4096 is +# intended to be larger than the its default stack size. The logic +# causes the test to be skipped if the stacksize cannot be brought +# below this value (uname -s value exits with an error status in Cygwin) .PHONY: run run: - @ulimit -s 1024; \ + @ul=`ulimit -s`; \ + if ( [ "$$ul" = "unlimited" ] || [ $$ul -gt 4096 ] ) ; then \ + ulimit -s 1024 && ul=1 || ul=0 ; \ + else \ + ul=1; \ + fi; \ for f in *.bytecode; do \ printf " ... testing '$$f':"; \ - $(OCAMLRUN) ./$$f >$$f.result 2>&1 || true; \ - DIFF="$(DIFF)" sh $$f.checker \ - && echo " => passed" || echo " => failed"; \ + if [ $$ul -eq 1 ] ; then \ + $(OCAMLRUN) ./$$f >$$f.result 2>&1 || true; \ + DIFF="$(DIFF)" sh $$f.checker \ + && echo " => passed" || echo " => failed"; \ + else \ + echo " => unexpected error"; \ + fi; \ fn=`basename $$f bytecode`native; \ - if $(BYTECODE_ONLY) || [ ! -f "$${fn}$(EXE)" ] ; then : ; else \ + if $(BYTECODE_ONLY) || [ ! -f "$${fn}$(EXE)" ] ; then \ + echo " ... testing '$$fn': => skipped" ; \ + else \ printf " ... testing '$$fn':"; \ - ./$${fn}$(EXE) >$$fn.result 2>&1 || true; \ - DIFF="$(DIFF)" sh $$fn.checker \ - && echo " => passed" || echo " => failed"; \ + if [ $$ul -eq 1 ] ; then \ + ./$${fn}$(EXE) >$$fn.result 2>&1 || true; \ + DIFF="$(DIFF)" sh $$fn.checker \ + && echo " => passed" || echo " => failed"; \ + else \ + echo " => unexpected error"; \ + fi; \ fi; \ done diff --git a/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker b/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker index b4f86ac6..c850ba05 100644 --- a/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker +++ b/testsuite/tests/runtime-errors/stackoverflow.bytecode.checker @@ -1,13 +1,16 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** $DIFF stackoverflow.bytecode.reference stackoverflow.bytecode.result diff --git a/testsuite/tests/runtime-errors/stackoverflow.ml b/testsuite/tests/runtime-errors/stackoverflow.ml index 21fe04bd..c32fb9a8 100644 --- a/testsuite/tests/runtime-errors/stackoverflow.ml +++ b/testsuite/tests/runtime-errors/stackoverflow.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) let rec f x = if not (x = 0 || x = 10000 || x = 20000) diff --git a/testsuite/tests/runtime-errors/stackoverflow.native.checker b/testsuite/tests/runtime-errors/stackoverflow.native.checker index 26c2ccf1..f640718a 100644 --- a/testsuite/tests/runtime-errors/stackoverflow.native.checker +++ b/testsuite/tests/runtime-errors/stackoverflow.native.checker @@ -1,13 +1,16 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** $DIFF stackoverflow.native.reference stackoverflow.native.result diff --git a/testsuite/tests/runtime-errors/syserror.bytecode.checker b/testsuite/tests/runtime-errors/syserror.bytecode.checker index a1cb88a5..6433b148 100644 --- a/testsuite/tests/runtime-errors/syserror.bytecode.checker +++ b/testsuite/tests/runtime-errors/syserror.bytecode.checker @@ -1,13 +1,16 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** grep 'Fatal error: exception Sys_error' syserror.bytecode.result >/dev/null diff --git a/testsuite/tests/runtime-errors/syserror.ml b/testsuite/tests/runtime-errors/syserror.ml index cf16ca0c..7a318fb7 100644 --- a/testsuite/tests/runtime-errors/syserror.ml +++ b/testsuite/tests/runtime-errors/syserror.ml @@ -1,13 +1,16 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let channel = open_out "titi:/toto" diff --git a/testsuite/tests/runtime-errors/syserror.native.checker b/testsuite/tests/runtime-errors/syserror.native.checker index 5d8ed3c3..41448fff 100644 --- a/testsuite/tests/runtime-errors/syserror.native.checker +++ b/testsuite/tests/runtime-errors/syserror.native.checker @@ -1,13 +1,16 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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. * +#* * +#************************************************************************** grep 'Fatal error: exception Sys_error' syserror.native.result >/dev/null diff --git a/testsuite/tests/tool-debugger/basic/.ignore b/testsuite/tests/tool-debugger/basic/.ignore deleted file mode 100644 index e09cf9eb..00000000 --- a/testsuite/tests/tool-debugger/basic/.ignore +++ /dev/null @@ -1 +0,0 @@ -compiler-libs diff --git a/testsuite/tests/tool-debugger/basic/Makefile b/testsuite/tests/tool-debugger/basic/Makefile index 3c171390..d732007a 100644 --- a/testsuite/tests/tool-debugger/basic/Makefile +++ b/testsuite/tests/tool-debugger/basic/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, EPI Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, EPI Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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=../../.. MAIN_MODULE=debuggee diff --git a/testsuite/tests/tool-debugger/find-artifacts/.ignore b/testsuite/tests/tool-debugger/find-artifacts/.ignore deleted file mode 100644 index 0a2c0c40..00000000 --- a/testsuite/tests/tool-debugger/find-artifacts/.ignore +++ /dev/null @@ -1,2 +0,0 @@ -compiler-libs -out diff --git a/testsuite/tests/tool-debugger/find-artifacts/Makefile b/testsuite/tests/tool-debugger/find-artifacts/Makefile index f313d864..84201111 100644 --- a/testsuite/tests/tool-debugger/find-artifacts/Makefile +++ b/testsuite/tests/tool-debugger/find-artifacts/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, EPI Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, EPI Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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=../../.. MAIN_MODULE=debuggee diff --git a/testsuite/tests/tool-debugger/no_debug_event/.ignore b/testsuite/tests/tool-debugger/no_debug_event/.ignore deleted file mode 100644 index cfbcf5c6..00000000 --- a/testsuite/tests/tool-debugger/no_debug_event/.ignore +++ /dev/null @@ -1,4 +0,0 @@ -compiler-libs -out -c -c.exe diff --git a/testsuite/tests/tool-debugger/no_debug_event/Makefile b/testsuite/tests/tool-debugger/no_debug_event/Makefile index c9a08d25..7ddafa35 100644 --- a/testsuite/tests/tool-debugger/no_debug_event/Makefile +++ b/testsuite/tests/tool-debugger/no_debug_event/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, EPI Gallium, INRIA Rocquencourt # -# # -# Copyright 2013 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, EPI Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2013 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=../../.. ADD_COMPFLAGS=-g -custom diff --git a/testsuite/tests/tool-lexyacc/.ignore b/testsuite/tests/tool-lexyacc/.ignore deleted file mode 100644 index 6bcc8514..00000000 --- a/testsuite/tests/tool-lexyacc/.ignore +++ /dev/null @@ -1,3 +0,0 @@ -scanner.ml -grammar.mli -grammar.ml diff --git a/testsuite/tests/tool-lexyacc/Makefile b/testsuite/tests/tool-lexyacc/Makefile index 082db4dc..479e8a25 100644 --- a/testsuite/tests/tool-lexyacc/Makefile +++ b/testsuite/tests/tool-lexyacc/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=syntax gram_aux grammar scan_aux scanner lexgen output diff --git a/testsuite/tests/tool-lexyacc/gram_aux.ml b/testsuite/tests/tool-lexyacc/gram_aux.ml index 255f58f3..be964b04 100644 --- a/testsuite/tests/tool-lexyacc/gram_aux.ml +++ b/testsuite/tests/tool-lexyacc/gram_aux.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Auxiliaries for the parser. *) diff --git a/testsuite/tests/tool-lexyacc/grammar.mly b/testsuite/tests/tool-lexyacc/grammar.mly index a1821367..26f9ce51 100644 --- a/testsuite/tests/tool-lexyacc/grammar.mly +++ b/testsuite/tests/tool-lexyacc/grammar.mly @@ -1,14 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 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. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/**************************************************************************/ /* The grammar for lexer definitions */ diff --git a/testsuite/tests/tool-lexyacc/input b/testsuite/tests/tool-lexyacc/input index c0d78594..6739bc30 100644 --- a/testsuite/tests/tool-lexyacc/input +++ b/testsuite/tests/tool-lexyacc/input @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexical analyzer for lexer definitions. *) diff --git a/testsuite/tests/tool-lexyacc/lexgen.ml b/testsuite/tests/tool-lexyacc/lexgen.ml index 005ea68d..6c158456 100644 --- a/testsuite/tests/tool-lexyacc/lexgen.ml +++ b/testsuite/tests/tool-lexyacc/lexgen.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compiling a lexer definition *) diff --git a/testsuite/tests/tool-lexyacc/main.ml b/testsuite/tests/tool-lexyacc/main.ml index 529eb12d..89ee9a1a 100644 --- a/testsuite/tests/tool-lexyacc/main.ml +++ b/testsuite/tests/tool-lexyacc/main.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexer generator. Command-line parsing. *) diff --git a/testsuite/tests/tool-lexyacc/output.ml b/testsuite/tests/tool-lexyacc/output.ml index d8e85440..f8bbb16c 100644 --- a/testsuite/tests/tool-lexyacc/output.ml +++ b/testsuite/tests/tool-lexyacc/output.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Generating a DFA as a set of mutually recursive functions *) diff --git a/testsuite/tests/tool-lexyacc/scan_aux.ml b/testsuite/tests/tool-lexyacc/scan_aux.ml index 81168f33..9f378d52 100644 --- a/testsuite/tests/tool-lexyacc/scan_aux.ml +++ b/testsuite/tests/tool-lexyacc/scan_aux.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Auxiliaries for the lexical analyzer *) diff --git a/testsuite/tests/tool-lexyacc/scanner.mll b/testsuite/tests/tool-lexyacc/scanner.mll index 7d71c685..8e07215a 100644 --- a/testsuite/tests/tool-lexyacc/scanner.mll +++ b/testsuite/tests/tool-lexyacc/scanner.mll @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexical analyzer for lexer definitions. *) diff --git a/testsuite/tests/tool-lexyacc/syntax.ml b/testsuite/tests/tool-lexyacc/syntax.ml index 8f634466..ece0584e 100644 --- a/testsuite/tests/tool-lexyacc/syntax.ml +++ b/testsuite/tests/tool-lexyacc/syntax.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The shallow abstract syntax *) diff --git a/testsuite/tests/tool-ocaml/Makefile b/testsuite/tests/tool-ocaml/Makefile index e1d92c88..cd4578d7 100644 --- a/testsuite/tests/tool-ocaml/Makefile +++ b/testsuite/tests/tool-ocaml/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. SHOULD_FAIL=t060-raise.ml diff --git a/testsuite/tests/tool-ocaml/t000.ml b/testsuite/tests/tool-ocaml/t000.ml index fafa1c89..27520c66 100644 --- a/testsuite/tests/tool-ocaml/t000.ml +++ b/testsuite/tests/tool-ocaml/t000.ml @@ -1,7 +1,7 @@ (* empty file *) (** - 0 ATOM0 + 0 ATOM0 1 SETGLOBAL T000 - 3 STOP + 3 STOP **) diff --git a/testsuite/tests/tool-ocaml/t010-const0.ml b/testsuite/tests/tool-ocaml/t010-const0.ml index 73ecbb1f..65bb3ded 100644 --- a/testsuite/tests/tool-ocaml/t010-const0.ml +++ b/testsuite/tests/tool-ocaml/t010-const0.ml @@ -1,8 +1,8 @@ 0;; (** - 0 CONST0 - 1 ATOM0 + 0 CONST0 + 1 ATOM0 2 SETGLOBAL T010-const0 - 4 STOP + 4 STOP **) diff --git a/testsuite/tests/tool-ocaml/t010-const1.ml b/testsuite/tests/tool-ocaml/t010-const1.ml index 75a00d57..8238b4fc 100644 --- a/testsuite/tests/tool-ocaml/t010-const1.ml +++ b/testsuite/tests/tool-ocaml/t010-const1.ml @@ -1,8 +1,8 @@ 1;; (** - 0 CONST1 - 1 ATOM0 + 0 CONST1 + 1 ATOM0 2 SETGLOBAL T010-const1 - 4 STOP + 4 STOP **) diff --git a/testsuite/tests/tool-ocaml/t010-const2.ml b/testsuite/tests/tool-ocaml/t010-const2.ml index f0ed8e7d..8bbffdbc 100644 --- a/testsuite/tests/tool-ocaml/t010-const2.ml +++ b/testsuite/tests/tool-ocaml/t010-const2.ml @@ -1,8 +1,8 @@ 2;; (** - 0 CONST2 - 1 ATOM0 + 0 CONST2 + 1 ATOM0 2 SETGLOBAL T010-const2 - 4 STOP + 4 STOP **) diff --git a/testsuite/tests/tool-ocaml/t010-const3.ml b/testsuite/tests/tool-ocaml/t010-const3.ml index 4f034c4b..e5767ccc 100644 --- a/testsuite/tests/tool-ocaml/t010-const3.ml +++ b/testsuite/tests/tool-ocaml/t010-const3.ml @@ -1,8 +1,8 @@ 3;; (** - 0 CONST3 - 1 ATOM0 + 0 CONST3 + 1 ATOM0 2 SETGLOBAL T010-const3 - 4 STOP + 4 STOP **) diff --git a/testsuite/tests/tool-ocaml/t011-constint.ml b/testsuite/tests/tool-ocaml/t011-constint.ml index 9ece6c53..104f6050 100644 --- a/testsuite/tests/tool-ocaml/t011-constint.ml +++ b/testsuite/tests/tool-ocaml/t011-constint.ml @@ -2,7 +2,7 @@ (** 0 CONSTINT 4 - 2 ATOM0 + 2 ATOM0 3 SETGLOBAL T011-constint - 5 STOP + 5 STOP **) diff --git a/testsuite/tests/tool-ocaml/t020.ml b/testsuite/tests/tool-ocaml/t020.ml index 5d6a3cfc..afbce871 100644 --- a/testsuite/tests/tool-ocaml/t020.ml +++ b/testsuite/tests/tool-ocaml/t020.ml @@ -1,10 +1,10 @@ let _ = () in ();; (** - 0 CONST0 - 1 PUSHCONST0 + 0 CONST0 + 1 PUSHCONST0 2 POP 1 - 4 ATOM0 + 4 ATOM0 5 SETGLOBAL T020 - 7 STOP + 7 STOP **) diff --git a/testsuite/tests/tool-ocaml/t021-pushconst1.ml b/testsuite/tests/tool-ocaml/t021-pushconst1.ml index 075997a8..863bd89a 100644 --- a/testsuite/tests/tool-ocaml/t021-pushconst1.ml +++ b/testsuite/tests/tool-ocaml/t021-pushconst1.ml @@ -1,10 +1,10 @@ let _ = () in 1;; (** - 0 CONST0 - 1 PUSHCONST1 + 0 CONST0 + 1 PUSHCONST1 2 POP 1 - 4 ATOM0 + 4 ATOM0 5 SETGLOBAL T021-pushconst1 - 7 STOP + 7 STOP **) diff --git a/testsuite/tests/tool-ocaml/t021-pushconst2.ml b/testsuite/tests/tool-ocaml/t021-pushconst2.ml index 17adb507..9e7e42a9 100644 --- a/testsuite/tests/tool-ocaml/t021-pushconst2.ml +++ b/testsuite/tests/tool-ocaml/t021-pushconst2.ml @@ -1,10 +1,10 @@ let _ = () in 2;; (** - 0 CONST0 - 1 PUSHCONST2 + 0 CONST0 + 1 PUSHCONST2 2 POP 1 - 4 ATOM0 + 4 ATOM0 5 SETGLOBAL T021-pushconst2 - 7 STOP + 7 STOP **) diff --git a/testsuite/tests/tool-ocaml/t021-pushconst3.ml b/testsuite/tests/tool-ocaml/t021-pushconst3.ml index 563c6093..5a674f6a 100644 --- a/testsuite/tests/tool-ocaml/t021-pushconst3.ml +++ b/testsuite/tests/tool-ocaml/t021-pushconst3.ml @@ -1,10 +1,10 @@ let _ = () in 3;; (** - 0 CONST0 - 1 PUSHCONST3 + 0 CONST0 + 1 PUSHCONST3 2 POP 1 - 4 ATOM0 + 4 ATOM0 5 SETGLOBAL T021-pushconst3 - 7 STOP + 7 STOP **) diff --git a/testsuite/tests/tool-ocaml/t022-pushconstint.ml b/testsuite/tests/tool-ocaml/t022-pushconstint.ml index 1b766a57..f1c71ea5 100644 --- a/testsuite/tests/tool-ocaml/t022-pushconstint.ml +++ b/testsuite/tests/tool-ocaml/t022-pushconstint.ml @@ -1,10 +1,10 @@ let _ = () in -1;; (** - 0 CONST0 + 0 CONST0 1 PUSHCONSTINT -1 3 POP 1 - 5 ATOM0 + 5 ATOM0 6 SETGLOBAL T022-pushconstint - 8 STOP + 8 STOP **) diff --git a/testsuite/tests/tool-ocaml/t040-makeblock1.ml b/testsuite/tests/tool-ocaml/t040-makeblock1.ml index 71516606..87458cd9 100644 --- a/testsuite/tests/tool-ocaml/t040-makeblock1.ml +++ b/testsuite/tests/tool-ocaml/t040-makeblock1.ml @@ -5,9 +5,9 @@ type t = { { a = 0 };; (** - 0 CONST0 + 0 CONST0 1 MAKEBLOCK1 0 - 3 ATOM0 + 3 ATOM0 4 SETGLOBAL T040-makeblock1 - 6 STOP + 6 STOP **) diff --git a/testsuite/tests/tool-ocaml/t040-makeblock2.ml b/testsuite/tests/tool-ocaml/t040-makeblock2.ml index e7c745b9..d64c3401 100644 --- a/testsuite/tests/tool-ocaml/t040-makeblock2.ml +++ b/testsuite/tests/tool-ocaml/t040-makeblock2.ml @@ -6,10 +6,10 @@ type t = { { a = 0; b = 0 };; (** - 0 CONST0 - 1 PUSHCONST0 + 0 CONST0 + 1 PUSHCONST0 2 MAKEBLOCK2 0 - 4 ATOM0 + 4 ATOM0 5 SETGLOBAL T040-makeblock2 - 7 STOP + 7 STOP **) diff --git a/testsuite/tests/tool-ocaml/t040-makeblock3.ml b/testsuite/tests/tool-ocaml/t040-makeblock3.ml index 8fb56054..03c79818 100644 --- a/testsuite/tests/tool-ocaml/t040-makeblock3.ml +++ b/testsuite/tests/tool-ocaml/t040-makeblock3.ml @@ -7,11 +7,11 @@ type t = { { a = 0; b = 0; c = 0 };; (** - 0 CONST0 - 1 PUSHCONST0 - 2 PUSHCONST0 + 0 CONST0 + 1 PUSHCONST0 + 2 PUSHCONST0 3 MAKEBLOCK3 0 - 5 ATOM0 + 5 ATOM0 6 SETGLOBAL T040-makeblock3 - 8 STOP + 8 STOP **) diff --git a/testsuite/tests/tool-ocaml/t041-makeblock.ml b/testsuite/tests/tool-ocaml/t041-makeblock.ml index 5ae255d6..4d38eac8 100644 --- a/testsuite/tests/tool-ocaml/t041-makeblock.ml +++ b/testsuite/tests/tool-ocaml/t041-makeblock.ml @@ -8,12 +8,12 @@ type t = { { a = 0; b = 0; c = 0; d = 0 };; (** - 0 CONST0 - 1 PUSHCONST0 - 2 PUSHCONST0 - 3 PUSHCONST0 + 0 CONST0 + 1 PUSHCONST0 + 2 PUSHCONST0 + 3 PUSHCONST0 4 MAKEBLOCK 4, 0 - 7 ATOM0 + 7 ATOM0 8 SETGLOBAL T041-makeblock - 10 STOP + 10 STOP **) diff --git a/testsuite/tests/tool-ocaml/t050-getglobal.ml b/testsuite/tests/tool-ocaml/t050-getglobal.ml index f10393cf..7481ca2a 100644 --- a/testsuite/tests/tool-ocaml/t050-getglobal.ml +++ b/testsuite/tests/tool-ocaml/t050-getglobal.ml @@ -2,7 +2,7 @@ (** 0 GETGLOBAL <0>(1, 0) - 2 ATOM0 + 2 ATOM0 3 SETGLOBAL T050-getglobal - 5 STOP + 5 STOP **) diff --git a/testsuite/tests/tool-ocaml/t050-pushgetglobal.ml b/testsuite/tests/tool-ocaml/t050-pushgetglobal.ml index e1172cc3..62be92f0 100644 --- a/testsuite/tests/tool-ocaml/t050-pushgetglobal.ml +++ b/testsuite/tests/tool-ocaml/t050-pushgetglobal.ml @@ -1,10 +1,10 @@ let _ = () in 0.01;; (** - 0 CONST0 + 0 CONST0 1 PUSHGETGLOBAL 0.01 3 POP 1 - 5 ATOM0 + 5 ATOM0 6 SETGLOBAL T050-pushgetglobal - 8 STOP + 8 STOP **) diff --git a/testsuite/tests/tool-ocaml/t051-getglobalfield.ml b/testsuite/tests/tool-ocaml/t051-getglobalfield.ml index 45d9ccea..eb3b6108 100644 --- a/testsuite/tests/tool-ocaml/t051-getglobalfield.ml +++ b/testsuite/tests/tool-ocaml/t051-getglobalfield.ml @@ -2,12 +2,12 @@ Lib.x;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBALFIELD Lib, 0 - 12 ATOM0 + 12 ATOM0 13 SETGLOBAL T051-getglobalfield - 15 STOP + 15 STOP **) diff --git a/testsuite/tests/tool-ocaml/t051-pushgetglobalfield.ml b/testsuite/tests/tool-ocaml/t051-pushgetglobalfield.ml index 2012a257..3e8a37e6 100644 --- a/testsuite/tests/tool-ocaml/t051-pushgetglobalfield.ml +++ b/testsuite/tests/tool-ocaml/t051-pushgetglobalfield.ml @@ -2,14 +2,14 @@ let _ = () in Lib.x;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 + 9 CONST0 10 PUSHGETGLOBALFIELD Lib, 0 13 POP 1 - 15 ATOM0 + 15 ATOM0 16 SETGLOBAL T051-pushgetglobalfield - 18 STOP + 18 STOP **) diff --git a/testsuite/tests/tool-ocaml/t060-raise.ml b/testsuite/tests/tool-ocaml/t060-raise.ml index 1aa48466..aff2e387 100644 --- a/testsuite/tests/tool-ocaml/t060-raise.ml +++ b/testsuite/tests/tool-ocaml/t060-raise.ml @@ -3,13 +3,13 @@ raise End_of_file;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL End_of_file 11 MAKEBLOCK1 0 - 13 RAISE + 13 RAISE 14 SETGLOBAL T060-raise - 16 STOP + 16 STOP **) diff --git a/testsuite/tests/tool-ocaml/t070-branch.ml b/testsuite/tests/tool-ocaml/t070-branch.ml index 4fc52d42..92e00c09 100644 --- a/testsuite/tests/tool-ocaml/t070-branch.ml +++ b/testsuite/tests/tool-ocaml/t070-branch.ml @@ -3,18 +3,18 @@ if true then 0 else raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 + 9 CONST1 10 BRANCHIFNOT 15 - 12 CONST0 + 12 CONST0 13 BRANCH 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE - 20 ATOM0 + 19 RAISE + 20 ATOM0 21 SETGLOBAL T070-branch - 23 STOP + 23 STOP **) diff --git a/testsuite/tests/tool-ocaml/t070-branchif.ml b/testsuite/tests/tool-ocaml/t070-branchif.ml index c256248c..26675771 100644 --- a/testsuite/tests/tool-ocaml/t070-branchif.ml +++ b/testsuite/tests/tool-ocaml/t070-branchif.ml @@ -3,18 +3,18 @@ if not false then 0 else raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 + 9 CONST0 10 BRANCHIF 15 - 12 CONST0 + 12 CONST0 13 BRANCH 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE - 20 ATOM0 + 19 RAISE + 20 ATOM0 21 SETGLOBAL T070-branchif - 23 STOP + 23 STOP **) diff --git a/testsuite/tests/tool-ocaml/t070-branchifnot.ml b/testsuite/tests/tool-ocaml/t070-branchifnot.ml index 9e6e4e8b..d8fa5950 100644 --- a/testsuite/tests/tool-ocaml/t070-branchifnot.ml +++ b/testsuite/tests/tool-ocaml/t070-branchifnot.ml @@ -3,16 +3,16 @@ if false then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 + 9 CONST0 10 BRANCHIFNOT 17 12 GETGLOBAL Not_found 14 MAKEBLOCK1 0 - 16 RAISE - 17 ATOM0 + 16 RAISE + 17 ATOM0 18 SETGLOBAL T070-branchifnot - 20 STOP + 20 STOP **) diff --git a/testsuite/tests/tool-ocaml/t071-boolnot.ml b/testsuite/tests/tool-ocaml/t071-boolnot.ml index b4a81943..8993d134 100644 --- a/testsuite/tests/tool-ocaml/t071-boolnot.ml +++ b/testsuite/tests/tool-ocaml/t071-boolnot.ml @@ -3,17 +3,17 @@ if not true then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 BOOLNOT + 9 CONST1 + 10 BOOLNOT 11 BRANCHIFNOT 18 13 GETGLOBAL Not_found 15 MAKEBLOCK1 0 - 17 RAISE - 18 ATOM0 + 17 RAISE + 18 ATOM0 19 SETGLOBAL T071-boolnot - 21 STOP + 21 STOP **) diff --git a/testsuite/tests/tool-ocaml/t080-eq.ml b/testsuite/tests/tool-ocaml/t080-eq.ml index 3ee735f0..53d82f2e 100644 --- a/testsuite/tests/tool-ocaml/t080-eq.ml +++ b/testsuite/tests/tool-ocaml/t080-eq.ml @@ -3,19 +3,19 @@ if not (0 = 0) then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 EQ - 12 BOOLNOT + 9 CONST0 + 10 PUSHCONST0 + 11 EQ + 12 BOOLNOT 13 BRANCHIFNOT 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE - 20 ATOM0 + 19 RAISE + 20 ATOM0 21 SETGLOBAL T080-eq - 23 STOP + 23 STOP **) diff --git a/testsuite/tests/tool-ocaml/t080-geint.ml b/testsuite/tests/tool-ocaml/t080-geint.ml index a220b7e9..9da5078f 100644 --- a/testsuite/tests/tool-ocaml/t080-geint.ml +++ b/testsuite/tests/tool-ocaml/t080-geint.ml @@ -3,19 +3,19 @@ if not (0 >= 0) then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 GEINT - 12 BOOLNOT + 9 CONST0 + 10 PUSHCONST0 + 11 GEINT + 12 BOOLNOT 13 BRANCHIFNOT 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE - 20 ATOM0 + 19 RAISE + 20 ATOM0 21 SETGLOBAL T080-geint - 23 STOP + 23 STOP **) diff --git a/testsuite/tests/tool-ocaml/t080-gtint.ml b/testsuite/tests/tool-ocaml/t080-gtint.ml index 32d57321..dfefd259 100644 --- a/testsuite/tests/tool-ocaml/t080-gtint.ml +++ b/testsuite/tests/tool-ocaml/t080-gtint.ml @@ -3,18 +3,18 @@ if 0 > 0 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 GTINT + 9 CONST0 + 10 PUSHCONST0 + 11 GTINT 12 BRANCHIFNOT 19 14 GETGLOBAL Not_found 16 MAKEBLOCK1 0 - 18 RAISE - 19 ATOM0 + 18 RAISE + 19 ATOM0 20 SETGLOBAL T080-gtint - 22 STOP + 22 STOP **) diff --git a/testsuite/tests/tool-ocaml/t080-leint.ml b/testsuite/tests/tool-ocaml/t080-leint.ml index cc983a08..04880dc0 100644 --- a/testsuite/tests/tool-ocaml/t080-leint.ml +++ b/testsuite/tests/tool-ocaml/t080-leint.ml @@ -3,19 +3,19 @@ if not (0 <= 0) then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 LEINT - 12 BOOLNOT + 9 CONST0 + 10 PUSHCONST0 + 11 LEINT + 12 BOOLNOT 13 BRANCHIFNOT 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE - 20 ATOM0 + 19 RAISE + 20 ATOM0 21 SETGLOBAL T080-leint - 23 STOP + 23 STOP **) diff --git a/testsuite/tests/tool-ocaml/t080-ltint.ml b/testsuite/tests/tool-ocaml/t080-ltint.ml index ae7d240a..8f23f297 100644 --- a/testsuite/tests/tool-ocaml/t080-ltint.ml +++ b/testsuite/tests/tool-ocaml/t080-ltint.ml @@ -3,18 +3,18 @@ if 0 < 0 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 LTINT + 9 CONST0 + 10 PUSHCONST0 + 11 LTINT 12 BRANCHIFNOT 19 14 GETGLOBAL Not_found 16 MAKEBLOCK1 0 - 18 RAISE - 19 ATOM0 + 18 RAISE + 19 ATOM0 20 SETGLOBAL T080-ltint - 22 STOP + 22 STOP **) diff --git a/testsuite/tests/tool-ocaml/t080-neq.ml b/testsuite/tests/tool-ocaml/t080-neq.ml index 5066e9cb..a43d84c9 100644 --- a/testsuite/tests/tool-ocaml/t080-neq.ml +++ b/testsuite/tests/tool-ocaml/t080-neq.ml @@ -3,18 +3,18 @@ if 0 <> 0 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 NEQ + 9 CONST0 + 10 PUSHCONST0 + 11 NEQ 12 BRANCHIFNOT 19 14 GETGLOBAL Not_found 16 MAKEBLOCK1 0 - 18 RAISE - 19 ATOM0 + 18 RAISE + 19 ATOM0 20 SETGLOBAL T080-neq - 22 STOP + 22 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc0.ml b/testsuite/tests/tool-ocaml/t090-acc0.ml index 74acceca..669249b6 100644 --- a/testsuite/tests/tool-ocaml/t090-acc0.ml +++ b/testsuite/tests/tool-ocaml/t090-acc0.ml @@ -6,20 +6,20 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 ACC0 - 12 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 ACC0 + 12 BOOLNOT 13 BRANCHIFNOT 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE + 19 RAISE 20 POP 1 - 22 ATOM0 + 22 ATOM0 23 SETGLOBAL T090-acc0 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc1.ml b/testsuite/tests/tool-ocaml/t090-acc1.ml index fc9b0254..33f3e4e3 100644 --- a/testsuite/tests/tool-ocaml/t090-acc1.ml +++ b/testsuite/tests/tool-ocaml/t090-acc1.ml @@ -7,21 +7,21 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 ACC1 - 13 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 ACC1 + 13 BOOLNOT 14 BRANCHIFNOT 21 16 GETGLOBAL Not_found 18 MAKEBLOCK1 0 - 20 RAISE + 20 RAISE 21 POP 2 - 23 ATOM0 + 23 ATOM0 24 SETGLOBAL T090-acc1 - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc2.ml b/testsuite/tests/tool-ocaml/t090-acc2.ml index 48659449..415727a1 100644 --- a/testsuite/tests/tool-ocaml/t090-acc2.ml +++ b/testsuite/tests/tool-ocaml/t090-acc2.ml @@ -8,22 +8,22 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 ACC2 - 14 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 ACC2 + 14 BOOLNOT 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 POP 3 - 24 ATOM0 + 24 ATOM0 25 SETGLOBAL T090-acc2 - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc3.ml b/testsuite/tests/tool-ocaml/t090-acc3.ml index 9622456a..4faf079c 100644 --- a/testsuite/tests/tool-ocaml/t090-acc3.ml +++ b/testsuite/tests/tool-ocaml/t090-acc3.ml @@ -9,23 +9,23 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 ACC3 - 15 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 ACC3 + 15 BOOLNOT 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE + 22 RAISE 23 POP 4 - 25 ATOM0 + 25 ATOM0 26 SETGLOBAL T090-acc3 - 28 STOP + 28 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc4.ml b/testsuite/tests/tool-ocaml/t090-acc4.ml index 992559b7..0d4bd892 100644 --- a/testsuite/tests/tool-ocaml/t090-acc4.ml +++ b/testsuite/tests/tool-ocaml/t090-acc4.ml @@ -10,24 +10,24 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHCONST0 - 15 ACC4 - 16 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHCONST0 + 15 ACC4 + 16 BOOLNOT 17 BRANCHIFNOT 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE + 23 RAISE 24 POP 5 - 26 ATOM0 + 26 ATOM0 27 SETGLOBAL T090-acc4 - 29 STOP + 29 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc5.ml b/testsuite/tests/tool-ocaml/t090-acc5.ml index 57f7453b..a4176c75 100644 --- a/testsuite/tests/tool-ocaml/t090-acc5.ml +++ b/testsuite/tests/tool-ocaml/t090-acc5.ml @@ -11,25 +11,25 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHCONST0 - 15 PUSHCONST0 - 16 ACC5 - 17 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHCONST0 + 15 PUSHCONST0 + 16 ACC5 + 17 BOOLNOT 18 BRANCHIFNOT 25 20 GETGLOBAL Not_found 22 MAKEBLOCK1 0 - 24 RAISE + 24 RAISE 25 POP 6 - 27 ATOM0 + 27 ATOM0 28 SETGLOBAL T090-acc5 - 30 STOP + 30 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc6.ml b/testsuite/tests/tool-ocaml/t090-acc6.ml index f9400282..db456b38 100644 --- a/testsuite/tests/tool-ocaml/t090-acc6.ml +++ b/testsuite/tests/tool-ocaml/t090-acc6.ml @@ -12,26 +12,26 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHCONST0 - 15 PUSHCONST0 - 16 PUSHCONST0 - 17 ACC6 - 18 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHCONST0 + 15 PUSHCONST0 + 16 PUSHCONST0 + 17 ACC6 + 18 BOOLNOT 19 BRANCHIFNOT 26 21 GETGLOBAL Not_found 23 MAKEBLOCK1 0 - 25 RAISE + 25 RAISE 26 POP 7 - 28 ATOM0 + 28 ATOM0 29 SETGLOBAL T090-acc6 - 31 STOP + 31 STOP **) diff --git a/testsuite/tests/tool-ocaml/t090-acc7.ml b/testsuite/tests/tool-ocaml/t090-acc7.ml index 366191bf..c53003c6 100644 --- a/testsuite/tests/tool-ocaml/t090-acc7.ml +++ b/testsuite/tests/tool-ocaml/t090-acc7.ml @@ -13,27 +13,27 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHCONST0 - 15 PUSHCONST0 - 16 PUSHCONST0 - 17 PUSHCONST0 - 18 ACC7 - 19 BOOLNOT + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHCONST0 + 15 PUSHCONST0 + 16 PUSHCONST0 + 17 PUSHCONST0 + 18 ACC7 + 19 BOOLNOT 20 BRANCHIFNOT 27 22 GETGLOBAL Not_found 24 MAKEBLOCK1 0 - 26 RAISE + 26 RAISE 27 POP 8 - 29 ATOM0 + 29 ATOM0 30 SETGLOBAL T090-acc7 - 32 STOP + 32 STOP **) diff --git a/testsuite/tests/tool-ocaml/t091-acc.ml b/testsuite/tests/tool-ocaml/t091-acc.ml index 26b003f6..06c2ad8d 100644 --- a/testsuite/tests/tool-ocaml/t091-acc.ml +++ b/testsuite/tests/tool-ocaml/t091-acc.ml @@ -14,28 +14,28 @@ if not x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHCONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHCONST0 - 15 PUSHCONST0 - 16 PUSHCONST0 - 17 PUSHCONST0 - 18 PUSHCONST0 + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHCONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHCONST0 + 15 PUSHCONST0 + 16 PUSHCONST0 + 17 PUSHCONST0 + 18 PUSHCONST0 19 ACC 8 - 21 BOOLNOT + 21 BOOLNOT 22 BRANCHIFNOT 29 24 GETGLOBAL Not_found 26 MAKEBLOCK1 0 - 28 RAISE + 28 RAISE 29 POP 9 - 31 ATOM0 + 31 ATOM0 32 SETGLOBAL T091-acc - 34 STOP + 34 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc.ml b/testsuite/tests/tool-ocaml/t092-pushacc.ml index c21561ec..75eac87f 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc.ml @@ -13,26 +13,26 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHCONST1 - 14 PUSHCONST1 - 15 PUSHCONST1 - 16 PUSHCONST1 - 17 PUSHCONST1 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHCONST1 + 14 PUSHCONST1 + 15 PUSHCONST1 + 16 PUSHCONST1 + 17 PUSHCONST1 18 PUSHACC 8 20 BRANCHIFNOT 27 22 GETGLOBAL Not_found 24 MAKEBLOCK1 0 - 26 RAISE + 26 RAISE 27 POP 9 - 29 ATOM0 + 29 ATOM0 30 SETGLOBAL T092-pushacc - 32 STOP + 32 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc0.ml b/testsuite/tests/tool-ocaml/t092-pushacc0.ml index ffdc3b04..756304df 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc0.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc0.ml @@ -5,18 +5,18 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHACC0 + 9 CONST0 + 10 PUSHACC0 11 BRANCHIFNOT 18 13 GETGLOBAL Not_found 15 MAKEBLOCK1 0 - 17 RAISE + 17 RAISE 18 POP 1 - 20 ATOM0 + 20 ATOM0 21 SETGLOBAL T092-pushacc0 - 23 STOP + 23 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc1.ml b/testsuite/tests/tool-ocaml/t092-pushacc1.ml index b923f4fc..e5cd00af 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc1.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc1.ml @@ -6,19 +6,19 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHACC1 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHACC1 12 BRANCHIFNOT 19 14 GETGLOBAL Not_found 16 MAKEBLOCK1 0 - 18 RAISE + 18 RAISE 19 POP 2 - 21 ATOM0 + 21 ATOM0 22 SETGLOBAL T092-pushacc1 - 24 STOP + 24 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc2.ml b/testsuite/tests/tool-ocaml/t092-pushacc2.ml index f6249783..b1c66c4d 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc2.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc2.ml @@ -7,20 +7,20 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHACC2 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHACC2 13 BRANCHIFNOT 20 15 GETGLOBAL Not_found 17 MAKEBLOCK1 0 - 19 RAISE + 19 RAISE 20 POP 3 - 22 ATOM0 + 22 ATOM0 23 SETGLOBAL T092-pushacc2 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc3.ml b/testsuite/tests/tool-ocaml/t092-pushacc3.ml index 5984fec7..0713c0b6 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc3.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc3.ml @@ -8,21 +8,21 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHACC3 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHACC3 14 BRANCHIFNOT 21 16 GETGLOBAL Not_found 18 MAKEBLOCK1 0 - 20 RAISE + 20 RAISE 21 POP 4 - 23 ATOM0 + 23 ATOM0 24 SETGLOBAL T092-pushacc3 - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc4.ml b/testsuite/tests/tool-ocaml/t092-pushacc4.ml index ce20e0b9..9052f7f6 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc4.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc4.ml @@ -9,22 +9,22 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHCONST1 - 14 PUSHACC4 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHCONST1 + 14 PUSHACC4 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 POP 5 - 24 ATOM0 + 24 ATOM0 25 SETGLOBAL T092-pushacc4 - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc5.ml b/testsuite/tests/tool-ocaml/t092-pushacc5.ml index 030f3f04..0f5e32e7 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc5.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc5.ml @@ -10,23 +10,23 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHCONST1 - 14 PUSHCONST1 - 15 PUSHACC5 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHCONST1 + 14 PUSHCONST1 + 15 PUSHACC5 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE + 22 RAISE 23 POP 6 - 25 ATOM0 + 25 ATOM0 26 SETGLOBAL T092-pushacc5 - 28 STOP + 28 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc6.ml b/testsuite/tests/tool-ocaml/t092-pushacc6.ml index 9c67b808..a3de52ca 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc6.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc6.ml @@ -11,24 +11,24 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHCONST1 - 14 PUSHCONST1 - 15 PUSHCONST1 - 16 PUSHACC6 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHCONST1 + 14 PUSHCONST1 + 15 PUSHCONST1 + 16 PUSHACC6 17 BRANCHIFNOT 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE + 23 RAISE 24 POP 7 - 26 ATOM0 + 26 ATOM0 27 SETGLOBAL T092-pushacc6 - 29 STOP + 29 STOP **) diff --git a/testsuite/tests/tool-ocaml/t092-pushacc7.ml b/testsuite/tests/tool-ocaml/t092-pushacc7.ml index 09fbbcaf..cd1481d2 100644 --- a/testsuite/tests/tool-ocaml/t092-pushacc7.ml +++ b/testsuite/tests/tool-ocaml/t092-pushacc7.ml @@ -12,25 +12,25 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHCONST1 - 14 PUSHCONST1 - 15 PUSHCONST1 - 16 PUSHCONST1 - 17 PUSHACC7 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHCONST1 + 14 PUSHCONST1 + 15 PUSHCONST1 + 16 PUSHCONST1 + 17 PUSHACC7 18 BRANCHIFNOT 25 20 GETGLOBAL Not_found 22 MAKEBLOCK1 0 - 24 RAISE + 24 RAISE 25 POP 8 - 27 ATOM0 + 27 ATOM0 28 SETGLOBAL T092-pushacc7 - 30 STOP + 30 STOP **) diff --git a/testsuite/tests/tool-ocaml/t093-pushacc.ml b/testsuite/tests/tool-ocaml/t093-pushacc.ml index 00a969ad..8e756b1c 100644 --- a/testsuite/tests/tool-ocaml/t093-pushacc.ml +++ b/testsuite/tests/tool-ocaml/t093-pushacc.ml @@ -13,26 +13,26 @@ if x then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST1 - 11 PUSHCONST1 - 12 PUSHCONST1 - 13 PUSHCONST1 - 14 PUSHCONST1 - 15 PUSHCONST1 - 16 PUSHCONST1 - 17 PUSHCONST1 + 9 CONST0 + 10 PUSHCONST1 + 11 PUSHCONST1 + 12 PUSHCONST1 + 13 PUSHCONST1 + 14 PUSHCONST1 + 15 PUSHCONST1 + 16 PUSHCONST1 + 17 PUSHCONST1 18 PUSHACC 8 20 BRANCHIFNOT 27 22 GETGLOBAL Not_found 24 MAKEBLOCK1 0 - 26 RAISE + 26 RAISE 27 POP 9 - 29 ATOM0 + 29 ATOM0 30 SETGLOBAL T093-pushacc - 32 STOP + 32 STOP **) diff --git a/testsuite/tests/tool-ocaml/t100-pushtrap.ml b/testsuite/tests/tool-ocaml/t100-pushtrap.ml index 7b02a862..8eae20e5 100644 --- a/testsuite/tests/tool-ocaml/t100-pushtrap.ml +++ b/testsuite/tests/tool-ocaml/t100-pushtrap.ml @@ -5,17 +5,17 @@ with _ -> () (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 PUSHTRAP 16 11 GETGLOBAL Not_found 13 MAKEBLOCK1 0 - 15 RAISE - 16 PUSHCONST0 + 15 RAISE + 16 PUSHCONST0 17 POP 1 - 19 ATOM0 + 19 ATOM0 20 SETGLOBAL T100-pushtrap - 22 STOP + 22 STOP **) diff --git a/testsuite/tests/tool-ocaml/t101-poptrap.ml b/testsuite/tests/tool-ocaml/t101-poptrap.ml index 3a754a06..cbb5944f 100644 --- a/testsuite/tests/tool-ocaml/t101-poptrap.ml +++ b/testsuite/tests/tool-ocaml/t101-poptrap.ml @@ -5,17 +5,17 @@ with _ -> () (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 PUSHTRAP 15 - 11 CONST0 - 12 POPTRAP + 11 CONST0 + 12 POPTRAP 13 BRANCH 18 - 15 PUSHCONST0 + 15 PUSHCONST0 16 POP 1 - 18 ATOM0 + 18 ATOM0 19 SETGLOBAL T101-poptrap - 21 STOP + 21 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-addint.ml b/testsuite/tests/tool-ocaml/t110-addint.ml index 5d683c57..39aa844d 100644 --- a/testsuite/tests/tool-ocaml/t110-addint.ml +++ b/testsuite/tests/tool-ocaml/t110-addint.ml @@ -5,22 +5,22 @@ if 1 + x <> 2 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST2 - 11 PUSHACC1 - 12 PUSHCONST1 - 13 ADDINT - 14 NEQ + 9 CONST1 + 10 PUSHCONST2 + 11 PUSHACC1 + 12 PUSHCONST1 + 13 ADDINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 POP 1 - 24 ATOM0 + 24 ATOM0 25 SETGLOBAL T110-addint - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-andint.ml b/testsuite/tests/tool-ocaml/t110-andint.ml index 016dc3cd..44017ece 100644 --- a/testsuite/tests/tool-ocaml/t110-andint.ml +++ b/testsuite/tests/tool-ocaml/t110-andint.ml @@ -3,20 +3,20 @@ if (3 land 6) <> 2 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST2 + 9 CONST2 10 PUSHCONSTINT 6 - 12 PUSHCONST3 - 13 ANDINT - 14 NEQ + 12 PUSHCONST3 + 13 ANDINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T110-andint - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-asrint-1.ml b/testsuite/tests/tool-ocaml/t110-asrint-1.ml index 173bdca2..bab98685 100644 --- a/testsuite/tests/tool-ocaml/t110-asrint-1.ml +++ b/testsuite/tests/tool-ocaml/t110-asrint-1.ml @@ -3,20 +3,20 @@ if (-2 asr 1) <> -1 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT -1 - 11 PUSHCONST1 + 11 PUSHCONST1 12 PUSHCONSTINT -2 - 14 ASRINT - 15 NEQ + 14 ASRINT + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T110-asrint-1 - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-asrint-2.ml b/testsuite/tests/tool-ocaml/t110-asrint-2.ml index 386fc64c..be714867 100644 --- a/testsuite/tests/tool-ocaml/t110-asrint-2.ml +++ b/testsuite/tests/tool-ocaml/t110-asrint-2.ml @@ -3,20 +3,20 @@ if (3 asr 1) <> 1 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST1 - 11 PUSHCONST3 - 12 ASRINT - 13 NEQ + 9 CONST1 + 10 PUSHCONST1 + 11 PUSHCONST3 + 12 ASRINT + 13 NEQ 14 BRANCHIFNOT 21 16 GETGLOBAL Not_found 18 MAKEBLOCK1 0 - 20 RAISE - 21 ATOM0 + 20 RAISE + 21 ATOM0 22 SETGLOBAL T110-asrint-2 - 24 STOP + 24 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-divint-1.ml b/testsuite/tests/tool-ocaml/t110-divint-1.ml index 5cde135d..2c1c5b94 100644 --- a/testsuite/tests/tool-ocaml/t110-divint-1.ml +++ b/testsuite/tests/tool-ocaml/t110-divint-1.ml @@ -3,20 +3,20 @@ if 2 / 2 <> 1 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST2 - 11 PUSHCONST2 - 12 DIVINT - 13 NEQ + 9 CONST1 + 10 PUSHCONST2 + 11 PUSHCONST2 + 12 DIVINT + 13 NEQ 14 BRANCHIFNOT 21 16 GETGLOBAL Not_found 18 MAKEBLOCK1 0 - 20 RAISE - 21 ATOM0 + 20 RAISE + 21 ATOM0 22 SETGLOBAL T110-divint-1 - 24 STOP + 24 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-divint-2.ml b/testsuite/tests/tool-ocaml/t110-divint-2.ml index 34f5b00c..effdf34b 100644 --- a/testsuite/tests/tool-ocaml/t110-divint-2.ml +++ b/testsuite/tests/tool-ocaml/t110-divint-2.ml @@ -3,20 +3,20 @@ if 3 / 2 <> 1 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST2 - 11 PUSHCONST3 - 12 DIVINT - 13 NEQ + 9 CONST1 + 10 PUSHCONST2 + 11 PUSHCONST3 + 12 DIVINT + 13 NEQ 14 BRANCHIFNOT 21 16 GETGLOBAL Not_found 18 MAKEBLOCK1 0 - 20 RAISE - 21 ATOM0 + 20 RAISE + 21 ATOM0 22 SETGLOBAL T110-divint-2 - 24 STOP + 24 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-divint-3.ml b/testsuite/tests/tool-ocaml/t110-divint-3.ml index cbb2bff1..3ccc1512 100644 --- a/testsuite/tests/tool-ocaml/t110-divint-3.ml +++ b/testsuite/tests/tool-ocaml/t110-divint-3.ml @@ -6,28 +6,28 @@ with Division_by_zero -> () (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 PUSHTRAP 19 - 11 CONST0 - 12 PUSHCONST3 - 13 DIVINT + 11 CONST0 + 12 PUSHCONST3 + 13 DIVINT 14 GETGLOBAL Not_found 16 MAKEBLOCK1 0 - 18 RAISE + 18 RAISE 19 PUSHGETGLOBAL Division_by_zero - 21 PUSHACC1 - 22 GETFIELD0 - 23 EQ + 21 PUSHACC1 + 22 GETFIELD0 + 23 EQ 24 BRANCHIFNOT 29 - 26 CONST0 + 26 CONST0 27 BRANCH 31 - 29 ACC0 - 30 RAISE + 29 ACC0 + 30 RAISE 31 POP 1 - 33 ATOM0 + 33 ATOM0 34 SETGLOBAL T110-divint-3 - 36 STOP + 36 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-lslint.ml b/testsuite/tests/tool-ocaml/t110-lslint.ml index 9dd197b4..bb25709e 100644 --- a/testsuite/tests/tool-ocaml/t110-lslint.ml +++ b/testsuite/tests/tool-ocaml/t110-lslint.ml @@ -3,20 +3,20 @@ if (3 lsl 2) <> 12 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 12 - 11 PUSHCONST2 - 12 PUSHCONST3 - 13 LSLINT - 14 NEQ + 11 PUSHCONST2 + 12 PUSHCONST3 + 13 LSLINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T110-lslint - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-lsrint.ml b/testsuite/tests/tool-ocaml/t110-lsrint.ml index 9777815c..21994a0b 100644 --- a/testsuite/tests/tool-ocaml/t110-lsrint.ml +++ b/testsuite/tests/tool-ocaml/t110-lsrint.ml @@ -3,20 +3,20 @@ if (14 lsr 2) <> 3 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST3 - 10 PUSHCONST2 + 9 CONST3 + 10 PUSHCONST2 11 PUSHCONSTINT 14 - 13 LSRINT - 14 NEQ + 13 LSRINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T110-lsrint - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-modint-1.ml b/testsuite/tests/tool-ocaml/t110-modint-1.ml index 2a690c08..97eaacdd 100644 --- a/testsuite/tests/tool-ocaml/t110-modint-1.ml +++ b/testsuite/tests/tool-ocaml/t110-modint-1.ml @@ -3,20 +3,20 @@ if 20 mod 3 <> 2 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST2 - 10 PUSHCONST3 + 9 CONST2 + 10 PUSHCONST3 11 PUSHCONSTINT 20 - 13 MODINT - 14 NEQ + 13 MODINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T110-modint-1 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-modint-2.ml b/testsuite/tests/tool-ocaml/t110-modint-2.ml index 0bc3be0c..edc7ceb0 100644 --- a/testsuite/tests/tool-ocaml/t110-modint-2.ml +++ b/testsuite/tests/tool-ocaml/t110-modint-2.ml @@ -7,28 +7,28 @@ with Division_by_zero -> () (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 PUSHTRAP 19 - 11 CONST0 - 12 PUSHCONST2 - 13 MODINT + 11 CONST0 + 12 PUSHCONST2 + 13 MODINT 14 GETGLOBAL Not_found 16 MAKEBLOCK1 0 - 18 RAISE + 18 RAISE 19 PUSHGETGLOBAL Division_by_zero - 21 PUSHACC1 - 22 GETFIELD0 - 23 EQ + 21 PUSHACC1 + 22 GETFIELD0 + 23 EQ 24 BRANCHIFNOT 29 - 26 CONST0 + 26 CONST0 27 BRANCH 31 - 29 ACC0 - 30 RAISE + 29 ACC0 + 30 RAISE 31 POP 1 - 33 ATOM0 + 33 ATOM0 34 SETGLOBAL T110-modint-2 - 36 STOP + 36 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-mulint.ml b/testsuite/tests/tool-ocaml/t110-mulint.ml index 97c1cf14..6c963f6a 100644 --- a/testsuite/tests/tool-ocaml/t110-mulint.ml +++ b/testsuite/tests/tool-ocaml/t110-mulint.ml @@ -3,20 +3,20 @@ if 2 * 2 <> 4 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 4 - 11 PUSHCONST2 - 12 PUSHCONST2 - 13 MULINT - 14 NEQ + 11 PUSHCONST2 + 12 PUSHCONST2 + 13 MULINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T110-mulint - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-negint.ml b/testsuite/tests/tool-ocaml/t110-negint.ml index 069a34b2..aef6121d 100644 --- a/testsuite/tests/tool-ocaml/t110-negint.ml +++ b/testsuite/tests/tool-ocaml/t110-negint.ml @@ -5,21 +5,21 @@ if -x <> -1 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 + 9 CONST1 10 PUSHCONSTINT -1 - 12 PUSHACC1 - 13 NEGINT - 14 NEQ + 12 PUSHACC1 + 13 NEGINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 POP 1 - 24 ATOM0 + 24 ATOM0 25 SETGLOBAL T110-negint - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-offsetint.ml b/testsuite/tests/tool-ocaml/t110-offsetint.ml index 925159e3..7793d003 100644 --- a/testsuite/tests/tool-ocaml/t110-offsetint.ml +++ b/testsuite/tests/tool-ocaml/t110-offsetint.ml @@ -3,19 +3,19 @@ if 2 + 2 <> 4 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 4 - 11 PUSHCONST2 + 11 PUSHCONST2 12 OFFSETINT 2 - 14 NEQ + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T110-offsetint - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-orint.ml b/testsuite/tests/tool-ocaml/t110-orint.ml index 56b63d80..bb5e9453 100644 --- a/testsuite/tests/tool-ocaml/t110-orint.ml +++ b/testsuite/tests/tool-ocaml/t110-orint.ml @@ -3,20 +3,20 @@ if (3 lor 6) <> 7 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 7 11 PUSHCONSTINT 6 - 13 PUSHCONST3 - 14 ORINT - 15 NEQ + 13 PUSHCONST3 + 14 ORINT + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T110-orint - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-subint.ml b/testsuite/tests/tool-ocaml/t110-subint.ml index f626cd0d..06a23dd6 100644 --- a/testsuite/tests/tool-ocaml/t110-subint.ml +++ b/testsuite/tests/tool-ocaml/t110-subint.ml @@ -5,22 +5,22 @@ if 1 - x <> 0 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST0 - 11 PUSHACC1 - 12 PUSHCONST1 - 13 SUBINT - 14 NEQ + 9 CONST1 + 10 PUSHCONST0 + 11 PUSHACC1 + 12 PUSHCONST1 + 13 SUBINT + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 POP 1 - 24 ATOM0 + 24 ATOM0 25 SETGLOBAL T110-subint - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t110-xorint.ml b/testsuite/tests/tool-ocaml/t110-xorint.ml index dfb278b7..ae248d23 100644 --- a/testsuite/tests/tool-ocaml/t110-xorint.ml +++ b/testsuite/tests/tool-ocaml/t110-xorint.ml @@ -3,20 +3,20 @@ if (3 lxor 6) <> 5 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 5 11 PUSHCONSTINT 6 - 13 PUSHCONST3 - 14 XORINT - 15 NEQ + 13 PUSHCONST3 + 14 XORINT + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T110-xorint - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t120-getstringchar.ml b/testsuite/tests/tool-ocaml/t120-getstringchar.ml index aaff2022..a663ecf4 100644 --- a/testsuite/tests/tool-ocaml/t120-getstringchar.ml +++ b/testsuite/tests/tool-ocaml/t120-getstringchar.ml @@ -3,20 +3,20 @@ if "foo".[2] <> 'o' then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 111 - 11 PUSHCONST2 + 11 PUSHCONST2 12 PUSHGETGLOBAL "foo" - 14 GETSTRINGCHAR - 15 NEQ + 14 GETSTRINGCHAR + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T120-getstringchar - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t121-setstringchar.ml b/testsuite/tests/tool-ocaml/t121-setstringchar.ml index 882d6e08..939ed973 100644 --- a/testsuite/tests/tool-ocaml/t121-setstringchar.ml +++ b/testsuite/tests/tool-ocaml/t121-setstringchar.ml @@ -6,26 +6,26 @@ if x.[2] <> 'x' then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL "foo" 11 PUSHCONSTINT 120 - 13 PUSHCONST2 - 14 PUSHACC2 - 15 SETSTRINGCHAR + 13 PUSHCONST2 + 14 PUSHACC2 + 15 SETSTRINGCHAR 16 CONSTINT 120 - 18 PUSHCONST2 - 19 PUSHACC2 - 20 GETSTRINGCHAR - 21 NEQ + 18 PUSHCONST2 + 19 PUSHACC2 + 20 GETSTRINGCHAR + 21 NEQ 22 BRANCHIFNOT 29 24 GETGLOBAL Not_found 26 MAKEBLOCK1 0 - 28 RAISE + 28 RAISE 29 POP 1 - 31 ATOM0 + 31 ATOM0 32 SETGLOBAL T121-setstringchar - 34 STOP + 34 STOP **) diff --git a/testsuite/tests/tool-ocaml/t130-getvectitem.ml b/testsuite/tests/tool-ocaml/t130-getvectitem.ml index d2903795..964ebc9f 100644 --- a/testsuite/tests/tool-ocaml/t130-getvectitem.ml +++ b/testsuite/tests/tool-ocaml/t130-getvectitem.ml @@ -3,22 +3,22 @@ if [| 1; 2 |].(1) <> 2 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST2 - 10 PUSHCONST1 - 11 PUSHCONST2 - 12 PUSHCONST1 + 9 CONST2 + 10 PUSHCONST1 + 11 PUSHCONST2 + 12 PUSHCONST1 13 MAKEBLOCK2 0 - 15 GETVECTITEM - 16 NEQ + 15 GETVECTITEM + 16 NEQ 17 BRANCHIFNOT 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE - 24 ATOM0 + 23 RAISE + 24 ATOM0 25 SETGLOBAL T130-getvectitem - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t130-vectlength.ml b/testsuite/tests/tool-ocaml/t130-vectlength.ml index ce0da0e4..aee59441 100644 --- a/testsuite/tests/tool-ocaml/t130-vectlength.ml +++ b/testsuite/tests/tool-ocaml/t130-vectlength.ml @@ -3,21 +3,21 @@ if Array.length [| 1; 2 |] <> 2 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST2 - 10 PUSHCONST2 - 11 PUSHCONST1 + 9 CONST2 + 10 PUSHCONST2 + 11 PUSHCONST1 12 MAKEBLOCK2 0 - 14 VECTLENGTH - 15 NEQ + 14 VECTLENGTH + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T130-vectlength - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t131-setvectitem.ml b/testsuite/tests/tool-ocaml/t131-setvectitem.ml index f544a3e0..b813e91b 100644 --- a/testsuite/tests/tool-ocaml/t131-setvectitem.ml +++ b/testsuite/tests/tool-ocaml/t131-setvectitem.ml @@ -6,28 +6,28 @@ if x.(0) <> 3 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST2 - 10 PUSHCONST1 + 9 CONST2 + 10 PUSHCONST1 11 MAKEBLOCK2 0 - 13 PUSHCONST3 - 14 PUSHCONST0 - 15 PUSHACC2 - 16 SETVECTITEM - 17 CONST3 - 18 PUSHCONST0 - 19 PUSHACC2 - 20 GETVECTITEM - 21 NEQ + 13 PUSHCONST3 + 14 PUSHCONST0 + 15 PUSHACC2 + 16 SETVECTITEM + 17 CONST3 + 18 PUSHCONST0 + 19 PUSHACC2 + 20 GETVECTITEM + 21 NEQ 22 BRANCHIFNOT 29 24 GETGLOBAL Not_found 26 MAKEBLOCK1 0 - 28 RAISE + 28 RAISE 29 POP 1 - 31 ATOM0 + 31 ATOM0 32 SETGLOBAL T131-setvectitem - 34 STOP + 34 STOP **) diff --git a/testsuite/tests/tool-ocaml/t140-switch-1.ml b/testsuite/tests/tool-ocaml/t140-switch-1.ml index b2d73521..9e3eee15 100644 --- a/testsuite/tests/tool-ocaml/t140-switch-1.ml +++ b/testsuite/tests/tool-ocaml/t140-switch-1.ml @@ -7,26 +7,26 @@ match 0 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHACC0 - 11 SWITCH + 9 CONST0 + 10 PUSHACC0 + 11 SWITCH int 0 -> 17 int 1 -> 20 15 BRANCH 25 - 17 CONST0 + 17 CONST0 18 BRANCH 30 20 GETGLOBAL Not_found 22 MAKEBLOCK1 0 - 24 RAISE + 24 RAISE 25 GETGLOBAL Not_found 27 MAKEBLOCK1 0 - 29 RAISE + 29 RAISE 30 POP 1 - 32 ATOM0 + 32 ATOM0 33 SETGLOBAL T140-switch-1 - 35 STOP + 35 STOP **) diff --git a/testsuite/tests/tool-ocaml/t140-switch-2.ml b/testsuite/tests/tool-ocaml/t140-switch-2.ml index 9004fa66..ecc5772a 100644 --- a/testsuite/tests/tool-ocaml/t140-switch-2.ml +++ b/testsuite/tests/tool-ocaml/t140-switch-2.ml @@ -7,26 +7,26 @@ match 1 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHACC0 - 11 SWITCH + 9 CONST1 + 10 PUSHACC0 + 11 SWITCH int 0 -> 17 int 1 -> 22 15 BRANCH 25 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 CONST0 + 21 RAISE + 22 CONST0 23 BRANCH 30 25 GETGLOBAL Not_found 27 MAKEBLOCK1 0 - 29 RAISE + 29 RAISE 30 POP 1 - 32 ATOM0 + 32 ATOM0 33 SETGLOBAL T140-switch-2 - 35 STOP + 35 STOP **) diff --git a/testsuite/tests/tool-ocaml/t140-switch-3.ml b/testsuite/tests/tool-ocaml/t140-switch-3.ml index b0c4bc8f..316461df 100644 --- a/testsuite/tests/tool-ocaml/t140-switch-3.ml +++ b/testsuite/tests/tool-ocaml/t140-switch-3.ml @@ -7,25 +7,25 @@ match 2 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST2 - 10 PUSHACC0 - 11 SWITCH + 9 CONST2 + 10 PUSHACC0 + 11 SWITCH int 0 -> 17 int 1 -> 22 15 BRANCH 27 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 GETGLOBAL Not_found 24 MAKEBLOCK1 0 - 26 RAISE - 27 CONST0 + 26 RAISE + 27 CONST0 28 POP 1 - 30 ATOM0 + 30 ATOM0 31 SETGLOBAL T140-switch-3 - 33 STOP + 33 STOP **) diff --git a/testsuite/tests/tool-ocaml/t140-switch-4.ml b/testsuite/tests/tool-ocaml/t140-switch-4.ml index 1826b09e..6f72ba35 100644 --- a/testsuite/tests/tool-ocaml/t140-switch-4.ml +++ b/testsuite/tests/tool-ocaml/t140-switch-4.ml @@ -7,25 +7,25 @@ match -1 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT -1 - 11 PUSHACC0 - 12 SWITCH + 11 PUSHACC0 + 12 SWITCH int 0 -> 18 int 1 -> 23 16 BRANCH 28 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE + 22 RAISE 23 GETGLOBAL Not_found 25 MAKEBLOCK1 0 - 27 RAISE - 28 CONST0 + 27 RAISE + 28 CONST0 29 POP 1 - 31 ATOM0 + 31 ATOM0 32 SETGLOBAL T140-switch-4 - 34 STOP + 34 STOP **) diff --git a/testsuite/tests/tool-ocaml/t141-switch-5.ml b/testsuite/tests/tool-ocaml/t141-switch-5.ml index ca44849e..e5b49e6a 100644 --- a/testsuite/tests/tool-ocaml/t141-switch-5.ml +++ b/testsuite/tests/tool-ocaml/t141-switch-5.ml @@ -13,26 +13,26 @@ match A 0 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL <0>(0) - 11 PUSHACC0 - 12 SWITCH + 11 PUSHACC0 + 12 SWITCH tag 0 -> 17 tag 1 -> 20 tag 2 -> 25 - 17 CONST0 + 17 CONST0 18 BRANCH 30 20 GETGLOBAL Not_found 22 MAKEBLOCK1 0 - 24 RAISE + 24 RAISE 25 GETGLOBAL Not_found 27 MAKEBLOCK1 0 - 29 RAISE + 29 RAISE 30 POP 1 - 32 ATOM0 + 32 ATOM0 33 SETGLOBAL T141-switch-5 - 35 STOP + 35 STOP **) diff --git a/testsuite/tests/tool-ocaml/t141-switch-6.ml b/testsuite/tests/tool-ocaml/t141-switch-6.ml index c48e80b5..5a720327 100644 --- a/testsuite/tests/tool-ocaml/t141-switch-6.ml +++ b/testsuite/tests/tool-ocaml/t141-switch-6.ml @@ -13,26 +13,26 @@ match B 0 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL <1>(0) - 11 PUSHACC0 - 12 SWITCH + 11 PUSHACC0 + 12 SWITCH tag 0 -> 17 tag 1 -> 22 tag 2 -> 25 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 CONST0 + 21 RAISE + 22 CONST0 23 BRANCH 30 25 GETGLOBAL Not_found 27 MAKEBLOCK1 0 - 29 RAISE + 29 RAISE 30 POP 1 - 32 ATOM0 + 32 ATOM0 33 SETGLOBAL T141-switch-6 - 35 STOP + 35 STOP **) diff --git a/testsuite/tests/tool-ocaml/t141-switch-7.ml b/testsuite/tests/tool-ocaml/t141-switch-7.ml index 00f4873c..a7082d08 100644 --- a/testsuite/tests/tool-ocaml/t141-switch-7.ml +++ b/testsuite/tests/tool-ocaml/t141-switch-7.ml @@ -13,25 +13,25 @@ match C 0 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL <2>(0) - 11 PUSHACC0 - 12 SWITCH + 11 PUSHACC0 + 12 SWITCH tag 0 -> 17 tag 1 -> 22 tag 2 -> 27 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE + 21 RAISE 22 GETGLOBAL Not_found 24 MAKEBLOCK1 0 - 26 RAISE - 27 CONST0 + 26 RAISE + 27 CONST0 28 POP 1 - 30 ATOM0 + 30 ATOM0 31 SETGLOBAL T141-switch-7 - 33 STOP + 33 STOP **) diff --git a/testsuite/tests/tool-ocaml/t142-switch-8.ml b/testsuite/tests/tool-ocaml/t142-switch-8.ml index 51459130..d32346fc 100644 --- a/testsuite/tests/tool-ocaml/t142-switch-8.ml +++ b/testsuite/tests/tool-ocaml/t142-switch-8.ml @@ -12,23 +12,23 @@ match A with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHACC0 - 11 SWITCH + 9 CONST0 + 10 PUSHACC0 + 11 SWITCH int 0 -> 16 tag 0 -> 19 tag 1 -> 19 - 16 CONST0 + 16 CONST0 17 BRANCH 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE + 23 RAISE 24 POP 1 - 26 ATOM0 + 26 ATOM0 27 SETGLOBAL T142-switch-8 - 29 STOP + 29 STOP **) diff --git a/testsuite/tests/tool-ocaml/t142-switch-9.ml b/testsuite/tests/tool-ocaml/t142-switch-9.ml index a0e43d32..5fbda767 100644 --- a/testsuite/tests/tool-ocaml/t142-switch-9.ml +++ b/testsuite/tests/tool-ocaml/t142-switch-9.ml @@ -12,23 +12,23 @@ match B 0 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL <0>(0) - 11 PUSHACC0 - 12 SWITCH + 11 PUSHACC0 + 12 SWITCH int 0 -> 20 tag 0 -> 17 tag 1 -> 20 - 17 CONST0 + 17 CONST0 18 BRANCH 25 20 GETGLOBAL Not_found 22 MAKEBLOCK1 0 - 24 RAISE + 24 RAISE 25 POP 1 - 27 ATOM0 + 27 ATOM0 28 SETGLOBAL T142-switch-9 - 30 STOP + 30 STOP **) diff --git a/testsuite/tests/tool-ocaml/t142-switch-A.ml b/testsuite/tests/tool-ocaml/t142-switch-A.ml index 4f66aec5..fc8aa5c6 100644 --- a/testsuite/tests/tool-ocaml/t142-switch-A.ml +++ b/testsuite/tests/tool-ocaml/t142-switch-A.ml @@ -12,23 +12,23 @@ match C 0 with (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL <1>(0) - 11 PUSHACC0 - 12 SWITCH + 11 PUSHACC0 + 12 SWITCH int 0 -> 20 tag 0 -> 20 tag 1 -> 17 - 17 CONST0 + 17 CONST0 18 BRANCH 25 20 GETGLOBAL Not_found 22 MAKEBLOCK1 0 - 24 RAISE + 24 RAISE 25 POP 1 - 27 ATOM0 + 27 ATOM0 28 SETGLOBAL T142-switch-A - 30 STOP + 30 STOP **) diff --git a/testsuite/tests/tool-ocaml/t150-push-1.ml b/testsuite/tests/tool-ocaml/t150-push-1.ml index 92649277..7319388a 100644 --- a/testsuite/tests/tool-ocaml/t150-push-1.ml +++ b/testsuite/tests/tool-ocaml/t150-push-1.ml @@ -5,20 +5,20 @@ try 0 with _ -> 0 (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSH + 9 CONST0 + 10 PUSH 11 PUSHTRAP 17 - 13 CONST0 - 14 POPTRAP + 13 CONST0 + 14 POPTRAP 15 BRANCH 20 - 17 PUSHCONST0 + 17 PUSHCONST0 18 POP 1 20 POP 1 - 22 ATOM0 + 22 ATOM0 23 SETGLOBAL T150-push-1 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t150-push-2.ml b/testsuite/tests/tool-ocaml/t150-push-2.ml index d6f51072..c0837bf1 100644 --- a/testsuite/tests/tool-ocaml/t150-push-2.ml +++ b/testsuite/tests/tool-ocaml/t150-push-2.ml @@ -6,34 +6,34 @@ with End_of_file -> () (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSH + 9 CONST1 + 10 PUSH 11 PUSHTRAP 26 - 13 CONST1 - 14 PUSHACC5 - 15 NEQ + 13 CONST1 + 14 PUSHACC5 + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 POPTRAP + 22 RAISE + 23 POPTRAP 24 BRANCH 40 26 PUSHGETGLOBAL End_of_file - 28 PUSHACC1 - 29 GETFIELD0 - 30 EQ + 28 PUSHACC1 + 29 GETFIELD0 + 30 EQ 31 BRANCHIFNOT 36 - 33 CONST0 + 33 CONST0 34 BRANCH 38 - 36 ACC0 - 37 RAISE + 36 ACC0 + 37 RAISE 38 POP 1 40 POP 1 - 42 ATOM0 + 42 ATOM0 43 SETGLOBAL T150-push-2 - 45 STOP + 45 STOP **) diff --git a/testsuite/tests/tool-ocaml/t160-closure.ml b/testsuite/tests/tool-ocaml/t160-closure.ml index 5eb61286..2d2f0cce 100644 --- a/testsuite/tests/tool-ocaml/t160-closure.ml +++ b/testsuite/tests/tool-ocaml/t160-closure.ml @@ -3,17 +3,17 @@ let f () = ();; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 14 - 11 CONST0 + 11 CONST0 12 RETURN 1 14 CLOSURE 0, 11 - 17 PUSHACC0 + 17 PUSHACC0 18 MAKEBLOCK1 0 20 POP 1 22 SETGLOBAL T160-closure - 24 STOP + 24 STOP **) diff --git a/testsuite/tests/tool-ocaml/t161-apply1.ml b/testsuite/tests/tool-ocaml/t161-apply1.ml index 5138c5f5..2892cbe7 100644 --- a/testsuite/tests/tool-ocaml/t161-apply1.ml +++ b/testsuite/tests/tool-ocaml/t161-apply1.ml @@ -8,35 +8,35 @@ with End_of_file -> 0 (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 16 11 GETGLOBAL End_of_file 13 MAKEBLOCK1 0 - 15 RAISE + 15 RAISE 16 CLOSURE 0, 11 - 19 PUSH + 19 PUSH 20 PUSHTRAP 30 - 22 CONST0 - 23 PUSHACC5 - 24 APPLY1 + 22 CONST0 + 23 PUSHACC5 + 24 APPLY1 25 GETGLOBAL Not_found 27 MAKEBLOCK1 0 - 29 RAISE + 29 RAISE 30 PUSHGETGLOBAL End_of_file - 32 PUSHACC1 - 33 GETFIELD0 - 34 EQ + 32 PUSHACC1 + 33 GETFIELD0 + 34 EQ 35 BRANCHIFNOT 40 - 37 CONST0 + 37 CONST0 38 BRANCH 42 - 40 ACC0 - 41 RAISE + 40 ACC0 + 41 RAISE 42 POP 1 44 POP 1 - 46 ATOM0 + 46 ATOM0 47 SETGLOBAL T161-apply1 - 49 STOP + 49 STOP **) diff --git a/testsuite/tests/tool-ocaml/t162-return.ml b/testsuite/tests/tool-ocaml/t162-return.ml index 1059c9fe..1e08ab4e 100644 --- a/testsuite/tests/tool-ocaml/t162-return.ml +++ b/testsuite/tests/tool-ocaml/t162-return.ml @@ -3,19 +3,19 @@ let f _ = 0 in f 0;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 14 - 11 CONST0 + 11 CONST0 12 RETURN 1 14 CLOSURE 0, 11 - 17 PUSHCONST0 - 18 PUSHACC1 - 19 APPLY1 + 17 PUSHCONST0 + 18 PUSHACC1 + 19 APPLY1 20 POP 1 - 22 ATOM0 + 22 ATOM0 23 SETGLOBAL T162-return - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t163.ml b/testsuite/tests/tool-ocaml/t163.ml index 9ec7790c..e2760b97 100644 --- a/testsuite/tests/tool-ocaml/t163.ml +++ b/testsuite/tests/tool-ocaml/t163.ml @@ -3,21 +3,21 @@ let f _ _ = 0 in f 0;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 17 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 CONST0 + 14 CONST0 15 RETURN 2 17 CLOSURE 0, 12 - 20 PUSHCONST0 - 21 PUSHACC1 - 22 APPLY1 + 20 PUSHCONST0 + 21 PUSHACC1 + 22 APPLY1 23 POP 1 - 25 ATOM0 + 25 ATOM0 26 SETGLOBAL T163 - 28 STOP + 28 STOP **) diff --git a/testsuite/tests/tool-ocaml/t164-apply2.ml b/testsuite/tests/tool-ocaml/t164-apply2.ml index 7fbe7d99..ae908538 100644 --- a/testsuite/tests/tool-ocaml/t164-apply2.ml +++ b/testsuite/tests/tool-ocaml/t164-apply2.ml @@ -3,22 +3,22 @@ let f _ _ = 0 in f 0 0;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 17 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 CONST0 + 14 CONST0 15 RETURN 2 17 CLOSURE 0, 12 - 20 PUSHCONST0 - 21 PUSHCONST0 - 22 PUSHACC2 - 23 APPLY2 + 20 PUSHCONST0 + 21 PUSHCONST0 + 22 PUSHACC2 + 23 APPLY2 24 POP 1 - 26 ATOM0 + 26 ATOM0 27 SETGLOBAL T164-apply2 - 29 STOP + 29 STOP **) diff --git a/testsuite/tests/tool-ocaml/t164-apply3.ml b/testsuite/tests/tool-ocaml/t164-apply3.ml index e7ebc3a4..a05aac2a 100644 --- a/testsuite/tests/tool-ocaml/t164-apply3.ml +++ b/testsuite/tests/tool-ocaml/t164-apply3.ml @@ -3,23 +3,23 @@ let f _ _ _ = 0 in f 0 0 0;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 17 - 11 RESTART + 11 RESTART 12 GRAB 2 - 14 CONST0 + 14 CONST0 15 RETURN 3 17 CLOSURE 0, 12 - 20 PUSHCONST0 - 21 PUSHCONST0 - 22 PUSHCONST0 - 23 PUSHACC3 - 24 APPLY3 + 20 PUSHCONST0 + 21 PUSHCONST0 + 22 PUSHCONST0 + 23 PUSHACC3 + 24 APPLY3 25 POP 1 - 27 ATOM0 + 27 ATOM0 28 SETGLOBAL T164-apply3 - 30 STOP + 30 STOP **) diff --git a/testsuite/tests/tool-ocaml/t165-apply.ml b/testsuite/tests/tool-ocaml/t165-apply.ml index 9d668550..e4787321 100644 --- a/testsuite/tests/tool-ocaml/t165-apply.ml +++ b/testsuite/tests/tool-ocaml/t165-apply.ml @@ -3,26 +3,26 @@ let f _ _ _ _ = 0 in f 0 0 0 0;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 17 - 11 RESTART + 11 RESTART 12 GRAB 3 - 14 CONST0 + 14 CONST0 15 RETURN 4 17 CLOSURE 0, 12 - 20 PUSH + 20 PUSH 21 PUSH_RETADDR 30 - 23 CONST0 - 24 PUSHCONST0 - 25 PUSHCONST0 - 26 PUSHCONST0 - 27 PUSHACC7 + 23 CONST0 + 24 PUSHCONST0 + 25 PUSHCONST0 + 26 PUSHCONST0 + 27 PUSHACC7 28 APPLY 4 30 POP 1 - 32 ATOM0 + 32 ATOM0 33 SETGLOBAL T165-apply - 35 STOP + 35 STOP **) diff --git a/testsuite/tests/tool-ocaml/t170-envacc2.ml b/testsuite/tests/tool-ocaml/t170-envacc2.ml index 3a373667..8e9a0219 100644 --- a/testsuite/tests/tool-ocaml/t170-envacc2.ml +++ b/testsuite/tests/tool-ocaml/t170-envacc2.ml @@ -7,31 +7,31 @@ if f 0 <> 2 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 16 - 11 ENVACC1 - 12 CONST0 - 13 ENVACC2 + 11 ENVACC1 + 12 CONST0 + 13 ENVACC2 14 RETURN 1 16 CONSTINT 5 - 18 PUSHCONST2 - 19 PUSHACC0 - 20 PUSHACC2 + 18 PUSHCONST2 + 19 PUSHACC0 + 20 PUSHACC2 21 CLOSURE 2, 11 - 24 PUSHCONST2 - 25 PUSHCONST0 - 26 PUSHACC2 - 27 APPLY1 - 28 NEQ + 24 PUSHCONST2 + 25 PUSHCONST0 + 26 PUSHACC2 + 27 APPLY1 + 28 NEQ 29 BRANCHIFNOT 36 31 GETGLOBAL Not_found 33 MAKEBLOCK1 0 - 35 RAISE + 35 RAISE 36 POP 3 - 38 ATOM0 + 38 ATOM0 39 SETGLOBAL T170-envacc2 - 41 STOP + 41 STOP **) diff --git a/testsuite/tests/tool-ocaml/t170-envacc3.ml b/testsuite/tests/tool-ocaml/t170-envacc3.ml index 9a2b8b5a..d0be88ce 100644 --- a/testsuite/tests/tool-ocaml/t170-envacc3.ml +++ b/testsuite/tests/tool-ocaml/t170-envacc3.ml @@ -8,35 +8,35 @@ if f 0 <> 1 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 18 - 11 ENVACC1 - 12 CONST0 - 13 ENVACC2 - 14 CONST0 - 15 ENVACC3 + 11 ENVACC1 + 12 CONST0 + 13 ENVACC2 + 14 CONST0 + 15 ENVACC3 16 RETURN 1 18 CONSTINT 5 - 20 PUSHCONST2 - 21 PUSHCONST1 - 22 PUSHACC0 - 23 PUSHACC2 - 24 PUSHACC4 + 20 PUSHCONST2 + 21 PUSHCONST1 + 22 PUSHACC0 + 23 PUSHACC2 + 24 PUSHACC4 25 CLOSURE 3, 11 - 28 PUSHCONST1 - 29 PUSHCONST0 - 30 PUSHACC2 - 31 APPLY1 - 32 NEQ + 28 PUSHCONST1 + 29 PUSHCONST0 + 30 PUSHACC2 + 31 APPLY1 + 32 NEQ 33 BRANCHIFNOT 40 35 GETGLOBAL Not_found 37 MAKEBLOCK1 0 - 39 RAISE + 39 RAISE 40 POP 4 - 42 ATOM0 + 42 ATOM0 43 SETGLOBAL T170-envacc3 - 45 STOP + 45 STOP **) diff --git a/testsuite/tests/tool-ocaml/t170-envacc4.ml b/testsuite/tests/tool-ocaml/t170-envacc4.ml index 215e3220..9764c3b2 100644 --- a/testsuite/tests/tool-ocaml/t170-envacc4.ml +++ b/testsuite/tests/tool-ocaml/t170-envacc4.ml @@ -9,39 +9,39 @@ if f 0 <> 4 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 20 - 11 ENVACC1 - 12 CONST0 - 13 ENVACC2 - 14 CONST0 - 15 ENVACC3 - 16 CONST0 - 17 ENVACC4 + 11 ENVACC1 + 12 CONST0 + 13 ENVACC2 + 14 CONST0 + 15 ENVACC3 + 16 CONST0 + 17 ENVACC4 18 RETURN 1 20 CONSTINT 5 - 22 PUSHCONST2 - 23 PUSHCONST1 + 22 PUSHCONST2 + 23 PUSHCONST1 24 PUSHCONSTINT 4 - 26 PUSHACC0 - 27 PUSHACC2 - 28 PUSHACC4 - 29 PUSHACC6 + 26 PUSHACC0 + 27 PUSHACC2 + 28 PUSHACC4 + 29 PUSHACC6 30 CLOSURE 4, 11 33 PUSHCONSTINT 4 - 35 PUSHCONST0 - 36 PUSHACC2 - 37 APPLY1 - 38 NEQ + 35 PUSHCONST0 + 36 PUSHACC2 + 37 APPLY1 + 38 NEQ 39 BRANCHIFNOT 46 41 GETGLOBAL Not_found 43 MAKEBLOCK1 0 - 45 RAISE + 45 RAISE 46 POP 5 - 48 ATOM0 + 48 ATOM0 49 SETGLOBAL T170-envacc4 - 51 STOP + 51 STOP **) diff --git a/testsuite/tests/tool-ocaml/t171-envacc.ml b/testsuite/tests/tool-ocaml/t171-envacc.ml index 4c4a3dfa..a83295b8 100644 --- a/testsuite/tests/tool-ocaml/t171-envacc.ml +++ b/testsuite/tests/tool-ocaml/t171-envacc.ml @@ -10,43 +10,43 @@ if f 0 <> 3 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 23 - 11 ENVACC1 - 12 CONST0 - 13 ENVACC2 - 14 CONST0 - 15 ENVACC3 - 16 CONST0 - 17 ENVACC4 - 18 CONST0 + 11 ENVACC1 + 12 CONST0 + 13 ENVACC2 + 14 CONST0 + 15 ENVACC3 + 16 CONST0 + 17 ENVACC4 + 18 CONST0 19 ENVACC 5 21 RETURN 1 23 CONSTINT 5 - 25 PUSHCONST2 - 26 PUSHCONST1 + 25 PUSHCONST2 + 26 PUSHCONST1 27 PUSHCONSTINT 4 - 29 PUSHCONST3 - 30 PUSHACC0 - 31 PUSHACC2 - 32 PUSHACC4 - 33 PUSHACC6 + 29 PUSHCONST3 + 30 PUSHACC0 + 31 PUSHACC2 + 32 PUSHACC4 + 33 PUSHACC6 34 PUSHACC 8 36 CLOSURE 5, 11 - 39 PUSHCONST3 - 40 PUSHCONST0 - 41 PUSHACC2 - 42 APPLY1 - 43 NEQ + 39 PUSHCONST3 + 40 PUSHCONST0 + 41 PUSHACC2 + 42 APPLY1 + 43 NEQ 44 BRANCHIFNOT 51 46 GETGLOBAL Not_found 48 MAKEBLOCK1 0 - 50 RAISE + 50 RAISE 51 POP 6 - 53 ATOM0 + 53 ATOM0 54 SETGLOBAL T171-envacc - 56 STOP + 56 STOP **) diff --git a/testsuite/tests/tool-ocaml/t172-pushenvacc1.ml b/testsuite/tests/tool-ocaml/t172-pushenvacc1.ml index 06c4011a..ba615ba7 100644 --- a/testsuite/tests/tool-ocaml/t172-pushenvacc1.ml +++ b/testsuite/tests/tool-ocaml/t172-pushenvacc1.ml @@ -6,29 +6,29 @@ if f 0 <> 10 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 16 - 11 ENVACC1 - 12 PUSHENVACC1 - 13 ADDINT + 11 ENVACC1 + 12 PUSHENVACC1 + 13 ADDINT 14 RETURN 1 16 CONSTINT 5 - 18 PUSHACC0 + 18 PUSHACC0 19 CLOSURE 1, 11 22 PUSHCONSTINT 10 - 24 PUSHCONST0 - 25 PUSHACC2 - 26 APPLY1 - 27 NEQ + 24 PUSHCONST0 + 25 PUSHACC2 + 26 APPLY1 + 27 NEQ 28 BRANCHIFNOT 35 30 GETGLOBAL Not_found 32 MAKEBLOCK1 0 - 34 RAISE + 34 RAISE 35 POP 2 - 37 ATOM0 + 37 ATOM0 38 SETGLOBAL T172-pushenvacc1 - 40 STOP + 40 STOP **) diff --git a/testsuite/tests/tool-ocaml/t172-pushenvacc2.ml b/testsuite/tests/tool-ocaml/t172-pushenvacc2.ml index c25e40a7..afdbcc5d 100644 --- a/testsuite/tests/tool-ocaml/t172-pushenvacc2.ml +++ b/testsuite/tests/tool-ocaml/t172-pushenvacc2.ml @@ -7,31 +7,31 @@ if f 0 <> 9 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 16 - 11 ENVACC1 - 12 PUSHENVACC2 - 13 ADDINT + 11 ENVACC1 + 12 PUSHENVACC2 + 13 ADDINT 14 RETURN 1 16 CONSTINT 5 18 PUSHCONSTINT 4 - 20 PUSHACC0 - 21 PUSHACC2 + 20 PUSHACC0 + 21 PUSHACC2 22 CLOSURE 2, 11 25 PUSHCONSTINT 9 - 27 PUSHCONST0 - 28 PUSHACC2 - 29 APPLY1 - 30 NEQ + 27 PUSHCONST0 + 28 PUSHACC2 + 29 APPLY1 + 30 NEQ 31 BRANCHIFNOT 38 33 GETGLOBAL Not_found 35 MAKEBLOCK1 0 - 37 RAISE + 37 RAISE 38 POP 3 - 40 ATOM0 + 40 ATOM0 41 SETGLOBAL T172-pushenvacc2 - 43 STOP + 43 STOP **) diff --git a/testsuite/tests/tool-ocaml/t172-pushenvacc3.ml b/testsuite/tests/tool-ocaml/t172-pushenvacc3.ml index 093f7f1e..308fd5ed 100644 --- a/testsuite/tests/tool-ocaml/t172-pushenvacc3.ml +++ b/testsuite/tests/tool-ocaml/t172-pushenvacc3.ml @@ -8,35 +8,35 @@ if f 0 <> 12 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 18 - 11 ENVACC1 - 12 PUSHENVACC2 - 13 PUSHENVACC3 - 14 ADDINT - 15 ADDINT + 11 ENVACC1 + 12 PUSHENVACC2 + 13 PUSHENVACC3 + 14 ADDINT + 15 ADDINT 16 RETURN 1 18 CONSTINT 5 20 PUSHCONSTINT 4 - 22 PUSHCONST3 - 23 PUSHACC0 - 24 PUSHACC2 - 25 PUSHACC4 + 22 PUSHCONST3 + 23 PUSHACC0 + 24 PUSHACC2 + 25 PUSHACC4 26 CLOSURE 3, 11 29 PUSHCONSTINT 12 - 31 PUSHCONST0 - 32 PUSHACC2 - 33 APPLY1 - 34 NEQ + 31 PUSHCONST0 + 32 PUSHACC2 + 33 APPLY1 + 34 NEQ 35 BRANCHIFNOT 42 37 GETGLOBAL Not_found 39 MAKEBLOCK1 0 - 41 RAISE + 41 RAISE 42 POP 4 - 44 ATOM0 + 44 ATOM0 45 SETGLOBAL T172-pushenvacc3 - 47 STOP + 47 STOP **) diff --git a/testsuite/tests/tool-ocaml/t172-pushenvacc4.ml b/testsuite/tests/tool-ocaml/t172-pushenvacc4.ml index 154c4a47..feba1281 100644 --- a/testsuite/tests/tool-ocaml/t172-pushenvacc4.ml +++ b/testsuite/tests/tool-ocaml/t172-pushenvacc4.ml @@ -9,39 +9,39 @@ if f 0 <> 14 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 21 - 11 ENVACC1 - 12 PUSHENVACC2 - 13 PUSHENVACC3 + 11 ENVACC1 + 12 PUSHENVACC2 + 13 PUSHENVACC3 14 PUSHENVACC 4 - 16 ADDINT - 17 ADDINT - 18 ADDINT + 16 ADDINT + 17 ADDINT + 18 ADDINT 19 RETURN 1 21 CONSTINT 5 23 PUSHCONSTINT 4 - 25 PUSHCONST3 - 26 PUSHCONST2 - 27 PUSHACC0 - 28 PUSHACC2 - 29 PUSHACC4 - 30 PUSHACC6 + 25 PUSHCONST3 + 26 PUSHCONST2 + 27 PUSHACC0 + 28 PUSHACC2 + 29 PUSHACC4 + 30 PUSHACC6 31 CLOSURE 4, 11 34 PUSHCONSTINT 14 - 36 PUSHCONST0 - 37 PUSHACC2 - 38 APPLY1 - 39 NEQ + 36 PUSHCONST0 + 37 PUSHACC2 + 38 APPLY1 + 39 NEQ 40 BRANCHIFNOT 47 42 GETGLOBAL Not_found 44 MAKEBLOCK1 0 - 46 RAISE + 46 RAISE 47 POP 5 - 49 ATOM0 + 49 ATOM0 50 SETGLOBAL T172-pushenvacc4 - 52 STOP + 52 STOP **) diff --git a/testsuite/tests/tool-ocaml/t173-pushenvacc.ml b/testsuite/tests/tool-ocaml/t173-pushenvacc.ml index 0d858b4a..ffddf8d7 100644 --- a/testsuite/tests/tool-ocaml/t173-pushenvacc.ml +++ b/testsuite/tests/tool-ocaml/t173-pushenvacc.ml @@ -10,43 +10,43 @@ if f 0 <> 15 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 24 - 11 ENVACC1 - 12 PUSHENVACC2 - 13 PUSHENVACC3 + 11 ENVACC1 + 12 PUSHENVACC2 + 13 PUSHENVACC3 14 PUSHENVACC 4 16 PUSHENVACC 5 - 18 ADDINT - 19 ADDINT - 20 ADDINT - 21 ADDINT + 18 ADDINT + 19 ADDINT + 20 ADDINT + 21 ADDINT 22 RETURN 1 24 CONSTINT 5 26 PUSHCONSTINT 4 - 28 PUSHCONST3 - 29 PUSHCONST2 - 30 PUSHCONST1 - 31 PUSHACC0 - 32 PUSHACC2 - 33 PUSHACC4 - 34 PUSHACC6 + 28 PUSHCONST3 + 29 PUSHCONST2 + 30 PUSHCONST1 + 31 PUSHACC0 + 32 PUSHACC2 + 33 PUSHACC4 + 34 PUSHACC6 35 PUSHACC 8 37 CLOSURE 5, 11 40 PUSHCONSTINT 15 - 42 PUSHCONST0 - 43 PUSHACC2 - 44 APPLY1 - 45 NEQ + 42 PUSHCONST0 + 43 PUSHACC2 + 44 APPLY1 + 45 NEQ 46 BRANCHIFNOT 53 48 GETGLOBAL Not_found 50 MAKEBLOCK1 0 - 52 RAISE + 52 RAISE 53 POP 6 - 55 ATOM0 + 55 ATOM0 56 SETGLOBAL T173-pushenvacc - 58 STOP + 58 STOP **) diff --git a/testsuite/tests/tool-ocaml/t180-appterm1.ml b/testsuite/tests/tool-ocaml/t180-appterm1.ml index 6b82f51b..a0006caf 100644 --- a/testsuite/tests/tool-ocaml/t180-appterm1.ml +++ b/testsuite/tests/tool-ocaml/t180-appterm1.ml @@ -6,30 +6,30 @@ if g 0 <> 12 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 19 - 11 CONST0 - 12 PUSHENVACC1 + 11 CONST0 + 12 PUSHENVACC1 13 APPTERM1 2 15 CONSTINT 12 17 RETURN 1 19 CLOSURE 0, 15 - 22 PUSHACC0 + 22 PUSHACC0 23 CLOSURE 1, 11 26 PUSHCONSTINT 12 - 28 PUSHCONST0 - 29 PUSHACC2 - 30 APPLY1 - 31 NEQ + 28 PUSHCONST0 + 29 PUSHACC2 + 30 APPLY1 + 31 NEQ 32 BRANCHIFNOT 39 34 GETGLOBAL Not_found 36 MAKEBLOCK1 0 - 38 RAISE + 38 RAISE 39 POP 2 - 41 ATOM0 + 41 ATOM0 42 SETGLOBAL T180-appterm1 - 44 STOP + 44 STOP **) diff --git a/testsuite/tests/tool-ocaml/t180-appterm2.ml b/testsuite/tests/tool-ocaml/t180-appterm2.ml index 28f32a93..850301d0 100644 --- a/testsuite/tests/tool-ocaml/t180-appterm2.ml +++ b/testsuite/tests/tool-ocaml/t180-appterm2.ml @@ -6,33 +6,33 @@ if g 0 <> 12 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 23 - 11 CONST0 - 12 PUSHCONST0 - 13 PUSHENVACC1 + 11 CONST0 + 12 PUSHCONST0 + 13 PUSHENVACC1 14 APPTERM2 3 - 16 RESTART + 16 RESTART 17 GRAB 1 19 CONSTINT 12 21 RETURN 2 23 CLOSURE 0, 17 - 26 PUSHACC0 + 26 PUSHACC0 27 CLOSURE 1, 11 30 PUSHCONSTINT 12 - 32 PUSHCONST0 - 33 PUSHACC2 - 34 APPLY1 - 35 NEQ + 32 PUSHCONST0 + 33 PUSHACC2 + 34 APPLY1 + 35 NEQ 36 BRANCHIFNOT 43 38 GETGLOBAL Not_found 40 MAKEBLOCK1 0 - 42 RAISE + 42 RAISE 43 POP 2 - 45 ATOM0 + 45 ATOM0 46 SETGLOBAL T180-appterm2 - 48 STOP + 48 STOP **) diff --git a/testsuite/tests/tool-ocaml/t180-appterm3.ml b/testsuite/tests/tool-ocaml/t180-appterm3.ml index fe8a0bd5..eedc52e5 100644 --- a/testsuite/tests/tool-ocaml/t180-appterm3.ml +++ b/testsuite/tests/tool-ocaml/t180-appterm3.ml @@ -6,34 +6,34 @@ if g 0 <> 13 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 24 - 11 CONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHENVACC1 + 11 CONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHENVACC1 15 APPTERM3 4 - 17 RESTART + 17 RESTART 18 GRAB 2 20 CONSTINT 13 22 RETURN 3 24 CLOSURE 0, 18 - 27 PUSHACC0 + 27 PUSHACC0 28 CLOSURE 1, 11 31 PUSHCONSTINT 13 - 33 PUSHCONST0 - 34 PUSHACC2 - 35 APPLY1 - 36 NEQ + 33 PUSHCONST0 + 34 PUSHACC2 + 35 APPLY1 + 36 NEQ 37 BRANCHIFNOT 44 39 GETGLOBAL Not_found 41 MAKEBLOCK1 0 - 43 RAISE + 43 RAISE 44 POP 2 - 46 ATOM0 + 46 ATOM0 47 SETGLOBAL T180-appterm3 - 49 STOP + 49 STOP **) diff --git a/testsuite/tests/tool-ocaml/t181-appterm.ml b/testsuite/tests/tool-ocaml/t181-appterm.ml index 03127bc8..2222bc40 100644 --- a/testsuite/tests/tool-ocaml/t181-appterm.ml +++ b/testsuite/tests/tool-ocaml/t181-appterm.ml @@ -6,35 +6,35 @@ if g 0 <> -10 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 26 - 11 CONST0 - 12 PUSHCONST0 - 13 PUSHCONST0 - 14 PUSHCONST0 - 15 PUSHENVACC1 + 11 CONST0 + 12 PUSHCONST0 + 13 PUSHCONST0 + 14 PUSHCONST0 + 15 PUSHENVACC1 16 APPTERM 4, 5 - 19 RESTART + 19 RESTART 20 GRAB 3 22 CONSTINT -10 24 RETURN 4 26 CLOSURE 0, 20 - 29 PUSHACC0 + 29 PUSHACC0 30 CLOSURE 1, 11 33 PUSHCONSTINT -10 - 35 PUSHCONST0 - 36 PUSHACC2 - 37 APPLY1 - 38 NEQ + 35 PUSHCONST0 + 36 PUSHACC2 + 37 APPLY1 + 38 NEQ 39 BRANCHIFNOT 46 41 GETGLOBAL Not_found 43 MAKEBLOCK1 0 - 45 RAISE + 45 RAISE 46 POP 2 - 48 ATOM0 + 48 ATOM0 49 SETGLOBAL T181-appterm - 51 STOP + 51 STOP **) diff --git a/testsuite/tests/tool-ocaml/t190-makefloatblock-1.ml b/testsuite/tests/tool-ocaml/t190-makefloatblock-1.ml index f63c6cd8..1d906c9c 100644 --- a/testsuite/tests/tool-ocaml/t190-makefloatblock-1.ml +++ b/testsuite/tests/tool-ocaml/t190-makefloatblock-1.ml @@ -3,15 +3,15 @@ let x = 0.0 in [| x |];; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL 0 - 11 PUSHACC0 + 11 PUSHACC0 12 MAKEFLOATBLOCK 1 14 POP 1 - 16 ATOM0 + 16 ATOM0 17 SETGLOBAL T190-makefloatblock-1 - 19 STOP + 19 STOP **) diff --git a/testsuite/tests/tool-ocaml/t190-makefloatblock-2.ml b/testsuite/tests/tool-ocaml/t190-makefloatblock-2.ml index 53b97f5d..bb06aba8 100644 --- a/testsuite/tests/tool-ocaml/t190-makefloatblock-2.ml +++ b/testsuite/tests/tool-ocaml/t190-makefloatblock-2.ml @@ -3,16 +3,16 @@ let x = 0.0 in [| x; x |];; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL 0 - 11 PUSHACC0 - 12 PUSHACC1 + 11 PUSHACC0 + 12 PUSHACC1 13 MAKEFLOATBLOCK 2 15 POP 1 - 17 ATOM0 + 17 ATOM0 18 SETGLOBAL T190-makefloatblock-2 - 20 STOP + 20 STOP **) diff --git a/testsuite/tests/tool-ocaml/t190-makefloatblock-3.ml b/testsuite/tests/tool-ocaml/t190-makefloatblock-3.ml index cebccaa3..581439df 100644 --- a/testsuite/tests/tool-ocaml/t190-makefloatblock-3.ml +++ b/testsuite/tests/tool-ocaml/t190-makefloatblock-3.ml @@ -3,17 +3,17 @@ let x = 0.0 in [| x; x; x |];; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL 0 - 11 PUSHACC0 - 12 PUSHACC1 - 13 PUSHACC2 + 11 PUSHACC0 + 12 PUSHACC1 + 13 PUSHACC2 14 MAKEFLOATBLOCK 3 16 POP 1 - 18 ATOM0 + 18 ATOM0 19 SETGLOBAL T190-makefloatblock-3 - 21 STOP + 21 STOP **) diff --git a/testsuite/tests/tool-ocaml/t191-vectlength.ml b/testsuite/tests/tool-ocaml/t191-vectlength.ml index 16f7d783..6cd19667 100644 --- a/testsuite/tests/tool-ocaml/t191-vectlength.ml +++ b/testsuite/tests/tool-ocaml/t191-vectlength.ml @@ -5,22 +5,22 @@ if Array.length [| x |] <> 1 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL 0 - 11 PUSHCONST1 - 12 PUSHACC1 + 11 PUSHCONST1 + 12 PUSHACC1 13 MAKEFLOATBLOCK 1 - 15 VECTLENGTH - 16 NEQ + 15 VECTLENGTH + 16 NEQ 17 BRANCHIFNOT 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE + 23 RAISE 24 POP 1 - 26 ATOM0 + 26 ATOM0 27 SETGLOBAL T191-vectlength - 29 STOP + 29 STOP **) diff --git a/testsuite/tests/tool-ocaml/t192-getfloatfield-1.ml b/testsuite/tests/tool-ocaml/t192-getfloatfield-1.ml index ba002b20..bd8109f4 100644 --- a/testsuite/tests/tool-ocaml/t192-getfloatfield-1.ml +++ b/testsuite/tests/tool-ocaml/t192-getfloatfield-1.ml @@ -5,7 +5,7 @@ if { a = 0.1; b = 0.2 }.a <> 0.1 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -16,8 +16,8 @@ if { a = 0.1; b = 0.2 }.a <> 0.1 then raise Not_found;; 17 BRANCHIFNOT 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE - 24 ATOM0 + 23 RAISE + 24 ATOM0 25 SETGLOBAL T192-getfloatfield-1 - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t192-getfloatfield-2.ml b/testsuite/tests/tool-ocaml/t192-getfloatfield-2.ml index 89230da3..0c62a4b0 100644 --- a/testsuite/tests/tool-ocaml/t192-getfloatfield-2.ml +++ b/testsuite/tests/tool-ocaml/t192-getfloatfield-2.ml @@ -5,7 +5,7 @@ if { a = 0.1; b = 0.2 }.b <> 0.2 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -16,8 +16,8 @@ if { a = 0.1; b = 0.2 }.b <> 0.2 then raise Not_found;; 17 BRANCHIFNOT 24 19 GETGLOBAL Not_found 21 MAKEBLOCK1 0 - 23 RAISE - 24 ATOM0 + 23 RAISE + 24 ATOM0 25 SETGLOBAL T192-getfloatfield-2 - 27 STOP + 27 STOP **) diff --git a/testsuite/tests/tool-ocaml/t193-setfloatfield-1.ml b/testsuite/tests/tool-ocaml/t193-setfloatfield-1.ml index b488e7da..c679c43a 100644 --- a/testsuite/tests/tool-ocaml/t193-setfloatfield-1.ml +++ b/testsuite/tests/tool-ocaml/t193-setfloatfield-1.ml @@ -11,7 +11,7 @@ if x.a <> 0.3 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -19,18 +19,18 @@ if x.a <> 0.3 then raise Not_found 11 PUSHGETGLOBAL 0.1 13 MAKEFLOATBLOCK 2 15 PUSHGETGLOBAL 0.3 - 17 PUSHACC1 + 17 PUSHACC1 18 SETFLOATFIELD 0 20 GETGLOBAL 0.3 - 22 PUSHACC1 + 22 PUSHACC1 23 GETFLOATFIELD 0 25 C_CALL2 neq_float 27 BRANCHIFNOT 34 29 GETGLOBAL Not_found 31 MAKEBLOCK1 0 - 33 RAISE + 33 RAISE 34 POP 1 - 36 ATOM0 + 36 ATOM0 37 SETGLOBAL T193-setfloatfield-1 - 39 STOP + 39 STOP **) diff --git a/testsuite/tests/tool-ocaml/t193-setfloatfield-2.ml b/testsuite/tests/tool-ocaml/t193-setfloatfield-2.ml index 7dde0a2c..2088257a 100644 --- a/testsuite/tests/tool-ocaml/t193-setfloatfield-2.ml +++ b/testsuite/tests/tool-ocaml/t193-setfloatfield-2.ml @@ -11,7 +11,7 @@ if x.b <> 0.3 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -19,18 +19,18 @@ if x.b <> 0.3 then raise Not_found 11 PUSHGETGLOBAL 0.1 13 MAKEFLOATBLOCK 2 15 PUSHGETGLOBAL 0.3 - 17 PUSHACC1 + 17 PUSHACC1 18 SETFLOATFIELD 1 20 GETGLOBAL 0.3 - 22 PUSHACC1 + 22 PUSHACC1 23 GETFLOATFIELD 1 25 C_CALL2 neq_float 27 BRANCHIFNOT 34 29 GETGLOBAL Not_found 31 MAKEBLOCK1 0 - 33 RAISE + 33 RAISE 34 POP 1 - 36 ATOM0 + 36 ATOM0 37 SETGLOBAL T193-setfloatfield-2 - 39 STOP + 39 STOP **) diff --git a/testsuite/tests/tool-ocaml/t200-getfield0.ml b/testsuite/tests/tool-ocaml/t200-getfield0.ml index 14ce1d54..b3f59fe5 100644 --- a/testsuite/tests/tool-ocaml/t200-getfield0.ml +++ b/testsuite/tests/tool-ocaml/t200-getfield0.ml @@ -7,19 +7,19 @@ if { a = 7 }.a <> 7 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 7 11 PUSHGETGLOBAL <0>(7) - 13 GETFIELD0 - 14 NEQ + 13 GETFIELD0 + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T200-getfield0 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t200-getfield1.ml b/testsuite/tests/tool-ocaml/t200-getfield1.ml index f4e2e019..4dcb2f7c 100644 --- a/testsuite/tests/tool-ocaml/t200-getfield1.ml +++ b/testsuite/tests/tool-ocaml/t200-getfield1.ml @@ -8,19 +8,19 @@ if { a = 7; b = 6 }.b <> 6 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 6 11 PUSHGETGLOBAL <0>(7, 6) - 13 GETFIELD1 - 14 NEQ + 13 GETFIELD1 + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T200-getfield1 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t200-getfield2.ml b/testsuite/tests/tool-ocaml/t200-getfield2.ml index df5c7172..02f3234f 100644 --- a/testsuite/tests/tool-ocaml/t200-getfield2.ml +++ b/testsuite/tests/tool-ocaml/t200-getfield2.ml @@ -9,19 +9,19 @@ if { a = 7; b = 6; c = 5 }.c <> 5 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 5 11 PUSHGETGLOBAL <0>(7, 6, 5) - 13 GETFIELD2 - 14 NEQ + 13 GETFIELD2 + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T200-getfield2 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t200-getfield3.ml b/testsuite/tests/tool-ocaml/t200-getfield3.ml index a0376a1f..b8ba042e 100644 --- a/testsuite/tests/tool-ocaml/t200-getfield3.ml +++ b/testsuite/tests/tool-ocaml/t200-getfield3.ml @@ -10,19 +10,19 @@ if { a = 7; b = 6; c = 5; d = 4 }.d <> 4 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 4 11 PUSHGETGLOBAL <0>(7, 6, 5, 4) - 13 GETFIELD3 - 14 NEQ + 13 GETFIELD3 + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T200-getfield3 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t201-getfield.ml b/testsuite/tests/tool-ocaml/t201-getfield.ml index 0fbbc63f..91f86fb7 100644 --- a/testsuite/tests/tool-ocaml/t201-getfield.ml +++ b/testsuite/tests/tool-ocaml/t201-getfield.ml @@ -11,19 +11,19 @@ if { a = 7; b = 6; c = 5; d = 4; e = 3 }.e <> 3 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST3 + 9 CONST3 10 PUSHGETGLOBAL <0>(7, 6, 5, 4, 3) 12 GETFIELD 4 - 14 NEQ + 14 NEQ 15 BRANCHIFNOT 22 17 GETGLOBAL Not_found 19 MAKEBLOCK1 0 - 21 RAISE - 22 ATOM0 + 21 RAISE + 22 ATOM0 23 SETGLOBAL T201-getfield - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t210-setfield0.ml b/testsuite/tests/tool-ocaml/t210-setfield0.ml index aa31d41f..b7fce85a 100644 --- a/testsuite/tests/tool-ocaml/t210-setfield0.ml +++ b/testsuite/tests/tool-ocaml/t210-setfield0.ml @@ -11,26 +11,26 @@ x (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 7 11 MAKEBLOCK1 0 13 PUSHCONSTINT 11 - 15 PUSHACC1 - 16 SETFIELD0 + 15 PUSHACC1 + 16 SETFIELD0 17 CONSTINT 11 - 19 PUSHACC1 - 20 GETFIELD0 - 21 NEQ + 19 PUSHACC1 + 20 GETFIELD0 + 21 NEQ 22 BRANCHIFNOT 29 24 GETGLOBAL Not_found 26 MAKEBLOCK1 0 - 28 RAISE - 29 ACC0 + 28 RAISE + 29 ACC0 30 POP 1 - 32 ATOM0 + 32 ATOM0 33 SETGLOBAL T210-setfield0 - 35 STOP + 35 STOP **) diff --git a/testsuite/tests/tool-ocaml/t210-setfield1.ml b/testsuite/tests/tool-ocaml/t210-setfield1.ml index 0d8e1676..7bb65c55 100644 --- a/testsuite/tests/tool-ocaml/t210-setfield1.ml +++ b/testsuite/tests/tool-ocaml/t210-setfield1.ml @@ -12,7 +12,7 @@ x (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -20,19 +20,19 @@ x 11 PUSHCONSTINT 7 13 MAKEBLOCK2 0 15 PUSHCONSTINT 11 - 17 PUSHACC1 - 18 SETFIELD1 + 17 PUSHACC1 + 18 SETFIELD1 19 CONSTINT 11 - 21 PUSHACC1 - 22 GETFIELD1 - 23 NEQ + 21 PUSHACC1 + 22 GETFIELD1 + 23 NEQ 24 BRANCHIFNOT 31 26 GETGLOBAL Not_found 28 MAKEBLOCK1 0 - 30 RAISE - 31 ACC0 + 30 RAISE + 31 ACC0 32 POP 1 - 34 ATOM0 + 34 ATOM0 35 SETGLOBAL T210-setfield1 - 37 STOP + 37 STOP **) diff --git a/testsuite/tests/tool-ocaml/t210-setfield2.ml b/testsuite/tests/tool-ocaml/t210-setfield2.ml index 727691d1..4cd42ecf 100644 --- a/testsuite/tests/tool-ocaml/t210-setfield2.ml +++ b/testsuite/tests/tool-ocaml/t210-setfield2.ml @@ -13,7 +13,7 @@ x (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -22,19 +22,19 @@ x 13 PUSHCONSTINT 7 15 MAKEBLOCK3 0 17 PUSHCONSTINT 11 - 19 PUSHACC1 - 20 SETFIELD2 + 19 PUSHACC1 + 20 SETFIELD2 21 CONSTINT 11 - 23 PUSHACC1 - 24 GETFIELD2 - 25 NEQ + 23 PUSHACC1 + 24 GETFIELD2 + 25 NEQ 26 BRANCHIFNOT 33 28 GETGLOBAL Not_found 30 MAKEBLOCK1 0 - 32 RAISE - 33 ACC0 + 32 RAISE + 33 ACC0 34 POP 1 - 36 ATOM0 + 36 ATOM0 37 SETGLOBAL T210-setfield2 - 39 STOP + 39 STOP **) diff --git a/testsuite/tests/tool-ocaml/t210-setfield3.ml b/testsuite/tests/tool-ocaml/t210-setfield3.ml index d50d2c2a..7df75362 100644 --- a/testsuite/tests/tool-ocaml/t210-setfield3.ml +++ b/testsuite/tests/tool-ocaml/t210-setfield3.ml @@ -14,7 +14,7 @@ x (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -24,19 +24,19 @@ x 15 PUSHCONSTINT 7 17 MAKEBLOCK 4, 0 20 PUSHCONSTINT 11 - 22 PUSHACC1 - 23 SETFIELD3 + 22 PUSHACC1 + 23 SETFIELD3 24 CONSTINT 11 - 26 PUSHACC1 - 27 GETFIELD3 - 28 NEQ + 26 PUSHACC1 + 27 GETFIELD3 + 28 NEQ 29 BRANCHIFNOT 36 31 GETGLOBAL Not_found 33 MAKEBLOCK1 0 - 35 RAISE - 36 ACC0 + 35 RAISE + 36 ACC0 37 POP 1 - 39 ATOM0 + 39 ATOM0 40 SETGLOBAL T210-setfield3 - 42 STOP + 42 STOP **) diff --git a/testsuite/tests/tool-ocaml/t211-setfield.ml b/testsuite/tests/tool-ocaml/t211-setfield.ml index 69c445e1..47e3b7db 100644 --- a/testsuite/tests/tool-ocaml/t211-setfield.ml +++ b/testsuite/tests/tool-ocaml/t211-setfield.ml @@ -15,7 +15,7 @@ x (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -26,19 +26,19 @@ x 17 PUSHCONSTINT 7 19 MAKEBLOCK 5, 0 22 PUSHCONSTINT 11 - 24 PUSHACC1 + 24 PUSHACC1 25 SETFIELD 4 27 CONSTINT 11 - 29 PUSHACC1 + 29 PUSHACC1 30 GETFIELD 4 - 32 NEQ + 32 NEQ 33 BRANCHIFNOT 40 35 GETGLOBAL Not_found 37 MAKEBLOCK1 0 - 39 RAISE - 40 ACC0 + 39 RAISE + 40 ACC0 41 POP 1 - 43 ATOM0 + 43 ATOM0 44 SETGLOBAL T211-setfield - 46 STOP + 46 STOP **) diff --git a/testsuite/tests/tool-ocaml/t220-assign.ml b/testsuite/tests/tool-ocaml/t220-assign.ml index 769f8fb2..ecb57e60 100644 --- a/testsuite/tests/tool-ocaml/t220-assign.ml +++ b/testsuite/tests/tool-ocaml/t220-assign.ml @@ -6,22 +6,22 @@ if !x <> 3 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST1 - 10 PUSHCONST3 + 9 CONST1 + 10 PUSHCONST3 11 ASSIGN 0 - 13 CONST3 - 14 PUSHACC1 - 15 NEQ + 13 CONST3 + 14 PUSHACC1 + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE + 22 RAISE 23 POP 1 - 25 ATOM0 + 25 ATOM0 26 SETGLOBAL T220-assign - 28 STOP + 28 STOP **) diff --git a/testsuite/tests/tool-ocaml/t230-check_signals.ml b/testsuite/tests/tool-ocaml/t230-check_signals.ml index 2c2b5d77..41e82d8c 100644 --- a/testsuite/tests/tool-ocaml/t230-check_signals.ml +++ b/testsuite/tests/tool-ocaml/t230-check_signals.ml @@ -3,26 +3,26 @@ for i = 0 to 0 do () done;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 - 10 PUSHCONST0 - 11 PUSH + 9 CONST0 + 10 PUSHCONST0 + 11 PUSH 12 BRANCH 21 - 14 CHECK_SIGNALS - 15 CONST0 - 16 ACC1 + 14 CHECK_SIGNALS + 15 CONST0 + 16 ACC1 17 OFFSETINT 1 19 ASSIGN 1 - 21 ACC0 - 22 PUSHACC2 - 23 LEINT + 21 ACC0 + 22 PUSHACC2 + 23 LEINT 24 BRANCHIF 14 - 26 CONST0 + 26 CONST0 27 POP 2 - 29 ATOM0 + 29 ATOM0 30 SETGLOBAL T230-check_signals - 32 STOP + 32 STOP **) diff --git a/testsuite/tests/tool-ocaml/t240-c_call1.ml b/testsuite/tests/tool-ocaml/t240-c_call1.ml index 3c7508cb..70809c75 100644 --- a/testsuite/tests/tool-ocaml/t240-c_call1.ml +++ b/testsuite/tests/tool-ocaml/t240-c_call1.ml @@ -1,21 +1,27 @@ open Lib;; if Pervasives.int_of_string "123" <> 123 then raise Not_found;; +(** test for fix of bug 6649: http://caml.inria.fr/mantis/view.php?id=6649 *) +if Pervasives.int_of_string "+123" <> 123 then raise Not_found;; + +if Int32.of_string "+123" <> Int32.of_int 123 then raise Not_found;; +if Int64.of_string "+123" <> Int64.of_int 123 then raise Not_found;; +if Nativeint.of_string "+123" <> Nativeint.of_int 123 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 123 11 PUSHGETGLOBAL "123" 13 C_CALL1 int_of_string - 15 NEQ + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T240-c_call1 - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t240-c_call2.ml b/testsuite/tests/tool-ocaml/t240-c_call2.ml index 23c98436..733b3412 100644 --- a/testsuite/tests/tool-ocaml/t240-c_call2.ml +++ b/testsuite/tests/tool-ocaml/t240-c_call2.ml @@ -3,20 +3,20 @@ if Pervasives.compare 1 2 <> -1 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT -1 - 11 PUSHCONST2 - 12 PUSHCONST1 + 11 PUSHCONST2 + 12 PUSHCONST1 13 C_CALL2 compare - 15 NEQ + 15 NEQ 16 BRANCHIFNOT 23 18 GETGLOBAL Not_found 20 MAKEBLOCK1 0 - 22 RAISE - 23 ATOM0 + 22 RAISE + 23 ATOM0 24 SETGLOBAL T240-c_call2 - 26 STOP + 26 STOP **) diff --git a/testsuite/tests/tool-ocaml/t240-c_call3.ml b/testsuite/tests/tool-ocaml/t240-c_call3.ml index a34e1dcf..4e91c3fd 100644 --- a/testsuite/tests/tool-ocaml/t240-c_call3.ml +++ b/testsuite/tests/tool-ocaml/t240-c_call3.ml @@ -3,7 +3,7 @@ if Hashtbl.hash_param 5 6 [1;2;3] <> 697606130 then raise Not_found;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -12,12 +12,12 @@ if Hashtbl.hash_param 5 6 [1;2;3] <> 697606130 then raise Not_found;; 13 PUSHCONSTINT 6 15 PUSHCONSTINT 5 17 C_CALL3 hash_univ_param - 19 NEQ + 19 NEQ 20 BRANCHIFNOT 27 22 GETGLOBAL Not_found 24 MAKEBLOCK1 0 - 26 RAISE - 27 ATOM0 + 26 RAISE + 27 ATOM0 28 SETGLOBAL T240-c_call3 - 30 STOP + 30 STOP **) diff --git a/testsuite/tests/tool-ocaml/t240-c_call4.ml b/testsuite/tests/tool-ocaml/t240-c_call4.ml index 2ab62d86..7b66ab14 100644 --- a/testsuite/tests/tool-ocaml/t240-c_call4.ml +++ b/testsuite/tests/tool-ocaml/t240-c_call4.ml @@ -6,27 +6,27 @@ if s.[5] <> 'x' then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL "abcdefgh" 11 PUSHCONSTINT 120 13 PUSHCONSTINT 6 - 15 PUSHCONST0 - 16 PUSHACC3 + 15 PUSHCONST0 + 16 PUSHACC3 17 C_CALL4 fill_string 19 CONSTINT 120 21 PUSHCONSTINT 5 - 23 PUSHACC2 - 24 GETSTRINGCHAR - 25 NEQ + 23 PUSHACC2 + 24 GETSTRINGCHAR + 25 NEQ 26 BRANCHIFNOT 33 28 GETGLOBAL Not_found 30 MAKEBLOCK1 0 - 32 RAISE + 32 RAISE 33 POP 1 - 35 ATOM0 + 35 ATOM0 36 SETGLOBAL T240-c_call4 - 38 STOP + 38 STOP **) diff --git a/testsuite/tests/tool-ocaml/t240-c_call5.ml b/testsuite/tests/tool-ocaml/t240-c_call5.ml index e817d550..4c6c92d1 100644 --- a/testsuite/tests/tool-ocaml/t240-c_call5.ml +++ b/testsuite/tests/tool-ocaml/t240-c_call5.ml @@ -6,28 +6,28 @@ if s.[0] <> 'd' then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 GETGLOBAL "abcdefgh" - 11 PUSHCONST3 - 12 PUSHCONST0 - 13 PUSHACC2 - 14 PUSHCONST3 - 15 PUSHACC4 + 11 PUSHCONST3 + 12 PUSHCONST0 + 13 PUSHACC2 + 14 PUSHCONST3 + 15 PUSHACC4 16 C_CALL5 blit_string 18 CONSTINT 100 - 20 PUSHCONST0 - 21 PUSHACC2 - 22 GETSTRINGCHAR - 23 NEQ + 20 PUSHCONST0 + 21 PUSHACC2 + 22 GETSTRINGCHAR + 23 NEQ 24 BRANCHIFNOT 31 26 GETGLOBAL Not_found 28 MAKEBLOCK1 0 - 30 RAISE + 30 RAISE 31 POP 1 - 33 ATOM0 + 33 ATOM0 34 SETGLOBAL T240-c_call5 - 36 STOP + 36 STOP **) diff --git a/testsuite/tests/tool-ocaml/t250-closurerec-1.ml b/testsuite/tests/tool-ocaml/t250-closurerec-1.ml index ded5036e..283b17a3 100644 --- a/testsuite/tests/tool-ocaml/t250-closurerec-1.ml +++ b/testsuite/tests/tool-ocaml/t250-closurerec-1.ml @@ -3,17 +3,17 @@ let rec f _ = 0;; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 14 - 11 CONST0 + 11 CONST0 12 RETURN 1 14 CLOSUREREC 0, 11 - 18 ACC0 + 18 ACC0 19 MAKEBLOCK1 0 21 POP 1 23 SETGLOBAL T250-closurerec-1 - 25 STOP + 25 STOP **) diff --git a/testsuite/tests/tool-ocaml/t250-closurerec-2.ml b/testsuite/tests/tool-ocaml/t250-closurerec-2.ml index 97eac0c7..ffe3d481 100644 --- a/testsuite/tests/tool-ocaml/t250-closurerec-2.ml +++ b/testsuite/tests/tool-ocaml/t250-closurerec-2.ml @@ -5,7 +5,7 @@ if f 0 <> 23 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib @@ -14,16 +14,16 @@ if f 0 <> 23 then raise Not_found 13 RETURN 1 15 CLOSUREREC 0, 11 19 CONSTINT 23 - 21 PUSHCONST0 - 22 PUSHACC2 - 23 APPLY1 - 24 NEQ + 21 PUSHCONST0 + 22 PUSHACC2 + 23 APPLY1 + 24 NEQ 25 BRANCHIFNOT 32 27 GETGLOBAL Not_found 29 MAKEBLOCK1 0 - 31 RAISE + 31 RAISE 32 POP 1 - 34 ATOM0 + 34 ATOM0 35 SETGLOBAL T250-closurerec-2 - 37 STOP + 37 STOP **) diff --git a/testsuite/tests/tool-ocaml/t251-pushoffsetclosure0.ml b/testsuite/tests/tool-ocaml/t251-pushoffsetclosure0.ml index b1c25555..1ea295a3 100644 --- a/testsuite/tests/tool-ocaml/t251-pushoffsetclosure0.ml +++ b/testsuite/tests/tool-ocaml/t251-pushoffsetclosure0.ml @@ -8,32 +8,32 @@ if f 5 <> 13 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 24 - 11 CONST0 - 12 PUSHACC1 - 13 EQ + 11 CONST0 + 12 PUSHACC1 + 13 EQ 14 BRANCHIFNOT 20 16 CONSTINT 13 18 RETURN 1 - 20 CONST0 - 21 PUSHOFFSETCLOSURE0 + 20 CONST0 + 21 PUSHOFFSETCLOSURE0 22 APPTERM1 2 24 CLOSUREREC 0, 11 28 CONSTINT 13 30 PUSHCONSTINT 5 - 32 PUSHACC2 - 33 APPLY1 - 34 NEQ + 32 PUSHACC2 + 33 APPLY1 + 34 NEQ 35 BRANCHIFNOT 42 37 GETGLOBAL Not_found 39 MAKEBLOCK1 0 - 41 RAISE + 41 RAISE 42 POP 1 - 44 ATOM0 + 44 ATOM0 45 SETGLOBAL T251-pushoffsetclosure0 - 47 STOP + 47 STOP **) diff --git a/testsuite/tests/tool-ocaml/t251-pushoffsetclosure2.ml b/testsuite/tests/tool-ocaml/t251-pushoffsetclosure2.ml index 0fbdd6ea..8634f29e 100644 --- a/testsuite/tests/tool-ocaml/t251-pushoffsetclosure2.ml +++ b/testsuite/tests/tool-ocaml/t251-pushoffsetclosure2.ml @@ -7,28 +7,28 @@ if f 5 <> 4 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 19 - 11 CONST0 - 12 PUSHOFFSETCLOSURE2 + 11 CONST0 + 12 PUSHOFFSETCLOSURE2 13 APPTERM1 2 15 CONSTINT 4 17 RETURN 1 19 CLOSUREREC 0, 11, 15 24 CONSTINT 4 26 PUSHCONSTINT 5 - 28 PUSHACC3 - 29 APPLY1 - 30 NEQ + 28 PUSHACC3 + 29 APPLY1 + 30 NEQ 31 BRANCHIFNOT 38 33 GETGLOBAL Not_found 35 MAKEBLOCK1 0 - 37 RAISE + 37 RAISE 38 POP 2 - 40 ATOM0 + 40 ATOM0 41 SETGLOBAL T251-pushoffsetclosure2 - 43 STOP + 43 STOP **) diff --git a/testsuite/tests/tool-ocaml/t251-pushoffsetclosurem2.ml b/testsuite/tests/tool-ocaml/t251-pushoffsetclosurem2.ml index 41ec196c..65267e5b 100644 --- a/testsuite/tests/tool-ocaml/t251-pushoffsetclosurem2.ml +++ b/testsuite/tests/tool-ocaml/t251-pushoffsetclosurem2.ml @@ -7,28 +7,28 @@ if g 5 <> 4 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 19 11 CONSTINT 4 13 RETURN 1 - 15 CONST2 - 16 PUSHOFFSETCLOSUREM2 + 15 CONST2 + 16 PUSHOFFSETCLOSUREM2 17 APPTERM1 2 19 CLOSUREREC 0, 11, 15 24 CONSTINT 4 26 PUSHCONSTINT 5 - 28 PUSHACC2 - 29 APPLY1 - 30 NEQ + 28 PUSHACC2 + 29 APPLY1 + 30 NEQ 31 BRANCHIFNOT 38 33 GETGLOBAL Not_found 35 MAKEBLOCK1 0 - 37 RAISE + 37 RAISE 38 POP 2 - 40 ATOM0 + 40 ATOM0 41 SETGLOBAL T251-pushoffsetclosurem2 - 43 STOP + 43 STOP **) diff --git a/testsuite/tests/tool-ocaml/t252-pushoffsetclosure.ml b/testsuite/tests/tool-ocaml/t252-pushoffsetclosure.ml index 18871334..dccce95a 100644 --- a/testsuite/tests/tool-ocaml/t252-pushoffsetclosure.ml +++ b/testsuite/tests/tool-ocaml/t252-pushoffsetclosure.ml @@ -8,31 +8,31 @@ if h 1 <> 6 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 25 - 11 ACC0 + 11 ACC0 12 RETURN 1 14 CONSTINT 4 - 16 PUSHOFFSETCLOSUREM2 + 16 PUSHOFFSETCLOSUREM2 17 APPTERM1 2 19 CONSTINT 6 21 PUSHOFFSETCLOSURE -4 23 APPTERM1 2 25 CLOSUREREC 0, 11, 14, 19 31 CONSTINT 6 - 33 PUSHCONST1 - 34 PUSHACC2 - 35 APPLY1 - 36 NEQ + 33 PUSHCONST1 + 34 PUSHACC2 + 35 APPLY1 + 36 NEQ 37 BRANCHIFNOT 44 39 GETGLOBAL Not_found 41 MAKEBLOCK1 0 - 43 RAISE + 43 RAISE 44 POP 3 - 46 ATOM0 + 46 ATOM0 47 SETGLOBAL T252-pushoffsetclosure - 49 STOP + 49 STOP **) diff --git a/testsuite/tests/tool-ocaml/t253-offsetclosure0.ml b/testsuite/tests/tool-ocaml/t253-offsetclosure0.ml index f6d12c6d..35d66ba3 100644 --- a/testsuite/tests/tool-ocaml/t253-offsetclosure0.ml +++ b/testsuite/tests/tool-ocaml/t253-offsetclosure0.ml @@ -7,28 +7,28 @@ if f 3 <> 10 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 19 - 11 OFFSETCLOSURE0 - 12 PUSHOFFSETCLOSURE2 + 11 OFFSETCLOSURE0 + 12 PUSHOFFSETCLOSURE2 13 APPTERM1 2 15 CONSTINT 10 17 RETURN 1 19 CLOSUREREC 0, 11, 15 24 CONSTINT 10 - 26 PUSHCONST3 - 27 PUSHACC3 - 28 APPLY1 - 29 NEQ + 26 PUSHCONST3 + 27 PUSHACC3 + 28 APPLY1 + 29 NEQ 30 BRANCHIFNOT 37 32 GETGLOBAL Not_found 34 MAKEBLOCK1 0 - 36 RAISE + 36 RAISE 37 POP 2 - 39 ATOM0 + 39 ATOM0 40 SETGLOBAL T253-offsetclosure0 - 42 STOP + 42 STOP **) diff --git a/testsuite/tests/tool-ocaml/t253-offsetclosure2.ml b/testsuite/tests/tool-ocaml/t253-offsetclosure2.ml index be940611..55adf632 100644 --- a/testsuite/tests/tool-ocaml/t253-offsetclosure2.ml +++ b/testsuite/tests/tool-ocaml/t253-offsetclosure2.ml @@ -7,28 +7,28 @@ if f 3 4 <> 10 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 18 - 11 OFFSETCLOSURE2 + 11 OFFSETCLOSURE2 12 RETURN 1 14 CONSTINT 10 16 RETURN 1 18 CLOSUREREC 0, 11, 14 23 CONSTINT 10 25 PUSHCONSTINT 4 - 27 PUSHCONST3 - 28 PUSHACC4 - 29 APPLY2 - 30 NEQ + 27 PUSHCONST3 + 28 PUSHACC4 + 29 APPLY2 + 30 NEQ 31 BRANCHIFNOT 38 33 GETGLOBAL Not_found 35 MAKEBLOCK1 0 - 37 RAISE + 37 RAISE 38 POP 2 - 40 ATOM0 + 40 ATOM0 41 SETGLOBAL T253-offsetclosure2 - 43 STOP + 43 STOP **) diff --git a/testsuite/tests/tool-ocaml/t253-offsetclosurem2.ml b/testsuite/tests/tool-ocaml/t253-offsetclosurem2.ml index cec37931..e61e0c22 100644 --- a/testsuite/tests/tool-ocaml/t253-offsetclosurem2.ml +++ b/testsuite/tests/tool-ocaml/t253-offsetclosurem2.ml @@ -7,28 +7,28 @@ if g 3 4 <> 11 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 18 11 CONSTINT 11 13 RETURN 1 - 15 OFFSETCLOSUREM2 + 15 OFFSETCLOSUREM2 16 RETURN 1 18 CLOSUREREC 0, 11, 15 23 CONSTINT 11 25 PUSHCONSTINT 4 - 27 PUSHCONST3 - 28 PUSHACC3 - 29 APPLY2 - 30 NEQ + 27 PUSHCONST3 + 28 PUSHACC3 + 29 APPLY2 + 30 NEQ 31 BRANCHIFNOT 38 33 GETGLOBAL Not_found 35 MAKEBLOCK1 0 - 37 RAISE + 37 RAISE 38 POP 2 - 40 ATOM0 + 40 ATOM0 41 SETGLOBAL T253-offsetclosurem2 - 43 STOP + 43 STOP **) diff --git a/testsuite/tests/tool-ocaml/t254-offsetclosure.ml b/testsuite/tests/tool-ocaml/t254-offsetclosure.ml index 6da8c28c..95eb1b0c 100644 --- a/testsuite/tests/tool-ocaml/t254-offsetclosure.ml +++ b/testsuite/tests/tool-ocaml/t254-offsetclosure.ml @@ -8,30 +8,30 @@ if h 3 4 <> 11 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 22 11 CONSTINT 11 13 RETURN 1 - 15 CONST0 + 15 CONST0 16 RETURN 1 18 OFFSETCLOSURE -4 20 RETURN 1 22 CLOSUREREC 0, 11, 15, 18 28 CONSTINT 11 30 PUSHCONSTINT 4 - 32 PUSHCONST3 - 33 PUSHACC3 - 34 APPLY2 - 35 NEQ + 32 PUSHCONST3 + 33 PUSHACC3 + 34 APPLY2 + 35 NEQ 36 BRANCHIFNOT 43 38 GETGLOBAL Not_found 40 MAKEBLOCK1 0 - 42 RAISE + 42 RAISE 43 POP 3 - 45 ATOM0 + 45 ATOM0 46 SETGLOBAL T254-offsetclosure - 48 STOP + 48 STOP **) diff --git a/testsuite/tests/tool-ocaml/t260-offsetref.ml b/testsuite/tests/tool-ocaml/t260-offsetref.ml index 968892ef..20dbf2c0 100644 --- a/testsuite/tests/tool-ocaml/t260-offsetref.ml +++ b/testsuite/tests/tool-ocaml/t260-offsetref.ml @@ -7,25 +7,25 @@ x (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 CONSTINT 32 11 MAKEBLOCK1 0 - 13 PUSHACC0 + 13 PUSHACC0 14 OFFSETREF 1 16 CONSTINT 33 - 18 PUSHACC1 - 19 GETFIELD0 - 20 NEQ + 18 PUSHACC1 + 19 GETFIELD0 + 20 NEQ 21 BRANCHIFNOT 28 23 GETGLOBAL Not_found 25 MAKEBLOCK1 0 - 27 RAISE - 28 ACC0 + 27 RAISE + 28 ACC0 29 POP 1 - 31 ATOM0 + 31 ATOM0 32 SETGLOBAL T260-offsetref - 34 STOP + 34 STOP **) diff --git a/testsuite/tests/tool-ocaml/t270-push_retaddr.ml b/testsuite/tests/tool-ocaml/t270-push_retaddr.ml index 0c7fb369..2c13f225 100644 --- a/testsuite/tests/tool-ocaml/t270-push_retaddr.ml +++ b/testsuite/tests/tool-ocaml/t270-push_retaddr.ml @@ -5,32 +5,32 @@ if f 0 1 2 3 <> 123 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 18 - 11 RESTART + 11 RESTART 12 GRAB 3 14 CONSTINT 123 16 RETURN 4 18 CLOSURE 0, 12 21 PUSHCONSTINT 123 - 23 PUSH + 23 PUSH 24 PUSH_RETADDR 34 - 26 CONST3 - 27 PUSHCONST2 - 28 PUSHCONST1 - 29 PUSHCONST0 + 26 CONST3 + 27 PUSHCONST2 + 28 PUSHCONST1 + 29 PUSHCONST0 30 PUSHACC 8 32 APPLY 4 - 34 NEQ + 34 NEQ 35 BRANCHIFNOT 42 37 GETGLOBAL Not_found 39 MAKEBLOCK1 0 - 41 RAISE + 41 RAISE 42 POP 1 - 44 ATOM0 + 44 ATOM0 45 SETGLOBAL T270-push_retaddr - 47 STOP + 47 STOP **) diff --git a/testsuite/tests/tool-ocaml/t300-getmethod.ml b/testsuite/tests/tool-ocaml/t300-getmethod.ml index e7894735..8108e801 100644 --- a/testsuite/tests/tool-ocaml/t300-getmethod.ml +++ b/testsuite/tests/tool-ocaml/t300-getmethod.ml @@ -10,599 +10,599 @@ if o#m <> 23 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -647,67 +647,67 @@ if o#m <> 23 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -751,38 +751,38 @@ if o#m <> 23 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -790,696 +790,696 @@ if o#m <> 23 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1502,9 +1502,9 @@ if o#m <> 23 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1543,729 +1543,729 @@ if o#m <> 23 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 3341 - 2406 RESTART + 2406 RESTART 2407 GRAB 2 - 2409 ACC2 - 2410 PUSHACC2 - 2411 VECTLENGTH + 2409 ACC2 + 2410 PUSHACC2 + 2411 VECTLENGTH 2412 OFFSETINT -1 - 2414 PUSHCONST0 - 2415 PUSH + 2414 PUSHCONST0 + 2415 PUSH 2416 BRANCH 2433 - 2418 CHECK_SIGNALS - 2419 ACC2 - 2420 PUSHACC2 - 2421 PUSHACC6 + 2418 CHECK_SIGNALS + 2419 ACC2 + 2420 PUSHACC2 + 2421 PUSHACC6 2422 C_CALL2 array_unsafe_get - 2424 PUSHACC5 - 2425 APPLY2 + 2424 PUSHACC5 + 2425 APPLY2 2426 ASSIGN 2 - 2428 ACC1 + 2428 ACC1 2429 OFFSETINT -1 2431 ASSIGN 1 - 2433 ACC0 - 2434 PUSHACC2 - 2435 GEINT + 2433 ACC0 + 2434 PUSHACC2 + 2435 GEINT 2436 BRANCHIF 2418 - 2438 CONST0 + 2438 CONST0 2439 POP 2 - 2441 ACC0 + 2441 ACC0 2442 RETURN 4 - 2444 RESTART + 2444 RESTART 2445 GRAB 2 - 2447 ACC1 - 2448 PUSHCONST0 - 2449 PUSHACC4 - 2450 VECTLENGTH + 2447 ACC1 + 2448 PUSHCONST0 + 2449 PUSHACC4 + 2450 VECTLENGTH 2451 OFFSETINT -1 - 2453 PUSH + 2453 PUSH 2454 BRANCH 2471 - 2456 CHECK_SIGNALS - 2457 ACC1 - 2458 PUSHACC6 + 2456 CHECK_SIGNALS + 2457 ACC1 + 2458 PUSHACC6 2459 C_CALL2 array_unsafe_get - 2461 PUSHACC3 - 2462 PUSHACC5 - 2463 APPLY2 + 2461 PUSHACC3 + 2462 PUSHACC5 + 2463 APPLY2 2464 ASSIGN 2 - 2466 ACC1 + 2466 ACC1 2467 OFFSETINT 1 2469 ASSIGN 1 - 2471 ACC0 - 2472 PUSHACC2 - 2473 LEINT + 2471 ACC0 + 2472 PUSHACC2 + 2473 LEINT 2474 BRANCHIF 2456 - 2476 CONST0 + 2476 CONST0 2477 POP 2 - 2479 ACC0 + 2479 ACC0 2480 RETURN 4 - 2482 RESTART + 2482 RESTART 2483 GRAB 1 - 2485 ACC1 + 2485 ACC1 2486 BRANCHIFNOT 2502 - 2488 ACC1 - 2489 GETFIELD0 - 2490 PUSHACC1 - 2491 PUSHENVACC1 + 2488 ACC1 + 2489 GETFIELD0 + 2490 PUSHACC1 + 2491 PUSHENVACC1 2492 C_CALL3 array_unsafe_set - 2494 ACC1 - 2495 GETFIELD1 - 2496 PUSHACC1 + 2494 ACC1 + 2495 GETFIELD1 + 2496 PUSHACC1 2497 OFFSETINT 1 - 2499 PUSHOFFSETCLOSURE0 + 2499 PUSHOFFSETCLOSURE0 2500 APPTERM2 4 - 2502 ENVACC1 + 2502 ENVACC1 2503 RETURN 2 - 2505 ACC0 + 2505 ACC0 2506 BRANCHIFNOT 2531 - 2508 ACC0 - 2509 GETFIELD1 - 2510 PUSHACC1 - 2511 GETFIELD0 - 2512 PUSHACC1 + 2508 ACC0 + 2509 GETFIELD1 + 2510 PUSHACC1 + 2511 GETFIELD0 + 2512 PUSHACC1 2513 PUSHGETGLOBALFIELD List, 0 - 2516 APPLY1 + 2516 APPLY1 2517 OFFSETINT 1 2519 C_CALL2 make_vect - 2521 PUSHACC0 + 2521 PUSHACC0 2522 CLOSUREREC 1, 2483 - 2526 ACC2 - 2527 PUSHCONST1 - 2528 PUSHACC2 + 2526 ACC2 + 2527 PUSHCONST1 + 2528 PUSHACC2 2529 APPTERM2 6 - 2531 ATOM0 + 2531 ATOM0 2532 RETURN 1 - 2534 RESTART + 2534 RESTART 2535 GRAB 1 - 2537 CONST0 - 2538 PUSHACC1 - 2539 LTINT + 2537 CONST0 + 2538 PUSHACC1 + 2539 LTINT 2540 BRANCHIFNOT 2545 - 2542 ACC1 + 2542 ACC1 2543 RETURN 2 - 2545 ACC1 - 2546 PUSHACC1 - 2547 PUSHENVACC1 + 2545 ACC1 + 2546 PUSHACC1 + 2547 PUSHENVACC1 2548 C_CALL2 array_unsafe_get 2550 MAKEBLOCK2 0 - 2552 PUSHACC1 + 2552 PUSHACC1 2553 OFFSETINT -1 - 2555 PUSHOFFSETCLOSURE0 + 2555 PUSHOFFSETCLOSURE0 2556 APPTERM2 4 - 2558 ACC0 + 2558 ACC0 2559 CLOSUREREC 1, 2535 - 2563 CONST0 - 2564 PUSHACC2 - 2565 VECTLENGTH + 2563 CONST0 + 2564 PUSHACC2 + 2565 VECTLENGTH 2566 OFFSETINT -1 - 2568 PUSHACC2 + 2568 PUSHACC2 2569 APPTERM2 4 - 2571 RESTART + 2571 RESTART 2572 GRAB 1 - 2574 ACC1 - 2575 VECTLENGTH - 2576 PUSHCONST0 - 2577 PUSHACC1 - 2578 EQ + 2574 ACC1 + 2575 VECTLENGTH + 2576 PUSHCONST0 + 2577 PUSHACC1 + 2578 EQ 2579 BRANCHIFNOT 2584 - 2581 ATOM0 + 2581 ATOM0 2582 RETURN 3 - 2584 CONST0 - 2585 PUSHACC3 + 2584 CONST0 + 2585 PUSHACC3 2586 C_CALL2 array_unsafe_get - 2588 PUSHCONST0 - 2589 PUSHACC3 - 2590 APPLY2 - 2591 PUSHACC1 + 2588 PUSHCONST0 + 2589 PUSHACC3 + 2590 APPLY2 + 2591 PUSHACC1 2592 C_CALL2 make_vect - 2594 PUSHCONST1 - 2595 PUSHACC2 + 2594 PUSHCONST1 + 2595 PUSHACC2 2596 OFFSETINT -1 - 2598 PUSH + 2598 PUSH 2599 BRANCH 2618 - 2601 CHECK_SIGNALS - 2602 ACC1 - 2603 PUSHACC6 + 2601 CHECK_SIGNALS + 2602 ACC1 + 2603 PUSHACC6 2604 C_CALL2 array_unsafe_get - 2606 PUSHACC2 - 2607 PUSHACC6 - 2608 APPLY2 - 2609 PUSHACC2 - 2610 PUSHACC4 + 2606 PUSHACC2 + 2607 PUSHACC6 + 2608 APPLY2 + 2609 PUSHACC2 + 2610 PUSHACC4 2611 C_CALL3 array_unsafe_set - 2613 ACC1 + 2613 ACC1 2614 OFFSETINT 1 2616 ASSIGN 1 - 2618 ACC0 - 2619 PUSHACC2 - 2620 LEINT + 2618 ACC0 + 2619 PUSHACC2 + 2620 LEINT 2621 BRANCHIF 2601 - 2623 CONST0 + 2623 CONST0 2624 POP 2 - 2626 ACC0 + 2626 ACC0 2627 RETURN 4 - 2629 RESTART + 2629 RESTART 2630 GRAB 1 - 2632 CONST0 - 2633 PUSHACC2 - 2634 VECTLENGTH + 2632 CONST0 + 2633 PUSHACC2 + 2634 VECTLENGTH 2635 OFFSETINT -1 - 2637 PUSH + 2637 PUSH 2638 BRANCH 2653 - 2640 CHECK_SIGNALS - 2641 ACC1 - 2642 PUSHACC4 + 2640 CHECK_SIGNALS + 2641 ACC1 + 2642 PUSHACC4 2643 C_CALL2 array_unsafe_get - 2645 PUSHACC2 - 2646 PUSHACC4 - 2647 APPLY2 - 2648 ACC1 + 2645 PUSHACC2 + 2646 PUSHACC4 + 2647 APPLY2 + 2648 ACC1 2649 OFFSETINT 1 2651 ASSIGN 1 - 2653 ACC0 - 2654 PUSHACC2 - 2655 LEINT + 2653 ACC0 + 2654 PUSHACC2 + 2655 LEINT 2656 BRANCHIF 2640 - 2658 CONST0 + 2658 CONST0 2659 RETURN 4 - 2661 RESTART + 2661 RESTART 2662 GRAB 1 - 2664 ACC1 - 2665 VECTLENGTH - 2666 PUSHCONST0 - 2667 PUSHACC1 - 2668 EQ + 2664 ACC1 + 2665 VECTLENGTH + 2666 PUSHCONST0 + 2667 PUSHACC1 + 2668 EQ 2669 BRANCHIFNOT 2674 - 2671 ATOM0 + 2671 ATOM0 2672 RETURN 3 - 2674 CONST0 - 2675 PUSHACC3 + 2674 CONST0 + 2675 PUSHACC3 2676 C_CALL2 array_unsafe_get - 2678 PUSHACC2 - 2679 APPLY1 - 2680 PUSHACC1 + 2678 PUSHACC2 + 2679 APPLY1 + 2680 PUSHACC1 2681 C_CALL2 make_vect - 2683 PUSHCONST1 - 2684 PUSHACC2 + 2683 PUSHCONST1 + 2684 PUSHACC2 2685 OFFSETINT -1 - 2687 PUSH + 2687 PUSH 2688 BRANCH 2706 - 2690 CHECK_SIGNALS - 2691 ACC1 - 2692 PUSHACC6 + 2690 CHECK_SIGNALS + 2691 ACC1 + 2692 PUSHACC6 2693 C_CALL2 array_unsafe_get - 2695 PUSHACC5 - 2696 APPLY1 - 2697 PUSHACC2 - 2698 PUSHACC4 + 2695 PUSHACC5 + 2696 APPLY1 + 2697 PUSHACC2 + 2698 PUSHACC4 2699 C_CALL3 array_unsafe_set - 2701 ACC1 + 2701 ACC1 2702 OFFSETINT 1 2704 ASSIGN 1 - 2706 ACC0 - 2707 PUSHACC2 - 2708 LEINT + 2706 ACC0 + 2707 PUSHACC2 + 2708 LEINT 2709 BRANCHIF 2690 - 2711 CONST0 + 2711 CONST0 2712 POP 2 - 2714 ACC0 + 2714 ACC0 2715 RETURN 4 - 2717 RESTART + 2717 RESTART 2718 GRAB 1 - 2720 CONST0 - 2721 PUSHACC2 - 2722 VECTLENGTH + 2720 CONST0 + 2721 PUSHACC2 + 2722 VECTLENGTH 2723 OFFSETINT -1 - 2725 PUSH + 2725 PUSH 2726 BRANCH 2740 - 2728 CHECK_SIGNALS - 2729 ACC1 - 2730 PUSHACC4 + 2728 CHECK_SIGNALS + 2729 ACC1 + 2730 PUSHACC4 2731 C_CALL2 array_unsafe_get - 2733 PUSHACC3 - 2734 APPLY1 - 2735 ACC1 + 2733 PUSHACC3 + 2734 APPLY1 + 2735 ACC1 2736 OFFSETINT 1 2738 ASSIGN 1 - 2740 ACC0 - 2741 PUSHACC2 - 2742 LEINT + 2740 ACC0 + 2741 PUSHACC2 + 2742 LEINT 2743 BRANCHIF 2728 - 2745 CONST0 + 2745 CONST0 2746 RETURN 4 - 2748 RESTART + 2748 RESTART 2749 GRAB 4 - 2751 CONST0 - 2752 PUSHACC5 - 2753 LTINT + 2751 CONST0 + 2752 PUSHACC5 + 2753 LTINT 2754 BRANCHIF 2782 - 2756 CONST0 - 2757 PUSHACC2 - 2758 LTINT + 2756 CONST0 + 2757 PUSHACC2 + 2758 LTINT 2759 BRANCHIF 2782 - 2761 ACC0 - 2762 VECTLENGTH - 2763 PUSHACC5 - 2764 PUSHACC3 - 2765 ADDINT - 2766 GTINT + 2761 ACC0 + 2762 VECTLENGTH + 2763 PUSHACC5 + 2764 PUSHACC3 + 2765 ADDINT + 2766 GTINT 2767 BRANCHIF 2782 - 2769 CONST0 - 2770 PUSHACC4 - 2771 LTINT + 2769 CONST0 + 2770 PUSHACC4 + 2771 LTINT 2772 BRANCHIF 2782 - 2774 ACC2 - 2775 VECTLENGTH - 2776 PUSHACC5 - 2777 PUSHACC5 - 2778 ADDINT - 2779 GTINT + 2774 ACC2 + 2775 VECTLENGTH + 2776 PUSHACC5 + 2777 PUSHACC5 + 2778 ADDINT + 2779 GTINT 2780 BRANCHIFNOT 2789 2782 GETGLOBAL "Array.blit" 2784 PUSHGETGLOBALFIELD Pervasives, 2 2787 APPTERM1 6 - 2789 ACC3 - 2790 PUSHACC2 - 2791 LTINT + 2789 ACC3 + 2790 PUSHACC2 + 2791 LTINT 2792 BRANCHIFNOT 2827 - 2794 ACC4 + 2794 ACC4 2795 OFFSETINT -1 - 2797 PUSHCONST0 - 2798 PUSH + 2797 PUSHCONST0 + 2798 PUSH 2799 BRANCH 2819 - 2801 CHECK_SIGNALS - 2802 ACC1 - 2803 PUSHACC4 - 2804 ADDINT - 2805 PUSHACC3 + 2801 CHECK_SIGNALS + 2802 ACC1 + 2803 PUSHACC4 + 2804 ADDINT + 2805 PUSHACC3 2806 C_CALL2 array_unsafe_get - 2808 PUSHACC2 - 2809 PUSHACC7 - 2810 ADDINT - 2811 PUSHACC6 + 2808 PUSHACC2 + 2809 PUSHACC7 + 2810 ADDINT + 2811 PUSHACC6 2812 C_CALL3 array_unsafe_set - 2814 ACC1 + 2814 ACC1 2815 OFFSETINT -1 2817 ASSIGN 1 - 2819 ACC0 - 2820 PUSHACC2 - 2821 GEINT + 2819 ACC0 + 2820 PUSHACC2 + 2821 GEINT 2822 BRANCHIF 2801 - 2824 CONST0 + 2824 CONST0 2825 RETURN 7 - 2827 CONST0 - 2828 PUSHACC5 + 2827 CONST0 + 2828 PUSHACC5 2829 OFFSETINT -1 - 2831 PUSH + 2831 PUSH 2832 BRANCH 2852 - 2834 CHECK_SIGNALS - 2835 ACC1 - 2836 PUSHACC4 - 2837 ADDINT - 2838 PUSHACC3 + 2834 CHECK_SIGNALS + 2835 ACC1 + 2836 PUSHACC4 + 2837 ADDINT + 2838 PUSHACC3 2839 C_CALL2 array_unsafe_get - 2841 PUSHACC2 - 2842 PUSHACC7 - 2843 ADDINT - 2844 PUSHACC6 + 2841 PUSHACC2 + 2842 PUSHACC7 + 2843 ADDINT + 2844 PUSHACC6 2845 C_CALL3 array_unsafe_set - 2847 ACC1 + 2847 ACC1 2848 OFFSETINT 1 2850 ASSIGN 1 - 2852 ACC0 - 2853 PUSHACC2 - 2854 LEINT + 2852 ACC0 + 2853 PUSHACC2 + 2854 LEINT 2855 BRANCHIF 2834 - 2857 CONST0 + 2857 CONST0 2858 RETURN 7 - 2860 RESTART + 2860 RESTART 2861 GRAB 3 - 2863 CONST0 - 2864 PUSHACC2 - 2865 LTINT + 2863 CONST0 + 2864 PUSHACC2 + 2865 LTINT 2866 BRANCHIF 2881 - 2868 CONST0 - 2869 PUSHACC3 - 2870 LTINT + 2868 CONST0 + 2869 PUSHACC3 + 2870 LTINT 2871 BRANCHIF 2881 - 2873 ACC0 - 2874 VECTLENGTH - 2875 PUSHACC3 - 2876 PUSHACC3 - 2877 ADDINT - 2878 GTINT + 2873 ACC0 + 2874 VECTLENGTH + 2875 PUSHACC3 + 2876 PUSHACC3 + 2877 ADDINT + 2878 GTINT 2879 BRANCHIFNOT 2888 2881 GETGLOBAL "Array.fill" 2883 PUSHGETGLOBALFIELD Pervasives, 2 2886 APPTERM1 5 - 2888 ACC1 - 2889 PUSHACC3 - 2890 PUSHACC3 - 2891 ADDINT + 2888 ACC1 + 2889 PUSHACC3 + 2890 PUSHACC3 + 2891 ADDINT 2892 OFFSETINT -1 - 2894 PUSH + 2894 PUSH 2895 BRANCH 2908 - 2897 CHECK_SIGNALS - 2898 ACC5 - 2899 PUSHACC2 - 2900 PUSHACC4 + 2897 CHECK_SIGNALS + 2898 ACC5 + 2899 PUSHACC2 + 2900 PUSHACC4 2901 C_CALL3 array_unsafe_set - 2903 ACC1 + 2903 ACC1 2904 OFFSETINT 1 2906 ASSIGN 1 - 2908 ACC0 - 2909 PUSHACC2 - 2910 LEINT + 2908 ACC0 + 2909 PUSHACC2 + 2910 LEINT 2911 BRANCHIF 2897 - 2913 CONST0 + 2913 CONST0 2914 RETURN 6 - 2916 RESTART + 2916 RESTART 2917 GRAB 2 - 2919 CONST0 - 2920 PUSHACC2 - 2921 LTINT + 2919 CONST0 + 2920 PUSHACC2 + 2921 LTINT 2922 BRANCHIF 2937 - 2924 CONST0 - 2925 PUSHACC3 - 2926 LTINT + 2924 CONST0 + 2925 PUSHACC3 + 2926 LTINT 2927 BRANCHIF 2937 - 2929 ACC0 - 2930 VECTLENGTH - 2931 PUSHACC3 - 2932 PUSHACC3 - 2933 ADDINT - 2934 GTINT + 2929 ACC0 + 2930 VECTLENGTH + 2931 PUSHACC3 + 2932 PUSHACC3 + 2933 ADDINT + 2934 GTINT 2935 BRANCHIFNOT 2944 2937 GETGLOBAL "Array.sub" 2939 PUSHGETGLOBALFIELD Pervasives, 2 2942 APPTERM1 4 - 2944 CONST0 - 2945 PUSHACC3 - 2946 EQ + 2944 CONST0 + 2945 PUSHACC3 + 2946 EQ 2947 BRANCHIFNOT 2952 - 2949 ATOM0 + 2949 ATOM0 2950 RETURN 3 - 2952 ACC1 - 2953 PUSHACC1 + 2952 ACC1 + 2953 PUSHACC1 2954 C_CALL2 array_unsafe_get - 2956 PUSHACC3 + 2956 PUSHACC3 2957 C_CALL2 make_vect - 2959 PUSHCONST1 - 2960 PUSHACC4 + 2959 PUSHCONST1 + 2960 PUSHACC4 2961 OFFSETINT -1 - 2963 PUSH + 2963 PUSH 2964 BRANCH 2982 - 2966 CHECK_SIGNALS - 2967 ACC1 - 2968 PUSHACC5 - 2969 ADDINT - 2970 PUSHACC4 + 2966 CHECK_SIGNALS + 2967 ACC1 + 2968 PUSHACC5 + 2969 ADDINT + 2970 PUSHACC4 2971 C_CALL2 array_unsafe_get - 2973 PUSHACC2 - 2974 PUSHACC4 + 2973 PUSHACC2 + 2974 PUSHACC4 2975 C_CALL3 array_unsafe_set - 2977 ACC1 + 2977 ACC1 2978 OFFSETINT 1 2980 ASSIGN 1 - 2982 ACC0 - 2983 PUSHACC2 - 2984 LEINT + 2982 ACC0 + 2983 PUSHACC2 + 2984 LEINT 2985 BRANCHIF 2966 - 2987 CONST0 + 2987 CONST0 2988 POP 2 - 2990 ACC0 + 2990 ACC0 2991 RETURN 4 - 2993 ACC0 + 2993 ACC0 2994 BRANCHIFNOT 3017 - 2996 ACC0 - 2997 GETFIELD0 - 2998 PUSHCONST0 - 2999 PUSHACC1 - 3000 VECTLENGTH - 3001 GTINT + 2996 ACC0 + 2997 GETFIELD0 + 2998 PUSHCONST0 + 2999 PUSHACC1 + 3000 VECTLENGTH + 3001 GTINT 3002 BRANCHIFNOT 3012 - 3004 ENVACC2 - 3005 PUSHCONST0 - 3006 PUSHACC2 + 3004 ENVACC2 + 3005 PUSHCONST0 + 3006 PUSHACC2 3007 C_CALL2 array_unsafe_get - 3009 PUSHENVACC1 + 3009 PUSHENVACC1 3010 APPTERM2 4 - 3012 ACC1 - 3013 GETFIELD1 - 3014 PUSHOFFSETCLOSURE0 + 3012 ACC1 + 3013 GETFIELD1 + 3014 PUSHOFFSETCLOSURE0 3015 APPTERM1 3 - 3017 ATOM0 + 3017 ATOM0 3018 RETURN 1 - 3020 ACC0 - 3021 PUSHENVACC1 + 3020 ACC0 + 3021 PUSHENVACC1 3022 CLOSUREREC 2, 2993 - 3026 ACC1 - 3027 PUSHACC1 + 3026 ACC1 + 3027 PUSHACC1 3028 APPTERM1 3 - 3030 CONST0 - 3031 PUSHACC1 - 3032 VECTLENGTH + 3030 CONST0 + 3031 PUSHACC1 + 3032 VECTLENGTH 3033 OFFSETINT -1 - 3035 PUSH + 3035 PUSH 3036 BRANCH 3056 - 3038 CHECK_SIGNALS - 3039 ACC1 - 3040 PUSHACC3 + 3038 CHECK_SIGNALS + 3039 ACC1 + 3040 PUSHACC3 3041 C_CALL2 array_unsafe_get - 3043 PUSHENVACC2 - 3044 GETFIELD0 - 3045 PUSHENVACC1 + 3043 PUSHENVACC2 + 3044 GETFIELD0 + 3045 PUSHENVACC1 3046 C_CALL3 array_unsafe_set - 3048 ENVACC2 + 3048 ENVACC2 3049 OFFSETREF 1 - 3051 ACC1 + 3051 ACC1 3052 OFFSETINT 1 3054 ASSIGN 1 - 3056 ACC0 - 3057 PUSHACC2 - 3058 LEINT + 3056 ACC0 + 3057 PUSHACC2 + 3058 LEINT 3059 BRANCHIF 3038 - 3061 CONST0 + 3061 CONST0 3062 RETURN 3 - 3064 RESTART + 3064 RESTART 3065 GRAB 1 - 3067 ACC1 - 3068 VECTLENGTH - 3069 PUSHACC1 - 3070 ADDINT + 3067 ACC1 + 3068 VECTLENGTH + 3069 PUSHACC1 + 3070 ADDINT 3071 RETURN 2 - 3073 RESTART + 3073 RESTART 3074 GRAB 1 - 3076 ACC1 - 3077 PUSHCONST0 - 3078 PUSH + 3076 ACC1 + 3077 PUSHCONST0 + 3078 PUSH 3079 CLOSURE 0, 3065 3082 PUSHGETGLOBALFIELD List, 12 - 3085 APPLY3 - 3086 PUSHACC1 - 3087 PUSHACC1 + 3085 APPLY3 + 3086 PUSHACC1 + 3087 PUSHACC1 3088 C_CALL2 make_vect - 3090 PUSHCONST0 + 3090 PUSHCONST0 3091 MAKEBLOCK1 0 - 3093 PUSHACC4 - 3094 PUSHACC1 - 3095 PUSHACC3 + 3093 PUSHACC4 + 3094 PUSHACC1 + 3095 PUSHACC3 3096 CLOSURE 2, 3030 3099 PUSHGETGLOBALFIELD List, 9 - 3102 APPLY2 - 3103 ACC1 + 3102 APPLY2 + 3103 ACC1 3104 RETURN 5 - 3106 RESTART + 3106 RESTART 3107 GRAB 1 - 3109 ACC0 - 3110 VECTLENGTH - 3111 PUSHACC2 - 3112 VECTLENGTH - 3113 PUSHCONST0 - 3114 PUSHACC2 - 3115 EQ + 3109 ACC0 + 3110 VECTLENGTH + 3111 PUSHACC2 + 3112 VECTLENGTH + 3113 PUSHCONST0 + 3114 PUSHACC2 + 3115 EQ 3116 BRANCHIFNOT 3126 - 3118 CONST0 - 3119 PUSHACC1 - 3120 EQ + 3118 CONST0 + 3119 PUSHACC1 + 3120 EQ 3121 BRANCHIFNOT 3126 - 3123 ATOM0 + 3123 ATOM0 3124 RETURN 4 - 3126 CONST0 - 3127 PUSHCONST0 - 3128 PUSHACC3 - 3129 GTINT + 3126 CONST0 + 3127 PUSHCONST0 + 3128 PUSHACC3 + 3129 GTINT 3130 BRANCHIFNOT 3135 - 3132 ACC3 + 3132 ACC3 3133 BRANCH 3136 - 3135 ACC4 + 3135 ACC4 3136 C_CALL2 array_unsafe_get - 3138 PUSHACC1 - 3139 PUSHACC3 - 3140 ADDINT + 3138 PUSHACC1 + 3139 PUSHACC3 + 3140 ADDINT 3141 C_CALL2 make_vect - 3143 PUSHCONST0 - 3144 PUSHACC3 + 3143 PUSHCONST0 + 3144 PUSHACC3 3145 OFFSETINT -1 - 3147 PUSH + 3147 PUSH 3148 BRANCH 3164 - 3150 CHECK_SIGNALS - 3151 ACC1 - 3152 PUSHACC6 + 3150 CHECK_SIGNALS + 3151 ACC1 + 3152 PUSHACC6 3153 C_CALL2 array_unsafe_get - 3155 PUSHACC2 - 3156 PUSHACC4 + 3155 PUSHACC2 + 3156 PUSHACC4 3157 C_CALL3 array_unsafe_set - 3159 ACC1 + 3159 ACC1 3160 OFFSETINT 1 3162 ASSIGN 1 - 3164 ACC0 - 3165 PUSHACC2 - 3166 LEINT + 3164 ACC0 + 3165 PUSHACC2 + 3166 LEINT 3167 BRANCHIF 3150 - 3169 CONST0 + 3169 CONST0 3170 POP 2 - 3172 CONST0 - 3173 PUSHACC2 + 3172 CONST0 + 3173 PUSHACC2 3174 OFFSETINT -1 - 3176 PUSH + 3176 PUSH 3177 BRANCH 3195 - 3179 CHECK_SIGNALS - 3180 ACC1 - 3181 PUSHACC7 + 3179 CHECK_SIGNALS + 3180 ACC1 + 3181 PUSHACC7 3182 C_CALL2 array_unsafe_get - 3184 PUSHACC5 - 3185 PUSHACC3 - 3186 ADDINT - 3187 PUSHACC4 + 3184 PUSHACC5 + 3185 PUSHACC3 + 3186 ADDINT + 3187 PUSHACC4 3188 C_CALL3 array_unsafe_set - 3190 ACC1 + 3190 ACC1 3191 OFFSETINT 1 3193 ASSIGN 1 - 3195 ACC0 - 3196 PUSHACC2 - 3197 LEINT + 3195 ACC0 + 3196 PUSHACC2 + 3197 LEINT 3198 BRANCHIF 3179 - 3200 CONST0 + 3200 CONST0 3201 POP 2 - 3203 ACC0 + 3203 ACC0 3204 RETURN 5 - 3206 ACC0 - 3207 VECTLENGTH - 3208 PUSHCONST0 - 3209 PUSHACC1 - 3210 EQ + 3206 ACC0 + 3207 VECTLENGTH + 3208 PUSHCONST0 + 3209 PUSHACC1 + 3210 EQ 3211 BRANCHIFNOT 3216 - 3213 ATOM0 + 3213 ATOM0 3214 RETURN 2 - 3216 CONST0 - 3217 PUSHACC2 + 3216 CONST0 + 3217 PUSHACC2 3218 C_CALL2 array_unsafe_get - 3220 PUSHACC1 + 3220 PUSHACC1 3221 C_CALL2 make_vect - 3223 PUSHCONST1 - 3224 PUSHACC2 + 3223 PUSHCONST1 + 3224 PUSHACC2 3225 OFFSETINT -1 - 3227 PUSH + 3227 PUSH 3228 BRANCH 3244 - 3230 CHECK_SIGNALS - 3231 ACC1 - 3232 PUSHACC5 + 3230 CHECK_SIGNALS + 3231 ACC1 + 3232 PUSHACC5 3233 C_CALL2 array_unsafe_get - 3235 PUSHACC2 - 3236 PUSHACC4 + 3235 PUSHACC2 + 3236 PUSHACC4 3237 C_CALL3 array_unsafe_set - 3239 ACC1 + 3239 ACC1 3240 OFFSETINT 1 3242 ASSIGN 1 - 3244 ACC0 - 3245 PUSHACC2 - 3246 LEINT + 3244 ACC0 + 3245 PUSHACC2 + 3246 LEINT 3247 BRANCHIF 3230 - 3249 CONST0 + 3249 CONST0 3250 POP 2 - 3252 ACC0 + 3252 ACC0 3253 RETURN 3 - 3255 RESTART + 3255 RESTART 3256 GRAB 2 - 3258 ATOM0 - 3259 PUSHACC1 + 3258 ATOM0 + 3259 PUSHACC1 3260 C_CALL2 make_vect - 3262 PUSHCONST0 - 3263 PUSHACC2 + 3262 PUSHCONST0 + 3263 PUSHACC2 3264 OFFSETINT -1 - 3266 PUSH + 3266 PUSH 3267 BRANCH 3282 - 3269 CHECK_SIGNALS - 3270 ACC5 - 3271 PUSHACC5 + 3269 CHECK_SIGNALS + 3270 ACC5 + 3271 PUSHACC5 3272 C_CALL2 make_vect - 3274 PUSHACC2 - 3275 PUSHACC4 - 3276 SETVECTITEM - 3277 ACC1 + 3274 PUSHACC2 + 3275 PUSHACC4 + 3276 SETVECTITEM + 3277 ACC1 3278 OFFSETINT 1 3280 ASSIGN 1 - 3282 ACC0 - 3283 PUSHACC2 - 3284 LEINT + 3282 ACC0 + 3283 PUSHACC2 + 3284 LEINT 3285 BRANCHIF 3269 - 3287 CONST0 + 3287 CONST0 3288 POP 2 - 3290 ACC0 + 3290 ACC0 3291 RETURN 4 - 3293 RESTART + 3293 RESTART 3294 GRAB 1 - 3296 CONST0 - 3297 PUSHACC1 - 3298 EQ + 3296 CONST0 + 3297 PUSHACC1 + 3298 EQ 3299 BRANCHIFNOT 3304 - 3301 ATOM0 + 3301 ATOM0 3302 RETURN 2 - 3304 CONST0 - 3305 PUSHACC2 - 3306 APPLY1 - 3307 PUSHACC1 + 3304 CONST0 + 3305 PUSHACC2 + 3306 APPLY1 + 3307 PUSHACC1 3308 C_CALL2 make_vect - 3310 PUSHCONST1 - 3311 PUSHACC2 + 3310 PUSHCONST1 + 3311 PUSHACC2 3312 OFFSETINT -1 - 3314 PUSH + 3314 PUSH 3315 BRANCH 3330 - 3317 CHECK_SIGNALS - 3318 ACC1 - 3319 PUSHACC5 - 3320 APPLY1 - 3321 PUSHACC2 - 3322 PUSHACC4 + 3317 CHECK_SIGNALS + 3318 ACC1 + 3319 PUSHACC5 + 3320 APPLY1 + 3321 PUSHACC2 + 3322 PUSHACC4 3323 C_CALL3 array_unsafe_set - 3325 ACC1 + 3325 ACC1 3326 OFFSETINT 1 3328 ASSIGN 1 - 3330 ACC0 - 3331 PUSHACC2 - 3332 LEINT + 3330 ACC0 + 3331 PUSHACC2 + 3332 LEINT 3333 BRANCHIF 3317 - 3335 CONST0 + 3335 CONST0 3336 POP 2 - 3338 ACC0 + 3338 ACC0 3339 RETURN 3 3341 CLOSURE 0, 3294 - 3344 PUSH + 3344 PUSH 3345 CLOSURE 0, 3256 - 3348 PUSH + 3348 PUSH 3349 CLOSURE 0, 3206 - 3352 PUSH + 3352 PUSH 3353 CLOSURE 0, 3107 - 3356 PUSH + 3356 PUSH 3357 CLOSURE 0, 3074 - 3360 PUSHACC0 + 3360 PUSHACC0 3361 CLOSURE 1, 3020 - 3364 PUSH + 3364 PUSH 3365 CLOSURE 0, 2917 - 3368 PUSH + 3368 PUSH 3369 CLOSURE 0, 2861 - 3372 PUSH + 3372 PUSH 3373 CLOSURE 0, 2749 - 3376 PUSH + 3376 PUSH 3377 CLOSURE 0, 2718 - 3380 PUSH + 3380 PUSH 3381 CLOSURE 0, 2662 - 3384 PUSH + 3384 PUSH 3385 CLOSURE 0, 2630 - 3388 PUSH + 3388 PUSH 3389 CLOSURE 0, 2572 - 3392 PUSH + 3392 PUSH 3393 CLOSURE 0, 2558 - 3396 PUSH + 3396 PUSH 3397 CLOSURE 0, 2505 - 3400 PUSH + 3400 PUSH 3401 CLOSURE 0, 2445 - 3404 PUSH + 3404 PUSH 3405 CLOSURE 0, 2407 - 3408 PUSHACC0 - 3409 PUSHACC2 - 3410 PUSHACC6 + 3408 PUSHACC0 + 3409 PUSHACC2 + 3410 PUSHACC6 3411 PUSHACC 8 3413 PUSHACC 10 3415 PUSHACC 12 @@ -2284,48 +2284,48 @@ if o#m <> 23 then raise Not_found 3442 POP 17 3444 SETGLOBAL Array 3446 BRANCH 3480 - 3448 ENVACC1 + 3448 ENVACC1 3449 MAKEBLOCK1 0 - 3451 RAISE - 3452 ACC0 + 3451 RAISE + 3452 ACC0 3453 BRANCHIFNOT 3465 - 3455 ENVACC3 + 3455 ENVACC3 3456 CLOSURE 1, 3448 3459 MAKEBLOCK1 0 - 3461 PUSHENVACC2 - 3462 PUSHENVACC1 + 3461 PUSHENVACC2 + 3462 PUSHENVACC1 3463 APPTERM2 3 - 3465 CONST0 - 3466 PUSHENVACC2 - 3467 PUSHENVACC1 + 3465 CONST0 + 3466 PUSHENVACC2 + 3467 PUSHENVACC1 3468 APPTERM2 3 - 3470 RESTART + 3470 RESTART 3471 GRAB 1 - 3473 ACC1 - 3474 PUSHACC1 + 3473 ACC1 + 3474 PUSHACC1 3475 C_CALL2 install_signal_handler - 3477 CONST0 + 3477 CONST0 3478 RETURN 2 - 3480 CONST0 + 3480 CONST0 3481 C_CALL1 sys_get_argv - 3483 PUSHCONST0 + 3483 PUSHCONST0 3484 C_CALL1 sys_get_config - 3486 PUSHACC0 - 3487 GETFIELD1 - 3488 PUSHACC0 + 3486 PUSHACC0 + 3487 GETFIELD1 + 3488 PUSHACC0 3489 OFFSETINT -10 - 3491 PUSHCONST1 - 3492 LSLINT + 3491 PUSHCONST1 + 3492 LSLINT 3493 OFFSETINT -1 - 3495 PUSHACC0 + 3495 PUSHACC0 3496 PUSHCONSTINT 8 - 3498 PUSHACC3 - 3499 DIVINT - 3500 MULINT + 3498 PUSHACC3 + 3499 DIVINT + 3500 MULINT 3501 OFFSETINT -1 - 3503 PUSHCONST0 + 3503 PUSHCONST0 3504 MAKEBLOCK1 0 - 3506 PUSH + 3506 PUSH 3507 CLOSURE 0, 3471 3510 PUSHCONSTINT -1 3512 PUSHCONSTINT -2 @@ -2350,14 +2350,14 @@ if o#m <> 23 then raise Not_found 3550 PUSHCONSTINT -21 3552 PUSHGETGLOBAL "Sys.Break" 3554 MAKEBLOCK1 0 - 3556 PUSHACC0 + 3556 PUSHACC0 3557 PUSHACC 17 3559 PUSHACC 24 3561 CLOSURE 3, 3452 - 3564 PUSHACC0 - 3565 PUSHACC2 - 3566 PUSHACC4 - 3567 PUSHACC6 + 3564 PUSHACC0 + 3565 PUSHACC2 + 3566 PUSHACC4 + 3567 PUSHACC6 3568 PUSHACC 8 3570 PUSHACC 10 3572 PUSHACC 12 @@ -2382,703 +2382,703 @@ if o#m <> 23 then raise Not_found 3610 PUSHACC 50 3612 PUSHACC 53 3614 PUSHACC 55 - 3616 GETFIELD0 + 3616 GETFIELD0 3617 PUSHACC 52 3619 PUSHACC 58 3621 MAKEBLOCK 30, 0 3624 POP 30 3626 SETGLOBAL Sys 3628 BRANCH 4510 - 3630 RESTART + 3630 RESTART 3631 GRAB 1 - 3633 CONST0 - 3634 PUSHACC1 - 3635 LTINT + 3633 CONST0 + 3634 PUSHACC1 + 3635 LTINT 3636 BRANCHIFNOT 3641 - 3638 CONST1 + 3638 CONST1 3639 RETURN 2 - 3641 ACC1 + 3641 ACC1 3642 BRANCHIFNOT 3652 - 3644 ACC1 - 3645 GETFIELD2 - 3646 PUSHACC1 + 3644 ACC1 + 3645 GETFIELD2 + 3646 PUSHACC1 3647 OFFSETINT -1 - 3649 PUSHOFFSETCLOSURE0 + 3649 PUSHOFFSETCLOSURE0 3650 APPTERM2 4 3652 RETURN 2 - 3654 ACC0 + 3654 ACC0 3655 BRANCHIFNOT 3670 - 3657 ENVACC2 - 3658 PUSHACC1 - 3659 GETFIELD0 - 3660 PUSHENVACC1 - 3661 GETFIELD0 - 3662 APPLY2 + 3657 ENVACC2 + 3658 PUSHACC1 + 3659 GETFIELD0 + 3660 PUSHENVACC1 + 3661 GETFIELD0 + 3662 APPLY2 3663 BRANCHIF 3670 - 3665 ACC0 - 3666 GETFIELD2 - 3667 PUSHOFFSETCLOSURE0 + 3665 ACC0 + 3666 GETFIELD2 + 3667 PUSHOFFSETCLOSURE0 3668 APPTERM1 2 3670 RETURN 1 - 3672 RESTART + 3672 RESTART 3673 GRAB 1 - 3675 ACC1 - 3676 PUSHENVACC1 + 3675 ACC1 + 3676 PUSHENVACC1 3677 CLOSUREREC 2, 3654 - 3681 ACC1 - 3682 GETFIELD1 - 3683 VECTLENGTH - 3684 PUSHACC3 - 3685 PUSHENVACC1 - 3686 GETFIELD1 - 3687 APPLY1 - 3688 MODINT - 3689 PUSHACC2 - 3690 GETFIELD1 + 3681 ACC1 + 3682 GETFIELD1 + 3683 VECTLENGTH + 3684 PUSHACC3 + 3685 PUSHENVACC1 + 3686 GETFIELD1 + 3687 APPLY1 + 3688 MODINT + 3689 PUSHACC2 + 3690 GETFIELD1 3691 C_CALL2 array_get_addr - 3693 PUSHACC1 + 3693 PUSHACC1 3694 APPTERM1 4 - 3696 ACC0 + 3696 ACC0 3697 BRANCHIFNOT 3722 - 3699 ACC0 - 3700 GETFIELD2 - 3701 PUSHENVACC2 - 3702 PUSHACC2 - 3703 GETFIELD0 - 3704 PUSHENVACC1 - 3705 GETFIELD0 - 3706 APPLY2 + 3699 ACC0 + 3700 GETFIELD2 + 3701 PUSHENVACC2 + 3702 PUSHACC2 + 3703 GETFIELD0 + 3704 PUSHENVACC1 + 3705 GETFIELD0 + 3706 APPLY2 3707 BRANCHIFNOT 3718 - 3709 ACC0 - 3710 PUSHOFFSETCLOSURE0 - 3711 APPLY1 - 3712 PUSHACC2 - 3713 GETFIELD1 + 3709 ACC0 + 3710 PUSHOFFSETCLOSURE0 + 3711 APPLY1 + 3712 PUSHACC2 + 3713 GETFIELD1 3714 MAKEBLOCK2 0 3716 RETURN 2 - 3718 ACC0 - 3719 PUSHOFFSETCLOSURE0 + 3718 ACC0 + 3719 PUSHOFFSETCLOSURE0 3720 APPTERM1 3 3722 RETURN 1 - 3724 RESTART + 3724 RESTART 3725 GRAB 1 - 3727 ACC1 - 3728 PUSHENVACC1 + 3727 ACC1 + 3728 PUSHENVACC1 3729 CLOSUREREC 2, 3696 - 3733 ACC1 - 3734 GETFIELD1 - 3735 VECTLENGTH - 3736 PUSHACC3 - 3737 PUSHENVACC1 - 3738 GETFIELD1 - 3739 APPLY1 - 3740 MODINT - 3741 PUSHACC2 - 3742 GETFIELD1 + 3733 ACC1 + 3734 GETFIELD1 + 3735 VECTLENGTH + 3736 PUSHACC3 + 3737 PUSHENVACC1 + 3738 GETFIELD1 + 3739 APPLY1 + 3740 MODINT + 3741 PUSHACC2 + 3742 GETFIELD1 3743 C_CALL2 array_get_addr - 3745 PUSHACC1 + 3745 PUSHACC1 3746 APPTERM1 4 - 3748 ACC0 + 3748 ACC0 3749 BRANCHIFNOT 3768 - 3751 ACC0 - 3752 GETFIELD0 - 3753 PUSHENVACC2 - 3754 PUSHENVACC1 - 3755 GETFIELD0 - 3756 APPLY2 + 3751 ACC0 + 3752 GETFIELD0 + 3753 PUSHENVACC2 + 3754 PUSHENVACC1 + 3755 GETFIELD0 + 3756 APPLY2 3757 BRANCHIFNOT 3763 - 3759 ACC0 - 3760 GETFIELD1 + 3759 ACC0 + 3760 GETFIELD1 3761 RETURN 1 - 3763 ACC0 - 3764 GETFIELD2 - 3765 PUSHOFFSETCLOSURE0 + 3763 ACC0 + 3764 GETFIELD2 + 3765 PUSHOFFSETCLOSURE0 3766 APPTERM1 2 3768 GETGLOBAL Not_found 3770 MAKEBLOCK1 0 - 3772 RAISE - 3773 RESTART + 3772 RAISE + 3773 RESTART 3774 GRAB 1 - 3776 ACC0 - 3777 GETFIELD1 - 3778 VECTLENGTH - 3779 PUSHACC2 - 3780 PUSHENVACC1 - 3781 GETFIELD1 - 3782 APPLY1 - 3783 MODINT - 3784 PUSHACC1 - 3785 GETFIELD1 + 3776 ACC0 + 3777 GETFIELD1 + 3778 VECTLENGTH + 3779 PUSHACC2 + 3780 PUSHENVACC1 + 3781 GETFIELD1 + 3782 APPLY1 + 3783 MODINT + 3784 PUSHACC1 + 3785 GETFIELD1 3786 C_CALL2 array_get_addr - 3788 PUSHACC0 + 3788 PUSHACC0 3789 BRANCHIFNOT 3858 - 3791 ACC0 - 3792 GETFIELD2 - 3793 PUSHACC1 - 3794 GETFIELD0 - 3795 PUSHACC4 - 3796 PUSHENVACC1 - 3797 GETFIELD0 - 3798 APPLY2 + 3791 ACC0 + 3792 GETFIELD2 + 3793 PUSHACC1 + 3794 GETFIELD0 + 3795 PUSHACC4 + 3796 PUSHENVACC1 + 3797 GETFIELD0 + 3798 APPLY2 3799 BRANCHIFNOT 3805 - 3801 ACC1 - 3802 GETFIELD1 + 3801 ACC1 + 3802 GETFIELD1 3803 RETURN 4 - 3805 ACC0 + 3805 ACC0 3806 BRANCHIFNOT 3853 - 3808 ACC0 - 3809 GETFIELD2 - 3810 PUSHACC1 - 3811 GETFIELD0 - 3812 PUSHACC5 - 3813 PUSHENVACC1 - 3814 GETFIELD0 - 3815 APPLY2 + 3808 ACC0 + 3809 GETFIELD2 + 3810 PUSHACC1 + 3811 GETFIELD0 + 3812 PUSHACC5 + 3813 PUSHENVACC1 + 3814 GETFIELD0 + 3815 APPLY2 3816 BRANCHIFNOT 3822 - 3818 ACC1 - 3819 GETFIELD1 + 3818 ACC1 + 3819 GETFIELD1 3820 RETURN 5 - 3822 ACC0 + 3822 ACC0 3823 BRANCHIFNOT 3848 - 3825 ACC0 - 3826 GETFIELD0 - 3827 PUSHACC5 - 3828 PUSHENVACC1 - 3829 GETFIELD0 - 3830 APPLY2 + 3825 ACC0 + 3826 GETFIELD0 + 3827 PUSHACC5 + 3828 PUSHENVACC1 + 3829 GETFIELD0 + 3830 APPLY2 3831 BRANCHIFNOT 3837 - 3833 ACC0 - 3834 GETFIELD1 + 3833 ACC0 + 3834 GETFIELD1 3835 RETURN 5 - 3837 ACC4 - 3838 PUSHENVACC1 + 3837 ACC4 + 3838 PUSHENVACC1 3839 CLOSUREREC 2, 3748 - 3843 ACC1 - 3844 GETFIELD2 - 3845 PUSHACC1 + 3843 ACC1 + 3844 GETFIELD2 + 3845 PUSHACC1 3846 APPTERM1 7 3848 GETGLOBAL Not_found 3850 MAKEBLOCK1 0 - 3852 RAISE + 3852 RAISE 3853 GETGLOBAL Not_found 3855 MAKEBLOCK1 0 - 3857 RAISE + 3857 RAISE 3858 GETGLOBAL Not_found 3860 MAKEBLOCK1 0 - 3862 RAISE - 3863 ACC0 + 3862 RAISE + 3863 ACC0 3864 BRANCHIFNOT 3890 - 3866 ACC0 - 3867 GETFIELD0 - 3868 PUSHACC1 - 3869 GETFIELD2 - 3870 PUSHENVACC2 - 3871 PUSHACC2 - 3872 PUSHENVACC1 - 3873 GETFIELD0 - 3874 APPLY2 + 3866 ACC0 + 3867 GETFIELD0 + 3868 PUSHACC1 + 3869 GETFIELD2 + 3870 PUSHENVACC2 + 3871 PUSHACC2 + 3872 PUSHENVACC1 + 3873 GETFIELD0 + 3874 APPLY2 3875 BRANCHIFNOT 3880 - 3877 ACC0 + 3877 ACC0 3878 RETURN 3 - 3880 ACC0 - 3881 PUSHOFFSETCLOSURE0 - 3882 APPLY1 - 3883 PUSHACC3 - 3884 GETFIELD1 - 3885 PUSHACC3 + 3880 ACC0 + 3881 PUSHOFFSETCLOSURE0 + 3882 APPLY1 + 3883 PUSHACC3 + 3884 GETFIELD1 + 3885 PUSHACC3 3886 MAKEBLOCK3 0 3888 POP 2 3890 RETURN 1 - 3892 RESTART + 3892 RESTART 3893 GRAB 1 - 3895 ACC1 - 3896 PUSHENVACC1 + 3895 ACC1 + 3896 PUSHENVACC1 3897 CLOSUREREC 2, 3863 - 3901 ACC1 - 3902 GETFIELD1 - 3903 VECTLENGTH - 3904 PUSHACC3 - 3905 PUSHENVACC1 - 3906 GETFIELD1 - 3907 APPLY1 - 3908 MODINT - 3909 PUSHACC0 - 3910 PUSHACC3 - 3911 GETFIELD1 + 3901 ACC1 + 3902 GETFIELD1 + 3903 VECTLENGTH + 3904 PUSHACC3 + 3905 PUSHENVACC1 + 3906 GETFIELD1 + 3907 APPLY1 + 3908 MODINT + 3909 PUSHACC0 + 3910 PUSHACC3 + 3911 GETFIELD1 3912 C_CALL2 array_get_addr - 3914 PUSHACC2 - 3915 APPLY1 - 3916 PUSHACC1 - 3917 PUSHACC4 - 3918 GETFIELD1 + 3914 PUSHACC2 + 3915 APPLY1 + 3916 PUSHACC1 + 3917 PUSHACC4 + 3918 GETFIELD1 3919 C_CALL3 array_set_addr 3921 RETURN 4 - 3923 RESTART + 3923 RESTART 3924 GRAB 2 - 3926 ACC0 - 3927 GETFIELD1 - 3928 VECTLENGTH - 3929 PUSHACC2 - 3930 PUSHENVACC3 - 3931 GETFIELD1 - 3932 APPLY1 - 3933 MODINT - 3934 PUSHACC0 - 3935 PUSHACC2 - 3936 GETFIELD1 + 3926 ACC0 + 3927 GETFIELD1 + 3928 VECTLENGTH + 3929 PUSHACC2 + 3930 PUSHENVACC3 + 3931 GETFIELD1 + 3932 APPLY1 + 3933 MODINT + 3934 PUSHACC0 + 3935 PUSHACC2 + 3936 GETFIELD1 3937 C_CALL2 array_get_addr - 3939 PUSHACC4 - 3940 PUSHACC4 + 3939 PUSHACC4 + 3940 PUSHACC4 3941 MAKEBLOCK3 0 - 3943 PUSHACC0 - 3944 PUSHACC2 - 3945 PUSHACC4 - 3946 GETFIELD1 + 3943 PUSHACC0 + 3944 PUSHACC2 + 3945 PUSHACC4 + 3946 GETFIELD1 3947 C_CALL3 array_set_addr - 3949 ACC0 - 3950 PUSHACC3 - 3951 GETFIELD0 - 3952 PUSHENVACC2 - 3953 APPLY2 + 3949 ACC0 + 3950 PUSHACC3 + 3951 GETFIELD0 + 3952 PUSHENVACC2 + 3953 APPLY2 3954 BRANCHIFNOT 3962 - 3956 ACC2 - 3957 PUSHENVACC3 - 3958 GETFIELD1 - 3959 PUSHENVACC1 + 3956 ACC2 + 3957 PUSHENVACC3 + 3958 GETFIELD1 + 3959 PUSHENVACC1 3960 APPTERM2 7 3962 RETURN 5 - 3964 ACC0 + 3964 ACC0 3965 PUSHENVACC 4 - 3967 PUSHENVACC3 + 3967 PUSHENVACC3 3968 CLOSURE 3, 3924 - 3971 PUSHACC1 + 3971 PUSHACC1 3972 CLOSURE 1, 3893 - 3975 PUSHACC2 + 3975 PUSHACC2 3976 CLOSURE 1, 3774 - 3979 PUSHACC3 + 3979 PUSHACC3 3980 CLOSURE 1, 3725 - 3983 PUSHACC4 + 3983 PUSHACC4 3984 CLOSURE 1, 3673 3987 PUSHENVACC 5 - 3989 PUSHACC1 - 3990 PUSHACC3 - 3991 PUSHACC5 - 3992 PUSHACC7 + 3989 PUSHACC1 + 3990 PUSHACC3 + 3991 PUSHACC5 + 3992 PUSHACC7 3993 PUSHACC 9 - 3995 PUSHENVACC2 - 3996 PUSHENVACC1 + 3995 PUSHENVACC2 + 3996 PUSHENVACC1 3997 MAKEBLOCK 8, 0 4000 RETURN 6 - 4002 ACC0 + 4002 ACC0 4003 BRANCHIFNOT 4016 - 4005 ACC0 - 4006 GETFIELD1 - 4007 PUSHACC1 - 4008 GETFIELD0 - 4009 PUSHENVACC1 - 4010 APPLY2 - 4011 ACC0 - 4012 GETFIELD2 - 4013 PUSHOFFSETCLOSURE0 + 4005 ACC0 + 4006 GETFIELD1 + 4007 PUSHACC1 + 4008 GETFIELD0 + 4009 PUSHENVACC1 + 4010 APPLY2 + 4011 ACC0 + 4012 GETFIELD2 + 4013 PUSHOFFSETCLOSURE0 4014 APPTERM1 2 4016 RETURN 1 - 4018 RESTART + 4018 RESTART 4019 GRAB 1 - 4021 ACC0 + 4021 ACC0 4022 CLOSUREREC 1, 4002 - 4026 ACC2 - 4027 GETFIELD1 - 4028 PUSHCONST0 - 4029 PUSHACC1 - 4030 VECTLENGTH + 4026 ACC2 + 4027 GETFIELD1 + 4028 PUSHCONST0 + 4029 PUSHACC1 + 4030 VECTLENGTH 4031 OFFSETINT -1 - 4033 PUSH + 4033 PUSH 4034 BRANCH 4048 - 4036 CHECK_SIGNALS - 4037 ACC1 - 4038 PUSHACC3 + 4036 CHECK_SIGNALS + 4037 ACC1 + 4038 PUSHACC3 4039 C_CALL2 array_get_addr - 4041 PUSHACC4 - 4042 APPLY1 - 4043 ACC1 + 4041 PUSHACC4 + 4042 APPLY1 + 4043 ACC1 4044 OFFSETINT 1 4046 ASSIGN 1 - 4048 ACC0 - 4049 PUSHACC2 - 4050 LEINT + 4048 ACC0 + 4049 PUSHACC2 + 4050 LEINT 4051 BRANCHIF 4036 - 4053 CONST0 + 4053 CONST0 4054 RETURN 6 - 4056 ACC0 + 4056 ACC0 4057 BRANCHIFNOT 4071 - 4059 ENVACC1 - 4060 PUSHACC1 - 4061 GETFIELD0 + 4059 ENVACC1 + 4060 PUSHACC1 + 4061 GETFIELD0 4062 C_CALL2 equal 4064 BRANCHIF 4071 - 4066 ACC0 - 4067 GETFIELD2 - 4068 PUSHOFFSETCLOSURE0 + 4066 ACC0 + 4067 GETFIELD2 + 4068 PUSHOFFSETCLOSURE0 4069 APPTERM1 2 4071 RETURN 1 - 4073 RESTART + 4073 RESTART 4074 GRAB 1 - 4076 ACC1 + 4076 ACC1 4077 CLOSUREREC 1, 4056 - 4081 ACC1 - 4082 GETFIELD1 - 4083 VECTLENGTH - 4084 PUSHACC3 - 4085 PUSHENVACC1 - 4086 APPLY1 - 4087 MODINT - 4088 PUSHACC2 - 4089 GETFIELD1 + 4081 ACC1 + 4082 GETFIELD1 + 4083 VECTLENGTH + 4084 PUSHACC3 + 4085 PUSHENVACC1 + 4086 APPLY1 + 4087 MODINT + 4088 PUSHACC2 + 4089 GETFIELD1 4090 C_CALL2 array_get_addr - 4092 PUSHACC1 + 4092 PUSHACC1 4093 APPTERM1 4 - 4095 ACC0 + 4095 ACC0 4096 BRANCHIFNOT 4120 - 4098 ACC0 - 4099 GETFIELD2 - 4100 PUSHENVACC1 - 4101 PUSHACC2 - 4102 GETFIELD0 + 4098 ACC0 + 4099 GETFIELD2 + 4100 PUSHENVACC1 + 4101 PUSHACC2 + 4102 GETFIELD0 4103 C_CALL2 equal 4105 BRANCHIFNOT 4116 - 4107 ACC0 - 4108 PUSHOFFSETCLOSURE0 - 4109 APPLY1 - 4110 PUSHACC2 - 4111 GETFIELD1 + 4107 ACC0 + 4108 PUSHOFFSETCLOSURE0 + 4109 APPLY1 + 4110 PUSHACC2 + 4111 GETFIELD1 4112 MAKEBLOCK2 0 4114 RETURN 2 - 4116 ACC0 - 4117 PUSHOFFSETCLOSURE0 + 4116 ACC0 + 4117 PUSHOFFSETCLOSURE0 4118 APPTERM1 3 4120 RETURN 1 - 4122 RESTART + 4122 RESTART 4123 GRAB 1 - 4125 ACC1 + 4125 ACC1 4126 CLOSUREREC 1, 4095 - 4130 ACC1 - 4131 GETFIELD1 - 4132 VECTLENGTH - 4133 PUSHACC3 - 4134 PUSHENVACC1 - 4135 APPLY1 - 4136 MODINT - 4137 PUSHACC2 - 4138 GETFIELD1 + 4130 ACC1 + 4131 GETFIELD1 + 4132 VECTLENGTH + 4133 PUSHACC3 + 4134 PUSHENVACC1 + 4135 APPLY1 + 4136 MODINT + 4137 PUSHACC2 + 4138 GETFIELD1 4139 C_CALL2 array_get_addr - 4141 PUSHACC1 + 4141 PUSHACC1 4142 APPTERM1 4 - 4144 ACC0 + 4144 ACC0 4145 BRANCHIFNOT 4163 - 4147 ACC0 - 4148 GETFIELD0 - 4149 PUSHENVACC1 + 4147 ACC0 + 4148 GETFIELD0 + 4149 PUSHENVACC1 4150 C_CALL2 equal 4152 BRANCHIFNOT 4158 - 4154 ACC0 - 4155 GETFIELD1 + 4154 ACC0 + 4155 GETFIELD1 4156 RETURN 1 - 4158 ACC0 - 4159 GETFIELD2 - 4160 PUSHOFFSETCLOSURE0 + 4158 ACC0 + 4159 GETFIELD2 + 4160 PUSHOFFSETCLOSURE0 4161 APPTERM1 2 4163 GETGLOBAL Not_found 4165 MAKEBLOCK1 0 - 4167 RAISE - 4168 RESTART + 4167 RAISE + 4168 RESTART 4169 GRAB 1 - 4171 ACC0 - 4172 GETFIELD1 - 4173 VECTLENGTH - 4174 PUSHACC2 - 4175 PUSHENVACC1 - 4176 APPLY1 - 4177 MODINT - 4178 PUSHACC1 - 4179 GETFIELD1 + 4171 ACC0 + 4172 GETFIELD1 + 4173 VECTLENGTH + 4174 PUSHACC2 + 4175 PUSHENVACC1 + 4176 APPLY1 + 4177 MODINT + 4178 PUSHACC1 + 4179 GETFIELD1 4180 C_CALL2 array_get_addr - 4182 PUSHACC0 + 4182 PUSHACC0 4183 BRANCHIFNOT 4248 - 4185 ACC0 - 4186 GETFIELD2 - 4187 PUSHACC1 - 4188 GETFIELD0 - 4189 PUSHACC4 + 4185 ACC0 + 4186 GETFIELD2 + 4187 PUSHACC1 + 4188 GETFIELD0 + 4189 PUSHACC4 4190 C_CALL2 equal 4192 BRANCHIFNOT 4198 - 4194 ACC1 - 4195 GETFIELD1 + 4194 ACC1 + 4195 GETFIELD1 4196 RETURN 4 - 4198 ACC0 + 4198 ACC0 4199 BRANCHIFNOT 4243 - 4201 ACC0 - 4202 GETFIELD2 - 4203 PUSHACC1 - 4204 GETFIELD0 - 4205 PUSHACC5 + 4201 ACC0 + 4202 GETFIELD2 + 4203 PUSHACC1 + 4204 GETFIELD0 + 4205 PUSHACC5 4206 C_CALL2 equal 4208 BRANCHIFNOT 4214 - 4210 ACC1 - 4211 GETFIELD1 + 4210 ACC1 + 4211 GETFIELD1 4212 RETURN 5 - 4214 ACC0 + 4214 ACC0 4215 BRANCHIFNOT 4238 - 4217 ACC0 - 4218 GETFIELD0 - 4219 PUSHACC5 + 4217 ACC0 + 4218 GETFIELD0 + 4219 PUSHACC5 4220 C_CALL2 equal 4222 BRANCHIFNOT 4228 - 4224 ACC0 - 4225 GETFIELD1 + 4224 ACC0 + 4225 GETFIELD1 4226 RETURN 5 - 4228 ACC4 + 4228 ACC4 4229 CLOSUREREC 1, 4144 - 4233 ACC1 - 4234 GETFIELD2 - 4235 PUSHACC1 + 4233 ACC1 + 4234 GETFIELD2 + 4235 PUSHACC1 4236 APPTERM1 7 4238 GETGLOBAL Not_found 4240 MAKEBLOCK1 0 - 4242 RAISE + 4242 RAISE 4243 GETGLOBAL Not_found 4245 MAKEBLOCK1 0 - 4247 RAISE + 4247 RAISE 4248 GETGLOBAL Not_found 4250 MAKEBLOCK1 0 - 4252 RAISE - 4253 ACC0 + 4252 RAISE + 4253 ACC0 4254 BRANCHIFNOT 4279 - 4256 ACC0 - 4257 GETFIELD0 - 4258 PUSHACC1 - 4259 GETFIELD2 - 4260 PUSHENVACC1 - 4261 PUSHACC2 + 4256 ACC0 + 4257 GETFIELD0 + 4258 PUSHACC1 + 4259 GETFIELD2 + 4260 PUSHENVACC1 + 4261 PUSHACC2 4262 C_CALL2 equal 4264 BRANCHIFNOT 4269 - 4266 ACC0 + 4266 ACC0 4267 RETURN 3 - 4269 ACC0 - 4270 PUSHOFFSETCLOSURE0 - 4271 APPLY1 - 4272 PUSHACC3 - 4273 GETFIELD1 - 4274 PUSHACC3 + 4269 ACC0 + 4270 PUSHOFFSETCLOSURE0 + 4271 APPLY1 + 4272 PUSHACC3 + 4273 GETFIELD1 + 4274 PUSHACC3 4275 MAKEBLOCK3 0 4277 POP 2 4279 RETURN 1 - 4281 RESTART + 4281 RESTART 4282 GRAB 1 - 4284 ACC1 + 4284 ACC1 4285 CLOSUREREC 1, 4253 - 4289 ACC1 - 4290 GETFIELD1 - 4291 VECTLENGTH - 4292 PUSHACC3 - 4293 PUSHENVACC1 - 4294 APPLY1 - 4295 MODINT - 4296 PUSHACC0 - 4297 PUSHACC3 - 4298 GETFIELD1 + 4289 ACC1 + 4290 GETFIELD1 + 4291 VECTLENGTH + 4292 PUSHACC3 + 4293 PUSHENVACC1 + 4294 APPLY1 + 4295 MODINT + 4296 PUSHACC0 + 4297 PUSHACC3 + 4298 GETFIELD1 4299 C_CALL2 array_get_addr - 4301 PUSHACC2 - 4302 APPLY1 - 4303 PUSHACC1 - 4304 PUSHACC4 - 4305 GETFIELD1 + 4301 PUSHACC2 + 4302 APPLY1 + 4303 PUSHACC1 + 4304 PUSHACC4 + 4305 GETFIELD1 4306 C_CALL3 array_set_addr 4308 RETURN 4 - 4310 RESTART + 4310 RESTART 4311 GRAB 2 - 4313 ACC0 - 4314 GETFIELD1 - 4315 VECTLENGTH - 4316 PUSHACC2 - 4317 PUSHENVACC1 - 4318 APPLY1 - 4319 MODINT - 4320 PUSHACC0 - 4321 PUSHACC2 - 4322 GETFIELD1 + 4313 ACC0 + 4314 GETFIELD1 + 4315 VECTLENGTH + 4316 PUSHACC2 + 4317 PUSHENVACC1 + 4318 APPLY1 + 4319 MODINT + 4320 PUSHACC0 + 4321 PUSHACC2 + 4322 GETFIELD1 4323 C_CALL2 array_get_addr - 4325 PUSHACC4 - 4326 PUSHACC4 + 4325 PUSHACC4 + 4326 PUSHACC4 4327 MAKEBLOCK3 0 - 4329 PUSHACC0 - 4330 PUSHACC2 - 4331 PUSHACC4 - 4332 GETFIELD1 + 4329 PUSHACC0 + 4330 PUSHACC2 + 4331 PUSHACC4 + 4332 GETFIELD1 4333 C_CALL3 array_set_addr - 4335 ACC0 - 4336 PUSHACC3 - 4337 GETFIELD0 - 4338 PUSHENVACC3 - 4339 APPLY2 + 4335 ACC0 + 4336 PUSHACC3 + 4337 GETFIELD0 + 4338 PUSHENVACC3 + 4339 APPLY2 4340 BRANCHIFNOT 4347 - 4342 ACC2 - 4343 PUSHENVACC1 - 4344 PUSHENVACC2 + 4342 ACC2 + 4343 PUSHENVACC1 + 4344 PUSHENVACC2 4345 APPTERM2 7 4347 RETURN 5 - 4349 ACC0 + 4349 ACC0 4350 BRANCHIFNOT 4378 - 4352 ACC0 - 4353 GETFIELD0 - 4354 PUSHACC1 - 4355 GETFIELD2 - 4356 PUSHOFFSETCLOSURE0 - 4357 APPLY1 - 4358 ENVACC2 - 4359 PUSHACC1 - 4360 PUSHENVACC1 - 4361 APPLY1 - 4362 MODINT - 4363 PUSHACC0 - 4364 PUSHENVACC3 + 4352 ACC0 + 4353 GETFIELD0 + 4354 PUSHACC1 + 4355 GETFIELD2 + 4356 PUSHOFFSETCLOSURE0 + 4357 APPLY1 + 4358 ENVACC2 + 4359 PUSHACC1 + 4360 PUSHENVACC1 + 4361 APPLY1 + 4362 MODINT + 4363 PUSHACC0 + 4364 PUSHENVACC3 4365 C_CALL2 array_get_addr - 4367 PUSHACC3 - 4368 GETFIELD1 - 4369 PUSHACC3 + 4367 PUSHACC3 + 4368 GETFIELD1 + 4369 PUSHACC3 4370 MAKEBLOCK3 0 - 4372 PUSHACC1 - 4373 PUSHENVACC3 + 4372 PUSHACC1 + 4373 PUSHENVACC3 4374 C_CALL3 array_set_addr 4376 POP 2 4378 RETURN 1 - 4380 RESTART + 4380 RESTART 4381 GRAB 1 - 4383 ACC1 - 4384 GETFIELD1 - 4385 PUSHACC0 - 4386 VECTLENGTH - 4387 PUSHACC0 - 4388 PUSHCONST2 - 4389 MULINT + 4383 ACC1 + 4384 GETFIELD1 + 4385 PUSHACC0 + 4386 VECTLENGTH + 4387 PUSHACC0 + 4388 PUSHCONST2 + 4389 MULINT 4390 OFFSETINT 1 - 4392 PUSHCONST0 - 4393 PUSHACC1 + 4392 PUSHCONST0 + 4393 PUSHACC1 4394 C_CALL2 make_vect - 4396 PUSHACC0 - 4397 PUSHACC2 - 4398 PUSHACC6 + 4396 PUSHACC0 + 4397 PUSHACC2 + 4398 PUSHACC6 4399 CLOSUREREC 3, 4349 - 4403 CONST0 - 4404 PUSHACC4 + 4403 CONST0 + 4404 PUSHACC4 4405 OFFSETINT -1 - 4407 PUSH + 4407 PUSH 4408 BRANCH 4422 - 4410 CHECK_SIGNALS - 4411 ACC1 - 4412 PUSHACC7 + 4410 CHECK_SIGNALS + 4411 ACC1 + 4412 PUSHACC7 4413 C_CALL2 array_get_addr - 4415 PUSHACC3 - 4416 APPLY1 - 4417 ACC1 + 4415 PUSHACC3 + 4416 APPLY1 + 4417 ACC1 4418 OFFSETINT 1 4420 ASSIGN 1 - 4422 ACC0 - 4423 PUSHACC2 - 4424 LEINT + 4422 ACC0 + 4423 PUSHACC2 + 4424 LEINT 4425 BRANCHIF 4410 - 4427 CONST0 + 4427 CONST0 4428 POP 2 - 4430 ACC1 - 4431 PUSHACC7 - 4432 SETFIELD1 - 4433 ACC6 - 4434 GETFIELD0 - 4435 PUSHCONST2 - 4436 MULINT - 4437 PUSHACC7 - 4438 SETFIELD0 + 4430 ACC1 + 4431 PUSHACC7 + 4432 SETFIELD1 + 4433 ACC6 + 4434 GETFIELD0 + 4435 PUSHCONST2 + 4436 MULINT + 4437 PUSHACC7 + 4438 SETFIELD0 4439 RETURN 7 - 4441 CONST0 - 4442 PUSHACC1 - 4443 GETFIELD1 - 4444 VECTLENGTH + 4441 CONST0 + 4442 PUSHACC1 + 4443 GETFIELD1 + 4444 VECTLENGTH 4445 OFFSETINT -1 - 4447 PUSH + 4447 PUSH 4448 BRANCH 4462 - 4450 CHECK_SIGNALS - 4451 CONST0 - 4452 PUSHACC2 - 4453 PUSHACC4 - 4454 GETFIELD1 + 4450 CHECK_SIGNALS + 4451 CONST0 + 4452 PUSHACC2 + 4453 PUSHACC4 + 4454 GETFIELD1 4455 C_CALL3 array_set_addr - 4457 ACC1 + 4457 ACC1 4458 OFFSETINT 1 4460 ASSIGN 1 - 4462 ACC0 - 4463 PUSHACC2 - 4464 LEINT + 4462 ACC0 + 4463 PUSHACC2 + 4464 LEINT 4465 BRANCHIF 4450 - 4467 CONST0 + 4467 CONST0 4468 RETURN 3 - 4470 CONST1 - 4471 PUSHACC1 - 4472 LTINT + 4470 CONST1 + 4471 PUSHACC1 + 4472 LTINT 4473 BRANCHIFNOT 4478 - 4475 CONST1 + 4475 CONST1 4476 BRANCH 4479 - 4478 ACC0 + 4478 ACC0 4479 PUSHGETGLOBALFIELD Sys, 5 - 4482 PUSHACC1 - 4483 GTINT + 4482 PUSHACC1 + 4483 GTINT 4484 BRANCHIFNOT 4491 4486 GETGLOBALFIELD Sys, 5 4489 BRANCH 4492 - 4491 ACC0 - 4492 PUSHCONST0 - 4493 PUSHACC1 + 4491 ACC0 + 4492 PUSHCONST0 + 4493 PUSHACC1 4494 C_CALL2 make_vect - 4496 PUSHCONST3 + 4496 PUSHCONST3 4497 MAKEBLOCK2 0 4499 RETURN 3 - 4501 ACC0 + 4501 ACC0 4502 PUSHCONSTINT 100 4504 PUSHCONSTINT 10 4506 C_CALL3 hash_univ_param 4508 RETURN 1 4510 CLOSURE 0, 4501 - 4513 PUSH + 4513 PUSH 4514 CLOSURE 0, 4470 - 4517 PUSH + 4517 PUSH 4518 CLOSURE 0, 4441 - 4521 PUSH + 4521 PUSH 4522 CLOSURE 0, 4381 - 4525 PUSH + 4525 PUSH 4526 CLOSUREREC 0, 3631 - 4530 ACC0 - 4531 PUSHACC2 - 4532 PUSHACC6 + 4530 ACC0 + 4531 PUSHACC2 + 4532 PUSHACC6 4533 CLOSURE 3, 4311 - 4536 PUSHACC5 + 4536 PUSHACC5 4537 CLOSURE 1, 4282 - 4540 PUSHACC6 + 4540 PUSHACC6 4541 CLOSURE 1, 4169 - 4544 PUSHACC7 + 4544 PUSHACC7 4545 CLOSURE 1, 4123 4548 PUSHACC 8 4550 CLOSURE 1, 4074 - 4553 PUSH + 4553 PUSH 4554 CLOSURE 0, 4019 - 4557 PUSHACC0 - 4558 PUSHACC7 + 4557 PUSHACC0 + 4558 PUSHACC7 4559 PUSHACC 9 4561 PUSHACC 11 4563 PUSHACC 13 4565 CLOSURE 5, 3964 4568 PUSHACC 11 - 4570 PUSHACC1 - 4571 PUSHACC3 + 4570 PUSHACC1 + 4571 PUSHACC3 4572 PUSHACC 8 - 4574 PUSHACC6 + 4574 PUSHACC6 4575 PUSHACC 8 4577 PUSHACC 10 4579 PUSHACC 13 @@ -3088,747 +3088,747 @@ if o#m <> 23 then raise Not_found 4588 POP 12 4590 SETGLOBAL Hashtbl 4592 BRANCH 5073 - 4594 RESTART + 4594 RESTART 4595 GRAB 2 - 4597 ACC1 + 4597 ACC1 4598 BRANCHIFNOT 4638 - 4600 ACC1 - 4601 GETFIELD0 - 4602 PUSHACC3 + 4600 ACC1 + 4601 GETFIELD0 + 4602 PUSHACC3 4603 BRANCHIFNOT 4635 - 4605 ACC3 - 4606 GETFIELD0 - 4607 PUSHACC0 - 4608 PUSHACC2 - 4609 PUSHACC4 - 4610 APPLY2 + 4605 ACC3 + 4606 GETFIELD0 + 4607 PUSHACC0 + 4608 PUSHACC2 + 4609 PUSHACC4 + 4610 APPLY2 4611 BRANCHIFNOT 4624 - 4613 ACC4 - 4614 PUSHACC4 - 4615 GETFIELD1 - 4616 PUSHACC4 - 4617 PUSHOFFSETCLOSURE0 - 4618 APPLY3 - 4619 PUSHACC2 + 4613 ACC4 + 4614 PUSHACC4 + 4615 GETFIELD1 + 4616 PUSHACC4 + 4617 PUSHOFFSETCLOSURE0 + 4618 APPLY3 + 4619 PUSHACC2 4620 MAKEBLOCK2 0 4622 RETURN 5 - 4624 ACC4 - 4625 GETFIELD1 - 4626 PUSHACC4 - 4627 PUSHACC4 - 4628 PUSHOFFSETCLOSURE0 - 4629 APPLY3 - 4630 PUSHACC1 + 4624 ACC4 + 4625 GETFIELD1 + 4626 PUSHACC4 + 4627 PUSHACC4 + 4628 PUSHOFFSETCLOSURE0 + 4629 APPLY3 + 4630 PUSHACC1 4631 MAKEBLOCK2 0 4633 RETURN 5 - 4635 ACC2 + 4635 ACC2 4636 RETURN 4 - 4638 ACC2 + 4638 ACC2 4639 RETURN 3 - 4641 RESTART + 4641 RESTART 4642 GRAB 1 4644 CONSTINT 6 - 4646 PUSHACC1 - 4647 PUSHACC3 - 4648 SUBINT - 4649 GEINT + 4646 PUSHACC1 + 4647 PUSHACC3 + 4648 SUBINT + 4649 GEINT 4650 BRANCHIFNOT 4809 - 4652 CONST1 - 4653 PUSHACC2 - 4654 PUSHACC2 - 4655 ADDINT - 4656 LSRINT - 4657 PUSHACC1 - 4658 PUSHENVACC3 + 4652 CONST1 + 4653 PUSHACC2 + 4654 PUSHACC2 + 4655 ADDINT + 4656 LSRINT + 4657 PUSHACC1 + 4658 PUSHENVACC3 4659 C_CALL2 array_unsafe_get - 4661 PUSHACC1 - 4662 PUSHENVACC3 + 4661 PUSHACC1 + 4662 PUSHENVACC3 4663 C_CALL2 array_unsafe_get - 4665 PUSHENVACC2 - 4666 APPLY2 + 4665 PUSHENVACC2 + 4666 APPLY2 4667 BRANCHIFNOT 4674 - 4669 ACC1 - 4670 PUSHACC1 - 4671 PUSHENVACC3 - 4672 PUSHENVACC1 - 4673 APPLY3 - 4674 ACC0 - 4675 PUSHENVACC3 + 4669 ACC1 + 4670 PUSHACC1 + 4671 PUSHENVACC3 + 4672 PUSHENVACC1 + 4673 APPLY3 + 4674 ACC0 + 4675 PUSHENVACC3 4676 C_CALL2 array_unsafe_get - 4678 PUSHACC3 - 4679 PUSHENVACC3 + 4678 PUSHACC3 + 4679 PUSHENVACC3 4680 C_CALL2 array_unsafe_get - 4682 PUSHENVACC2 - 4683 APPLY2 + 4682 PUSHENVACC2 + 4683 APPLY2 4684 BRANCHIFNOT 4708 - 4686 ACC2 - 4687 PUSHACC1 - 4688 PUSHENVACC3 - 4689 PUSHENVACC1 - 4690 APPLY3 - 4691 ACC1 - 4692 PUSHENVACC3 + 4686 ACC2 + 4687 PUSHACC1 + 4688 PUSHENVACC3 + 4689 PUSHENVACC1 + 4690 APPLY3 + 4691 ACC1 + 4692 PUSHENVACC3 4693 C_CALL2 array_unsafe_get - 4695 PUSHACC1 - 4696 PUSHENVACC3 + 4695 PUSHACC1 + 4696 PUSHENVACC3 4697 C_CALL2 array_unsafe_get - 4699 PUSHENVACC2 - 4700 APPLY2 + 4699 PUSHENVACC2 + 4700 APPLY2 4701 BRANCHIFNOT 4708 - 4703 ACC1 - 4704 PUSHACC1 - 4705 PUSHENVACC3 - 4706 PUSHENVACC1 - 4707 APPLY3 - 4708 ACC0 - 4709 PUSHENVACC3 + 4703 ACC1 + 4704 PUSHACC1 + 4705 PUSHENVACC3 + 4706 PUSHENVACC1 + 4707 APPLY3 + 4708 ACC0 + 4709 PUSHENVACC3 4710 C_CALL2 array_unsafe_get - 4712 PUSHACC2 + 4712 PUSHACC2 4713 OFFSETINT 1 - 4715 PUSHACC4 + 4715 PUSHACC4 4716 OFFSETINT -1 - 4718 PUSH + 4718 PUSH 4719 BRANCH 4777 - 4721 CHECK_SIGNALS + 4721 CHECK_SIGNALS 4722 BRANCH 4730 - 4724 CHECK_SIGNALS - 4725 ACC1 + 4724 CHECK_SIGNALS + 4725 ACC1 4726 OFFSETINT 1 4728 ASSIGN 1 - 4730 ACC1 - 4731 PUSHENVACC3 + 4730 ACC1 + 4731 PUSHENVACC3 4732 C_CALL2 array_unsafe_get - 4734 PUSHACC3 - 4735 PUSHENVACC2 - 4736 APPLY2 + 4734 PUSHACC3 + 4735 PUSHENVACC2 + 4736 APPLY2 4737 BRANCHIFNOT 4724 - 4739 CONST0 + 4739 CONST0 4740 BRANCH 4748 - 4742 CHECK_SIGNALS - 4743 ACC0 + 4742 CHECK_SIGNALS + 4743 ACC0 4744 OFFSETINT -1 4746 ASSIGN 0 - 4748 ACC2 - 4749 PUSHACC1 - 4750 PUSHENVACC3 + 4748 ACC2 + 4749 PUSHACC1 + 4750 PUSHENVACC3 4751 C_CALL2 array_unsafe_get - 4753 PUSHENVACC2 - 4754 APPLY2 + 4753 PUSHENVACC2 + 4754 APPLY2 4755 BRANCHIFNOT 4742 - 4757 ACC0 - 4758 PUSHACC2 - 4759 LTINT + 4757 ACC0 + 4758 PUSHACC2 + 4759 LTINT 4760 BRANCHIFNOT 4767 - 4762 ACC0 - 4763 PUSHACC2 - 4764 PUSHENVACC3 - 4765 PUSHENVACC1 - 4766 APPLY3 - 4767 ACC1 + 4762 ACC0 + 4763 PUSHACC2 + 4764 PUSHENVACC3 + 4765 PUSHENVACC1 + 4766 APPLY3 + 4767 ACC1 4768 OFFSETINT 1 4770 ASSIGN 1 - 4772 ACC0 + 4772 ACC0 4773 OFFSETINT -1 4775 ASSIGN 0 - 4777 ACC0 - 4778 PUSHACC2 - 4779 LTINT + 4777 ACC0 + 4778 PUSHACC2 + 4779 LTINT 4780 BRANCHIF 4721 - 4782 ACC1 - 4783 PUSHACC6 - 4784 SUBINT - 4785 PUSHACC5 - 4786 PUSHACC2 - 4787 SUBINT - 4788 LEINT + 4782 ACC1 + 4783 PUSHACC6 + 4784 SUBINT + 4785 PUSHACC5 + 4786 PUSHACC2 + 4787 SUBINT + 4788 LEINT 4789 BRANCHIFNOT 4800 - 4791 ACC0 - 4792 PUSHACC5 - 4793 PUSHOFFSETCLOSURE0 - 4794 APPLY2 - 4795 ACC5 - 4796 PUSHACC2 - 4797 PUSHOFFSETCLOSURE0 + 4791 ACC0 + 4792 PUSHACC5 + 4793 PUSHOFFSETCLOSURE0 + 4794 APPLY2 + 4795 ACC5 + 4796 PUSHACC2 + 4797 PUSHOFFSETCLOSURE0 4798 APPTERM2 8 - 4800 ACC5 - 4801 PUSHACC2 - 4802 PUSHOFFSETCLOSURE0 - 4803 APPLY2 - 4804 ACC0 - 4805 PUSHACC5 - 4806 PUSHOFFSETCLOSURE0 + 4800 ACC5 + 4801 PUSHACC2 + 4802 PUSHOFFSETCLOSURE0 + 4803 APPLY2 + 4804 ACC0 + 4805 PUSHACC5 + 4806 PUSHOFFSETCLOSURE0 4807 APPTERM2 8 4809 RETURN 2 - 4811 RESTART + 4811 RESTART 4812 GRAB 1 - 4814 ACC1 - 4815 PUSHACC1 - 4816 PUSHENVACC1 + 4814 ACC1 + 4815 PUSHACC1 + 4816 PUSHENVACC1 4817 CLOSUREREC 3, 4642 - 4821 ACC2 - 4822 VECTLENGTH + 4821 ACC2 + 4822 VECTLENGTH 4823 OFFSETINT -1 - 4825 PUSHCONST0 - 4826 PUSHACC2 - 4827 APPLY2 - 4828 CONST1 - 4829 PUSHACC3 - 4830 VECTLENGTH + 4825 PUSHCONST0 + 4826 PUSHACC2 + 4827 APPLY2 + 4828 CONST1 + 4829 PUSHACC3 + 4830 VECTLENGTH 4831 OFFSETINT -1 - 4833 PUSH + 4833 PUSH 4834 BRANCH 4918 - 4836 CHECK_SIGNALS - 4837 ACC1 - 4838 PUSHACC5 + 4836 CHECK_SIGNALS + 4837 ACC1 + 4838 PUSHACC5 4839 C_CALL2 array_unsafe_get - 4841 PUSHACC0 - 4842 PUSHACC3 + 4841 PUSHACC0 + 4842 PUSHACC3 4843 OFFSETINT -1 - 4845 PUSHACC7 + 4845 PUSHACC7 4846 C_CALL2 array_unsafe_get - 4848 PUSHACC6 - 4849 APPLY2 - 4850 BOOLNOT + 4848 PUSHACC6 + 4849 APPLY2 + 4850 BOOLNOT 4851 BRANCHIFNOT 4911 - 4853 ACC2 + 4853 ACC2 4854 OFFSETINT -1 - 4856 PUSHACC6 + 4856 PUSHACC6 4857 C_CALL2 array_unsafe_get - 4859 PUSHACC3 - 4860 PUSHACC7 + 4859 PUSHACC3 + 4860 PUSHACC7 4861 C_CALL3 array_unsafe_set - 4863 ACC2 + 4863 ACC2 4864 OFFSETINT -1 - 4866 PUSH + 4866 PUSH 4867 BRANCH 4886 - 4869 CHECK_SIGNALS - 4870 ACC0 + 4869 CHECK_SIGNALS + 4870 ACC0 4871 OFFSETINT -1 - 4873 PUSHACC7 + 4873 PUSHACC7 4874 C_CALL2 array_unsafe_get - 4876 PUSHACC1 + 4876 PUSHACC1 4877 PUSHACC 8 4879 C_CALL3 array_unsafe_set - 4881 ACC0 + 4881 ACC0 4882 OFFSETINT -1 4884 ASSIGN 0 - 4886 CONST1 - 4887 PUSHACC1 - 4888 GEINT + 4886 CONST1 + 4887 PUSHACC1 + 4888 GEINT 4889 BRANCHIFNOT 4903 - 4891 ACC1 - 4892 PUSHACC1 + 4891 ACC1 + 4892 PUSHACC1 4893 OFFSETINT -1 4895 PUSHACC 8 4897 C_CALL2 array_unsafe_get - 4899 PUSHACC7 - 4900 APPLY2 + 4899 PUSHACC7 + 4900 APPLY2 4901 BRANCHIFNOT 4869 - 4903 ACC1 - 4904 PUSHACC1 + 4903 ACC1 + 4904 PUSHACC1 4905 PUSHACC 8 4907 C_CALL3 array_unsafe_set 4909 POP 1 4911 POP 1 - 4913 ACC1 + 4913 ACC1 4914 OFFSETINT 1 4916 ASSIGN 1 - 4918 ACC0 - 4919 PUSHACC2 - 4920 LEINT + 4918 ACC0 + 4919 PUSHACC2 + 4920 LEINT 4921 BRANCHIF 4836 - 4923 CONST0 + 4923 CONST0 4924 RETURN 5 - 4926 RESTART + 4926 RESTART 4927 GRAB 2 - 4929 ACC1 - 4930 PUSHACC1 + 4929 ACC1 + 4930 PUSHACC1 4931 C_CALL2 array_unsafe_get - 4933 PUSHACC3 - 4934 PUSHACC2 + 4933 PUSHACC3 + 4934 PUSHACC2 4935 C_CALL2 array_unsafe_get - 4937 PUSHACC3 - 4938 PUSHACC3 + 4937 PUSHACC3 + 4938 PUSHACC3 4939 C_CALL3 array_unsafe_set - 4941 ACC0 - 4942 PUSHACC4 - 4943 PUSHACC3 + 4941 ACC0 + 4942 PUSHACC4 + 4943 PUSHACC3 4944 C_CALL3 array_unsafe_set 4946 RETURN 4 - 4948 ACC0 + 4948 ACC0 4949 BRANCHIFNOT 4999 - 4951 ACC0 - 4952 GETFIELD0 - 4953 PUSHACC1 - 4954 GETFIELD1 - 4955 PUSHACC0 + 4951 ACC0 + 4952 GETFIELD0 + 4953 PUSHACC1 + 4954 GETFIELD1 + 4955 PUSHACC0 4956 BRANCHIFNOT 4990 - 4958 ACC0 - 4959 GETFIELD0 - 4960 PUSHACC1 - 4961 GETFIELD1 - 4962 PUSHOFFSETCLOSURE0 - 4963 APPLY1 - 4964 PUSHACC1 - 4965 PUSHACC4 - 4966 PUSHENVACC1 - 4967 APPLY2 + 4958 ACC0 + 4959 GETFIELD0 + 4960 PUSHACC1 + 4961 GETFIELD1 + 4962 PUSHOFFSETCLOSURE0 + 4963 APPLY1 + 4964 PUSHACC1 + 4965 PUSHACC4 + 4966 PUSHENVACC1 + 4967 APPLY2 4968 BRANCHIFNOT 4979 - 4970 CONST0 - 4971 PUSHACC2 + 4970 CONST0 + 4971 PUSHACC2 4972 MAKEBLOCK2 0 - 4974 PUSHACC4 + 4974 PUSHACC4 4975 MAKEBLOCK2 0 4977 BRANCH 4986 - 4979 CONST0 - 4980 PUSHACC4 + 4979 CONST0 + 4980 PUSHACC4 4981 MAKEBLOCK2 0 - 4983 PUSHACC2 + 4983 PUSHACC2 4984 MAKEBLOCK2 0 4986 MAKEBLOCK2 0 4988 RETURN 4 - 4990 CONST0 - 4991 PUSHCONST0 - 4992 PUSHACC3 + 4990 CONST0 + 4991 PUSHCONST0 + 4992 PUSHACC3 4993 MAKEBLOCK2 0 4995 MAKEBLOCK2 0 4997 POP 2 4999 RETURN 1 - 5001 ACC0 + 5001 ACC0 5002 BRANCHIFNOT 5028 - 5004 ACC0 - 5005 GETFIELD1 - 5006 PUSHACC0 + 5004 ACC0 + 5005 GETFIELD1 + 5006 PUSHACC0 5007 BRANCHIFNOT 5024 - 5009 ACC0 - 5010 GETFIELD1 - 5011 PUSHOFFSETCLOSURE0 - 5012 APPLY1 - 5013 PUSHACC1 - 5014 GETFIELD0 - 5015 PUSHACC3 - 5016 GETFIELD0 - 5017 PUSHENVACC2 - 5018 PUSHENVACC1 - 5019 APPLY3 + 5009 ACC0 + 5010 GETFIELD1 + 5011 PUSHOFFSETCLOSURE0 + 5012 APPLY1 + 5013 PUSHACC1 + 5014 GETFIELD0 + 5015 PUSHACC3 + 5016 GETFIELD0 + 5017 PUSHENVACC2 + 5018 PUSHENVACC1 + 5019 APPLY3 5020 MAKEBLOCK2 0 5022 RETURN 2 5024 POP 1 5026 BRANCH 5028 - 5028 ACC0 + 5028 ACC0 5029 RETURN 1 - 5031 ACC0 + 5031 ACC0 5032 BRANCHIFNOT 5040 - 5034 ACC0 - 5035 GETFIELD1 + 5034 ACC0 + 5035 GETFIELD1 5036 BRANCHIF 5042 - 5038 ACC0 - 5039 GETFIELD0 + 5038 ACC0 + 5039 GETFIELD0 5040 RETURN 1 - 5042 ACC0 - 5043 PUSHENVACC1 - 5044 APPLY1 - 5045 PUSHOFFSETCLOSURE0 + 5042 ACC0 + 5043 PUSHENVACC1 + 5044 APPLY1 + 5045 PUSHOFFSETCLOSURE0 5046 APPTERM1 2 - 5048 RESTART + 5048 RESTART 5049 GRAB 1 - 5051 ACC0 + 5051 ACC0 5052 CLOSUREREC 1, 4948 - 5056 ACC1 - 5057 PUSHENVACC1 + 5056 ACC1 + 5057 PUSHENVACC1 5058 CLOSUREREC 2, 5001 - 5062 ACC0 + 5062 ACC0 5063 CLOSUREREC 1, 5031 - 5067 ACC4 - 5068 PUSHACC3 - 5069 APPLY1 - 5070 PUSHACC1 + 5067 ACC4 + 5068 PUSHACC3 + 5069 APPLY1 + 5070 PUSHACC1 5071 APPTERM1 6 5073 CLOSUREREC 0, 4595 - 5077 ACC0 + 5077 ACC0 5078 CLOSURE 1, 5049 - 5081 PUSH + 5081 PUSH 5082 CLOSURE 0, 4927 - 5085 PUSHACC0 + 5085 PUSHACC0 5086 CLOSURE 1, 4812 - 5089 PUSHACC3 - 5090 PUSHACC1 - 5091 PUSHACC4 + 5089 PUSHACC3 + 5090 PUSHACC1 + 5091 PUSHACC4 5092 MAKEBLOCK3 0 5094 POP 4 5096 SETGLOBAL Sort 5098 BRANCH 5847 - 5100 ACC0 - 5101 PUSHENVACC1 - 5102 APPLY1 - 5103 PUSHACC0 + 5100 ACC0 + 5101 PUSHENVACC1 + 5102 APPLY1 + 5103 PUSHACC0 5104 GETFIELD 11 - 5106 PUSHACC1 + 5106 PUSHACC1 5107 GETFIELD 10 - 5109 PUSHACC2 + 5109 PUSHACC2 5110 GETFIELD 9 - 5112 PUSHACC3 + 5112 PUSHACC3 5113 GETFIELD 6 - 5115 PUSHACC4 + 5115 PUSHACC4 5116 GETFIELD 8 - 5118 PUSHACC5 + 5118 PUSHACC5 5119 GETFIELD 5 - 5121 PUSHACC6 + 5121 PUSHACC6 5122 GETFIELD 4 - 5124 PUSHACC7 - 5125 GETFIELD0 + 5124 PUSHACC7 + 5125 GETFIELD0 5126 MAKEBLOCK 8, 0 5129 RETURN 2 - 5131 RESTART + 5131 RESTART 5132 GRAB 2 - 5134 ACC2 + 5134 ACC2 5135 BRANCHIFNOT 5201 - 5137 ACC2 - 5138 GETFIELD0 - 5139 PUSHACC3 - 5140 GETFIELD1 - 5141 PUSHACC4 - 5142 GETFIELD2 - 5143 PUSHACC5 - 5144 GETFIELD3 - 5145 PUSHACC2 - 5146 PUSHACC5 - 5147 PUSHENVACC1 - 5148 GETFIELD0 - 5149 APPLY2 - 5150 PUSHCONST0 - 5151 PUSHACC1 - 5152 EQ + 5137 ACC2 + 5138 GETFIELD0 + 5139 PUSHACC3 + 5140 GETFIELD1 + 5141 PUSHACC4 + 5142 GETFIELD2 + 5143 PUSHACC5 + 5144 GETFIELD3 + 5145 PUSHACC2 + 5146 PUSHACC5 + 5147 PUSHENVACC1 + 5148 GETFIELD0 + 5149 APPLY2 + 5150 PUSHCONST0 + 5151 PUSHACC1 + 5152 EQ 5153 BRANCHIFNOT 5170 - 5155 ACC7 + 5155 ACC7 5156 GETFIELD 4 - 5158 PUSHACC2 + 5158 PUSHACC2 5159 PUSHACC 8 5161 PUSHACC 8 5163 PUSHACC 8 5165 MAKEBLOCK 5, 0 5168 RETURN 8 - 5170 CONST0 - 5171 PUSHACC1 - 5172 LTINT + 5170 CONST0 + 5171 PUSHACC1 + 5172 LTINT 5173 BRANCHIFNOT 5189 - 5175 ACC1 - 5176 PUSHACC3 - 5177 PUSHACC5 - 5178 PUSHACC7 + 5175 ACC1 + 5176 PUSHACC3 + 5177 PUSHACC5 + 5178 PUSHACC7 5179 PUSHACC 10 5181 PUSHACC 10 - 5183 PUSHOFFSETCLOSURE0 - 5184 APPLY3 - 5185 PUSHENVACC2 + 5183 PUSHOFFSETCLOSURE0 + 5184 APPLY3 + 5185 PUSHENVACC2 5186 APPTERM 4, 12 - 5189 ACC1 - 5190 PUSHACC7 - 5191 PUSHACC7 - 5192 PUSHOFFSETCLOSURE0 - 5193 APPLY3 - 5194 PUSHACC3 - 5195 PUSHACC5 - 5196 PUSHACC7 - 5197 PUSHENVACC2 + 5189 ACC1 + 5190 PUSHACC7 + 5191 PUSHACC7 + 5192 PUSHOFFSETCLOSURE0 + 5193 APPLY3 + 5194 PUSHACC3 + 5195 PUSHACC5 + 5196 PUSHACC7 + 5197 PUSHENVACC2 5198 APPTERM 4, 12 - 5201 CONST1 - 5202 PUSHCONST0 - 5203 PUSHACC3 - 5204 PUSHACC3 - 5205 PUSHCONST0 + 5201 CONST1 + 5202 PUSHCONST0 + 5203 PUSHACC3 + 5204 PUSHACC3 + 5205 PUSHCONST0 5206 MAKEBLOCK 5, 0 5209 RETURN 3 - 5211 RESTART + 5211 RESTART 5212 GRAB 1 - 5214 ACC1 + 5214 ACC1 5215 BRANCHIFNOT 5247 - 5217 ACC1 - 5218 GETFIELD1 - 5219 PUSHACC1 - 5220 PUSHENVACC1 - 5221 GETFIELD0 - 5222 APPLY2 - 5223 PUSHCONST0 - 5224 PUSHACC1 - 5225 EQ + 5217 ACC1 + 5218 GETFIELD1 + 5219 PUSHACC1 + 5220 PUSHENVACC1 + 5221 GETFIELD0 + 5222 APPLY2 + 5223 PUSHCONST0 + 5224 PUSHACC1 + 5225 EQ 5226 BRANCHIFNOT 5232 - 5228 ACC2 - 5229 GETFIELD2 + 5228 ACC2 + 5229 GETFIELD2 5230 RETURN 3 - 5232 CONST0 - 5233 PUSHACC1 - 5234 LTINT + 5232 CONST0 + 5233 PUSHACC1 + 5234 LTINT 5235 BRANCHIFNOT 5241 - 5237 ACC2 - 5238 GETFIELD0 + 5237 ACC2 + 5238 GETFIELD0 5239 BRANCH 5243 - 5241 ACC2 - 5242 GETFIELD3 - 5243 PUSHACC2 - 5244 PUSHOFFSETCLOSURE0 + 5241 ACC2 + 5242 GETFIELD3 + 5243 PUSHACC2 + 5244 PUSHOFFSETCLOSURE0 5245 APPTERM2 5 5247 GETGLOBAL Not_found 5249 MAKEBLOCK1 0 - 5251 RAISE - 5252 RESTART + 5251 RAISE + 5252 RESTART 5253 GRAB 1 - 5255 ACC1 + 5255 ACC1 5256 BRANCHIFNOT 5286 - 5258 ACC1 - 5259 GETFIELD1 - 5260 PUSHACC1 - 5261 PUSHENVACC1 - 5262 GETFIELD0 - 5263 APPLY2 - 5264 PUSHCONST0 - 5265 PUSHACC1 - 5266 EQ + 5258 ACC1 + 5259 GETFIELD1 + 5260 PUSHACC1 + 5261 PUSHENVACC1 + 5262 GETFIELD0 + 5263 APPLY2 + 5264 PUSHCONST0 + 5265 PUSHACC1 + 5266 EQ 5267 BRANCHIF 5284 - 5269 CONST0 - 5270 PUSHACC1 - 5271 LTINT + 5269 CONST0 + 5270 PUSHACC1 + 5271 LTINT 5272 BRANCHIFNOT 5278 - 5274 ACC2 - 5275 GETFIELD0 + 5274 ACC2 + 5275 GETFIELD0 5276 BRANCH 5280 - 5278 ACC2 - 5279 GETFIELD3 - 5280 PUSHACC2 - 5281 PUSHOFFSETCLOSURE0 + 5278 ACC2 + 5279 GETFIELD3 + 5280 PUSHACC2 + 5281 PUSHOFFSETCLOSURE0 5282 APPTERM2 5 5284 POP 1 5286 RETURN 2 - 5288 RESTART + 5288 RESTART 5289 GRAB 1 - 5291 ACC0 + 5291 ACC0 5292 BRANCHIF 5297 - 5294 ACC1 + 5294 ACC1 5295 RETURN 2 - 5297 ACC1 + 5297 ACC1 5298 BRANCHIF 5303 - 5300 ACC0 + 5300 ACC0 5301 RETURN 2 - 5303 ACC0 + 5303 ACC0 5304 BRANCHIFNOT 5336 - 5306 ACC1 + 5306 ACC1 5307 BRANCHIFNOT 5336 5309 PUSH_RETADDR 5326 - 5311 ACC4 - 5312 GETFIELD3 - 5313 PUSHACC5 - 5314 GETFIELD2 - 5315 PUSHACC6 - 5316 GETFIELD1 - 5317 PUSHACC7 - 5318 GETFIELD0 - 5319 PUSHACC7 - 5320 GETFIELD3 - 5321 PUSHOFFSETCLOSURE0 - 5322 APPLY2 - 5323 PUSHENVACC1 + 5311 ACC4 + 5312 GETFIELD3 + 5313 PUSHACC5 + 5314 GETFIELD2 + 5315 PUSHACC6 + 5316 GETFIELD1 + 5317 PUSHACC7 + 5318 GETFIELD0 + 5319 PUSHACC7 + 5320 GETFIELD3 + 5321 PUSHOFFSETCLOSURE0 + 5322 APPLY2 + 5323 PUSHENVACC1 5324 APPLY 4 - 5326 PUSHACC1 - 5327 GETFIELD2 - 5328 PUSHACC2 - 5329 GETFIELD1 - 5330 PUSHACC3 - 5331 GETFIELD0 - 5332 PUSHENVACC1 + 5326 PUSHACC1 + 5327 GETFIELD2 + 5328 PUSHACC2 + 5329 GETFIELD1 + 5330 PUSHACC3 + 5331 GETFIELD0 + 5332 PUSHENVACC1 5333 APPTERM 4, 6 5336 GETGLOBAL <0>("map.ml", 3614, 3797) 5338 PUSHGETGLOBAL Match_failure 5340 MAKEBLOCK2 0 - 5342 RAISE - 5343 RESTART + 5342 RAISE + 5343 RESTART 5344 GRAB 1 - 5346 ACC1 + 5346 ACC1 5347 BRANCHIFNOT 5400 - 5349 ACC1 - 5350 GETFIELD0 - 5351 PUSHACC2 - 5352 GETFIELD1 - 5353 PUSHACC3 - 5354 GETFIELD2 - 5355 PUSHACC4 - 5356 GETFIELD3 - 5357 PUSHACC2 - 5358 PUSHACC5 - 5359 PUSHENVACC1 - 5360 GETFIELD0 - 5361 APPLY2 - 5362 PUSHCONST0 - 5363 PUSHACC1 - 5364 EQ + 5349 ACC1 + 5350 GETFIELD0 + 5351 PUSHACC2 + 5352 GETFIELD1 + 5353 PUSHACC3 + 5354 GETFIELD2 + 5355 PUSHACC4 + 5356 GETFIELD3 + 5357 PUSHACC2 + 5358 PUSHACC5 + 5359 PUSHENVACC1 + 5360 GETFIELD0 + 5361 APPLY2 + 5362 PUSHCONST0 + 5363 PUSHACC1 + 5364 EQ 5365 BRANCHIFNOT 5372 - 5367 ACC1 - 5368 PUSHACC5 - 5369 PUSHENVACC3 + 5367 ACC1 + 5368 PUSHACC5 + 5369 PUSHENVACC3 5370 APPTERM2 9 - 5372 CONST0 - 5373 PUSHACC1 - 5374 LTINT + 5372 CONST0 + 5373 PUSHACC1 + 5374 LTINT 5375 BRANCHIFNOT 5389 - 5377 ACC1 - 5378 PUSHACC3 - 5379 PUSHACC5 - 5380 PUSHACC7 + 5377 ACC1 + 5378 PUSHACC3 + 5379 PUSHACC5 + 5380 PUSHACC7 5381 PUSHACC 9 - 5383 PUSHOFFSETCLOSURE0 - 5384 APPLY2 - 5385 PUSHENVACC2 + 5383 PUSHOFFSETCLOSURE0 + 5384 APPLY2 + 5385 PUSHENVACC2 5386 APPTERM 4, 11 - 5389 ACC1 - 5390 PUSHACC6 - 5391 PUSHOFFSETCLOSURE0 - 5392 APPLY2 - 5393 PUSHACC3 - 5394 PUSHACC5 - 5395 PUSHACC7 - 5396 PUSHENVACC2 + 5389 ACC1 + 5390 PUSHACC6 + 5391 PUSHOFFSETCLOSURE0 + 5392 APPLY2 + 5393 PUSHACC3 + 5394 PUSHACC5 + 5395 PUSHACC7 + 5396 PUSHENVACC2 5397 APPTERM 4, 11 5400 RETURN 2 - 5402 RESTART + 5402 RESTART 5403 GRAB 1 - 5405 ACC1 + 5405 ACC1 5406 BRANCHIFNOT 5425 - 5408 ACC1 - 5409 GETFIELD0 - 5410 PUSHACC1 - 5411 PUSHOFFSETCLOSURE0 - 5412 APPLY2 - 5413 ACC1 - 5414 GETFIELD2 - 5415 PUSHACC2 - 5416 GETFIELD1 - 5417 PUSHACC2 - 5418 APPLY2 - 5419 ACC1 - 5420 GETFIELD3 - 5421 PUSHACC1 - 5422 PUSHOFFSETCLOSURE0 + 5408 ACC1 + 5409 GETFIELD0 + 5410 PUSHACC1 + 5411 PUSHOFFSETCLOSURE0 + 5412 APPLY2 + 5413 ACC1 + 5414 GETFIELD2 + 5415 PUSHACC2 + 5416 GETFIELD1 + 5417 PUSHACC2 + 5418 APPLY2 + 5419 ACC1 + 5420 GETFIELD3 + 5421 PUSHACC1 + 5422 PUSHOFFSETCLOSURE0 5423 APPTERM2 4 5425 RETURN 2 - 5427 RESTART + 5427 RESTART 5428 GRAB 1 - 5430 ACC1 + 5430 ACC1 5431 BRANCHIFNOT 5455 - 5433 ACC1 + 5433 ACC1 5434 GETFIELD 4 - 5436 PUSHACC2 - 5437 GETFIELD3 - 5438 PUSHACC2 - 5439 PUSHOFFSETCLOSURE0 - 5440 APPLY2 - 5441 PUSHACC3 - 5442 GETFIELD2 - 5443 PUSHACC3 - 5444 APPLY1 - 5445 PUSHACC4 - 5446 GETFIELD1 - 5447 PUSHACC5 - 5448 GETFIELD0 - 5449 PUSHACC5 - 5450 PUSHOFFSETCLOSURE0 - 5451 APPLY2 + 5436 PUSHACC2 + 5437 GETFIELD3 + 5438 PUSHACC2 + 5439 PUSHOFFSETCLOSURE0 + 5440 APPLY2 + 5441 PUSHACC3 + 5442 GETFIELD2 + 5443 PUSHACC3 + 5444 APPLY1 + 5445 PUSHACC4 + 5446 GETFIELD1 + 5447 PUSHACC5 + 5448 GETFIELD0 + 5449 PUSHACC5 + 5450 PUSHOFFSETCLOSURE0 + 5451 APPLY2 5452 MAKEBLOCK 5, 0 5455 RETURN 2 - 5457 RESTART + 5457 RESTART 5458 GRAB 2 - 5460 ACC1 + 5460 ACC1 5461 BRANCHIFNOT 5481 - 5463 ACC2 - 5464 PUSHACC2 - 5465 GETFIELD3 - 5466 PUSHACC2 - 5467 PUSHOFFSETCLOSURE0 - 5468 APPLY3 - 5469 PUSHACC2 - 5470 GETFIELD2 - 5471 PUSHACC3 - 5472 GETFIELD1 - 5473 PUSHACC3 - 5474 APPLY3 - 5475 PUSHACC2 - 5476 GETFIELD0 - 5477 PUSHACC2 - 5478 PUSHOFFSETCLOSURE0 + 5463 ACC2 + 5464 PUSHACC2 + 5465 GETFIELD3 + 5466 PUSHACC2 + 5467 PUSHOFFSETCLOSURE0 + 5468 APPLY3 + 5469 PUSHACC2 + 5470 GETFIELD2 + 5471 PUSHACC3 + 5472 GETFIELD1 + 5473 PUSHACC3 + 5474 APPLY3 + 5475 PUSHACC2 + 5476 GETFIELD0 + 5477 PUSHACC2 + 5478 PUSHOFFSETCLOSURE0 5479 APPTERM3 6 - 5481 ACC2 + 5481 ACC2 5482 RETURN 3 - 5484 RESTART + 5484 RESTART 5485 GRAB 3 - 5487 ACC0 + 5487 ACC0 5488 BRANCHIFNOT 5495 - 5490 ACC0 + 5490 ACC0 5491 GETFIELD 4 5493 BRANCH 5496 - 5495 CONST0 - 5496 PUSHACC4 + 5495 CONST0 + 5496 PUSHACC4 5497 BRANCHIFNOT 5504 - 5499 ACC4 + 5499 ACC4 5500 GETFIELD 4 5502 BRANCH 5505 - 5504 CONST0 - 5505 PUSHACC0 + 5504 CONST0 + 5505 PUSHACC0 5506 OFFSETINT 2 - 5508 PUSHACC2 - 5509 GTINT + 5508 PUSHACC2 + 5509 GTINT 5510 BRANCHIFNOT 5603 - 5512 ACC2 + 5512 ACC2 5513 BRANCHIFNOT 5596 - 5515 ACC2 - 5516 GETFIELD0 - 5517 PUSHACC3 - 5518 GETFIELD1 - 5519 PUSHACC4 - 5520 GETFIELD2 - 5521 PUSHACC5 - 5522 GETFIELD3 - 5523 PUSHACC0 - 5524 PUSHENVACC1 - 5525 APPLY1 - 5526 PUSHACC4 - 5527 PUSHENVACC1 - 5528 APPLY1 - 5529 GEINT + 5515 ACC2 + 5516 GETFIELD0 + 5517 PUSHACC3 + 5518 GETFIELD1 + 5519 PUSHACC4 + 5520 GETFIELD2 + 5521 PUSHACC5 + 5522 GETFIELD3 + 5523 PUSHACC0 + 5524 PUSHENVACC1 + 5525 APPLY1 + 5526 PUSHACC4 + 5527 PUSHENVACC1 + 5528 APPLY1 + 5529 GEINT 5530 BRANCHIFNOT 5551 5532 PUSH_RETADDR 5544 5534 ACC 12 5536 PUSHACC 12 5538 PUSHACC 12 - 5540 PUSHACC6 - 5541 PUSHENVACC2 + 5540 PUSHACC6 + 5541 PUSHENVACC2 5542 APPLY 4 - 5544 PUSHACC2 - 5545 PUSHACC4 - 5546 PUSHACC6 - 5547 PUSHENVACC2 + 5544 PUSHACC2 + 5545 PUSHACC4 + 5546 PUSHACC6 + 5547 PUSHENVACC2 5548 APPTERM 4, 14 - 5551 ACC0 + 5551 ACC0 5552 BRANCHIFNOT 5589 5554 PUSH_RETADDR 5567 5556 ACC 12 5558 PUSHACC 12 5560 PUSHACC 12 - 5562 PUSHACC6 - 5563 GETFIELD3 - 5564 PUSHENVACC2 + 5562 PUSHACC6 + 5563 GETFIELD3 + 5564 PUSHENVACC2 5565 APPLY 4 - 5567 PUSHACC1 - 5568 GETFIELD2 - 5569 PUSHACC2 - 5570 GETFIELD1 - 5571 PUSH + 5567 PUSHACC1 + 5568 GETFIELD2 + 5569 PUSHACC2 + 5570 GETFIELD1 + 5571 PUSH 5572 PUSH_RETADDR 5585 - 5574 ACC6 - 5575 GETFIELD0 + 5574 ACC6 + 5575 GETFIELD0 5576 PUSHACC 8 5578 PUSHACC 10 5580 PUSHACC 12 - 5582 PUSHENVACC2 + 5582 PUSHENVACC2 5583 APPLY 4 - 5585 PUSHENVACC2 + 5585 PUSHENVACC2 5586 APPTERM 4, 14 5589 GETGLOBAL "Map.bal" 5591 PUSHGETGLOBALFIELD Pervasives, 2 @@ -3836,66 +3836,66 @@ if o#m <> 23 then raise Not_found 5596 GETGLOBAL "Map.bal" 5598 PUSHGETGLOBALFIELD Pervasives, 2 5601 APPTERM1 7 - 5603 ACC1 + 5603 ACC1 5604 OFFSETINT 2 - 5606 PUSHACC1 - 5607 GTINT + 5606 PUSHACC1 + 5607 GTINT 5608 BRANCHIFNOT 5703 - 5610 ACC5 + 5610 ACC5 5611 BRANCHIFNOT 5696 - 5613 ACC5 - 5614 GETFIELD0 - 5615 PUSHACC6 - 5616 GETFIELD1 - 5617 PUSHACC7 - 5618 GETFIELD2 + 5613 ACC5 + 5614 GETFIELD0 + 5615 PUSHACC6 + 5616 GETFIELD1 + 5617 PUSHACC7 + 5618 GETFIELD2 5619 PUSHACC 8 - 5621 GETFIELD3 - 5622 PUSHACC3 - 5623 PUSHENVACC1 - 5624 APPLY1 - 5625 PUSHACC1 - 5626 PUSHENVACC1 - 5627 APPLY1 - 5628 GEINT + 5621 GETFIELD3 + 5622 PUSHACC3 + 5623 PUSHENVACC1 + 5624 APPLY1 + 5625 PUSHACC1 + 5626 PUSHENVACC1 + 5627 APPLY1 + 5628 GEINT 5629 BRANCHIFNOT 5652 - 5631 ACC0 - 5632 PUSHACC2 - 5633 PUSHACC4 - 5634 PUSH + 5631 ACC0 + 5632 PUSHACC2 + 5633 PUSHACC4 + 5634 PUSH 5635 PUSH_RETADDR 5648 5637 ACC 9 5639 PUSHACC 15 5641 PUSHACC 15 5643 PUSHACC 15 - 5645 PUSHENVACC2 + 5645 PUSHENVACC2 5646 APPLY 4 - 5648 PUSHENVACC2 + 5648 PUSHENVACC2 5649 APPTERM 4, 14 - 5652 ACC3 + 5652 ACC3 5653 BRANCHIFNOT 5689 5655 PUSH_RETADDR 5666 - 5657 ACC3 - 5658 PUSHACC5 - 5659 PUSHACC7 + 5657 ACC3 + 5658 PUSHACC5 + 5659 PUSHACC7 5660 PUSHACC 9 - 5662 GETFIELD3 - 5663 PUSHENVACC2 + 5662 GETFIELD3 + 5663 PUSHENVACC2 5664 APPLY 4 - 5666 PUSHACC4 - 5667 GETFIELD2 - 5668 PUSHACC5 - 5669 GETFIELD1 - 5670 PUSH + 5666 PUSHACC4 + 5667 GETFIELD2 + 5668 PUSHACC5 + 5669 GETFIELD1 + 5670 PUSH 5671 PUSH_RETADDR 5685 5673 ACC 9 - 5675 GETFIELD0 + 5675 GETFIELD0 5676 PUSHACC 15 5678 PUSHACC 15 5680 PUSHACC 15 - 5682 PUSHENVACC2 + 5682 PUSHENVACC2 5683 APPLY 4 - 5685 PUSHENVACC2 + 5685 PUSHENVACC2 5686 APPTERM 4, 14 5689 GETGLOBAL "Map.bal" 5691 PUSHGETGLOBALFIELD Pervasives, 2 @@ -3903,79 +3903,79 @@ if o#m <> 23 then raise Not_found 5696 GETGLOBAL "Map.bal" 5698 PUSHGETGLOBALFIELD Pervasives, 2 5701 APPTERM1 7 - 5703 ACC0 - 5704 PUSHACC2 - 5705 GEINT + 5703 ACC0 + 5704 PUSHACC2 + 5705 GEINT 5706 BRANCHIFNOT 5713 - 5708 ACC1 + 5708 ACC1 5709 OFFSETINT 1 5711 BRANCH 5716 - 5713 ACC0 + 5713 ACC0 5714 OFFSETINT 1 - 5716 PUSHACC6 - 5717 PUSHACC6 - 5718 PUSHACC6 - 5719 PUSHACC6 + 5716 PUSHACC6 + 5717 PUSHACC6 + 5718 PUSHACC6 + 5719 PUSHACC6 5720 MAKEBLOCK 5, 0 5723 RETURN 6 - 5725 RESTART + 5725 RESTART 5726 GRAB 3 - 5728 ACC0 - 5729 PUSHENVACC1 - 5730 APPLY1 - 5731 PUSHACC4 - 5732 PUSHENVACC1 - 5733 APPLY1 - 5734 PUSHACC0 - 5735 PUSHACC2 - 5736 GEINT + 5728 ACC0 + 5729 PUSHENVACC1 + 5730 APPLY1 + 5731 PUSHACC4 + 5732 PUSHENVACC1 + 5733 APPLY1 + 5734 PUSHACC0 + 5735 PUSHACC2 + 5736 GEINT 5737 BRANCHIFNOT 5744 - 5739 ACC1 + 5739 ACC1 5740 OFFSETINT 1 5742 BRANCH 5747 - 5744 ACC0 + 5744 ACC0 5745 OFFSETINT 1 - 5747 PUSHACC6 - 5748 PUSHACC6 - 5749 PUSHACC6 - 5750 PUSHACC6 + 5747 PUSHACC6 + 5748 PUSHACC6 + 5749 PUSHACC6 + 5750 PUSHACC6 5751 MAKEBLOCK 5, 0 5754 RETURN 6 - 5756 ACC0 + 5756 ACC0 5757 BRANCHIFNOT 5764 - 5759 ACC0 + 5759 ACC0 5760 GETFIELD 4 5762 RETURN 1 - 5764 CONST0 + 5764 CONST0 5765 RETURN 1 - 5767 CONST0 - 5768 PUSH + 5767 CONST0 + 5768 PUSH 5769 CLOSURE 0, 5756 - 5772 PUSHACC0 + 5772 PUSHACC0 5773 CLOSURE 1, 5726 - 5776 PUSHACC0 - 5777 PUSHACC2 + 5776 PUSHACC0 + 5777 PUSHACC2 5778 CLOSURE 2, 5485 - 5781 PUSHACC0 - 5782 PUSHACC5 + 5781 PUSHACC0 + 5782 PUSHACC5 5783 CLOSUREREC 2, 5132 - 5787 ACC5 + 5787 ACC5 5788 CLOSUREREC 1, 5212 - 5792 ACC6 + 5792 ACC6 5793 CLOSUREREC 1, 5253 - 5797 ACC3 + 5797 ACC3 5798 CLOSUREREC 1, 5289 - 5802 ACC0 - 5803 PUSHACC5 + 5802 ACC0 + 5803 PUSHACC5 5804 PUSHACC 10 5806 CLOSUREREC 3, 5344 5810 CLOSUREREC 0, 5403 5814 CLOSUREREC 0, 5428 5818 CLOSUREREC 0, 5458 - 5822 ACC0 - 5823 PUSHACC2 - 5824 PUSHACC4 - 5825 PUSHACC6 + 5822 ACC0 + 5823 PUSHACC2 + 5824 PUSHACC4 + 5825 PUSHACC6 5826 PUSHACC 8 5828 PUSHACC 10 5830 PUSHACC 12 @@ -3987,7 +3987,7 @@ if o#m <> 23 then raise Not_found 5842 MAKEBLOCK 12, 0 5845 RETURN 13 5847 CLOSURE 0, 5767 - 5850 PUSHACC0 + 5850 PUSHACC0 5851 CLOSURE 1, 5100 5854 MAKEBLOCK1 0 5856 POP 1 @@ -3995,238 +3995,238 @@ if o#m <> 23 then raise Not_found 5860 BRANCH 5957 5862 CONSTINT 16 5864 C_CALL1 create_string - 5866 PUSH + 5866 PUSH 5867 PUSH_RETADDR 5879 5869 CONSTINT 16 - 5871 PUSHCONST0 - 5872 PUSHACC5 - 5873 PUSHACC7 + 5871 PUSHCONST0 + 5872 PUSHACC5 + 5873 PUSHACC7 5874 PUSHGETGLOBALFIELD Pervasives, 56 5877 APPLY 4 - 5879 ACC0 + 5879 ACC0 5880 RETURN 2 - 5882 RESTART + 5882 RESTART 5883 GRAB 1 5885 CONSTINT 16 - 5887 PUSHCONST0 - 5888 PUSHACC3 - 5889 PUSHACC3 + 5887 PUSHCONST0 + 5888 PUSHACC3 + 5889 PUSHACC3 5890 PUSHGETGLOBALFIELD Pervasives, 41 5893 APPTERM 4, 6 - 5896 ACC0 + 5896 ACC0 5897 PUSHGETGLOBALFIELD Pervasives, 51 - 5900 APPLY1 - 5901 PUSHACC0 + 5900 APPLY1 + 5901 PUSHACC0 5902 PUSHGETGLOBALFIELD Pervasives, 62 - 5905 APPLY1 - 5906 PUSHACC1 + 5905 APPLY1 + 5906 PUSHACC1 5907 C_CALL2 md5_chan - 5909 PUSHACC1 + 5909 PUSHACC1 5910 PUSHGETGLOBALFIELD Pervasives, 63 - 5913 APPLY1 - 5914 ACC0 + 5913 APPLY1 + 5914 ACC0 5915 RETURN 3 - 5917 RESTART + 5917 RESTART 5918 GRAB 2 - 5920 CONST0 - 5921 PUSHACC2 - 5922 LTINT + 5920 CONST0 + 5921 PUSHACC2 + 5922 LTINT 5923 BRANCHIF 5934 - 5925 ACC0 + 5925 ACC0 5926 C_CALL1 ml_string_length - 5928 PUSHACC3 - 5929 PUSHACC3 - 5930 ADDINT - 5931 GTINT + 5928 PUSHACC3 + 5929 PUSHACC3 + 5930 ADDINT + 5931 GTINT 5932 BRANCHIFNOT 5941 5934 GETGLOBAL "Digest.substring" 5936 PUSHGETGLOBALFIELD Pervasives, 2 5939 APPTERM1 4 - 5941 ACC2 - 5942 PUSHACC2 - 5943 PUSHACC2 + 5941 ACC2 + 5942 PUSHACC2 + 5943 PUSHACC2 5944 C_CALL3 md5_string 5946 RETURN 3 - 5948 ACC0 + 5948 ACC0 5949 C_CALL1 ml_string_length - 5951 PUSHCONST0 - 5952 PUSHACC2 + 5951 PUSHCONST0 + 5952 PUSHACC2 5953 C_CALL3 md5_string 5955 RETURN 1 5957 CLOSURE 0, 5948 - 5960 PUSH + 5960 PUSH 5961 CLOSURE 0, 5918 - 5964 PUSH + 5964 PUSH 5965 CLOSURE 0, 5896 - 5968 PUSH + 5968 PUSH 5969 CLOSURE 0, 5883 - 5972 PUSH + 5972 PUSH 5973 CLOSURE 0, 5862 - 5976 PUSHACC0 - 5977 PUSHACC2 - 5978 PUSHACC4 - 5979 PUSHACC6 + 5976 PUSHACC0 + 5977 PUSHACC2 + 5978 PUSHACC4 + 5979 PUSHACC6 5980 PUSHACC 8 5982 MAKEBLOCK 5, 0 5985 POP 5 5987 SETGLOBAL Digest 5989 BRANCH 6245 - 5991 CONST0 - 5992 PUSHENVACC1 - 5993 APPLY1 - 5994 PUSHACC1 - 5995 PUSHACC1 - 5996 GEINT + 5991 CONST0 + 5992 PUSHENVACC1 + 5993 APPLY1 + 5994 PUSHACC1 + 5995 PUSHACC1 + 5996 GEINT 5997 BRANCHIFNOT 6003 - 5999 ACC1 - 6000 PUSHOFFSETCLOSURE0 + 5999 ACC1 + 6000 PUSHOFFSETCLOSURE0 6001 APPTERM1 3 - 6003 ACC0 + 6003 ACC0 6004 RETURN 2 - 6006 CONST0 + 6006 CONST0 6007 C_CALL1 sys_random_seed - 6009 PUSHENVACC1 + 6009 PUSHENVACC1 6010 APPTERM1 2 6012 CONSTINT 27182818 - 6014 PUSHENVACC2 - 6015 APPLY1 - 6016 CONST0 - 6017 PUSHACC1 - 6018 VECTLENGTH + 6014 PUSHENVACC2 + 6015 APPLY1 + 6016 CONST0 + 6017 PUSHACC1 + 6018 VECTLENGTH 6019 OFFSETINT -1 - 6021 PUSH + 6021 PUSH 6022 BRANCH 6046 - 6024 CHECK_SIGNALS + 6024 CHECK_SIGNALS 6025 CONSTINT 55 - 6027 PUSHACC2 - 6028 MODINT - 6029 PUSHACC2 - 6030 PUSHACC4 - 6031 GETVECTITEM - 6032 PUSHACC1 - 6033 PUSHENVACC1 - 6034 GETVECTITEM - 6035 ADDINT - 6036 PUSHACC1 - 6037 PUSHENVACC1 - 6038 SETVECTITEM + 6027 PUSHACC2 + 6028 MODINT + 6029 PUSHACC2 + 6030 PUSHACC4 + 6031 GETVECTITEM + 6032 PUSHACC1 + 6033 PUSHENVACC1 + 6034 GETVECTITEM + 6035 ADDINT + 6036 PUSHACC1 + 6037 PUSHENVACC1 + 6038 SETVECTITEM 6039 POP 1 - 6041 ACC1 + 6041 ACC1 6042 OFFSETINT 1 6044 ASSIGN 1 - 6046 ACC0 - 6047 PUSHACC2 - 6048 LEINT + 6046 ACC0 + 6047 PUSHACC2 + 6048 LEINT 6049 BRANCHIF 6024 - 6051 CONST0 + 6051 CONST0 6052 RETURN 3 - 6054 ENVACC1 - 6055 GETFIELD0 + 6054 ENVACC1 + 6055 GETFIELD0 6056 OFFSETINT 1 - 6058 PUSHENVACC1 - 6059 SETFIELD0 - 6060 ENVACC1 - 6061 GETFIELD0 + 6058 PUSHENVACC1 + 6059 SETFIELD0 + 6060 ENVACC1 + 6061 GETFIELD0 6062 PUSHGETGLOBALFIELD Pervasives, 14 - 6065 APPLY1 + 6065 APPLY1 6066 PUSHGETGLOBALFIELD Digest, 0 - 6069 APPLY1 + 6069 APPLY1 6070 PUSHCONSTINT 22 - 6072 PUSHCONST3 - 6073 PUSHACC2 + 6072 PUSHCONST3 + 6073 PUSHACC2 6074 C_CALL2 string_get - 6076 LSLINT + 6076 LSLINT 6077 PUSHCONSTINT 16 - 6079 PUSHCONST2 - 6080 PUSHACC3 + 6079 PUSHCONST2 + 6080 PUSHACC3 6081 C_CALL2 string_get - 6083 LSLINT + 6083 LSLINT 6084 PUSHCONSTINT 8 - 6086 PUSHCONST1 - 6087 PUSHACC4 + 6086 PUSHCONST1 + 6087 PUSHACC4 6088 C_CALL2 string_get - 6090 LSLINT - 6091 PUSHCONST0 - 6092 PUSHACC4 + 6090 LSLINT + 6091 PUSHCONST0 + 6092 PUSHACC4 6093 C_CALL2 string_get - 6095 ADDINT - 6096 ADDINT - 6097 XORINT + 6095 ADDINT + 6096 ADDINT + 6097 XORINT 6098 RETURN 2 - 6100 ACC0 + 6100 ACC0 6101 MAKEBLOCK1 0 - 6103 PUSHACC0 + 6103 PUSHACC0 6104 CLOSURE 1, 6054 - 6107 PUSHCONST0 + 6107 PUSHCONST0 6108 PUSHCONSTINT 54 - 6110 PUSH + 6110 PUSH 6111 BRANCH 6125 - 6113 CHECK_SIGNALS - 6114 CONST0 - 6115 PUSHACC3 - 6116 APPLY1 - 6117 PUSHACC2 - 6118 PUSHENVACC1 - 6119 SETVECTITEM - 6120 ACC1 + 6113 CHECK_SIGNALS + 6114 CONST0 + 6115 PUSHACC3 + 6116 APPLY1 + 6117 PUSHACC2 + 6118 PUSHENVACC1 + 6119 SETVECTITEM + 6120 ACC1 6121 OFFSETINT 1 6123 ASSIGN 1 - 6125 ACC0 - 6126 PUSHACC2 - 6127 LEINT + 6125 ACC0 + 6126 PUSHACC2 + 6127 LEINT 6128 BRANCHIF 6113 - 6130 CONST0 + 6130 CONST0 6131 POP 2 - 6133 CONST0 - 6134 PUSHENVACC2 - 6135 SETFIELD0 + 6133 CONST0 + 6134 PUSHENVACC2 + 6135 SETFIELD0 6136 RETURN 3 - 6138 ACC0 - 6139 PUSHCONST0 - 6140 PUSHENVACC1 - 6141 APPLY1 + 6138 ACC0 + 6139 PUSHCONST0 + 6140 PUSHENVACC1 + 6141 APPLY1 6142 C_CALL2 mul_float 6144 RETURN 1 6146 CONSTINT 1073741823 - 6148 PUSHACC1 - 6149 GTINT + 6148 PUSHACC1 + 6149 GTINT 6150 BRANCHIF 6157 - 6152 CONST0 - 6153 PUSHACC1 - 6154 LEINT + 6152 CONST0 + 6153 PUSHACC1 + 6154 LEINT 6155 BRANCHIFNOT 6164 6157 GETGLOBAL "Random.int" 6159 PUSHGETGLOBALFIELD Pervasives, 2 6162 APPTERM1 2 - 6164 ACC0 - 6165 PUSHACC1 - 6166 PUSHACC2 + 6164 ACC0 + 6165 PUSHACC1 + 6166 PUSHACC2 6167 PUSHCONSTINT 1073741823 - 6169 DIVINT - 6170 MULINT - 6171 PUSHENVACC1 - 6172 APPLY1 - 6173 MODINT + 6169 DIVINT + 6170 MULINT + 6171 PUSHENVACC1 + 6172 APPLY1 + 6173 MODINT 6174 RETURN 1 6176 GETGLOBAL 1073741824 - 6178 PUSHCONST0 - 6179 PUSHENVACC1 - 6180 APPLY1 + 6178 PUSHCONST0 + 6179 PUSHENVACC1 + 6180 APPLY1 6181 C_CALL1 float_of_int - 6183 PUSHCONST0 - 6184 PUSHENVACC1 - 6185 APPLY1 + 6183 PUSHCONST0 + 6184 PUSHENVACC1 + 6185 APPLY1 6186 C_CALL1 float_of_int - 6188 PUSHCONST0 - 6189 PUSHENVACC1 - 6190 APPLY1 + 6188 PUSHCONST0 + 6189 PUSHENVACC1 + 6190 APPLY1 6191 C_CALL1 float_of_int - 6193 PUSHACC3 - 6194 PUSHACC1 - 6195 PUSHACC5 - 6196 PUSHACC4 - 6197 PUSHACC7 - 6198 PUSHACC7 + 6193 PUSHACC3 + 6194 PUSHACC1 + 6195 PUSHACC5 + 6196 PUSHACC4 + 6197 PUSHACC7 + 6198 PUSHACC7 6199 C_CALL2 div_float 6201 C_CALL2 add_float 6203 C_CALL2 div_float @@ -4234,32 +4234,32 @@ if o#m <> 23 then raise Not_found 6207 C_CALL2 div_float 6209 RETURN 5 6211 CONSTINT 55 - 6213 PUSHENVACC2 - 6214 GETFIELD0 + 6213 PUSHENVACC2 + 6214 GETFIELD0 6215 OFFSETINT 1 - 6217 MODINT - 6218 PUSHENVACC2 - 6219 SETFIELD0 - 6220 ENVACC2 - 6221 GETFIELD0 - 6222 PUSHENVACC1 - 6223 GETVECTITEM + 6217 MODINT + 6218 PUSHENVACC2 + 6219 SETFIELD0 + 6220 ENVACC2 + 6221 GETFIELD0 + 6222 PUSHENVACC1 + 6223 GETVECTITEM 6224 PUSHCONSTINT 55 - 6226 PUSHENVACC2 - 6227 GETFIELD0 + 6226 PUSHENVACC2 + 6227 GETFIELD0 6228 OFFSETINT 24 - 6230 MODINT - 6231 PUSHENVACC1 - 6232 GETVECTITEM - 6233 ADDINT - 6234 PUSHACC0 - 6235 PUSHENVACC2 - 6236 GETFIELD0 - 6237 PUSHENVACC1 - 6238 SETVECTITEM + 6230 MODINT + 6231 PUSHENVACC1 + 6232 GETVECTITEM + 6233 ADDINT + 6234 PUSHACC0 + 6235 PUSHENVACC2 + 6236 GETFIELD0 + 6237 PUSHENVACC1 + 6238 SETVECTITEM 6239 CONSTINT 1073741823 - 6241 PUSHACC1 - 6242 ANDINT + 6241 PUSHACC1 + 6242 ANDINT 6243 RETURN 2 6245 CONSTINT 440266690 6247 PUSHCONSTINT 124177607 @@ -4317,1429 +4317,1429 @@ if o#m <> 23 then raise Not_found 6351 PUSHCONSTINT 1051173471 6353 PUSHCONSTINT 561073064 6355 MAKEBLOCK 55, 0 - 6358 PUSHCONST0 + 6358 PUSHCONST0 6359 MAKEBLOCK1 0 - 6361 PUSHACC0 - 6362 PUSHACC2 + 6361 PUSHACC0 + 6362 PUSHACC2 6363 CLOSURE 2, 6211 - 6366 PUSHACC0 + 6366 PUSHACC0 6367 CLOSURE 1, 6176 - 6370 PUSHACC1 + 6370 PUSHACC1 6371 CLOSUREREC 1, 5991 - 6375 ACC0 + 6375 ACC0 6376 CLOSURE 1, 6146 - 6379 PUSHACC2 + 6379 PUSHACC2 6380 CLOSURE 1, 6138 - 6383 PUSHACC5 - 6384 PUSHACC7 + 6383 PUSHACC5 + 6384 PUSHACC7 6385 CLOSURE 2, 6100 - 6388 PUSHACC0 + 6388 PUSHACC0 6389 PUSHACC 8 6391 CLOSURE 2, 6012 - 6394 PUSHACC1 + 6394 PUSHACC1 6395 CLOSURE 1, 6006 - 6398 PUSHACC3 - 6399 PUSHACC5 + 6398 PUSHACC3 + 6399 PUSHACC5 6400 PUSHACC 9 - 6402 PUSHACC3 - 6403 PUSHACC5 - 6404 PUSHACC7 + 6402 PUSHACC3 + 6403 PUSHACC5 + 6404 PUSHACC7 6405 MAKEBLOCK 6, 0 6408 POP 10 6410 SETGLOBAL Random 6412 BRANCH 8038 - 6414 RESTART + 6414 RESTART 6415 GRAB 1 - 6417 ACC1 + 6417 ACC1 6418 BRANCHIFNOT 6441 - 6420 ACC1 - 6421 GETFIELD0 - 6422 PUSHACC2 - 6423 GETFIELD1 - 6424 PUSHACC1 - 6425 PUSHACC3 - 6426 EQ + 6420 ACC1 + 6421 GETFIELD0 + 6422 PUSHACC2 + 6423 GETFIELD1 + 6424 PUSHACC1 + 6425 PUSHACC3 + 6426 EQ 6427 BRANCHIFNOT 6432 - 6429 ACC0 + 6429 ACC0 6430 RETURN 4 - 6432 ACC0 - 6433 PUSHACC3 - 6434 PUSHOFFSETCLOSURE0 - 6435 APPLY2 - 6436 PUSHACC2 + 6432 ACC0 + 6433 PUSHACC3 + 6434 PUSHOFFSETCLOSURE0 + 6435 APPLY2 + 6436 PUSHACC2 6437 MAKEBLOCK2 0 6439 POP 2 6441 RETURN 2 - 6443 RESTART + 6443 RESTART 6444 GRAB 1 - 6446 CONST0 - 6447 PUSHACC2 - 6448 GTINT + 6446 CONST0 + 6447 PUSHACC2 + 6448 GTINT 6449 BRANCHIFNOT 6512 - 6451 CONST0 - 6452 PUSHENVACC2 - 6453 GETFIELD0 - 6454 GTINT + 6451 CONST0 + 6452 PUSHENVACC2 + 6453 GETFIELD0 + 6454 GTINT 6455 BRANCHIFNOT 6512 - 6457 ENVACC2 - 6458 GETFIELD0 + 6457 ENVACC2 + 6458 GETFIELD0 6459 PUSHGETGLOBALFIELD Random, 4 - 6462 APPLY1 - 6463 PUSHACC0 - 6464 PUSHENVACC1 - 6465 GETFIELD0 + 6462 APPLY1 + 6463 PUSHACC0 + 6464 PUSHENVACC1 + 6465 GETFIELD0 6466 C_CALL2 array_get_addr 6468 PUSHENVACC 5 - 6470 APPLY1 + 6470 APPLY1 6471 BRANCHIF 6482 - 6473 ACC0 + 6473 ACC0 6474 PUSHENVACC 4 - 6476 APPLY1 - 6477 ACC2 - 6478 PUSHACC2 - 6479 PUSHOFFSETCLOSURE0 + 6476 APPLY1 + 6477 ACC2 + 6478 PUSHACC2 + 6479 PUSHOFFSETCLOSURE0 6480 APPTERM2 5 6482 PUSHTRAP 6496 - 6484 ACC5 - 6485 PUSHACC5 - 6486 PUSHENVACC1 - 6487 GETFIELD0 + 6484 ACC5 + 6485 PUSHACC5 + 6486 PUSHENVACC1 + 6487 GETFIELD0 6488 C_CALL2 array_get_addr 6490 PUSHENVACC 7 - 6492 APPLY2 - 6493 POPTRAP + 6492 APPLY2 + 6493 POPTRAP 6494 RETURN 3 6496 PUSHENVACC 6 - 6498 PUSHACC1 - 6499 GETFIELD0 - 6500 EQ + 6498 PUSHACC1 + 6499 GETFIELD0 + 6500 EQ 6501 BRANCHIFNOT 6510 - 6503 ACC3 + 6503 ACC3 6504 OFFSETINT -1 - 6506 PUSHACC3 - 6507 PUSHOFFSETCLOSURE0 + 6506 PUSHACC3 + 6507 PUSHOFFSETCLOSURE0 6508 APPTERM2 6 - 6510 ACC0 - 6511 RAISE - 6512 ACC0 - 6513 PUSHENVACC3 - 6514 APPLY1 - 6515 ACC0 + 6510 ACC0 + 6511 RAISE + 6512 ACC0 + 6513 PUSHENVACC3 + 6514 APPLY1 + 6515 ACC0 6516 RETURN 2 - 6518 RESTART + 6518 RESTART 6519 GRAB 1 - 6521 ACC1 + 6521 ACC1 6522 BRANCHIFNOT 6534 - 6524 ACC0 - 6525 PUSHACC2 - 6526 GETFIELD0 - 6527 APPLY1 - 6528 ACC1 - 6529 GETFIELD1 - 6530 PUSHACC1 - 6531 PUSHOFFSETCLOSURE0 + 6524 ACC0 + 6525 PUSHACC2 + 6526 GETFIELD0 + 6527 APPLY1 + 6528 ACC1 + 6529 GETFIELD1 + 6530 PUSHACC1 + 6531 PUSHOFFSETCLOSURE0 6532 APPTERM2 4 6534 RETURN 2 - 6536 CONST0 - 6537 PUSHENVACC1 + 6536 CONST0 + 6537 PUSHENVACC1 6538 OFFSETINT -1 - 6540 PUSH + 6540 PUSH 6541 BRANCH 6567 - 6543 CHECK_SIGNALS - 6544 ENVACC2 - 6545 PUSHACC2 - 6546 PUSHACC4 + 6543 CHECK_SIGNALS + 6544 ENVACC2 + 6545 PUSHACC2 + 6546 PUSHACC4 6547 C_CALL2 array_get - 6549 EQ + 6549 EQ 6550 BRANCHIFNOT 6556 6552 CONSTINT 46 6554 BRANCH 6558 6556 CONSTINT 42 6558 PUSHGETGLOBALFIELD Pervasives, 20 - 6561 APPLY1 - 6562 ACC1 + 6561 APPLY1 + 6562 ACC1 6563 OFFSETINT 1 6565 ASSIGN 1 - 6567 ACC0 - 6568 PUSHACC2 - 6569 LEINT + 6567 ACC0 + 6568 PUSHACC2 + 6569 LEINT 6570 BRANCHIF 6543 - 6572 CONST0 + 6572 CONST0 6573 POP 2 - 6575 CONST0 + 6575 CONST0 6576 PUSHGETGLOBALFIELD Pervasives, 25 6579 APPTERM1 2 - 6581 ENVACC3 - 6582 GETFIELD0 + 6581 ENVACC3 + 6582 GETFIELD0 6583 PUSHENVACC 4 - 6585 APPLY1 - 6586 PUSHENVACC2 - 6587 PUSHENVACC1 + 6585 APPLY1 + 6586 PUSHENVACC2 + 6587 PUSHENVACC1 6588 CLOSURE 2, 6536 6591 PUSHGETGLOBALFIELD List, 9 6594 APPTERM2 3 - 6596 ACC0 - 6597 GETFIELD1 + 6596 ACC0 + 6597 GETFIELD1 6598 RETURN 1 - 6600 RESTART + 6600 RESTART 6601 GRAB 1 - 6603 ACC1 - 6604 GETFIELD0 - 6605 PUSHACC1 - 6606 GETFIELD0 - 6607 LEINT + 6603 ACC1 + 6604 GETFIELD0 + 6605 PUSHACC1 + 6606 GETFIELD0 + 6607 LEINT 6608 RETURN 2 - 6610 ACC0 - 6611 PUSHACC1 - 6612 PUSHENVACC1 - 6613 APPLY1 + 6610 ACC0 + 6611 PUSHACC1 + 6612 PUSHENVACC1 + 6613 APPLY1 6614 MAKEBLOCK2 0 6616 RETURN 1 - 6618 ACC0 - 6619 PUSHENVACC1 + 6618 ACC0 + 6619 PUSHENVACC1 6620 CLOSURE 1, 6610 6623 PUSHGETGLOBALFIELD List, 10 - 6626 APPLY2 - 6627 PUSH + 6626 APPLY2 + 6627 PUSH 6628 CLOSURE 0, 6601 6631 PUSHGETGLOBALFIELD Sort, 0 - 6634 APPLY2 - 6635 PUSH + 6634 APPLY2 + 6635 PUSH 6636 CLOSURE 0, 6596 6639 PUSHGETGLOBALFIELD List, 10 6642 APPTERM2 3 - 6644 ENVACC3 - 6645 GETFIELD0 - 6646 VECTLENGTH + 6644 ENVACC3 + 6645 GETFIELD0 + 6646 VECTLENGTH 6647 PUSHENVACC 4 - 6649 GETFIELD0 - 6650 PUSHCONST0 + 6649 GETFIELD0 + 6650 PUSHCONST0 6651 PUSHENVACC 8 - 6653 APPLY1 - 6654 PUSHENVACC2 - 6655 GETFIELD0 + 6653 APPLY1 + 6654 PUSHENVACC2 + 6655 GETFIELD0 6656 PUSHGETGLOBALFIELD List, 0 - 6659 APPLY1 + 6659 APPLY1 6660 PUSHENVACC 7 - 6662 GETFIELD0 + 6662 GETFIELD0 6663 PUSHENVACC 6 - 6665 GETFIELD0 - 6666 PUSHENVACC1 - 6667 GETFIELD0 + 6665 GETFIELD0 + 6666 PUSHENVACC1 + 6667 GETFIELD0 6668 PUSHENVACC 5 - 6670 GETFIELD0 + 6670 GETFIELD0 6671 MAKEBLOCK 8, 0 6674 RETURN 1 - 6676 ACC0 - 6677 PUSHENVACC1 - 6678 APPLY1 - 6679 PUSHACC0 + 6676 ACC0 + 6677 PUSHENVACC1 + 6678 APPLY1 + 6679 PUSHACC0 6680 OFFSETINT -1 - 6682 PUSHENVACC2 + 6682 PUSHENVACC2 6683 C_CALL2 array_get_addr 6685 OFFSETINT 1 - 6687 PUSHACC1 + 6687 PUSHACC1 6688 OFFSETINT -1 - 6690 PUSHENVACC2 + 6690 PUSHENVACC2 6691 C_CALL3 array_set_addr 6693 RETURN 2 - 6695 CONST0 + 6695 CONST0 6696 PUSHCONSTINT 32 6698 C_CALL2 make_vect - 6700 PUSHENVACC1 - 6701 GETFIELD0 - 6702 PUSHACC1 - 6703 PUSHENVACC2 + 6700 PUSHENVACC1 + 6701 GETFIELD0 + 6702 PUSHACC1 + 6703 PUSHENVACC2 6704 CLOSURE 2, 6676 6707 PUSHGETGLOBALFIELD List, 9 - 6710 APPLY2 - 6711 ACC0 + 6710 APPLY2 + 6711 ACC0 6712 RETURN 2 - 6714 RESTART + 6714 RESTART 6715 GRAB 1 - 6717 ACC1 - 6718 PUSHENVACC1 - 6719 APPLY1 - 6720 PUSHACC1 - 6721 PUSHACC1 - 6722 GETFIELD1 - 6723 PUSHACC2 - 6724 GETFIELD0 - 6725 PUSHCONST0 - 6726 PUSHACC5 + 6717 ACC1 + 6718 PUSHENVACC1 + 6719 APPLY1 + 6720 PUSHACC1 + 6721 PUSHACC1 + 6722 GETFIELD1 + 6723 PUSHACC2 + 6724 GETFIELD0 + 6725 PUSHCONST0 + 6726 PUSHACC5 6727 C_CALL2 array_get_addr 6729 C_CALL2 array_get_addr 6731 C_CALL2 array_get_addr 6733 APPTERM1 4 - 6735 ACC0 - 6736 GETFIELD0 + 6735 ACC0 + 6736 GETFIELD0 6737 C_CALL1 obj_dup - 6739 PUSHENVACC1 - 6740 PUSHACC1 - 6741 PUSHENVACC2 - 6742 APPLY2 - 6743 ACC1 - 6744 GETFIELD2 - 6745 PUSHACC1 - 6746 PUSHENVACC3 - 6747 APPLY2 - 6748 ACC0 + 6739 PUSHENVACC1 + 6740 PUSHACC1 + 6741 PUSHENVACC2 + 6742 APPLY2 + 6743 ACC1 + 6744 GETFIELD2 + 6745 PUSHACC1 + 6746 PUSHENVACC3 + 6747 APPLY2 + 6748 ACC0 6749 RETURN 2 - 6751 RESTART + 6751 RESTART 6752 GRAB 1 - 6754 ACC1 + 6754 ACC1 6755 GETFIELD 7 - 6757 PUSHCONST0 - 6758 PUSHACC1 - 6759 NEQ + 6757 PUSHCONST0 + 6758 PUSHACC1 + 6759 NEQ 6760 BRANCHIFNOT 6767 - 6762 ACC0 - 6763 PUSHACC2 - 6764 PUSHENVACC1 + 6762 ACC0 + 6763 PUSHACC2 + 6764 PUSHENVACC1 6765 APPTERM2 5 6767 RETURN 3 - 6769 ACC0 - 6770 GETFIELD0 - 6771 PUSHENVACC1 + 6769 ACC0 + 6770 GETFIELD0 + 6771 PUSHENVACC1 6772 C_CALL2 obj_block - 6774 PUSHACC1 - 6775 GETFIELD1 - 6776 PUSHCONST0 - 6777 PUSHACC2 + 6774 PUSHACC1 + 6775 GETFIELD1 + 6776 PUSHCONST0 + 6777 PUSHACC2 6778 C_CALL3 array_unsafe_set - 6780 ENVACC2 - 6781 PUSHACC1 - 6782 PUSHENVACC3 - 6783 APPLY2 - 6784 ACC0 + 6780 ENVACC2 + 6781 PUSHACC1 + 6782 PUSHENVACC3 + 6783 APPLY2 + 6784 ACC0 6785 RETURN 2 - 6787 ACC0 - 6788 GETFIELD0 - 6789 PUSHENVACC3 - 6790 GETFIELD0 - 6791 ADDINT + 6787 ACC0 + 6788 GETFIELD0 + 6789 PUSHENVACC3 + 6790 GETFIELD0 + 6791 ADDINT 6792 OFFSETINT -1 - 6794 PUSHENVACC3 - 6795 SETFIELD0 - 6796 ENVACC1 - 6797 GETFIELD0 + 6794 PUSHENVACC3 + 6795 SETFIELD0 + 6796 ENVACC1 + 6797 GETFIELD0 6798 BRANCHIFNOT 6804 - 6800 ACC0 - 6801 GETFIELD1 - 6802 PUSHENVACC2 - 6803 APPLY1 - 6804 ACC0 + 6800 ACC0 + 6801 GETFIELD1 + 6802 PUSHENVACC2 + 6803 APPLY1 + 6804 ACC0 6805 GETFIELD 7 6807 PUSHGETGLOBALFIELD List, 4 - 6810 APPLY1 - 6811 PUSHACC1 + 6810 APPLY1 + 6811 PUSHACC1 6812 SETFIELD 7 6814 RETURN 1 - 6816 ACC0 - 6817 PUSHENVACC1 - 6818 APPLY1 + 6816 ACC0 + 6817 PUSHENVACC1 + 6818 APPLY1 6819 PUSHENVACC 4 - 6821 GETFIELD2 - 6822 PUSHACC1 - 6823 PUSHACC3 - 6824 PUSHENVACC2 - 6825 GETFIELD1 - 6826 APPLY3 + 6821 GETFIELD2 + 6822 PUSHACC1 + 6823 PUSHACC3 + 6824 PUSHENVACC2 + 6825 GETFIELD1 + 6826 APPLY3 6827 PUSHENVACC 4 - 6829 SETFIELD2 - 6830 ENVACC4 - 6831 GETFIELD3 - 6832 PUSHCONST1 - 6833 PUSHACC2 - 6834 PUSHENVACC3 - 6835 GETFIELD1 - 6836 APPLY3 + 6829 SETFIELD2 + 6830 ENVACC4 + 6831 GETFIELD3 + 6832 PUSHCONST1 + 6833 PUSHACC2 + 6834 PUSHENVACC3 + 6835 GETFIELD1 + 6836 APPLY3 6837 PUSHENVACC 4 - 6839 SETFIELD3 + 6839 SETFIELD3 6840 RETURN 2 - 6842 CONST0 + 6842 CONST0 6843 PUSHENVACC 4 - 6845 APPLY1 - 6846 PUSHACC1 - 6847 PUSHACC1 - 6848 PUSHENVACC3 - 6849 PUSHENVACC2 - 6850 PUSHENVACC1 + 6845 APPLY1 + 6846 PUSHACC1 + 6847 PUSHACC1 + 6848 PUSHENVACC3 + 6849 PUSHENVACC2 + 6850 PUSHENVACC1 6851 CLOSURE 4, 6816 6854 PUSHGETGLOBALFIELD List, 9 - 6857 APPLY2 - 6858 ACC0 + 6857 APPLY2 + 6858 ACC0 6859 RETURN 2 - 6861 RESTART + 6861 RESTART 6862 GRAB 1 - 6864 ACC0 + 6864 ACC0 6865 GETFIELD 7 - 6867 PUSHACC2 + 6867 PUSHACC2 6868 MAKEBLOCK2 0 - 6870 PUSHACC1 + 6870 PUSHACC1 6871 SETFIELD 7 6873 RETURN 2 - 6875 ENVACC1 - 6876 PUSHENVACC3 - 6877 PUSH + 6875 ENVACC1 + 6876 PUSHENVACC3 + 6877 PUSH 6878 BRANCH 6895 - 6880 CHECK_SIGNALS - 6881 ACC1 - 6882 PUSHENVACC2 - 6883 GETVECTITEM + 6880 CHECK_SIGNALS + 6881 ACC1 + 6882 PUSHENVACC2 + 6883 GETVECTITEM 6884 PUSHENVACC 4 - 6886 PUSHACC3 - 6887 ADDINT - 6888 PUSHACC4 - 6889 SETVECTITEM - 6890 ACC1 + 6886 PUSHACC3 + 6887 ADDINT + 6888 PUSHACC4 + 6889 SETVECTITEM + 6890 ACC1 6891 OFFSETINT 1 6893 ASSIGN 1 - 6895 ACC0 - 6896 PUSHACC2 - 6897 LEINT + 6895 ACC0 + 6896 PUSHACC2 + 6897 LEINT 6898 BRANCHIF 6880 - 6900 CONST0 + 6900 CONST0 6901 RETURN 3 - 6903 ENVACC2 - 6904 GETFIELD0 - 6905 PUSHENVACC2 - 6906 GETFIELD2 - 6907 GETFIELD0 + 6903 ENVACC2 + 6904 GETFIELD0 + 6905 PUSHENVACC2 + 6906 GETFIELD2 + 6907 GETFIELD0 6908 OFFSETINT -1 - 6910 PUSHENVACC3 - 6911 GETFIELD0 + 6910 PUSHENVACC3 + 6911 GETFIELD0 6912 OFFSETINT -1 - 6914 PUSHACC1 - 6915 PUSHACC1 - 6916 SUBINT - 6917 PUSHACC0 - 6918 PUSHACC3 - 6919 PUSHACC5 - 6920 PUSHENVACC1 + 6914 PUSHACC1 + 6915 PUSHACC1 + 6916 SUBINT + 6917 PUSHACC0 + 6918 PUSHACC3 + 6919 PUSHACC5 + 6920 PUSHENVACC1 6921 CLOSURE 4, 6875 6924 RETURN 5 - 6926 RESTART + 6926 RESTART 6927 GRAB 1 - 6929 CONST0 - 6930 ACC1 - 6931 PUSHACC1 - 6932 PUSHENVACC1 + 6929 CONST0 + 6930 ACC1 + 6931 PUSHACC1 + 6932 PUSHENVACC1 6933 CLOSURE 3, 6903 6936 RETURN 2 - 6938 RESTART + 6938 RESTART 6939 GRAB 1 - 6941 ACC0 + 6941 ACC0 6942 GETFIELD 6 - 6944 PUSHACC2 - 6945 PUSHENVACC1 - 6946 GETFIELD2 + 6944 PUSHACC2 + 6945 PUSHENVACC1 + 6946 GETFIELD2 6947 APPTERM2 4 - 6949 RESTART + 6949 RESTART 6950 GRAB 1 - 6952 ACC0 - 6953 PUSHENVACC2 - 6954 APPLY1 - 6955 PUSHACC1 + 6952 ACC0 + 6953 PUSHENVACC2 + 6954 APPLY1 + 6955 PUSHACC1 6956 GETFIELD 6 - 6958 PUSHACC1 - 6959 PUSHACC4 - 6960 PUSHENVACC1 - 6961 GETFIELD1 - 6962 APPLY3 - 6963 PUSHACC2 + 6958 PUSHACC1 + 6959 PUSHACC4 + 6960 PUSHENVACC1 + 6961 GETFIELD1 + 6962 APPLY3 + 6963 PUSHACC2 6964 SETFIELD 6 - 6966 ACC0 + 6966 ACC0 6967 RETURN 3 - 6969 ACC0 - 6970 GETFIELD0 - 6971 PUSHACC0 + 6969 ACC0 + 6970 GETFIELD0 + 6971 PUSHACC0 6972 OFFSETINT 1 - 6974 PUSHACC2 - 6975 SETFIELD0 - 6976 ACC0 + 6974 PUSHACC2 + 6975 SETFIELD0 + 6976 ACC0 6977 RETURN 2 - 6979 RESTART + 6979 RESTART 6980 GRAB 1 - 6982 CONST0 - 6983 PUSHACC1 - 6984 PUSHACC3 - 6985 GETFIELD1 + 6982 CONST0 + 6983 PUSHACC1 + 6984 PUSHACC3 + 6985 GETFIELD1 6986 APPTERM2 4 - 6988 RESTART + 6988 RESTART 6989 GRAB 1 - 6991 ENVACC1 + 6991 ENVACC1 6992 GETFIELD 4 - 6994 PUSHACC1 - 6995 GETFIELD0 + 6994 PUSHACC1 + 6995 GETFIELD0 6996 PUSHGETGLOBALFIELD List, 23 - 6999 APPLY2 + 6999 APPLY2 7000 BRANCHIFNOT 7005 - 7002 ACC1 + 7002 ACC1 7003 RETURN 2 - 7005 ACC1 - 7006 PUSHACC1 + 7005 ACC1 + 7006 PUSHACC1 7007 MAKEBLOCK2 0 7009 RETURN 2 - 7011 RESTART + 7011 RESTART 7012 GRAB 1 - 7014 ACC0 - 7015 PUSHENVACC2 + 7014 ACC0 + 7015 PUSHENVACC2 7016 GETFIELD 6 - 7018 PUSHACC3 - 7019 PUSHENVACC1 - 7020 GETFIELD2 - 7021 APPLY2 - 7022 PUSHACC3 - 7023 PUSHENVACC1 - 7024 GETFIELD1 + 7018 PUSHACC3 + 7019 PUSHENVACC1 + 7020 GETFIELD2 + 7021 APPLY2 + 7022 PUSHACC3 + 7023 PUSHENVACC1 + 7024 GETFIELD1 7025 APPTERM3 5 - 7027 ACC0 + 7027 ACC0 7028 GETFIELD 4 7030 PUSHGETGLOBALFIELD List, 1 - 7033 APPLY1 - 7034 PUSHACC1 + 7033 APPLY1 + 7034 PUSHACC1 7035 GETFIELD 4 7037 PUSHGETGLOBALFIELD List, 2 - 7040 APPLY1 - 7041 PUSHACC2 + 7040 APPLY1 + 7041 PUSHACC2 7042 SETFIELD 4 - 7044 ACC0 + 7044 ACC0 7045 GETFIELD 5 - 7047 PUSHACC1 - 7048 GETFIELD3 - 7049 PUSHACC3 - 7050 PUSHENVACC1 + 7047 PUSHACC1 + 7048 GETFIELD3 + 7049 PUSHACC3 + 7050 PUSHENVACC1 7051 CLOSURE 2, 7012 7054 PUSHGETGLOBALFIELD List, 12 - 7057 APPLY3 - 7058 PUSHACC2 + 7057 APPLY3 + 7058 PUSHACC2 7059 SETFIELD 6 - 7061 ACC0 - 7062 GETFIELD0 - 7063 PUSHACC2 - 7064 SETFIELD2 - 7065 ACC0 - 7066 GETFIELD1 - 7067 PUSHACC2 - 7068 SETFIELD3 - 7069 ACC0 - 7070 GETFIELD2 - 7071 PUSHACC2 + 7061 ACC0 + 7062 GETFIELD0 + 7063 PUSHACC2 + 7064 SETFIELD2 + 7065 ACC0 + 7066 GETFIELD1 + 7067 PUSHACC2 + 7068 SETFIELD3 + 7069 ACC0 + 7070 GETFIELD2 + 7071 PUSHACC2 7072 GETFIELD 5 - 7074 PUSHACC2 + 7074 PUSHACC2 7075 CLOSURE 1, 6989 7078 PUSHGETGLOBALFIELD List, 13 - 7081 APPLY3 - 7082 PUSHACC2 + 7081 APPLY3 + 7082 PUSHACC2 7083 SETFIELD 5 7085 RETURN 2 - 7087 RESTART + 7087 RESTART 7088 GRAB 1 - 7090 ENVACC1 - 7091 PUSHACC1 - 7092 GETFIELD0 + 7090 ENVACC1 + 7091 PUSHACC1 + 7092 GETFIELD0 7093 PUSHGETGLOBALFIELD List, 23 - 7096 APPLY2 + 7096 APPLY2 7097 BRANCHIFNOT 7102 - 7099 ACC1 + 7099 ACC1 7100 RETURN 2 - 7102 ACC1 - 7103 PUSHACC1 + 7102 ACC1 + 7103 PUSHACC1 7104 MAKEBLOCK2 0 7106 RETURN 2 - 7108 RESTART + 7108 RESTART 7109 GRAB 1 - 7111 ENVACC3 - 7112 GETFIELD0 - 7113 PUSHACC2 - 7114 PUSHACC2 - 7115 PUSHENVACC1 - 7116 GETFIELD1 - 7117 APPLY3 - 7118 PUSHENVACC3 - 7119 SETFIELD0 - 7120 ENVACC4 - 7121 GETFIELD0 - 7122 PUSHCONST0 - 7123 PUSHACC3 - 7124 PUSHENVACC2 - 7125 GETFIELD1 - 7126 APPLY3 + 7111 ENVACC3 + 7112 GETFIELD0 + 7113 PUSHACC2 + 7114 PUSHACC2 + 7115 PUSHENVACC1 + 7116 GETFIELD1 + 7117 APPLY3 + 7118 PUSHENVACC3 + 7119 SETFIELD0 + 7120 ENVACC4 + 7121 GETFIELD0 + 7122 PUSHCONST0 + 7123 PUSHACC3 + 7124 PUSHENVACC2 + 7125 GETFIELD1 + 7126 APPLY3 7127 PUSHENVACC 4 - 7129 SETFIELD0 + 7129 SETFIELD0 7130 RETURN 2 - 7132 ACC0 + 7132 ACC0 7133 PUSHENVACC 4 - 7135 PUSHENVACC3 - 7136 APPLY2 + 7135 PUSHENVACC3 + 7136 APPLY2 7137 PUSHENVACC 5 - 7139 GETFIELD0 - 7140 PUSHACC1 - 7141 PUSHACC3 - 7142 PUSHENVACC1 - 7143 GETFIELD1 - 7144 APPLY3 + 7139 GETFIELD0 + 7140 PUSHACC1 + 7141 PUSHACC3 + 7142 PUSHENVACC1 + 7143 GETFIELD1 + 7144 APPLY3 7145 PUSHENVACC 5 - 7147 SETFIELD0 + 7147 SETFIELD0 7148 ENVACC 6 - 7150 GETFIELD0 - 7151 PUSH + 7150 GETFIELD0 + 7151 PUSH 7152 PUSHTRAP 7163 - 7154 ENVACC4 - 7155 GETFIELD3 - 7156 PUSHACC6 - 7157 PUSHENVACC2 - 7158 GETFIELD2 - 7159 APPLY2 - 7160 POPTRAP + 7154 ENVACC4 + 7155 GETFIELD3 + 7156 PUSHACC6 + 7157 PUSHENVACC2 + 7158 GETFIELD2 + 7159 APPLY2 + 7160 POPTRAP 7161 BRANCH 7177 7163 PUSHGETGLOBAL Not_found - 7165 PUSHACC1 - 7166 GETFIELD0 - 7167 EQ + 7165 PUSHACC1 + 7166 GETFIELD0 + 7167 EQ 7168 BRANCHIFNOT 7173 - 7170 CONST1 + 7170 CONST1 7171 BRANCH 7175 - 7173 ACC0 - 7174 RAISE + 7173 ACC0 + 7174 RAISE 7175 POP 1 - 7177 PUSHACC2 - 7178 PUSHENVACC2 - 7179 GETFIELD1 - 7180 APPLY3 + 7177 PUSHACC2 + 7178 PUSHENVACC2 + 7179 GETFIELD1 + 7180 APPLY3 7181 PUSHENVACC 6 - 7183 SETFIELD0 + 7183 SETFIELD0 7184 RETURN 2 - 7186 RESTART + 7186 RESTART 7187 GRAB 3 - 7189 ACC2 - 7190 PUSHACC1 + 7189 ACC2 + 7190 PUSHACC1 7191 PUSHENVACC 4 - 7193 APPLY1 + 7193 APPLY1 7194 PUSHGETGLOBALFIELD List, 10 - 7197 APPLY2 - 7198 PUSHACC1 + 7197 APPLY2 + 7198 PUSHACC1 7199 GETFIELD 4 - 7201 PUSHACC3 - 7202 PUSHACC2 - 7203 PUSHACC4 + 7201 PUSHACC3 + 7202 PUSHACC2 + 7203 PUSHACC4 7204 GETFIELD 6 - 7206 PUSHACC5 + 7206 PUSHACC5 7207 GETFIELD 5 - 7209 PUSHACC6 - 7210 GETFIELD3 - 7211 PUSHACC7 - 7212 GETFIELD2 + 7209 PUSHACC6 + 7210 GETFIELD3 + 7211 PUSHACC7 + 7212 GETFIELD2 7213 MAKEBLOCK 6, 0 7216 MAKEBLOCK2 0 - 7218 PUSHACC2 + 7218 PUSHACC2 7219 SETFIELD 4 - 7221 ENVACC1 - 7222 GETFIELD0 - 7223 PUSHACC2 + 7221 ENVACC1 + 7222 GETFIELD0 + 7223 PUSHACC2 7224 SETFIELD 6 - 7226 ENVACC2 - 7227 GETFIELD0 + 7226 ENVACC2 + 7227 GETFIELD0 7228 MAKEBLOCK1 0 - 7230 PUSHENVACC3 - 7231 GETFIELD0 + 7230 PUSHENVACC3 + 7231 GETFIELD0 7232 MAKEBLOCK1 0 - 7234 PUSHACC6 - 7235 PUSHACC1 - 7236 PUSHACC3 - 7237 PUSHACC6 + 7234 PUSHACC6 + 7235 PUSHACC1 + 7236 PUSHACC3 + 7237 PUSHACC6 7238 PUSHENVACC 4 - 7240 PUSHENVACC3 - 7241 PUSHENVACC2 + 7240 PUSHENVACC3 + 7241 PUSHENVACC2 7242 CLOSURE 6, 7132 7245 PUSHGETGLOBALFIELD List, 9 - 7248 APPLY2 - 7249 ACC2 - 7250 PUSHACC6 - 7251 PUSHACC2 - 7252 PUSHACC4 - 7253 PUSHENVACC3 - 7254 PUSHENVACC2 + 7248 APPLY2 + 7249 ACC2 + 7250 PUSHACC6 + 7251 PUSHACC2 + 7252 PUSHACC4 + 7253 PUSHENVACC3 + 7254 PUSHENVACC2 7255 CLOSURE 4, 7109 7258 PUSHGETGLOBALFIELD List, 14 - 7261 APPLY3 - 7262 ACC1 - 7263 GETFIELD0 - 7264 PUSHACC4 - 7265 SETFIELD2 - 7266 ACC0 - 7267 GETFIELD0 - 7268 PUSHACC4 - 7269 SETFIELD3 - 7270 CONST0 - 7271 PUSHACC4 + 7261 APPLY3 + 7262 ACC1 + 7263 GETFIELD0 + 7264 PUSHACC4 + 7265 SETFIELD2 + 7266 ACC0 + 7267 GETFIELD0 + 7268 PUSHACC4 + 7269 SETFIELD3 + 7270 CONST0 + 7271 PUSHACC4 7272 GETFIELD 5 - 7274 PUSHACC4 + 7274 PUSHACC4 7275 CLOSURE 1, 7088 7278 PUSHGETGLOBALFIELD List, 13 - 7281 APPLY3 - 7282 PUSHACC4 + 7281 APPLY3 + 7282 PUSHACC4 7283 SETFIELD 5 7285 RETURN 7 - 7287 RESTART + 7287 RESTART 7288 GRAB 1 7290 PUSHTRAP 7303 - 7292 ACC4 + 7292 ACC4 7293 GETFIELD 5 - 7295 PUSHACC6 + 7295 PUSHACC6 7296 PUSHGETGLOBALFIELD List, 29 - 7299 APPLY2 - 7300 POPTRAP + 7299 APPLY2 + 7300 POPTRAP 7301 RETURN 2 7303 PUSHGETGLOBAL Not_found - 7305 PUSHACC1 - 7306 GETFIELD0 - 7307 EQ + 7305 PUSHACC1 + 7306 GETFIELD0 + 7307 EQ 7308 BRANCHIFNOT 7325 - 7310 ACC2 - 7311 PUSHENVACC1 - 7312 APPLY1 - 7313 PUSHACC0 - 7314 GETFIELD1 - 7315 PUSHACC1 - 7316 GETFIELD0 - 7317 PUSHACC4 - 7318 GETFIELD1 + 7310 ACC2 + 7311 PUSHENVACC1 + 7312 APPLY1 + 7313 PUSHACC0 + 7314 GETFIELD1 + 7315 PUSHACC1 + 7316 GETFIELD0 + 7317 PUSHACC4 + 7318 GETFIELD1 7319 C_CALL2 array_get_addr 7321 C_CALL2 array_get 7323 RETURN 4 - 7325 ACC0 - 7326 RAISE - 7327 RESTART + 7325 ACC0 + 7326 RAISE + 7327 RESTART 7328 GRAB 2 - 7330 ENVACC3 + 7330 ENVACC3 7331 OFFSETREF 1 - 7333 ACC0 - 7334 GETFIELD3 - 7335 PUSHACC2 - 7336 PUSHENVACC1 - 7337 GETFIELD2 - 7338 APPLY2 + 7333 ACC0 + 7334 GETFIELD3 + 7335 PUSHACC2 + 7336 PUSHENVACC1 + 7337 GETFIELD2 + 7338 APPLY2 7339 BRANCHIFNOT 7347 - 7341 ACC2 - 7342 PUSHACC2 - 7343 PUSHACC2 - 7344 PUSHENVACC2 + 7341 ACC2 + 7342 PUSHACC2 + 7343 PUSHACC2 + 7344 PUSHENVACC2 7345 APPTERM3 6 - 7347 ACC0 + 7347 ACC0 7348 GETFIELD 5 - 7350 PUSHACC3 - 7351 PUSHACC3 + 7350 PUSHACC3 + 7351 PUSHACC3 7352 MAKEBLOCK2 0 7354 MAKEBLOCK2 0 - 7356 PUSHACC1 + 7356 PUSHACC1 7357 SETFIELD 5 7359 RETURN 3 - 7361 RESTART + 7361 RESTART 7362 GRAB 1 7364 PUSHTRAP 7375 - 7366 ACC4 - 7367 GETFIELD2 - 7368 PUSHACC6 - 7369 PUSHENVACC2 - 7370 GETFIELD2 - 7371 APPLY2 - 7372 POPTRAP + 7366 ACC4 + 7367 GETFIELD2 + 7368 PUSHACC6 + 7369 PUSHENVACC2 + 7370 GETFIELD2 + 7371 APPLY2 + 7372 POPTRAP 7373 RETURN 2 7375 PUSHGETGLOBAL Not_found - 7377 PUSHACC1 - 7378 GETFIELD0 - 7379 EQ + 7377 PUSHACC1 + 7378 GETFIELD0 + 7379 EQ 7380 BRANCHIFNOT 7406 - 7382 CONST0 - 7383 PUSHENVACC1 - 7384 APPLY1 - 7385 PUSHACC2 - 7386 GETFIELD2 - 7387 PUSHACC1 - 7388 PUSHACC5 - 7389 PUSHENVACC2 - 7390 GETFIELD1 - 7391 APPLY3 - 7392 PUSHACC3 - 7393 SETFIELD2 - 7394 ACC2 - 7395 GETFIELD3 - 7396 PUSHCONST1 - 7397 PUSHACC2 - 7398 PUSHENVACC3 - 7399 GETFIELD1 - 7400 APPLY3 - 7401 PUSHACC3 - 7402 SETFIELD3 - 7403 ACC0 + 7382 CONST0 + 7383 PUSHENVACC1 + 7384 APPLY1 + 7385 PUSHACC2 + 7386 GETFIELD2 + 7387 PUSHACC1 + 7388 PUSHACC5 + 7389 PUSHENVACC2 + 7390 GETFIELD1 + 7391 APPLY3 + 7392 PUSHACC3 + 7393 SETFIELD2 + 7394 ACC2 + 7395 GETFIELD3 + 7396 PUSHCONST1 + 7397 PUSHACC2 + 7398 PUSHENVACC3 + 7399 GETFIELD1 + 7400 APPLY3 + 7401 PUSHACC3 + 7402 SETFIELD3 + 7403 ACC0 7404 RETURN 4 - 7406 ACC0 - 7407 RAISE - 7408 RESTART + 7406 ACC0 + 7407 RAISE + 7408 RESTART 7409 GRAB 2 - 7411 ACC1 - 7412 PUSHENVACC1 - 7413 APPLY1 - 7414 PUSHACC0 - 7415 GETFIELD0 - 7416 PUSHACC0 + 7411 ACC1 + 7412 PUSHENVACC1 + 7413 APPLY1 + 7414 PUSHACC0 + 7415 GETFIELD0 + 7416 PUSHACC0 7417 OFFSETINT 1 - 7419 PUSHACC3 + 7419 PUSHACC3 7420 PUSHENVACC 4 - 7422 APPLY2 - 7423 ACC0 - 7424 PUSHACC3 - 7425 GETFIELD1 + 7422 APPLY2 + 7423 ACC0 + 7424 PUSHACC3 + 7425 GETFIELD1 7426 C_CALL2 array_get_addr - 7428 PUSHENVACC2 - 7429 PUSHACC1 - 7430 EQ + 7428 PUSHENVACC2 + 7429 PUSHACC1 + 7430 EQ 7431 BRANCHIFNOT 7444 - 7433 CONST0 - 7434 PUSHENVACC3 - 7435 APPLY1 + 7433 CONST0 + 7434 PUSHENVACC3 + 7435 APPLY1 7436 ASSIGN 0 - 7438 ACC0 - 7439 PUSHACC2 - 7440 PUSHACC5 - 7441 GETFIELD1 + 7438 ACC0 + 7439 PUSHACC2 + 7440 PUSHACC5 + 7441 GETFIELD1 7442 C_CALL3 array_set_addr - 7444 ACC5 - 7445 PUSHACC3 - 7446 GETFIELD1 - 7447 PUSHACC2 + 7444 ACC5 + 7445 PUSHACC3 + 7446 GETFIELD1 + 7447 PUSHACC2 7448 C_CALL3 array_set 7450 RETURN 6 - 7452 RESTART + 7452 RESTART 7453 GRAB 1 - 7455 ACC0 - 7456 GETFIELD1 - 7457 VECTLENGTH - 7458 PUSHACC0 - 7459 PUSHACC3 - 7460 GTINT + 7455 ACC0 + 7456 GETFIELD1 + 7457 VECTLENGTH + 7458 PUSHACC0 + 7459 PUSHACC3 + 7460 GTINT 7461 BRANCHIFNOT 7487 - 7463 ENVACC1 - 7464 PUSHACC3 + 7463 ENVACC1 + 7464 PUSHACC3 7465 C_CALL2 make_vect - 7467 PUSH + 7467 PUSH 7468 PUSH_RETADDR 7482 - 7470 ACC4 - 7471 PUSHCONST0 - 7472 PUSHACC5 - 7473 PUSHCONST0 + 7470 ACC4 + 7471 PUSHCONST0 + 7472 PUSHACC5 + 7473 PUSHCONST0 7474 PUSHACC 9 - 7476 GETFIELD1 + 7476 GETFIELD1 7477 PUSHGETGLOBALFIELD Array, 8 7480 APPLY 5 - 7482 ACC0 - 7483 PUSHACC3 - 7484 SETFIELD1 + 7482 ACC0 + 7483 PUSHACC3 + 7484 SETFIELD1 7485 POP 1 7487 RETURN 3 7489 ENVACC 5 7491 OFFSETREF 1 - 7493 CONST0 - 7494 PUSHENVACC2 - 7495 GETFIELD0 - 7496 PUSHCONST0 - 7497 PUSHCONST0 + 7493 CONST0 + 7494 PUSHENVACC2 + 7495 GETFIELD0 + 7496 PUSHCONST0 + 7497 PUSHCONST0 7498 PUSHENVACC 4 - 7500 GETFIELD0 - 7501 PUSHENVACC3 - 7502 GETFIELD0 - 7503 PUSH - 7504 ATOM0 - 7505 PUSHENVACC1 + 7500 GETFIELD0 + 7501 PUSHENVACC3 + 7502 GETFIELD0 + 7503 PUSH + 7504 ATOM0 + 7505 PUSHENVACC1 7506 MAKEBLOCK 8, 0 7509 RETURN 1 - 7511 RESTART + 7511 RESTART 7512 GRAB 1 - 7514 ACC1 - 7515 PUSHACC1 + 7514 ACC1 + 7515 PUSHACC1 7516 C_CALL2 compare 7518 RETURN 2 - 7520 RESTART + 7520 RESTART 7521 GRAB 1 - 7523 ACC1 - 7524 PUSHACC1 + 7523 ACC1 + 7524 PUSHACC1 7525 C_CALL2 compare 7527 RETURN 2 - 7529 RESTART + 7529 RESTART 7530 GRAB 1 - 7532 ACC1 - 7533 PUSHACC1 + 7532 ACC1 + 7533 PUSHACC1 7534 C_CALL2 compare 7536 RETURN 2 7538 PUSHTRAP 7549 - 7540 ACC4 - 7541 PUSHENVACC1 + 7540 ACC4 + 7541 PUSHENVACC1 7542 PUSHGETGLOBALFIELD Hashtbl, 3 - 7545 APPLY2 - 7546 POPTRAP + 7545 APPLY2 + 7546 POPTRAP 7547 RETURN 1 7549 PUSHGETGLOBAL Not_found - 7551 PUSHACC1 - 7552 GETFIELD0 - 7553 EQ + 7551 PUSHACC1 + 7552 GETFIELD0 + 7553 EQ 7554 BRANCHIFNOT 7569 - 7556 CONST0 - 7557 PUSHENVACC2 - 7558 APPLY1 - 7559 PUSHACC0 - 7560 PUSHACC3 - 7561 PUSHENVACC1 + 7556 CONST0 + 7557 PUSHENVACC2 + 7558 APPLY1 + 7559 PUSHACC0 + 7560 PUSHACC3 + 7561 PUSHENVACC1 7562 PUSHGETGLOBALFIELD Hashtbl, 2 - 7565 APPLY3 - 7566 ACC0 + 7565 APPLY3 + 7566 ACC0 7567 RETURN 3 - 7569 ACC0 - 7570 RAISE - 7571 ENVACC2 - 7572 GETFIELD0 - 7573 PUSHENVACC2 - 7574 GETFIELD0 - 7575 PUSHENVACC1 - 7576 APPLY1 - 7577 PUSHENVACC2 - 7578 SETFIELD0 - 7579 ACC0 + 7569 ACC0 + 7570 RAISE + 7571 ENVACC2 + 7572 GETFIELD0 + 7573 PUSHENVACC2 + 7574 GETFIELD0 + 7575 PUSHENVACC1 + 7576 APPLY1 + 7577 PUSHENVACC2 + 7578 SETFIELD0 + 7579 ACC0 7580 RETURN 2 - 7582 ENVACC1 - 7583 PUSHACC1 - 7584 VECTLENGTH + 7582 ENVACC1 + 7583 PUSHACC1 + 7584 VECTLENGTH 7585 OFFSETINT -1 - 7587 PUSH + 7587 PUSH 7588 BRANCH 7606 - 7590 CHECK_SIGNALS - 7591 ACC1 - 7592 PUSHACC3 + 7590 CHECK_SIGNALS + 7591 ACC1 + 7592 PUSHACC3 7593 C_CALL2 array_get_addr - 7595 PUSHENVACC2 - 7596 APPLY1 - 7597 PUSHACC2 - 7598 PUSHACC4 + 7595 PUSHENVACC2 + 7596 APPLY1 + 7597 PUSHACC2 + 7598 PUSHACC4 7599 C_CALL3 array_set_addr - 7601 ACC1 + 7601 ACC1 7602 OFFSETINT 1 7604 ASSIGN 1 - 7606 ACC0 - 7607 PUSHACC2 - 7608 LEINT + 7606 ACC0 + 7607 PUSHACC2 + 7608 LEINT 7609 BRANCHIF 7590 - 7611 CONST0 + 7611 CONST0 7612 RETURN 3 - 7614 ENVACC4 - 7615 PUSHACC1 - 7616 NEQ + 7614 ENVACC4 + 7615 PUSHACC1 + 7616 NEQ 7617 BRANCHIFNOT 7640 - 7619 ENVACC2 - 7620 GETFIELD0 - 7621 PUSHACC1 - 7622 PUSHENVACC3 - 7623 APPLY1 - 7624 EQ + 7619 ENVACC2 + 7620 GETFIELD0 + 7621 PUSHACC1 + 7622 PUSHENVACC3 + 7623 APPLY1 + 7624 EQ 7625 BRANCHIFNOT 7640 - 7627 ACC0 + 7627 ACC0 7628 PUSHENVACC 5 - 7630 APPLY1 + 7630 APPLY1 7631 BRANCHIFNOT 7640 - 7633 ENVACC1 - 7634 GETFIELD3 - 7635 PUSHACC1 + 7633 ENVACC1 + 7634 GETFIELD3 + 7635 PUSHACC1 7636 PUSHENVACC 6 7638 APPTERM2 3 - 7640 ACC0 + 7640 ACC0 7641 RETURN 1 - 7643 RESTART + 7643 RESTART 7644 GRAB 1 - 7646 CONST0 - 7647 PUSHENVACC1 + 7646 CONST0 + 7647 PUSHENVACC1 7648 OFFSETINT -1 - 7650 PUSH + 7650 PUSH 7651 BRANCH 7690 - 7653 CHECK_SIGNALS - 7654 ENVACC2 - 7655 PUSHACC2 - 7656 PUSHACC5 + 7653 CHECK_SIGNALS + 7654 ENVACC2 + 7655 PUSHACC2 + 7656 PUSHACC5 7657 C_CALL2 array_get - 7659 NEQ + 7659 NEQ 7660 BRANCHIFNOT 7679 - 7662 ENVACC2 - 7663 PUSHACC2 - 7664 PUSHACC4 + 7662 ENVACC2 + 7663 PUSHACC2 + 7664 PUSHACC4 7665 C_CALL2 array_get - 7667 NEQ + 7667 NEQ 7668 BRANCHIFNOT 7679 - 7670 ACC1 - 7671 PUSHACC3 + 7670 ACC1 + 7671 PUSHACC3 7672 C_CALL2 array_get - 7674 PUSHACC2 - 7675 PUSHACC5 + 7674 PUSHACC2 + 7675 PUSHACC5 7676 C_CALL2 array_get - 7678 NEQ + 7678 NEQ 7679 BRANCHIFNOT 7685 - 7681 ENVACC4 + 7681 ENVACC4 7682 MAKEBLOCK1 0 - 7684 RAISE - 7685 ACC1 + 7684 RAISE + 7685 ACC1 7686 OFFSETINT 1 7688 ASSIGN 1 - 7690 ACC0 - 7691 PUSHACC2 - 7692 LEINT + 7690 ACC0 + 7691 PUSHACC2 + 7692 LEINT 7693 BRANCHIF 7653 - 7695 CONST0 + 7695 CONST0 7696 POP 2 - 7698 CONST0 - 7699 PUSHENVACC1 + 7698 CONST0 + 7699 PUSHENVACC1 7700 OFFSETINT -1 - 7702 PUSH + 7702 PUSH 7703 BRANCH 7727 - 7705 CHECK_SIGNALS - 7706 ENVACC2 - 7707 PUSHACC2 - 7708 PUSHACC5 + 7705 CHECK_SIGNALS + 7706 ENVACC2 + 7707 PUSHACC2 + 7708 PUSHACC5 7709 C_CALL2 array_get - 7711 NEQ + 7711 NEQ 7712 BRANCHIFNOT 7722 - 7714 ACC1 - 7715 PUSHACC4 + 7714 ACC1 + 7715 PUSHACC4 7716 C_CALL2 array_get - 7718 PUSHACC2 - 7719 PUSHACC4 + 7718 PUSHACC2 + 7719 PUSHACC4 7720 C_CALL3 array_set - 7722 ACC1 + 7722 ACC1 7723 OFFSETINT 1 7725 ASSIGN 1 - 7727 ACC0 - 7728 PUSHACC2 - 7729 LEINT + 7727 ACC0 + 7728 PUSHACC2 + 7729 LEINT 7730 BRANCHIF 7705 - 7732 CONST0 + 7732 CONST0 7733 POP 2 - 7735 ENVACC3 - 7736 GETFIELD0 - 7737 PUSHACC2 + 7735 ENVACC3 + 7736 GETFIELD0 + 7737 PUSHACC2 7738 PUSHENVACC 5 - 7740 APPLY2 - 7741 PUSHENVACC3 - 7742 SETFIELD0 - 7743 ACC0 + 7740 APPLY2 + 7741 PUSHENVACC3 + 7742 SETFIELD0 + 7743 ACC0 7744 RETURN 2 - 7746 ENVACC1 + 7746 ENVACC1 7747 GETFIELD 4 - 7749 PUSHACC1 - 7750 PUSHENVACC2 - 7751 APPLY1 - 7752 LEINT + 7749 PUSHACC1 + 7750 PUSHENVACC2 + 7751 APPLY1 + 7752 LEINT 7753 RETURN 1 - 7755 CONST0 - 7756 PUSHCONST0 - 7757 PUSHENVACC1 + 7755 CONST0 + 7756 PUSHCONST0 + 7757 PUSHENVACC1 7758 OFFSETINT -1 - 7760 PUSH + 7760 PUSH 7761 BRANCH 7782 - 7763 CHECK_SIGNALS - 7764 ENVACC2 - 7765 PUSHACC2 - 7766 PUSHACC5 + 7763 CHECK_SIGNALS + 7764 ENVACC2 + 7765 PUSHACC2 + 7766 PUSHACC5 7767 C_CALL2 array_get - 7769 NEQ + 7769 NEQ 7770 BRANCHIFNOT 7777 - 7772 ACC2 + 7772 ACC2 7773 OFFSETINT 1 7775 ASSIGN 2 - 7777 ACC1 + 7777 ACC1 7778 OFFSETINT 1 7780 ASSIGN 1 - 7782 ACC0 - 7783 PUSHACC2 - 7784 LEINT + 7782 ACC0 + 7783 PUSHACC2 + 7784 LEINT 7785 BRANCHIF 7763 - 7787 CONST0 + 7787 CONST0 7788 POP 2 - 7790 ACC0 + 7790 ACC0 7791 RETURN 2 - 7793 ENVACC2 - 7794 GETFIELD0 + 7793 ENVACC2 + 7794 GETFIELD0 7795 OFFSETINT -1 - 7797 PUSHENVACC1 - 7798 GETFIELD0 + 7797 PUSHENVACC1 + 7798 GETFIELD0 7799 C_CALL2 array_get_addr - 7801 PUSHACC1 - 7802 PUSHENVACC1 - 7803 GETFIELD0 + 7801 PUSHACC1 + 7802 PUSHENVACC1 + 7803 GETFIELD0 7804 C_CALL3 array_set_addr - 7806 ENVACC2 + 7806 ENVACC2 7807 OFFSETREF -1 7809 RETURN 1 - 7811 ENVACC1 - 7812 GETFIELD0 - 7813 VECTLENGTH - 7814 PUSHACC0 - 7815 PUSHENVACC2 - 7816 GETFIELD0 - 7817 GEINT + 7811 ENVACC1 + 7812 GETFIELD0 + 7813 VECTLENGTH + 7814 PUSHACC0 + 7815 PUSHENVACC2 + 7816 GETFIELD0 + 7817 GEINT 7818 BRANCHIFNOT 7845 - 7820 ATOM0 - 7821 PUSHACC1 - 7822 PUSHCONST2 - 7823 MULINT + 7820 ATOM0 + 7821 PUSHACC1 + 7822 PUSHCONST2 + 7823 MULINT 7824 C_CALL2 make_vect - 7826 PUSH + 7826 PUSH 7827 PUSH_RETADDR 7840 - 7829 ACC4 - 7830 PUSHCONST0 - 7831 PUSHACC5 - 7832 PUSHCONST0 - 7833 PUSHENVACC1 - 7834 GETFIELD0 + 7829 ACC4 + 7830 PUSHCONST0 + 7831 PUSHACC5 + 7832 PUSHCONST0 + 7833 PUSHENVACC1 + 7834 GETFIELD0 7835 PUSHGETGLOBALFIELD Array, 8 7838 APPLY 5 - 7840 ACC0 - 7841 PUSHENVACC1 - 7842 SETFIELD0 + 7840 ACC0 + 7841 PUSHENVACC1 + 7842 SETFIELD0 7843 POP 1 - 7845 ACC1 - 7846 PUSHENVACC2 - 7847 GETFIELD0 - 7848 PUSHENVACC1 - 7849 GETFIELD0 + 7845 ACC1 + 7846 PUSHENVACC2 + 7847 GETFIELD0 + 7848 PUSHENVACC1 + 7849 GETFIELD0 7850 C_CALL3 array_set_addr - 7852 ENVACC2 + 7852 ENVACC2 7853 OFFSETREF 1 7855 RETURN 2 - 7857 ACC0 - 7858 GETFIELD0 - 7859 PUSHENVACC1 - 7860 APPLY1 - 7861 PUSHENVACC2 - 7862 PUSHACC1 - 7863 GETFIELD0 - 7864 EQ + 7857 ACC0 + 7858 GETFIELD0 + 7859 PUSHENVACC1 + 7860 APPLY1 + 7861 PUSHENVACC2 + 7862 PUSHACC1 + 7863 GETFIELD0 + 7864 EQ 7865 BRANCHIFNOT 7874 - 7867 ACC1 - 7868 GETFIELD1 - 7869 PUSHACC1 - 7870 GETFIELD1 - 7871 PUSHENVACC3 + 7867 ACC1 + 7868 GETFIELD1 + 7869 PUSHACC1 + 7870 GETFIELD1 + 7871 PUSHENVACC3 7872 C_CALL3 array_set 7874 RETURN 2 - 7876 RESTART + 7876 RESTART 7877 GRAB 1 - 7879 CONST0 - 7880 PUSHENVACC2 - 7881 APPLY1 - 7882 PUSHACC2 + 7879 CONST0 + 7880 PUSHENVACC2 + 7881 APPLY1 + 7882 PUSHACC2 7883 PUSHGETGLOBALFIELD List, 4 - 7886 APPLY1 - 7887 PUSHACC1 - 7888 PUSHACC3 - 7889 PUSHENVACC1 + 7886 APPLY1 + 7887 PUSHACC1 + 7888 PUSHACC3 + 7889 PUSHENVACC1 7890 CLOSURE 3, 7857 7893 PUSHGETGLOBALFIELD List, 9 - 7896 APPLY2 - 7897 ACC0 + 7896 APPLY2 + 7897 ACC0 7898 RETURN 3 - 7900 ACC0 + 7900 ACC0 7901 PUSHGETGLOBALFIELD Array, 6 - 7904 APPLY1 - 7905 PUSHACC0 - 7906 PUSHENVACC3 - 7907 APPLY1 - 7908 ENVACC2 - 7909 GETFIELD0 - 7910 PUSHENVACC1 - 7911 PUSHACC2 + 7904 APPLY1 + 7905 PUSHACC0 + 7906 PUSHENVACC3 + 7907 APPLY1 + 7908 ENVACC2 + 7909 GETFIELD0 + 7910 PUSHENVACC1 + 7911 PUSHACC2 7912 C_CALL3 array_set - 7914 ENVACC4 - 7915 GETFIELD0 - 7916 PUSHACC1 + 7914 ENVACC4 + 7915 GETFIELD0 + 7916 PUSHACC1 7917 MAKEBLOCK2 0 7919 PUSHENVACC 4 - 7921 SETFIELD0 - 7922 ACC0 + 7921 SETFIELD0 + 7922 ACC0 7923 RETURN 2 - 7925 ENVACC2 - 7926 PUSHENVACC1 + 7925 ENVACC2 + 7926 PUSHENVACC1 7927 OFFSETINT 1 7929 C_CALL2 make_vect - 7931 PUSHACC0 - 7932 PUSHENVACC3 - 7933 APPLY1 - 7934 ENVACC4 - 7935 GETFIELD0 - 7936 PUSHACC1 + 7931 PUSHACC0 + 7932 PUSHENVACC3 + 7933 APPLY1 + 7934 ENVACC4 + 7935 GETFIELD0 + 7936 PUSHACC1 7937 MAKEBLOCK2 0 7939 PUSHENVACC 4 - 7941 SETFIELD0 - 7942 ACC0 + 7941 SETFIELD0 + 7942 ACC0 7943 RETURN 2 - 7945 ENVACC1 - 7946 PUSHACC1 + 7945 ENVACC1 + 7946 PUSHACC1 7947 C_CALL2 array_get 7949 RETURN 1 - 7951 ENVACC2 - 7952 GETFIELD0 - 7953 PUSHENVACC1 - 7954 PUSHACC2 + 7951 ENVACC2 + 7952 GETFIELD0 + 7953 PUSHENVACC1 + 7954 PUSHACC2 7955 C_CALL3 array_set 7957 RETURN 1 - 7959 ENVACC1 - 7960 PUSHENVACC2 - 7961 PUSHENVACC1 - 7962 MULINT - 7963 PUSHACC2 - 7964 MODINT - 7965 DIVINT - 7966 PUSHENVACC1 + 7959 ENVACC1 + 7960 PUSHENVACC2 + 7961 PUSHENVACC1 + 7962 MULINT + 7963 PUSHACC2 + 7964 MODINT + 7965 DIVINT + 7966 PUSHENVACC1 7967 PUSHCONSTINT 65536 - 7969 PUSHACC3 - 7970 DIVINT - 7971 DIVINT + 7969 PUSHACC3 + 7970 DIVINT + 7971 DIVINT 7972 MAKEBLOCK2 0 7974 RETURN 1 - 7976 ENVACC3 + 7976 ENVACC3 7977 OFFSETREF 1 - 7979 ENVACC1 - 7980 PUSHACC1 - 7981 ADDINT - 7982 PUSHCONST0 - 7983 PUSHENVACC2 - 7984 PUSHENVACC1 - 7985 MULINT - 7986 PUSHACC2 - 7987 MODINT - 7988 EQ + 7979 ENVACC1 + 7980 PUSHACC1 + 7981 ADDINT + 7982 PUSHCONST0 + 7983 PUSHENVACC2 + 7984 PUSHENVACC1 + 7985 MULINT + 7986 PUSHACC2 + 7987 MODINT + 7988 EQ 7989 BRANCHIFNOT 8001 - 7991 ENVACC2 + 7991 ENVACC2 7992 PUSHCONSTINT 65536 - 7994 SUBINT - 7995 PUSHENVACC1 - 7996 MULINT - 7997 PUSHACC1 - 7998 ADDINT + 7994 SUBINT + 7995 PUSHENVACC1 + 7996 MULINT + 7997 PUSHACC1 + 7998 ADDINT 7999 RETURN 2 - 8001 ACC0 + 8001 ACC0 8002 RETURN 2 - 8004 ACC0 + 8004 ACC0 8005 C_CALL1 obj_dup - 8007 PUSHENVACC1 - 8008 PUSHACC1 - 8009 PUSHENVACC2 - 8010 APPLY2 - 8011 ACC0 + 8007 PUSHENVACC1 + 8008 PUSHACC1 + 8009 PUSHENVACC2 + 8010 APPLY2 + 8011 ACC0 8012 RETURN 2 - 8014 RESTART + 8014 RESTART 8015 GRAB 1 - 8017 ACC1 - 8018 GETFIELD0 - 8019 PUSHACC0 - 8020 PUSHCONST1 - 8021 PUSHACC3 - 8022 SETVECTITEM - 8023 ACC0 + 8017 ACC1 + 8018 GETFIELD0 + 8019 PUSHACC0 + 8020 PUSHCONST1 + 8021 PUSHACC3 + 8022 SETVECTITEM + 8023 ACC0 8024 OFFSETINT 1 - 8026 PUSHACC3 - 8027 SETFIELD0 + 8026 PUSHACC3 + 8027 SETFIELD0 8028 RETURN 3 - 8030 ENVACC1 - 8031 GETFIELD0 - 8032 PUSHENVACC1 + 8030 ENVACC1 + 8031 GETFIELD0 + 8032 PUSHENVACC1 8033 OFFSETREF 1 - 8035 ACC0 + 8035 ACC0 8036 RETURN 2 8038 CONSTINT 248 - 8040 PUSHCONST0 + 8040 PUSHCONST0 8041 MAKEBLOCK1 0 - 8043 PUSHACC0 + 8043 PUSHACC0 8044 CLOSURE 1, 8030 - 8047 PUSH + 8047 PUSH 8048 CLOSURE 0, 8015 - 8051 PUSHACC0 - 8052 PUSHACC3 + 8051 PUSHACC0 + 8052 PUSHACC3 8053 CLOSURE 2, 8004 8056 PUSHCONSTINT 16 - 8058 PUSHCONST3 - 8059 PUSHCONST1 - 8060 PUSHCONST1 - 8061 PUSHCONST1 + 8058 PUSHCONST3 + 8059 PUSHCONST1 + 8060 PUSHCONST1 + 8061 PUSHCONST1 8062 MAKEBLOCK 5, 0 8065 PUSHCONSTINT 16 8067 PUSHGETGLOBALFIELD Sys, 3 - 8070 DIVINT - 8071 PUSHCONST0 + 8070 DIVINT + 8071 PUSHCONST0 8072 PUSHCONSTINT 32 - 8074 PUSHCONST2 - 8075 PUSHCONST0 + 8074 PUSHCONST2 + 8075 PUSHCONST0 8076 MAKEBLOCK1 0 - 8078 PUSHACC0 - 8079 PUSHACC3 - 8080 PUSHACC6 + 8078 PUSHACC0 + 8079 PUSHACC3 + 8080 PUSHACC6 8081 CLOSURE 3, 7976 - 8084 PUSHACC3 - 8085 PUSHACC6 + 8084 PUSHACC3 + 8085 PUSHACC6 8086 CLOSURE 2, 7959 - 8089 PUSHCONST0 - 8090 PUSHCONST0 + 8089 PUSHCONST0 + 8090 PUSHCONST0 8091 MAKEBLOCK1 0 - 8093 PUSHACC0 - 8094 PUSHACC7 + 8093 PUSHACC0 + 8094 PUSHACC7 8095 CLOSURE 2, 7951 - 8098 PUSHACC7 + 8098 PUSHACC7 8099 CLOSURE 1, 7945 - 8102 PUSHCONST0 + 8102 PUSHCONST0 8103 MAKEBLOCK1 0 - 8105 PUSH - 8106 ATOM0 - 8107 PUSHACC1 - 8108 PUSHACC4 - 8109 PUSHACC7 + 8105 PUSH + 8106 ATOM0 + 8107 PUSHACC1 + 8108 PUSHACC4 + 8109 PUSHACC7 8110 PUSHACC 13 8112 CLOSURE 4, 7925 - 8115 PUSHACC2 - 8116 PUSHACC5 - 8117 PUSHACC7 + 8115 PUSHACC2 + 8116 PUSHACC5 + 8117 PUSHACC7 8118 PUSHACC 14 8120 CLOSURE 4, 7900 - 8123 PUSHACC1 + 8123 PUSHACC1 8124 PUSHACC 9 8126 CLOSURE 2, 7877 - 8129 PUSH - 8130 ATOM0 + 8129 PUSH + 8130 ATOM0 8131 PUSHCONSTINT 10 8133 C_CALL2 make_vect 8135 MAKEBLOCK1 0 - 8137 PUSHCONST0 + 8137 PUSHCONST0 8138 MAKEBLOCK1 0 - 8140 PUSHACC0 - 8141 PUSHACC2 + 8140 PUSHACC0 + 8141 PUSHACC2 8142 CLOSURE 2, 7811 - 8145 PUSHACC1 - 8146 PUSHACC3 + 8145 PUSHACC1 + 8146 PUSHACC3 8147 CLOSURE 2, 7793 8150 PUSHACC 12 8152 PUSHACC 18 8154 CLOSURE 2, 7755 - 8157 PUSHACC0 + 8157 PUSHACC0 8158 PUSHACC 22 8160 CLOSURE 2, 7746 8163 PUSHGETGLOBAL "Oo.Failed" 8165 MAKEBLOCK1 0 - 8167 PUSH + 8167 PUSH 8168 CLOSUREREC 0, 6415 - 8172 ACC0 - 8173 PUSHACC2 + 8172 ACC0 + 8173 PUSHACC2 8174 PUSHACC 14 8176 PUSHACC 19 8178 PUSHACC 25 8180 CLOSURE 5, 7644 - 8183 PUSHACC0 - 8184 PUSHACC3 - 8185 PUSHACC5 + 8183 PUSHACC0 + 8184 PUSHACC3 + 8185 PUSHACC5 8186 PUSHACC 8 8188 PUSHACC 10 8190 PUSHACC 12 8192 PUSHACC 14 8194 CLOSUREREC 7, 6444 - 8198 ACC0 - 8199 PUSHACC5 + 8198 ACC0 + 8199 PUSHACC5 8200 PUSHACC 15 8202 PUSHACC 18 8204 PUSHACC 21 8206 PUSHACC 31 8208 CLOSURE 6, 7614 - 8211 PUSHACC0 + 8211 PUSHACC0 8212 PUSHACC 26 8214 CLOSURE 2, 7582 8217 PUSHACC 27 8219 PUSHCONSTINT 65536 8221 PUSHACC 28 - 8223 MULINT - 8224 MULINT - 8225 PUSHACC0 + 8223 MULINT + 8224 MULINT + 8225 PUSHACC0 8226 MAKEBLOCK1 0 8228 PUSHCONSTINT 101 8230 PUSHGETGLOBALFIELD Hashtbl, 0 - 8233 APPLY1 - 8234 PUSHACC1 + 8233 APPLY1 + 8234 PUSHACC1 8235 PUSHACC 26 8237 CLOSURE 2, 7571 - 8240 PUSHACC0 - 8241 PUSHACC2 + 8240 PUSHACC0 + 8241 PUSHACC2 8242 CLOSURE 2, 7538 - 8245 PUSH + 8245 PUSH 8246 CLOSURE 0, 7530 - 8249 PUSHACC0 + 8249 PUSHACC0 8250 MAKEBLOCK1 0 8252 POP 1 8254 PUSHGETGLOBALFIELD Map, 0 - 8257 APPLY1 - 8258 PUSH + 8257 APPLY1 + 8258 PUSH 8259 CLOSURE 0, 7521 - 8262 PUSHACC0 + 8262 PUSHACC0 8263 MAKEBLOCK1 0 8265 POP 1 8267 PUSHGETGLOBALFIELD Map, 0 - 8270 APPLY1 - 8271 PUSH + 8270 APPLY1 + 8271 PUSH 8272 CLOSURE 0, 7512 - 8275 PUSHACC0 + 8275 PUSHACC0 8276 MAKEBLOCK1 0 8278 POP 1 8280 PUSHGETGLOBALFIELD Map, 0 - 8283 APPLY1 - 8284 PUSHCONST0 + 8283 APPLY1 + 8284 PUSHCONST0 8285 MAKEBLOCK1 0 - 8287 PUSHACC0 - 8288 PUSHACC2 - 8289 PUSHACC4 - 8290 PUSHACC6 + 8287 PUSHACC0 + 8288 PUSHACC2 + 8289 PUSHACC4 + 8290 PUSHACC6 8291 PUSHACC 37 8293 CLOSURE 5, 7489 8296 PUSHACC 25 8298 CLOSURE 1, 7453 - 8301 PUSHACC0 + 8301 PUSHACC0 8302 PUSHACC 26 8304 PUSHACC 28 8306 PUSHACC 35 8308 CLOSURE 4, 7409 - 8311 PUSHCONST0 + 8311 PUSHCONST0 8312 MAKEBLOCK1 0 - 8314 PUSHCONST0 + 8314 PUSHCONST0 8315 MAKEBLOCK1 0 - 8317 PUSHACC6 + 8317 PUSHACC6 8318 PUSHACC 8 8320 PUSHACC 12 8322 CLOSURE 3, 7362 - 8325 PUSHACC2 - 8326 PUSHACC4 + 8325 PUSHACC2 + 8326 PUSHACC4 8327 PUSHACC 9 8329 CLOSURE 3, 7328 8332 PUSHACC 37 8334 CLOSURE 1, 7288 - 8337 PUSHACC2 + 8337 PUSHACC2 8338 PUSHACC 10 8340 PUSHACC 12 8342 PUSHACC 14 8344 CLOSURE 4, 7187 8347 PUSHACC 12 8349 CLOSURE 1, 7027 - 8352 PUSH + 8352 PUSH 8353 CLOSURE 0, 6980 - 8356 PUSH + 8356 PUSH 8357 CLOSURE 0, 6969 - 8360 PUSHACC0 + 8360 PUSHACC0 8361 PUSHACC 16 8363 CLOSURE 2, 6950 8366 PUSHACC 16 8368 CLOSURE 1, 6939 8371 PUSHACC 47 8373 CLOSURE 1, 6927 - 8376 PUSH + 8376 PUSH 8377 CLOSURE 0, 6862 8380 PUSHACC 15 8382 PUSHACC 18 @@ -5754,11 +5754,11 @@ if o#m <> 23 then raise Not_found 8402 PUSHACC 60 8404 PUSHACC 62 8406 CLOSURE 3, 6769 - 8409 PUSH + 8409 PUSH 8410 CLOSUREREC 0, 6519 - 8414 ACC0 + 8414 ACC0 8415 CLOSURE 1, 6752 - 8418 PUSHACC0 + 8418 PUSHACC0 8419 PUSHACC 61 8421 PUSHACC 64 8423 CLOSURE 3, 6735 @@ -5767,7 +5767,7 @@ if o#m <> 23 then raise Not_found 8431 PUSHACC 39 8433 PUSHACC 49 8435 CLOSURE 2, 6695 - 8438 PUSHACC0 + 8438 PUSHACC0 8439 PUSHACC 20 8441 PUSHACC 22 8443 PUSHACC 27 @@ -5778,15 +5778,15 @@ if o#m <> 23 then raise Not_found 8453 CLOSURE 8, 6644 8456 PUSHACC 41 8458 CLOSURE 1, 6618 - 8461 PUSHACC0 + 8461 PUSHACC0 8462 PUSHACC 52 8464 PUSHACC 57 8466 PUSHACC 63 8468 CLOSURE 4, 6581 - 8471 PUSHACC0 - 8472 PUSHACC3 + 8471 PUSHACC0 + 8472 PUSHACC3 8473 PUSHACC 66 - 8475 PUSHACC7 + 8475 PUSHACC7 8476 PUSHACC 9 8478 PUSHACC 11 8480 PUSHACC 14 @@ -5808,78 +5808,78 @@ if o#m <> 23 then raise Not_found 8513 POP 70 8515 SETGLOBAL Oo 8517 BRANCH 8568 - 8519 ACC0 + 8519 ACC0 8520 BRANCHIFNOT 8525 - 8522 ACC0 + 8522 ACC0 8523 BRANCH 8530 - 8525 ENVACC1 + 8525 ENVACC1 8526 PUSHGETGLOBALFIELD Oo, 14 - 8529 APPLY1 - 8530 PUSHCONST0 - 8531 ACC1 + 8529 APPLY1 + 8530 PUSHCONST0 + 8531 ACC1 8532 BRANCHIFNOT 8537 - 8534 CONST0 + 8534 CONST0 8535 BRANCH 8543 - 8537 ENVACC1 - 8538 PUSHACC1 + 8537 ENVACC1 + 8538 PUSHACC1 8539 PUSHGETGLOBALFIELD Oo, 15 - 8542 APPLY2 - 8543 ACC0 + 8542 APPLY2 + 8543 ACC0 8544 RETURN 2 8546 CONSTINT 23 8548 RETURN 1 8550 CLOSURE 0, 8546 - 8553 PUSHACC0 + 8553 PUSHACC0 8554 POP 1 - 8556 PUSHENVACC1 - 8557 PUSHACC2 + 8556 PUSHENVACC1 + 8557 PUSHACC2 8558 PUSHGETGLOBALFIELD Oo, 8 - 8561 APPLY3 - 8562 ACC0 + 8561 APPLY3 + 8562 ACC0 8563 CLOSURE 1, 8519 8566 RETURN 1 8568 GETGLOBALFIELD Oo, 1 8571 PUSHGETGLOBAL "m" - 8573 PUSHACC1 - 8574 APPLY1 - 8575 PUSHCONST3 + 8573 PUSHACC1 + 8574 APPLY1 + 8575 PUSHCONST3 8576 C_CALL1 alloc_dummy 8578 PUSHGETGLOBAL <0>("m", 0) 8580 PUSHGETGLOBALFIELD Oo, 12 - 8583 APPLY1 - 8584 PUSHACC2 + 8583 APPLY1 + 8584 PUSHACC2 8585 CLOSURE 1, 8550 - 8588 PUSHACC1 - 8589 PUSHACC1 - 8590 APPLY1 - 8591 PUSHACC2 + 8588 PUSHACC1 + 8589 PUSHACC1 + 8590 APPLY1 + 8591 PUSHACC2 8592 PUSHGETGLOBALFIELD Oo, 13 - 8595 APPLY1 - 8596 ACC2 - 8597 PUSHACC2 - 8598 PUSHACC2 + 8595 APPLY1 + 8596 ACC2 + 8597 PUSHACC2 + 8598 PUSHACC2 8599 MAKEBLOCK3 0 8601 POP 3 - 8603 PUSHACC1 + 8603 PUSHACC1 8604 C_CALL2 update_dummy - 8606 CONST0 - 8607 PUSHACC1 - 8608 GETFIELD0 - 8609 APPLY1 + 8606 CONST0 + 8607 PUSHACC1 + 8608 GETFIELD0 + 8609 APPLY1 8610 PUSHCONSTINT 23 - 8612 PUSHACC1 - 8613 PUSHACC4 - 8614 GETMETHOD - 8615 APPLY1 - 8616 NEQ + 8612 PUSHACC1 + 8613 PUSHACC4 + 8614 GETMETHOD + 8615 APPLY1 + 8616 NEQ 8617 BRANCHIFNOT 8624 8619 GETGLOBAL Not_found 8621 MAKEBLOCK1 0 - 8623 RAISE + 8623 RAISE 8624 POP 1 - 8626 ACC0 + 8626 ACC0 8627 MAKEBLOCK1 0 8629 POP 3 8631 SETGLOBAL T300-getmethod - 8633 STOP + 8633 STOP **) diff --git a/testsuite/tests/tool-ocaml/t301-object.ml b/testsuite/tests/tool-ocaml/t301-object.ml index ac4a4e03..6b33f827 100644 --- a/testsuite/tests/tool-ocaml/t301-object.ml +++ b/testsuite/tests/tool-ocaml/t301-object.ml @@ -1,5 +1,5 @@ -(**** file testinterp/t301-object.ml - suggested by Jacques Garrigue to Basile Starynkevitch +(**** file testinterp/t301-object.ml + suggested by Jacques Garrigue to Basile Starynkevitch compilable with ocamlc -nostdlib -I ../../stdlib \ diff --git a/testsuite/tests/tool-ocaml/t310-alloc-1.ml b/testsuite/tests/tool-ocaml/t310-alloc-1.ml index c438cc97..9e0ff1a2 100644 --- a/testsuite/tests/tool-ocaml/t310-alloc-1.ml +++ b/testsuite/tests/tool-ocaml/t310-alloc-1.ml @@ -9,599 +9,599 @@ if List.fold_left (+) 0 l <> 30000 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -646,67 +646,67 @@ if List.fold_left (+) 0 l <> 30000 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -750,38 +750,38 @@ if List.fold_left (+) 0 l <> 30000 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -789,696 +789,696 @@ if List.fold_left (+) 0 l <> 30000 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1501,9 +1501,9 @@ if List.fold_left (+) 0 l <> 30000 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1542,46 +1542,46 @@ if List.fold_left (+) 0 l <> 30000 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 2435 - 2406 RESTART + 2406 RESTART 2407 GRAB 1 - 2409 CONST0 - 2410 PUSHACC2 - 2411 LEINT + 2409 CONST0 + 2410 PUSHACC2 + 2411 LEINT 2412 BRANCHIFNOT 2417 - 2414 ACC0 + 2414 ACC0 2415 RETURN 2 - 2417 ACC1 + 2417 ACC1 2418 OFFSETINT -1 - 2420 PUSHACC1 - 2421 PUSHCONST1 + 2420 PUSHACC1 + 2421 PUSHCONST1 2422 MAKEBLOCK2 0 - 2424 PUSHOFFSETCLOSURE0 + 2424 PUSHOFFSETCLOSURE0 2425 APPTERM2 4 - 2427 RESTART + 2427 RESTART 2428 GRAB 1 - 2430 ACC1 - 2431 PUSHACC1 - 2432 ADDINT + 2430 ACC1 + 2431 PUSHACC1 + 2432 ADDINT 2433 RETURN 2 2435 CLOSUREREC 0, 2407 2439 CONSTINT 30000 - 2441 PUSHCONST0 - 2442 PUSHACC2 - 2443 APPLY2 + 2441 PUSHCONST0 + 2442 PUSHACC2 + 2443 APPLY2 2444 PUSHCONSTINT 30000 - 2446 PUSHACC1 - 2447 PUSHCONST0 - 2448 PUSH + 2446 PUSHACC1 + 2447 PUSHCONST0 + 2448 PUSH 2449 CLOSURE 0, 2428 2452 PUSHGETGLOBALFIELD List, 12 - 2455 APPLY3 - 2456 NEQ + 2455 APPLY3 + 2456 NEQ 2457 BRANCHIFNOT 2464 2459 GETGLOBAL Not_found 2461 MAKEBLOCK1 0 - 2463 RAISE + 2463 RAISE 2464 POP 2 - 2466 ATOM0 + 2466 ATOM0 2467 SETGLOBAL T310-alloc-1 - 2469 STOP + 2469 STOP **) diff --git a/testsuite/tests/tool-ocaml/t310-alloc-2.ml b/testsuite/tests/tool-ocaml/t310-alloc-2.ml index 81034e78..efdc399b 100644 --- a/testsuite/tests/tool-ocaml/t310-alloc-2.ml +++ b/testsuite/tests/tool-ocaml/t310-alloc-2.ml @@ -7,599 +7,599 @@ if !t <> 400000 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -644,67 +644,67 @@ if !t <> 400000 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -748,38 +748,38 @@ if !t <> 400000 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -787,696 +787,696 @@ if !t <> 400000 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1499,9 +1499,9 @@ if !t <> 400000 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1540,729 +1540,729 @@ if !t <> 400000 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 3341 - 2406 RESTART + 2406 RESTART 2407 GRAB 2 - 2409 ACC2 - 2410 PUSHACC2 - 2411 VECTLENGTH + 2409 ACC2 + 2410 PUSHACC2 + 2411 VECTLENGTH 2412 OFFSETINT -1 - 2414 PUSHCONST0 - 2415 PUSH + 2414 PUSHCONST0 + 2415 PUSH 2416 BRANCH 2433 - 2418 CHECK_SIGNALS - 2419 ACC2 - 2420 PUSHACC2 - 2421 PUSHACC6 + 2418 CHECK_SIGNALS + 2419 ACC2 + 2420 PUSHACC2 + 2421 PUSHACC6 2422 C_CALL2 array_unsafe_get - 2424 PUSHACC5 - 2425 APPLY2 + 2424 PUSHACC5 + 2425 APPLY2 2426 ASSIGN 2 - 2428 ACC1 + 2428 ACC1 2429 OFFSETINT -1 2431 ASSIGN 1 - 2433 ACC0 - 2434 PUSHACC2 - 2435 GEINT + 2433 ACC0 + 2434 PUSHACC2 + 2435 GEINT 2436 BRANCHIF 2418 - 2438 CONST0 + 2438 CONST0 2439 POP 2 - 2441 ACC0 + 2441 ACC0 2442 RETURN 4 - 2444 RESTART + 2444 RESTART 2445 GRAB 2 - 2447 ACC1 - 2448 PUSHCONST0 - 2449 PUSHACC4 - 2450 VECTLENGTH + 2447 ACC1 + 2448 PUSHCONST0 + 2449 PUSHACC4 + 2450 VECTLENGTH 2451 OFFSETINT -1 - 2453 PUSH + 2453 PUSH 2454 BRANCH 2471 - 2456 CHECK_SIGNALS - 2457 ACC1 - 2458 PUSHACC6 + 2456 CHECK_SIGNALS + 2457 ACC1 + 2458 PUSHACC6 2459 C_CALL2 array_unsafe_get - 2461 PUSHACC3 - 2462 PUSHACC5 - 2463 APPLY2 + 2461 PUSHACC3 + 2462 PUSHACC5 + 2463 APPLY2 2464 ASSIGN 2 - 2466 ACC1 + 2466 ACC1 2467 OFFSETINT 1 2469 ASSIGN 1 - 2471 ACC0 - 2472 PUSHACC2 - 2473 LEINT + 2471 ACC0 + 2472 PUSHACC2 + 2473 LEINT 2474 BRANCHIF 2456 - 2476 CONST0 + 2476 CONST0 2477 POP 2 - 2479 ACC0 + 2479 ACC0 2480 RETURN 4 - 2482 RESTART + 2482 RESTART 2483 GRAB 1 - 2485 ACC1 + 2485 ACC1 2486 BRANCHIFNOT 2502 - 2488 ACC1 - 2489 GETFIELD0 - 2490 PUSHACC1 - 2491 PUSHENVACC1 + 2488 ACC1 + 2489 GETFIELD0 + 2490 PUSHACC1 + 2491 PUSHENVACC1 2492 C_CALL3 array_unsafe_set - 2494 ACC1 - 2495 GETFIELD1 - 2496 PUSHACC1 + 2494 ACC1 + 2495 GETFIELD1 + 2496 PUSHACC1 2497 OFFSETINT 1 - 2499 PUSHOFFSETCLOSURE0 + 2499 PUSHOFFSETCLOSURE0 2500 APPTERM2 4 - 2502 ENVACC1 + 2502 ENVACC1 2503 RETURN 2 - 2505 ACC0 + 2505 ACC0 2506 BRANCHIFNOT 2531 - 2508 ACC0 - 2509 GETFIELD1 - 2510 PUSHACC1 - 2511 GETFIELD0 - 2512 PUSHACC1 + 2508 ACC0 + 2509 GETFIELD1 + 2510 PUSHACC1 + 2511 GETFIELD0 + 2512 PUSHACC1 2513 PUSHGETGLOBALFIELD List, 0 - 2516 APPLY1 + 2516 APPLY1 2517 OFFSETINT 1 2519 C_CALL2 make_vect - 2521 PUSHACC0 + 2521 PUSHACC0 2522 CLOSUREREC 1, 2483 - 2526 ACC2 - 2527 PUSHCONST1 - 2528 PUSHACC2 + 2526 ACC2 + 2527 PUSHCONST1 + 2528 PUSHACC2 2529 APPTERM2 6 - 2531 ATOM0 + 2531 ATOM0 2532 RETURN 1 - 2534 RESTART + 2534 RESTART 2535 GRAB 1 - 2537 CONST0 - 2538 PUSHACC1 - 2539 LTINT + 2537 CONST0 + 2538 PUSHACC1 + 2539 LTINT 2540 BRANCHIFNOT 2545 - 2542 ACC1 + 2542 ACC1 2543 RETURN 2 - 2545 ACC1 - 2546 PUSHACC1 - 2547 PUSHENVACC1 + 2545 ACC1 + 2546 PUSHACC1 + 2547 PUSHENVACC1 2548 C_CALL2 array_unsafe_get 2550 MAKEBLOCK2 0 - 2552 PUSHACC1 + 2552 PUSHACC1 2553 OFFSETINT -1 - 2555 PUSHOFFSETCLOSURE0 + 2555 PUSHOFFSETCLOSURE0 2556 APPTERM2 4 - 2558 ACC0 + 2558 ACC0 2559 CLOSUREREC 1, 2535 - 2563 CONST0 - 2564 PUSHACC2 - 2565 VECTLENGTH + 2563 CONST0 + 2564 PUSHACC2 + 2565 VECTLENGTH 2566 OFFSETINT -1 - 2568 PUSHACC2 + 2568 PUSHACC2 2569 APPTERM2 4 - 2571 RESTART + 2571 RESTART 2572 GRAB 1 - 2574 ACC1 - 2575 VECTLENGTH - 2576 PUSHCONST0 - 2577 PUSHACC1 - 2578 EQ + 2574 ACC1 + 2575 VECTLENGTH + 2576 PUSHCONST0 + 2577 PUSHACC1 + 2578 EQ 2579 BRANCHIFNOT 2584 - 2581 ATOM0 + 2581 ATOM0 2582 RETURN 3 - 2584 CONST0 - 2585 PUSHACC3 + 2584 CONST0 + 2585 PUSHACC3 2586 C_CALL2 array_unsafe_get - 2588 PUSHCONST0 - 2589 PUSHACC3 - 2590 APPLY2 - 2591 PUSHACC1 + 2588 PUSHCONST0 + 2589 PUSHACC3 + 2590 APPLY2 + 2591 PUSHACC1 2592 C_CALL2 make_vect - 2594 PUSHCONST1 - 2595 PUSHACC2 + 2594 PUSHCONST1 + 2595 PUSHACC2 2596 OFFSETINT -1 - 2598 PUSH + 2598 PUSH 2599 BRANCH 2618 - 2601 CHECK_SIGNALS - 2602 ACC1 - 2603 PUSHACC6 + 2601 CHECK_SIGNALS + 2602 ACC1 + 2603 PUSHACC6 2604 C_CALL2 array_unsafe_get - 2606 PUSHACC2 - 2607 PUSHACC6 - 2608 APPLY2 - 2609 PUSHACC2 - 2610 PUSHACC4 + 2606 PUSHACC2 + 2607 PUSHACC6 + 2608 APPLY2 + 2609 PUSHACC2 + 2610 PUSHACC4 2611 C_CALL3 array_unsafe_set - 2613 ACC1 + 2613 ACC1 2614 OFFSETINT 1 2616 ASSIGN 1 - 2618 ACC0 - 2619 PUSHACC2 - 2620 LEINT + 2618 ACC0 + 2619 PUSHACC2 + 2620 LEINT 2621 BRANCHIF 2601 - 2623 CONST0 + 2623 CONST0 2624 POP 2 - 2626 ACC0 + 2626 ACC0 2627 RETURN 4 - 2629 RESTART + 2629 RESTART 2630 GRAB 1 - 2632 CONST0 - 2633 PUSHACC2 - 2634 VECTLENGTH + 2632 CONST0 + 2633 PUSHACC2 + 2634 VECTLENGTH 2635 OFFSETINT -1 - 2637 PUSH + 2637 PUSH 2638 BRANCH 2653 - 2640 CHECK_SIGNALS - 2641 ACC1 - 2642 PUSHACC4 + 2640 CHECK_SIGNALS + 2641 ACC1 + 2642 PUSHACC4 2643 C_CALL2 array_unsafe_get - 2645 PUSHACC2 - 2646 PUSHACC4 - 2647 APPLY2 - 2648 ACC1 + 2645 PUSHACC2 + 2646 PUSHACC4 + 2647 APPLY2 + 2648 ACC1 2649 OFFSETINT 1 2651 ASSIGN 1 - 2653 ACC0 - 2654 PUSHACC2 - 2655 LEINT + 2653 ACC0 + 2654 PUSHACC2 + 2655 LEINT 2656 BRANCHIF 2640 - 2658 CONST0 + 2658 CONST0 2659 RETURN 4 - 2661 RESTART + 2661 RESTART 2662 GRAB 1 - 2664 ACC1 - 2665 VECTLENGTH - 2666 PUSHCONST0 - 2667 PUSHACC1 - 2668 EQ + 2664 ACC1 + 2665 VECTLENGTH + 2666 PUSHCONST0 + 2667 PUSHACC1 + 2668 EQ 2669 BRANCHIFNOT 2674 - 2671 ATOM0 + 2671 ATOM0 2672 RETURN 3 - 2674 CONST0 - 2675 PUSHACC3 + 2674 CONST0 + 2675 PUSHACC3 2676 C_CALL2 array_unsafe_get - 2678 PUSHACC2 - 2679 APPLY1 - 2680 PUSHACC1 + 2678 PUSHACC2 + 2679 APPLY1 + 2680 PUSHACC1 2681 C_CALL2 make_vect - 2683 PUSHCONST1 - 2684 PUSHACC2 + 2683 PUSHCONST1 + 2684 PUSHACC2 2685 OFFSETINT -1 - 2687 PUSH + 2687 PUSH 2688 BRANCH 2706 - 2690 CHECK_SIGNALS - 2691 ACC1 - 2692 PUSHACC6 + 2690 CHECK_SIGNALS + 2691 ACC1 + 2692 PUSHACC6 2693 C_CALL2 array_unsafe_get - 2695 PUSHACC5 - 2696 APPLY1 - 2697 PUSHACC2 - 2698 PUSHACC4 + 2695 PUSHACC5 + 2696 APPLY1 + 2697 PUSHACC2 + 2698 PUSHACC4 2699 C_CALL3 array_unsafe_set - 2701 ACC1 + 2701 ACC1 2702 OFFSETINT 1 2704 ASSIGN 1 - 2706 ACC0 - 2707 PUSHACC2 - 2708 LEINT + 2706 ACC0 + 2707 PUSHACC2 + 2708 LEINT 2709 BRANCHIF 2690 - 2711 CONST0 + 2711 CONST0 2712 POP 2 - 2714 ACC0 + 2714 ACC0 2715 RETURN 4 - 2717 RESTART + 2717 RESTART 2718 GRAB 1 - 2720 CONST0 - 2721 PUSHACC2 - 2722 VECTLENGTH + 2720 CONST0 + 2721 PUSHACC2 + 2722 VECTLENGTH 2723 OFFSETINT -1 - 2725 PUSH + 2725 PUSH 2726 BRANCH 2740 - 2728 CHECK_SIGNALS - 2729 ACC1 - 2730 PUSHACC4 + 2728 CHECK_SIGNALS + 2729 ACC1 + 2730 PUSHACC4 2731 C_CALL2 array_unsafe_get - 2733 PUSHACC3 - 2734 APPLY1 - 2735 ACC1 + 2733 PUSHACC3 + 2734 APPLY1 + 2735 ACC1 2736 OFFSETINT 1 2738 ASSIGN 1 - 2740 ACC0 - 2741 PUSHACC2 - 2742 LEINT + 2740 ACC0 + 2741 PUSHACC2 + 2742 LEINT 2743 BRANCHIF 2728 - 2745 CONST0 + 2745 CONST0 2746 RETURN 4 - 2748 RESTART + 2748 RESTART 2749 GRAB 4 - 2751 CONST0 - 2752 PUSHACC5 - 2753 LTINT + 2751 CONST0 + 2752 PUSHACC5 + 2753 LTINT 2754 BRANCHIF 2782 - 2756 CONST0 - 2757 PUSHACC2 - 2758 LTINT + 2756 CONST0 + 2757 PUSHACC2 + 2758 LTINT 2759 BRANCHIF 2782 - 2761 ACC0 - 2762 VECTLENGTH - 2763 PUSHACC5 - 2764 PUSHACC3 - 2765 ADDINT - 2766 GTINT + 2761 ACC0 + 2762 VECTLENGTH + 2763 PUSHACC5 + 2764 PUSHACC3 + 2765 ADDINT + 2766 GTINT 2767 BRANCHIF 2782 - 2769 CONST0 - 2770 PUSHACC4 - 2771 LTINT + 2769 CONST0 + 2770 PUSHACC4 + 2771 LTINT 2772 BRANCHIF 2782 - 2774 ACC2 - 2775 VECTLENGTH - 2776 PUSHACC5 - 2777 PUSHACC5 - 2778 ADDINT - 2779 GTINT + 2774 ACC2 + 2775 VECTLENGTH + 2776 PUSHACC5 + 2777 PUSHACC5 + 2778 ADDINT + 2779 GTINT 2780 BRANCHIFNOT 2789 2782 GETGLOBAL "Array.blit" 2784 PUSHGETGLOBALFIELD Pervasives, 2 2787 APPTERM1 6 - 2789 ACC3 - 2790 PUSHACC2 - 2791 LTINT + 2789 ACC3 + 2790 PUSHACC2 + 2791 LTINT 2792 BRANCHIFNOT 2827 - 2794 ACC4 + 2794 ACC4 2795 OFFSETINT -1 - 2797 PUSHCONST0 - 2798 PUSH + 2797 PUSHCONST0 + 2798 PUSH 2799 BRANCH 2819 - 2801 CHECK_SIGNALS - 2802 ACC1 - 2803 PUSHACC4 - 2804 ADDINT - 2805 PUSHACC3 + 2801 CHECK_SIGNALS + 2802 ACC1 + 2803 PUSHACC4 + 2804 ADDINT + 2805 PUSHACC3 2806 C_CALL2 array_unsafe_get - 2808 PUSHACC2 - 2809 PUSHACC7 - 2810 ADDINT - 2811 PUSHACC6 + 2808 PUSHACC2 + 2809 PUSHACC7 + 2810 ADDINT + 2811 PUSHACC6 2812 C_CALL3 array_unsafe_set - 2814 ACC1 + 2814 ACC1 2815 OFFSETINT -1 2817 ASSIGN 1 - 2819 ACC0 - 2820 PUSHACC2 - 2821 GEINT + 2819 ACC0 + 2820 PUSHACC2 + 2821 GEINT 2822 BRANCHIF 2801 - 2824 CONST0 + 2824 CONST0 2825 RETURN 7 - 2827 CONST0 - 2828 PUSHACC5 + 2827 CONST0 + 2828 PUSHACC5 2829 OFFSETINT -1 - 2831 PUSH + 2831 PUSH 2832 BRANCH 2852 - 2834 CHECK_SIGNALS - 2835 ACC1 - 2836 PUSHACC4 - 2837 ADDINT - 2838 PUSHACC3 + 2834 CHECK_SIGNALS + 2835 ACC1 + 2836 PUSHACC4 + 2837 ADDINT + 2838 PUSHACC3 2839 C_CALL2 array_unsafe_get - 2841 PUSHACC2 - 2842 PUSHACC7 - 2843 ADDINT - 2844 PUSHACC6 + 2841 PUSHACC2 + 2842 PUSHACC7 + 2843 ADDINT + 2844 PUSHACC6 2845 C_CALL3 array_unsafe_set - 2847 ACC1 + 2847 ACC1 2848 OFFSETINT 1 2850 ASSIGN 1 - 2852 ACC0 - 2853 PUSHACC2 - 2854 LEINT + 2852 ACC0 + 2853 PUSHACC2 + 2854 LEINT 2855 BRANCHIF 2834 - 2857 CONST0 + 2857 CONST0 2858 RETURN 7 - 2860 RESTART + 2860 RESTART 2861 GRAB 3 - 2863 CONST0 - 2864 PUSHACC2 - 2865 LTINT + 2863 CONST0 + 2864 PUSHACC2 + 2865 LTINT 2866 BRANCHIF 2881 - 2868 CONST0 - 2869 PUSHACC3 - 2870 LTINT + 2868 CONST0 + 2869 PUSHACC3 + 2870 LTINT 2871 BRANCHIF 2881 - 2873 ACC0 - 2874 VECTLENGTH - 2875 PUSHACC3 - 2876 PUSHACC3 - 2877 ADDINT - 2878 GTINT + 2873 ACC0 + 2874 VECTLENGTH + 2875 PUSHACC3 + 2876 PUSHACC3 + 2877 ADDINT + 2878 GTINT 2879 BRANCHIFNOT 2888 2881 GETGLOBAL "Array.fill" 2883 PUSHGETGLOBALFIELD Pervasives, 2 2886 APPTERM1 5 - 2888 ACC1 - 2889 PUSHACC3 - 2890 PUSHACC3 - 2891 ADDINT + 2888 ACC1 + 2889 PUSHACC3 + 2890 PUSHACC3 + 2891 ADDINT 2892 OFFSETINT -1 - 2894 PUSH + 2894 PUSH 2895 BRANCH 2908 - 2897 CHECK_SIGNALS - 2898 ACC5 - 2899 PUSHACC2 - 2900 PUSHACC4 + 2897 CHECK_SIGNALS + 2898 ACC5 + 2899 PUSHACC2 + 2900 PUSHACC4 2901 C_CALL3 array_unsafe_set - 2903 ACC1 + 2903 ACC1 2904 OFFSETINT 1 2906 ASSIGN 1 - 2908 ACC0 - 2909 PUSHACC2 - 2910 LEINT + 2908 ACC0 + 2909 PUSHACC2 + 2910 LEINT 2911 BRANCHIF 2897 - 2913 CONST0 + 2913 CONST0 2914 RETURN 6 - 2916 RESTART + 2916 RESTART 2917 GRAB 2 - 2919 CONST0 - 2920 PUSHACC2 - 2921 LTINT + 2919 CONST0 + 2920 PUSHACC2 + 2921 LTINT 2922 BRANCHIF 2937 - 2924 CONST0 - 2925 PUSHACC3 - 2926 LTINT + 2924 CONST0 + 2925 PUSHACC3 + 2926 LTINT 2927 BRANCHIF 2937 - 2929 ACC0 - 2930 VECTLENGTH - 2931 PUSHACC3 - 2932 PUSHACC3 - 2933 ADDINT - 2934 GTINT + 2929 ACC0 + 2930 VECTLENGTH + 2931 PUSHACC3 + 2932 PUSHACC3 + 2933 ADDINT + 2934 GTINT 2935 BRANCHIFNOT 2944 2937 GETGLOBAL "Array.sub" 2939 PUSHGETGLOBALFIELD Pervasives, 2 2942 APPTERM1 4 - 2944 CONST0 - 2945 PUSHACC3 - 2946 EQ + 2944 CONST0 + 2945 PUSHACC3 + 2946 EQ 2947 BRANCHIFNOT 2952 - 2949 ATOM0 + 2949 ATOM0 2950 RETURN 3 - 2952 ACC1 - 2953 PUSHACC1 + 2952 ACC1 + 2953 PUSHACC1 2954 C_CALL2 array_unsafe_get - 2956 PUSHACC3 + 2956 PUSHACC3 2957 C_CALL2 make_vect - 2959 PUSHCONST1 - 2960 PUSHACC4 + 2959 PUSHCONST1 + 2960 PUSHACC4 2961 OFFSETINT -1 - 2963 PUSH + 2963 PUSH 2964 BRANCH 2982 - 2966 CHECK_SIGNALS - 2967 ACC1 - 2968 PUSHACC5 - 2969 ADDINT - 2970 PUSHACC4 + 2966 CHECK_SIGNALS + 2967 ACC1 + 2968 PUSHACC5 + 2969 ADDINT + 2970 PUSHACC4 2971 C_CALL2 array_unsafe_get - 2973 PUSHACC2 - 2974 PUSHACC4 + 2973 PUSHACC2 + 2974 PUSHACC4 2975 C_CALL3 array_unsafe_set - 2977 ACC1 + 2977 ACC1 2978 OFFSETINT 1 2980 ASSIGN 1 - 2982 ACC0 - 2983 PUSHACC2 - 2984 LEINT + 2982 ACC0 + 2983 PUSHACC2 + 2984 LEINT 2985 BRANCHIF 2966 - 2987 CONST0 + 2987 CONST0 2988 POP 2 - 2990 ACC0 + 2990 ACC0 2991 RETURN 4 - 2993 ACC0 + 2993 ACC0 2994 BRANCHIFNOT 3017 - 2996 ACC0 - 2997 GETFIELD0 - 2998 PUSHCONST0 - 2999 PUSHACC1 - 3000 VECTLENGTH - 3001 GTINT + 2996 ACC0 + 2997 GETFIELD0 + 2998 PUSHCONST0 + 2999 PUSHACC1 + 3000 VECTLENGTH + 3001 GTINT 3002 BRANCHIFNOT 3012 - 3004 ENVACC2 - 3005 PUSHCONST0 - 3006 PUSHACC2 + 3004 ENVACC2 + 3005 PUSHCONST0 + 3006 PUSHACC2 3007 C_CALL2 array_unsafe_get - 3009 PUSHENVACC1 + 3009 PUSHENVACC1 3010 APPTERM2 4 - 3012 ACC1 - 3013 GETFIELD1 - 3014 PUSHOFFSETCLOSURE0 + 3012 ACC1 + 3013 GETFIELD1 + 3014 PUSHOFFSETCLOSURE0 3015 APPTERM1 3 - 3017 ATOM0 + 3017 ATOM0 3018 RETURN 1 - 3020 ACC0 - 3021 PUSHENVACC1 + 3020 ACC0 + 3021 PUSHENVACC1 3022 CLOSUREREC 2, 2993 - 3026 ACC1 - 3027 PUSHACC1 + 3026 ACC1 + 3027 PUSHACC1 3028 APPTERM1 3 - 3030 CONST0 - 3031 PUSHACC1 - 3032 VECTLENGTH + 3030 CONST0 + 3031 PUSHACC1 + 3032 VECTLENGTH 3033 OFFSETINT -1 - 3035 PUSH + 3035 PUSH 3036 BRANCH 3056 - 3038 CHECK_SIGNALS - 3039 ACC1 - 3040 PUSHACC3 + 3038 CHECK_SIGNALS + 3039 ACC1 + 3040 PUSHACC3 3041 C_CALL2 array_unsafe_get - 3043 PUSHENVACC2 - 3044 GETFIELD0 - 3045 PUSHENVACC1 + 3043 PUSHENVACC2 + 3044 GETFIELD0 + 3045 PUSHENVACC1 3046 C_CALL3 array_unsafe_set - 3048 ENVACC2 + 3048 ENVACC2 3049 OFFSETREF 1 - 3051 ACC1 + 3051 ACC1 3052 OFFSETINT 1 3054 ASSIGN 1 - 3056 ACC0 - 3057 PUSHACC2 - 3058 LEINT + 3056 ACC0 + 3057 PUSHACC2 + 3058 LEINT 3059 BRANCHIF 3038 - 3061 CONST0 + 3061 CONST0 3062 RETURN 3 - 3064 RESTART + 3064 RESTART 3065 GRAB 1 - 3067 ACC1 - 3068 VECTLENGTH - 3069 PUSHACC1 - 3070 ADDINT + 3067 ACC1 + 3068 VECTLENGTH + 3069 PUSHACC1 + 3070 ADDINT 3071 RETURN 2 - 3073 RESTART + 3073 RESTART 3074 GRAB 1 - 3076 ACC1 - 3077 PUSHCONST0 - 3078 PUSH + 3076 ACC1 + 3077 PUSHCONST0 + 3078 PUSH 3079 CLOSURE 0, 3065 3082 PUSHGETGLOBALFIELD List, 12 - 3085 APPLY3 - 3086 PUSHACC1 - 3087 PUSHACC1 + 3085 APPLY3 + 3086 PUSHACC1 + 3087 PUSHACC1 3088 C_CALL2 make_vect - 3090 PUSHCONST0 + 3090 PUSHCONST0 3091 MAKEBLOCK1 0 - 3093 PUSHACC4 - 3094 PUSHACC1 - 3095 PUSHACC3 + 3093 PUSHACC4 + 3094 PUSHACC1 + 3095 PUSHACC3 3096 CLOSURE 2, 3030 3099 PUSHGETGLOBALFIELD List, 9 - 3102 APPLY2 - 3103 ACC1 + 3102 APPLY2 + 3103 ACC1 3104 RETURN 5 - 3106 RESTART + 3106 RESTART 3107 GRAB 1 - 3109 ACC0 - 3110 VECTLENGTH - 3111 PUSHACC2 - 3112 VECTLENGTH - 3113 PUSHCONST0 - 3114 PUSHACC2 - 3115 EQ + 3109 ACC0 + 3110 VECTLENGTH + 3111 PUSHACC2 + 3112 VECTLENGTH + 3113 PUSHCONST0 + 3114 PUSHACC2 + 3115 EQ 3116 BRANCHIFNOT 3126 - 3118 CONST0 - 3119 PUSHACC1 - 3120 EQ + 3118 CONST0 + 3119 PUSHACC1 + 3120 EQ 3121 BRANCHIFNOT 3126 - 3123 ATOM0 + 3123 ATOM0 3124 RETURN 4 - 3126 CONST0 - 3127 PUSHCONST0 - 3128 PUSHACC3 - 3129 GTINT + 3126 CONST0 + 3127 PUSHCONST0 + 3128 PUSHACC3 + 3129 GTINT 3130 BRANCHIFNOT 3135 - 3132 ACC3 + 3132 ACC3 3133 BRANCH 3136 - 3135 ACC4 + 3135 ACC4 3136 C_CALL2 array_unsafe_get - 3138 PUSHACC1 - 3139 PUSHACC3 - 3140 ADDINT + 3138 PUSHACC1 + 3139 PUSHACC3 + 3140 ADDINT 3141 C_CALL2 make_vect - 3143 PUSHCONST0 - 3144 PUSHACC3 + 3143 PUSHCONST0 + 3144 PUSHACC3 3145 OFFSETINT -1 - 3147 PUSH + 3147 PUSH 3148 BRANCH 3164 - 3150 CHECK_SIGNALS - 3151 ACC1 - 3152 PUSHACC6 + 3150 CHECK_SIGNALS + 3151 ACC1 + 3152 PUSHACC6 3153 C_CALL2 array_unsafe_get - 3155 PUSHACC2 - 3156 PUSHACC4 + 3155 PUSHACC2 + 3156 PUSHACC4 3157 C_CALL3 array_unsafe_set - 3159 ACC1 + 3159 ACC1 3160 OFFSETINT 1 3162 ASSIGN 1 - 3164 ACC0 - 3165 PUSHACC2 - 3166 LEINT + 3164 ACC0 + 3165 PUSHACC2 + 3166 LEINT 3167 BRANCHIF 3150 - 3169 CONST0 + 3169 CONST0 3170 POP 2 - 3172 CONST0 - 3173 PUSHACC2 + 3172 CONST0 + 3173 PUSHACC2 3174 OFFSETINT -1 - 3176 PUSH + 3176 PUSH 3177 BRANCH 3195 - 3179 CHECK_SIGNALS - 3180 ACC1 - 3181 PUSHACC7 + 3179 CHECK_SIGNALS + 3180 ACC1 + 3181 PUSHACC7 3182 C_CALL2 array_unsafe_get - 3184 PUSHACC5 - 3185 PUSHACC3 - 3186 ADDINT - 3187 PUSHACC4 + 3184 PUSHACC5 + 3185 PUSHACC3 + 3186 ADDINT + 3187 PUSHACC4 3188 C_CALL3 array_unsafe_set - 3190 ACC1 + 3190 ACC1 3191 OFFSETINT 1 3193 ASSIGN 1 - 3195 ACC0 - 3196 PUSHACC2 - 3197 LEINT + 3195 ACC0 + 3196 PUSHACC2 + 3197 LEINT 3198 BRANCHIF 3179 - 3200 CONST0 + 3200 CONST0 3201 POP 2 - 3203 ACC0 + 3203 ACC0 3204 RETURN 5 - 3206 ACC0 - 3207 VECTLENGTH - 3208 PUSHCONST0 - 3209 PUSHACC1 - 3210 EQ + 3206 ACC0 + 3207 VECTLENGTH + 3208 PUSHCONST0 + 3209 PUSHACC1 + 3210 EQ 3211 BRANCHIFNOT 3216 - 3213 ATOM0 + 3213 ATOM0 3214 RETURN 2 - 3216 CONST0 - 3217 PUSHACC2 + 3216 CONST0 + 3217 PUSHACC2 3218 C_CALL2 array_unsafe_get - 3220 PUSHACC1 + 3220 PUSHACC1 3221 C_CALL2 make_vect - 3223 PUSHCONST1 - 3224 PUSHACC2 + 3223 PUSHCONST1 + 3224 PUSHACC2 3225 OFFSETINT -1 - 3227 PUSH + 3227 PUSH 3228 BRANCH 3244 - 3230 CHECK_SIGNALS - 3231 ACC1 - 3232 PUSHACC5 + 3230 CHECK_SIGNALS + 3231 ACC1 + 3232 PUSHACC5 3233 C_CALL2 array_unsafe_get - 3235 PUSHACC2 - 3236 PUSHACC4 + 3235 PUSHACC2 + 3236 PUSHACC4 3237 C_CALL3 array_unsafe_set - 3239 ACC1 + 3239 ACC1 3240 OFFSETINT 1 3242 ASSIGN 1 - 3244 ACC0 - 3245 PUSHACC2 - 3246 LEINT + 3244 ACC0 + 3245 PUSHACC2 + 3246 LEINT 3247 BRANCHIF 3230 - 3249 CONST0 + 3249 CONST0 3250 POP 2 - 3252 ACC0 + 3252 ACC0 3253 RETURN 3 - 3255 RESTART + 3255 RESTART 3256 GRAB 2 - 3258 ATOM0 - 3259 PUSHACC1 + 3258 ATOM0 + 3259 PUSHACC1 3260 C_CALL2 make_vect - 3262 PUSHCONST0 - 3263 PUSHACC2 + 3262 PUSHCONST0 + 3263 PUSHACC2 3264 OFFSETINT -1 - 3266 PUSH + 3266 PUSH 3267 BRANCH 3282 - 3269 CHECK_SIGNALS - 3270 ACC5 - 3271 PUSHACC5 + 3269 CHECK_SIGNALS + 3270 ACC5 + 3271 PUSHACC5 3272 C_CALL2 make_vect - 3274 PUSHACC2 - 3275 PUSHACC4 - 3276 SETVECTITEM - 3277 ACC1 + 3274 PUSHACC2 + 3275 PUSHACC4 + 3276 SETVECTITEM + 3277 ACC1 3278 OFFSETINT 1 3280 ASSIGN 1 - 3282 ACC0 - 3283 PUSHACC2 - 3284 LEINT + 3282 ACC0 + 3283 PUSHACC2 + 3284 LEINT 3285 BRANCHIF 3269 - 3287 CONST0 + 3287 CONST0 3288 POP 2 - 3290 ACC0 + 3290 ACC0 3291 RETURN 4 - 3293 RESTART + 3293 RESTART 3294 GRAB 1 - 3296 CONST0 - 3297 PUSHACC1 - 3298 EQ + 3296 CONST0 + 3297 PUSHACC1 + 3298 EQ 3299 BRANCHIFNOT 3304 - 3301 ATOM0 + 3301 ATOM0 3302 RETURN 2 - 3304 CONST0 - 3305 PUSHACC2 - 3306 APPLY1 - 3307 PUSHACC1 + 3304 CONST0 + 3305 PUSHACC2 + 3306 APPLY1 + 3307 PUSHACC1 3308 C_CALL2 make_vect - 3310 PUSHCONST1 - 3311 PUSHACC2 + 3310 PUSHCONST1 + 3311 PUSHACC2 3312 OFFSETINT -1 - 3314 PUSH + 3314 PUSH 3315 BRANCH 3330 - 3317 CHECK_SIGNALS - 3318 ACC1 - 3319 PUSHACC5 - 3320 APPLY1 - 3321 PUSHACC2 - 3322 PUSHACC4 + 3317 CHECK_SIGNALS + 3318 ACC1 + 3319 PUSHACC5 + 3320 APPLY1 + 3321 PUSHACC2 + 3322 PUSHACC4 3323 C_CALL3 array_unsafe_set - 3325 ACC1 + 3325 ACC1 3326 OFFSETINT 1 3328 ASSIGN 1 - 3330 ACC0 - 3331 PUSHACC2 - 3332 LEINT + 3330 ACC0 + 3331 PUSHACC2 + 3332 LEINT 3333 BRANCHIF 3317 - 3335 CONST0 + 3335 CONST0 3336 POP 2 - 3338 ACC0 + 3338 ACC0 3339 RETURN 3 3341 CLOSURE 0, 3294 - 3344 PUSH + 3344 PUSH 3345 CLOSURE 0, 3256 - 3348 PUSH + 3348 PUSH 3349 CLOSURE 0, 3206 - 3352 PUSH + 3352 PUSH 3353 CLOSURE 0, 3107 - 3356 PUSH + 3356 PUSH 3357 CLOSURE 0, 3074 - 3360 PUSHACC0 + 3360 PUSHACC0 3361 CLOSURE 1, 3020 - 3364 PUSH + 3364 PUSH 3365 CLOSURE 0, 2917 - 3368 PUSH + 3368 PUSH 3369 CLOSURE 0, 2861 - 3372 PUSH + 3372 PUSH 3373 CLOSURE 0, 2749 - 3376 PUSH + 3376 PUSH 3377 CLOSURE 0, 2718 - 3380 PUSH + 3380 PUSH 3381 CLOSURE 0, 2662 - 3384 PUSH + 3384 PUSH 3385 CLOSURE 0, 2630 - 3388 PUSH + 3388 PUSH 3389 CLOSURE 0, 2572 - 3392 PUSH + 3392 PUSH 3393 CLOSURE 0, 2558 - 3396 PUSH + 3396 PUSH 3397 CLOSURE 0, 2505 - 3400 PUSH + 3400 PUSH 3401 CLOSURE 0, 2445 - 3404 PUSH + 3404 PUSH 3405 CLOSURE 0, 2407 - 3408 PUSHACC0 - 3409 PUSHACC2 - 3410 PUSHACC6 + 3408 PUSHACC0 + 3409 PUSHACC2 + 3410 PUSHACC6 3411 PUSHACC 8 3413 PUSHACC 10 3415 PUSHACC 12 @@ -2281,33 +2281,33 @@ if !t <> 400000 then raise Not_found 3442 POP 17 3444 SETGLOBAL Array 3446 BRANCH 3456 - 3448 ACC0 - 3449 PUSHENVACC1 - 3450 GETFIELD0 - 3451 ADDINT - 3452 PUSHENVACC1 - 3453 SETFIELD0 + 3448 ACC0 + 3449 PUSHENVACC1 + 3450 GETFIELD0 + 3451 ADDINT + 3452 PUSHENVACC1 + 3453 SETFIELD0 3454 RETURN 1 - 3456 CONST2 + 3456 CONST2 3457 PUSHCONSTINT 200000 3459 C_CALL2 make_vect - 3461 PUSHCONST0 + 3461 PUSHCONST0 3462 MAKEBLOCK1 0 - 3464 PUSHACC1 - 3465 PUSHACC1 + 3464 PUSHACC1 + 3465 PUSHACC1 3466 CLOSURE 1, 3448 3469 PUSHGETGLOBALFIELD Array, 11 - 3472 APPLY2 + 3472 APPLY2 3473 CONSTINT 400000 - 3475 PUSHACC1 - 3476 GETFIELD0 - 3477 NEQ + 3475 PUSHACC1 + 3476 GETFIELD0 + 3477 NEQ 3478 BRANCHIFNOT 3485 3480 GETGLOBAL Not_found 3482 MAKEBLOCK1 0 - 3484 RAISE + 3484 RAISE 3485 POP 2 - 3487 ATOM0 + 3487 ATOM0 3488 SETGLOBAL T310-alloc-2 - 3490 STOP + 3490 STOP **) diff --git a/testsuite/tests/tool-ocaml/t320-gc-1.ml b/testsuite/tests/tool-ocaml/t320-gc-1.ml index 4d5d6d96..dde4e0b6 100644 --- a/testsuite/tests/tool-ocaml/t320-gc-1.ml +++ b/testsuite/tests/tool-ocaml/t320-gc-1.ml @@ -10,599 +10,599 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -647,67 +647,67 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -751,38 +751,38 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -790,696 +790,696 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1502,9 +1502,9 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1543,47 +1543,47 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 2432 - 2406 CONST0 - 2407 PUSHACC1 - 2408 LEINT + 2406 CONST0 + 2407 PUSHACC1 + 2408 LEINT 2409 BRANCHIFNOT 2414 - 2411 CONST0 + 2411 CONST0 2412 RETURN 1 - 2414 ACC0 + 2414 ACC0 2415 OFFSETINT -1 - 2417 PUSHOFFSETCLOSURE0 - 2418 APPLY1 - 2419 PUSHACC1 + 2417 PUSHOFFSETCLOSURE0 + 2418 APPLY1 + 2419 PUSHACC1 2420 MAKEBLOCK2 0 2422 RETURN 1 - 2424 RESTART + 2424 RESTART 2425 GRAB 1 - 2427 ACC1 - 2428 PUSHACC1 - 2429 ADDINT + 2427 ACC1 + 2428 PUSHACC1 + 2429 ADDINT 2430 RETURN 2 2432 CLOSUREREC 0, 2406 2436 CONSTINT 300 - 2438 PUSHACC1 - 2439 APPLY1 - 2440 PUSHCONST0 + 2438 PUSHACC1 + 2439 APPLY1 + 2440 PUSHCONST0 2441 C_CALL1 gc_minor 2443 CONSTINT 150 2445 PUSHCONSTINT 301 - 2447 MULINT - 2448 PUSHACC1 - 2449 PUSHCONST0 - 2450 PUSH + 2447 MULINT + 2448 PUSHACC1 + 2449 PUSHCONST0 + 2450 PUSH 2451 CLOSURE 0, 2425 2454 PUSHGETGLOBALFIELD List, 12 - 2457 APPLY3 - 2458 NEQ + 2457 APPLY3 + 2458 NEQ 2459 BRANCHIFNOT 2466 2461 GETGLOBAL Not_found 2463 MAKEBLOCK1 0 - 2465 RAISE + 2465 RAISE 2466 POP 2 - 2468 ATOM0 + 2468 ATOM0 2469 SETGLOBAL T320-gc-1 - 2471 STOP + 2471 STOP **) diff --git a/testsuite/tests/tool-ocaml/t320-gc-2.ml b/testsuite/tests/tool-ocaml/t320-gc-2.ml index f607f651..39ec57c4 100644 --- a/testsuite/tests/tool-ocaml/t320-gc-2.ml +++ b/testsuite/tests/tool-ocaml/t320-gc-2.ml @@ -10,599 +10,599 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -647,67 +647,67 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -751,38 +751,38 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -790,696 +790,696 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1502,9 +1502,9 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1543,47 +1543,47 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 2432 - 2406 CONST0 - 2407 PUSHACC1 - 2408 LEINT + 2406 CONST0 + 2407 PUSHACC1 + 2408 LEINT 2409 BRANCHIFNOT 2414 - 2411 CONST0 + 2411 CONST0 2412 RETURN 1 - 2414 ACC0 + 2414 ACC0 2415 OFFSETINT -1 - 2417 PUSHOFFSETCLOSURE0 - 2418 APPLY1 - 2419 PUSHACC1 + 2417 PUSHOFFSETCLOSURE0 + 2418 APPLY1 + 2419 PUSHACC1 2420 MAKEBLOCK2 0 2422 RETURN 1 - 2424 RESTART + 2424 RESTART 2425 GRAB 1 - 2427 ACC1 - 2428 PUSHACC1 - 2429 ADDINT + 2427 ACC1 + 2428 PUSHACC1 + 2429 ADDINT 2430 RETURN 2 2432 CLOSUREREC 0, 2406 2436 CONSTINT 300 - 2438 PUSHACC1 - 2439 APPLY1 - 2440 PUSHCONST0 + 2438 PUSHACC1 + 2439 APPLY1 + 2440 PUSHCONST0 2441 C_CALL1 gc_major 2443 CONSTINT 150 2445 PUSHCONSTINT 301 - 2447 MULINT - 2448 PUSHACC1 - 2449 PUSHCONST0 - 2450 PUSH + 2447 MULINT + 2448 PUSHACC1 + 2449 PUSHCONST0 + 2450 PUSH 2451 CLOSURE 0, 2425 2454 PUSHGETGLOBALFIELD List, 12 - 2457 APPLY3 - 2458 NEQ + 2457 APPLY3 + 2458 NEQ 2459 BRANCHIFNOT 2466 2461 GETGLOBAL Not_found 2463 MAKEBLOCK1 0 - 2465 RAISE + 2465 RAISE 2466 POP 2 - 2468 ATOM0 + 2468 ATOM0 2469 SETGLOBAL T320-gc-2 - 2471 STOP + 2471 STOP **) diff --git a/testsuite/tests/tool-ocaml/t320-gc-3.ml b/testsuite/tests/tool-ocaml/t320-gc-3.ml index 7c33d2fd..69a63682 100644 --- a/testsuite/tests/tool-ocaml/t320-gc-3.ml +++ b/testsuite/tests/tool-ocaml/t320-gc-3.ml @@ -10,599 +10,599 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -647,67 +647,67 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -751,38 +751,38 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -790,696 +790,696 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1502,9 +1502,9 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1543,47 +1543,47 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 2432 - 2406 CONST0 - 2407 PUSHACC1 - 2408 LEINT + 2406 CONST0 + 2407 PUSHACC1 + 2408 LEINT 2409 BRANCHIFNOT 2414 - 2411 CONST0 + 2411 CONST0 2412 RETURN 1 - 2414 ACC0 + 2414 ACC0 2415 OFFSETINT -1 - 2417 PUSHOFFSETCLOSURE0 - 2418 APPLY1 - 2419 PUSHACC1 + 2417 PUSHOFFSETCLOSURE0 + 2418 APPLY1 + 2419 PUSHACC1 2420 MAKEBLOCK2 0 2422 RETURN 1 - 2424 RESTART + 2424 RESTART 2425 GRAB 1 - 2427 ACC1 - 2428 PUSHACC1 - 2429 ADDINT + 2427 ACC1 + 2428 PUSHACC1 + 2429 ADDINT 2430 RETURN 2 2432 CLOSUREREC 0, 2406 2436 CONSTINT 300 - 2438 PUSHACC1 - 2439 APPLY1 - 2440 PUSHCONST0 + 2438 PUSHACC1 + 2439 APPLY1 + 2440 PUSHCONST0 2441 C_CALL1 gc_full_major 2443 CONSTINT 150 2445 PUSHCONSTINT 301 - 2447 MULINT - 2448 PUSHACC1 - 2449 PUSHCONST0 - 2450 PUSH + 2447 MULINT + 2448 PUSHACC1 + 2449 PUSHCONST0 + 2450 PUSH 2451 CLOSURE 0, 2425 2454 PUSHGETGLOBALFIELD List, 12 - 2457 APPLY3 - 2458 NEQ + 2457 APPLY3 + 2458 NEQ 2459 BRANCHIFNOT 2466 2461 GETGLOBAL Not_found 2463 MAKEBLOCK1 0 - 2465 RAISE + 2465 RAISE 2466 POP 2 - 2468 ATOM0 + 2468 ATOM0 2469 SETGLOBAL T320-gc-3 - 2471 STOP + 2471 STOP **) diff --git a/testsuite/tests/tool-ocaml/t330-compact-1.ml b/testsuite/tests/tool-ocaml/t330-compact-1.ml index efa958fd..aaa80f0f 100644 --- a/testsuite/tests/tool-ocaml/t330-compact-1.ml +++ b/testsuite/tests/tool-ocaml/t330-compact-1.ml @@ -3,13 +3,13 @@ Gc.compact ();; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib - 9 CONST0 + 9 CONST0 10 C_CALL1 gc_compaction - 12 ATOM0 + 12 ATOM0 13 SETGLOBAL T330-compact-1 - 15 STOP + 15 STOP **) diff --git a/testsuite/tests/tool-ocaml/t330-compact-2.ml b/testsuite/tests/tool-ocaml/t330-compact-2.ml index 62ab0141..fa91834e 100644 --- a/testsuite/tests/tool-ocaml/t330-compact-2.ml +++ b/testsuite/tests/tool-ocaml/t330-compact-2.ml @@ -4,599 +4,599 @@ let _ = Pervasives.do_at_exit();; (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -641,67 +641,67 @@ let _ = Pervasives.do_at_exit();; 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -744,12 +744,12 @@ let _ = Pervasives.do_at_exit();; 1190 MAKEBLOCK 69, 0 1193 POP 53 1195 SETGLOBAL Pervasives - 1197 CONST0 + 1197 CONST0 1198 C_CALL1 gc_compaction - 1200 CONST0 + 1200 CONST0 1201 PUSHGETGLOBALFIELD Pervasives, 68 - 1204 APPLY1 - 1205 ATOM0 + 1204 APPLY1 + 1205 ATOM0 1206 SETGLOBAL T330-compact-2 - 1208 STOP + 1208 STOP **) diff --git a/testsuite/tests/tool-ocaml/t330-compact-3.ml b/testsuite/tests/tool-ocaml/t330-compact-3.ml index f25c64ef..44d80a7d 100644 --- a/testsuite/tests/tool-ocaml/t330-compact-3.ml +++ b/testsuite/tests/tool-ocaml/t330-compact-3.ml @@ -10,599 +10,599 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -647,67 +647,67 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -751,38 +751,38 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -790,696 +790,696 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1502,9 +1502,9 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1543,47 +1543,47 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 2432 - 2406 CONST0 - 2407 PUSHACC1 - 2408 LEINT + 2406 CONST0 + 2407 PUSHACC1 + 2408 LEINT 2409 BRANCHIFNOT 2414 - 2411 CONST0 + 2411 CONST0 2412 RETURN 1 - 2414 ACC0 + 2414 ACC0 2415 OFFSETINT -1 - 2417 PUSHOFFSETCLOSURE0 - 2418 APPLY1 - 2419 PUSHACC1 + 2417 PUSHOFFSETCLOSURE0 + 2418 APPLY1 + 2419 PUSHACC1 2420 MAKEBLOCK2 0 2422 RETURN 1 - 2424 RESTART + 2424 RESTART 2425 GRAB 1 - 2427 ACC1 - 2428 PUSHACC1 - 2429 ADDINT + 2427 ACC1 + 2428 PUSHACC1 + 2429 ADDINT 2430 RETURN 2 2432 CLOSUREREC 0, 2406 2436 CONSTINT 300 - 2438 PUSHACC1 - 2439 APPLY1 - 2440 PUSHCONST0 + 2438 PUSHACC1 + 2439 APPLY1 + 2440 PUSHCONST0 2441 C_CALL1 gc_compaction 2443 CONSTINT 150 2445 PUSHCONSTINT 301 - 2447 MULINT - 2448 PUSHACC1 - 2449 PUSHCONST0 - 2450 PUSH + 2447 MULINT + 2448 PUSHACC1 + 2449 PUSHCONST0 + 2450 PUSH 2451 CLOSURE 0, 2425 2454 PUSHGETGLOBALFIELD List, 12 - 2457 APPLY3 - 2458 NEQ + 2457 APPLY3 + 2458 NEQ 2459 BRANCHIFNOT 2466 2461 GETGLOBAL Not_found 2463 MAKEBLOCK1 0 - 2465 RAISE + 2465 RAISE 2466 POP 2 - 2468 ATOM0 + 2468 ATOM0 2469 SETGLOBAL T330-compact-3 - 2471 STOP + 2471 STOP **) diff --git a/testsuite/tests/tool-ocaml/t330-compact-4.ml b/testsuite/tests/tool-ocaml/t330-compact-4.ml index 1c190f75..60161a5f 100644 --- a/testsuite/tests/tool-ocaml/t330-compact-4.ml +++ b/testsuite/tests/tool-ocaml/t330-compact-4.ml @@ -10,599 +10,599 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 746 - 11 RESTART + 11 RESTART 12 GRAB 1 - 14 ACC0 + 14 ACC0 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 + 17 ACC1 + 18 PUSHACC1 + 19 GETFIELD1 + 20 PUSHOFFSETCLOSURE0 + 21 APPLY2 + 22 PUSHACC1 + 23 GETFIELD0 24 MAKEBLOCK2 0 26 RETURN 2 - 28 ACC1 + 28 ACC1 29 RETURN 2 - 31 RESTART + 31 RESTART 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT + 34 CONST0 + 35 PUSHACC4 + 36 LEINT 37 BRANCHIFNOT 42 - 39 CONST0 + 39 CONST0 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 + 42 ACC3 + 43 PUSHACC3 + 44 PUSHACC3 + 45 PUSHACC3 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ + 48 PUSHCONST0 + 49 PUSHACC1 + 50 EQ 51 BRANCHIFNOT 58 53 GETGLOBAL End_of_file 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 + 57 RAISE + 58 ACC0 + 59 PUSHACC5 + 60 SUBINT + 61 PUSHACC1 + 62 PUSHACC5 + 63 ADDINT + 64 PUSHACC4 + 65 PUSHACC4 + 66 PUSHOFFSETCLOSURE0 67 APPTERM 4, 9 - 70 ACC0 + 70 ACC0 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ + 73 PUSHCONST0 + 74 PUSHACC1 + 75 EQ 76 BRANCHIFNOT 83 78 GETGLOBAL End_of_file 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT + 82 RAISE + 83 CONST0 + 84 PUSHACC1 + 85 GTINT 86 BRANCHIFNOT 107 - 88 ACC0 + 88 ACC0 89 OFFSETINT -1 91 C_CALL1 create_string - 93 PUSHACC1 + 93 PUSHACC1 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 + 96 PUSHCONST0 + 97 PUSHACC2 + 98 PUSHACC5 99 C_CALL4 caml_input - 101 ACC2 + 101 ACC2 102 C_CALL1 caml_input_char - 104 ACC0 + 104 ACC0 105 RETURN 3 - 107 ACC0 - 108 NEGINT + 107 ACC0 + 108 NEGINT 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 + 111 PUSHACC1 + 112 NEGINT + 113 PUSHCONST0 + 114 PUSHACC2 + 115 PUSHACC5 116 C_CALL4 caml_input - 118 CONST0 + 118 CONST0 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP + 121 ACC6 + 122 PUSHOFFSETCLOSURE0 + 123 APPLY1 + 124 PUSHACC5 + 125 PUSHENVACC1 + 126 APPLY2 + 127 POPTRAP 128 RETURN 3 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ + 132 PUSHACC1 + 133 GETFIELD0 + 134 EQ 135 BRANCHIFNOT 140 - 137 ACC1 + 137 ACC1 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 + 140 ACC0 + 141 RAISE + 142 ACC0 143 C_CALL1 caml_flush 145 RETURN 1 - 147 RESTART + 147 RESTART 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 + 150 ACC1 + 151 PUSHACC1 152 C_CALL2 caml_output_char 154 RETURN 2 - 156 RESTART + 156 RESTART 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 + 159 ACC1 + 160 PUSHACC1 161 C_CALL2 caml_output_char 163 RETURN 2 - 165 RESTART + 165 RESTART 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 + 168 ACC1 + 169 PUSHACC1 170 C_CALL2 caml_output_int 172 RETURN 2 - 174 RESTART + 174 RESTART 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 + 177 ACC1 + 178 PUSHACC1 179 C_CALL2 caml_seek_out 181 RETURN 2 - 183 ACC0 + 183 ACC0 184 C_CALL1 caml_pos_out 186 RETURN 1 - 188 ACC0 + 188 ACC0 189 C_CALL1 caml_channel_size 191 RETURN 1 - 193 RESTART + 193 RESTART 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 + 196 ACC1 + 197 PUSHACC1 198 C_CALL2 caml_set_binary_mode 200 RETURN 2 - 202 ACC0 + 202 ACC0 203 C_CALL1 caml_input_char 205 RETURN 1 - 207 ACC0 + 207 ACC0 208 C_CALL1 caml_input_char 210 RETURN 1 - 212 ACC0 + 212 ACC0 213 C_CALL1 caml_input_int 215 RETURN 1 - 217 ACC0 + 217 ACC0 218 C_CALL1 input_value 220 RETURN 1 - 222 RESTART + 222 RESTART 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 + 225 ACC1 + 226 PUSHACC1 227 C_CALL2 caml_seek_in 229 RETURN 2 - 231 ACC0 + 231 ACC0 232 C_CALL1 caml_pos_in 234 RETURN 1 - 236 ACC0 + 236 ACC0 237 C_CALL1 caml_channel_size 239 RETURN 1 - 241 ACC0 + 241 ACC0 242 C_CALL1 caml_close_channel 244 RETURN 1 - 246 RESTART + 246 RESTART 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 + 249 ACC1 + 250 PUSHACC1 251 C_CALL2 caml_set_binary_mode 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 + 255 CONST0 + 256 PUSHENVACC1 + 257 APPLY1 + 258 ACC0 259 C_CALL1 sys_exit 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 + 263 CONST0 + 264 PUSHENVACC1 + 265 GETFIELD0 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 + 268 CONST0 + 269 PUSHENVACC1 + 270 APPLY1 + 271 CONST0 + 272 PUSHENVACC2 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 + 275 ENVACC1 + 276 GETFIELD0 + 277 PUSHACC0 + 278 PUSHACC2 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 + 282 PUSHENVACC1 + 283 SETFIELD0 284 RETURN 2 - 286 ENVACC1 + 286 ENVACC1 287 C_CALL1 caml_flush - 289 ENVACC2 + 289 ENVACC2 290 C_CALL1 caml_flush 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 + 294 CONST0 + 295 PUSHENVACC1 + 296 APPLY1 297 C_CALL1 float_of_string 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 + 301 CONST0 + 302 PUSHENVACC1 + 303 APPLY1 304 C_CALL1 int_of_string 306 RETURN 1 - 308 ENVACC2 + 308 ENVACC2 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 + 311 ENVACC1 + 312 PUSHENVACC3 313 APPTERM1 2 315 CONSTINT 13 - 317 PUSHENVACC1 + 317 PUSHENVACC1 318 C_CALL2 caml_output_char - 320 ENVACC1 + 320 ENVACC1 321 C_CALL1 caml_flush 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 + 325 ACC0 + 326 PUSHENVACC1 + 327 PUSHENVACC2 + 328 APPLY2 329 CONSTINT 13 - 331 PUSHENVACC1 + 331 PUSHENVACC1 332 C_CALL2 caml_output_char - 334 ENVACC1 + 334 ENVACC1 335 C_CALL1 caml_flush 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 + 339 ACC0 + 340 PUSHENVACC1 + 341 APPLY1 + 342 PUSHENVACC2 + 343 PUSHENVACC3 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 + 346 ACC0 + 347 PUSHENVACC1 + 348 APPLY1 + 349 PUSHENVACC2 + 350 PUSHENVACC3 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 + 353 ACC0 + 354 PUSHENVACC1 + 355 PUSHENVACC2 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 + 358 ACC0 + 359 PUSHENVACC1 360 C_CALL2 caml_output_char 362 RETURN 1 364 CONSTINT 13 - 366 PUSHENVACC1 + 366 PUSHENVACC1 367 C_CALL2 caml_output_char - 369 ENVACC1 + 369 ENVACC1 370 C_CALL1 caml_flush 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 + 374 ACC0 + 375 PUSHENVACC1 + 376 PUSHENVACC2 + 377 APPLY2 378 CONSTINT 13 - 380 PUSHENVACC1 + 380 PUSHENVACC1 381 C_CALL2 caml_output_char 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 + 385 ACC0 + 386 PUSHENVACC1 + 387 APPLY1 + 388 PUSHENVACC2 + 389 PUSHENVACC3 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 + 392 ACC0 + 393 PUSHENVACC1 + 394 APPLY1 + 395 PUSHENVACC2 + 396 PUSHENVACC3 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 + 399 ACC0 + 400 PUSHENVACC1 + 401 PUSHENVACC2 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 + 404 ACC0 + 405 PUSHENVACC1 406 C_CALL2 caml_output_char 408 RETURN 1 - 410 RESTART + 410 RESTART 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT + 413 CONST0 + 414 PUSHACC3 + 415 LTINT 416 BRANCHIF 427 - 418 ACC1 + 418 ACC1 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT + 421 PUSHACC4 + 422 PUSHACC4 + 423 ADDINT + 424 GTINT 425 BRANCHIFNOT 432 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 + 429 PUSHENVACC1 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 + 432 ACC3 + 433 PUSHACC3 + 434 PUSHACC3 + 435 PUSHACC3 + 436 PUSHENVACC2 437 APPTERM 4, 8 - 440 RESTART + 440 RESTART 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT + 443 CONST0 + 444 PUSHACC3 + 445 LTINT 446 BRANCHIF 457 - 448 ACC1 + 448 ACC1 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT + 451 PUSHACC4 + 452 PUSHACC4 + 453 ADDINT + 454 GTINT 455 BRANCHIFNOT 462 457 GETGLOBAL "input" - 459 PUSHENVACC1 + 459 PUSHENVACC1 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 + 462 ACC3 + 463 PUSHACC3 + 464 PUSHACC3 + 465 PUSHACC3 466 C_CALL4 caml_input 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 + 470 ACC0 + 471 PUSHCONST0 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 + 474 PUSHENVACC1 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 + 477 ACC0 + 478 PUSHCONST0 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 + 481 PUSHENVACC1 482 APPTERM3 4 - 484 RESTART + 484 RESTART 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 + 487 ACC1 + 488 PUSHACC1 + 489 PUSHACC4 490 C_CALL3 sys_open 492 C_CALL1 caml_open_descriptor 494 RETURN 3 - 496 ACC0 + 496 ACC0 497 C_CALL1 caml_flush - 499 ACC0 + 499 ACC0 500 C_CALL1 caml_close_channel 502 RETURN 1 - 504 RESTART + 504 RESTART 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 + 507 CONST0 + 508 PUSHACC2 + 509 PUSHACC2 510 C_CALL3 output_value 512 RETURN 2 - 514 RESTART + 514 RESTART 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT + 517 CONST0 + 518 PUSHACC3 + 519 LTINT 520 BRANCHIF 531 - 522 ACC1 + 522 ACC1 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT + 525 PUSHACC4 + 526 PUSHACC4 + 527 ADDINT + 528 GTINT 529 BRANCHIFNOT 536 531 GETGLOBAL "output" - 533 PUSHENVACC1 + 533 PUSHENVACC1 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 + 536 ACC3 + 537 PUSHACC3 + 538 PUSHACC3 + 539 PUSHACC3 540 C_CALL4 caml_output 542 RETURN 4 - 544 RESTART + 544 RESTART 545 GRAB 1 - 547 ACC1 + 547 ACC1 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 + 550 PUSHCONST0 + 551 PUSHACC3 + 552 PUSHACC3 553 C_CALL4 caml_output 555 RETURN 2 - 557 ACC0 + 557 ACC0 558 PUSHCONSTINT 438 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 + 562 PUSHENVACC1 563 APPTERM3 4 - 565 ACC0 + 565 ACC0 566 PUSHCONSTINT 438 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 + 570 PUSHENVACC1 571 APPTERM3 4 - 573 RESTART + 573 RESTART 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 + 576 ACC1 + 577 PUSHACC1 + 578 PUSHACC4 579 C_CALL3 sys_open 581 C_CALL1 caml_open_descriptor 583 RETURN 3 - 585 ACC0 + 585 ACC0 586 PUSHGETGLOBAL "%.12g" 588 C_CALL2 format_float 590 RETURN 1 - 592 ACC0 + 592 ACC0 593 PUSHGETGLOBAL "%d" 595 C_CALL2 format_int 597 RETURN 1 599 GETGLOBAL "false" - 601 PUSHACC1 + 601 PUSHACC1 602 C_CALL2 string_equal 604 BRANCHIFNOT 609 - 606 CONST0 + 606 CONST0 607 RETURN 1 609 GETGLOBAL "true" - 611 PUSHACC1 + 611 PUSHACC1 612 C_CALL2 string_equal 614 BRANCHIFNOT 619 - 616 CONST1 + 616 CONST1 617 RETURN 1 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 + 621 PUSHENVACC1 622 APPTERM1 2 - 624 ACC0 + 624 ACC0 625 BRANCHIFNOT 631 627 GETGLOBAL "true" 629 RETURN 1 631 GETGLOBAL "false" 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT + 635 CONST0 + 636 PUSHACC1 + 637 LTINT 638 BRANCHIF 646 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT + 642 PUSHACC1 + 643 GTINT 644 BRANCHIFNOT 651 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 + 648 PUSHENVACC1 649 APPTERM1 2 - 651 ACC0 + 651 ACC0 652 RETURN 1 - 654 RESTART + 654 RESTART 655 GRAB 1 - 657 ACC0 + 657 ACC0 658 C_CALL1 ml_string_length - 660 PUSHACC2 + 660 PUSHACC2 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT + 663 PUSHACC0 + 664 PUSHACC2 + 665 ADDINT 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 + 668 PUSHACC2 + 669 PUSHCONST0 + 670 PUSHACC2 + 671 PUSHCONST0 + 672 PUSHACC7 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 + 675 ACC1 + 676 PUSHACC3 + 677 PUSHACC2 + 678 PUSHCONST0 679 PUSHACC 8 681 C_CALL5 blit_string - 683 ACC0 + 683 ACC0 684 RETURN 5 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT + 688 PUSHACC1 + 689 XORINT 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT + 692 CONST0 + 693 PUSHACC1 + 694 GEINT 695 BRANCHIFNOT 700 - 697 ACC0 + 697 ACC0 698 RETURN 1 - 700 ACC0 - 701 NEGINT + 700 ACC0 + 701 NEGINT 702 RETURN 1 - 704 RESTART + 704 RESTART 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 + 707 ACC1 + 708 PUSHACC1 709 C_CALL2 greaterequal 711 BRANCHIFNOT 716 - 713 ACC0 + 713 ACC0 714 RETURN 2 - 716 ACC1 + 716 ACC1 717 RETURN 2 - 719 RESTART + 719 RESTART 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 + 722 ACC1 + 723 PUSHACC1 724 C_CALL2 lessequal 726 BRANCHIFNOT 731 - 728 ACC0 + 728 ACC0 729 RETURN 2 - 731 ACC1 + 731 ACC1 732 RETURN 2 - 734 ACC0 + 734 ACC0 735 PUSHGETGLOBAL Invalid_argument 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 + 739 RAISE + 740 ACC0 741 PUSHGETGLOBAL Failure 743 MAKEBLOCK2 0 - 745 RAISE + 745 RAISE 746 CLOSURE 0, 740 - 749 PUSH + 749 PUSH 750 CLOSURE 0, 734 753 PUSHGETGLOBAL "Pervasives.Exit" 755 MAKEBLOCK1 0 757 PUSHGETGLOBAL "Pervasives.Assert_failure" 759 MAKEBLOCK1 0 - 761 PUSH + 761 PUSH 762 CLOSURE 0, 720 - 765 PUSH + 765 PUSH 766 CLOSURE 0, 705 - 769 PUSH + 769 PUSH 770 CLOSURE 0, 692 - 773 PUSH + 773 PUSH 774 CLOSURE 0, 686 - 777 PUSHCONST0 + 777 PUSHCONST0 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ + 780 PUSHCONST1 + 781 LSLINT + 782 EQ 783 BRANCHIFNOT 789 785 CONSTINT 30 787 BRANCH 791 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 + 791 PUSHCONST1 + 792 LSLINT + 793 PUSHACC0 794 OFFSETINT -1 - 796 PUSH + 796 PUSH 797 CLOSURE 0, 655 800 PUSHACC 9 802 CLOSURE 1, 635 - 805 PUSH + 805 PUSH 806 CLOSURE 0, 624 809 PUSHACC 11 811 CLOSURE 1, 599 - 814 PUSH + 814 PUSH 815 CLOSURE 0, 592 - 818 PUSH + 818 PUSH 819 CLOSURE 0, 585 - 822 PUSH + 822 PUSH 823 CLOSUREREC 0, 12 - 827 CONST0 + 827 CONST0 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 + 830 PUSHCONST1 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 + 833 PUSHCONST2 834 C_CALL1 caml_open_descriptor - 836 PUSH + 836 PUSH 837 CLOSURE 0, 574 - 840 PUSHACC0 + 840 PUSHACC0 841 CLOSURE 1, 565 - 844 PUSHACC1 + 844 PUSHACC1 845 CLOSURE 1, 557 - 848 PUSH + 848 PUSH 849 CLOSURE 0, 545 852 PUSHACC 22 854 CLOSURE 1, 515 - 857 PUSH + 857 PUSH 858 CLOSURE 0, 505 - 861 PUSH + 861 PUSH 862 CLOSURE 0, 496 - 865 PUSH + 865 PUSH 866 CLOSURE 0, 485 - 869 PUSHACC0 + 869 PUSHACC0 870 CLOSURE 1, 477 - 873 PUSHACC1 + 873 PUSHACC1 874 CLOSURE 1, 470 877 PUSHACC 28 879 CLOSURE 1, 441 - 882 PUSH + 882 PUSH 883 CLOSUREREC 0, 32 - 887 ACC0 + 887 ACC0 888 PUSHACC 31 890 CLOSURE 2, 411 893 PUSHACC 22 @@ -647,67 +647,67 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 985 PUSHACC 28 987 PUSHACC 30 989 CLOSURE 3, 308 - 992 PUSHACC0 + 992 PUSHACC0 993 CLOSURE 1, 301 - 996 PUSHACC1 + 996 PUSHACC1 997 CLOSURE 1, 294 1000 PUSHACC 29 1002 PUSHACC 31 1004 CLOSURE 2, 286 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 + 1009 PUSHACC0 1010 CLOSURE 1, 275 - 1013 PUSHACC1 + 1013 PUSHACC1 1014 CLOSURE 1, 263 - 1017 PUSHACC0 + 1017 PUSHACC0 1018 CLOSURE 1, 255 - 1021 PUSHACC1 + 1021 PUSHACC1 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH + 1024 PUSHACC4 + 1025 PUSHACC3 + 1026 PUSH 1027 CLOSURE 0, 247 - 1030 PUSH + 1030 PUSH 1031 CLOSURE 0, 241 - 1034 PUSH + 1034 PUSH 1035 CLOSURE 0, 236 - 1038 PUSH + 1038 PUSH 1039 CLOSURE 0, 231 - 1042 PUSH + 1042 PUSH 1043 CLOSURE 0, 223 - 1046 PUSH + 1046 PUSH 1047 CLOSURE 0, 217 - 1050 PUSH + 1050 PUSH 1051 CLOSURE 0, 212 - 1054 PUSH + 1054 PUSH 1055 CLOSURE 0, 207 1058 PUSHACC 32 1060 PUSHACC 35 1062 PUSHACC 33 - 1064 PUSH + 1064 PUSH 1065 CLOSURE 0, 202 1068 PUSHACC 41 1070 PUSHACC 40 1072 PUSHACC 42 - 1074 PUSH + 1074 PUSH 1075 CLOSURE 0, 194 1078 PUSHACC 46 - 1080 PUSH + 1080 PUSH 1081 CLOSURE 0, 188 - 1084 PUSH + 1084 PUSH 1085 CLOSURE 0, 183 - 1088 PUSH + 1088 PUSH 1089 CLOSURE 0, 175 1092 PUSHACC 51 - 1094 PUSH + 1094 PUSH 1095 CLOSURE 0, 166 - 1098 PUSH + 1098 PUSH 1099 CLOSURE 0, 157 1102 PUSHACC 55 1104 PUSHACC 57 - 1106 PUSH + 1106 PUSH 1107 CLOSURE 0, 148 - 1110 PUSH + 1110 PUSH 1111 CLOSURE 0, 142 1114 PUSHACC 63 1116 PUSHACC 62 @@ -751,38 +751,38 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1193 POP 53 1195 SETGLOBAL Pervasives 1197 BRANCH 2177 - 1199 RESTART + 1199 RESTART 1200 GRAB 1 - 1202 ACC1 + 1202 ACC1 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 + 1205 ACC1 + 1206 GETFIELD1 + 1207 PUSHACC1 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 + 1210 PUSHOFFSETCLOSURE0 1211 APPTERM2 4 - 1213 ACC0 + 1213 ACC0 1214 RETURN 2 - 1216 RESTART + 1216 RESTART 1217 GRAB 1 - 1219 ACC0 + 1219 ACC0 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ + 1222 CONST0 + 1223 PUSHACC2 + 1224 EQ 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 + 1227 ACC0 + 1228 GETFIELD0 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT + 1231 CONST0 + 1232 PUSHACC2 + 1233 GTINT 1234 BRANCHIFNOT 1244 - 1236 ACC1 + 1236 ACC1 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 + 1239 PUSHACC1 + 1240 GETFIELD1 + 1241 PUSHOFFSETCLOSURE0 1242 APPTERM2 4 1244 GETGLOBAL "List.nth" 1246 PUSHGETGLOBALFIELD Pervasives, 2 @@ -790,696 +790,696 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 1251 GETGLOBAL "nth" 1253 PUSHGETGLOBALFIELD Pervasives, 3 1256 APPTERM1 3 - 1258 RESTART + 1258 RESTART 1259 GRAB 1 - 1261 ACC0 + 1261 ACC0 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 + 1264 ACC1 + 1265 PUSHACC1 + 1266 GETFIELD0 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 + 1269 PUSHACC1 + 1270 GETFIELD1 + 1271 PUSHOFFSETCLOSURE0 1272 APPTERM2 4 - 1274 ACC1 + 1274 ACC1 1275 RETURN 2 - 1277 ACC0 + 1277 ACC0 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 + 1280 ACC0 + 1281 GETFIELD1 + 1282 PUSHOFFSETCLOSURE0 + 1283 APPLY1 + 1284 PUSHACC1 + 1285 GETFIELD0 1286 PUSHGETGLOBALFIELD Pervasives, 16 1289 APPTERM2 3 1291 RETURN 1 - 1293 RESTART + 1293 RESTART 1294 GRAB 1 - 1296 ACC1 + 1296 ACC1 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 + 1299 ACC1 + 1300 GETFIELD0 + 1301 PUSHACC1 + 1302 APPLY1 + 1303 PUSHACC2 + 1304 GETFIELD1 + 1305 PUSHACC2 + 1306 PUSHOFFSETCLOSURE0 + 1307 APPLY2 + 1308 PUSHACC1 1309 MAKEBLOCK2 0 1311 POP 1 1313 RETURN 2 - 1315 RESTART + 1315 RESTART 1316 GRAB 1 - 1318 ACC1 + 1318 ACC1 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 + 1321 ACC1 + 1322 GETFIELD0 + 1323 PUSHACC1 + 1324 APPLY1 + 1325 ACC1 + 1326 GETFIELD1 + 1327 PUSHACC1 + 1328 PUSHOFFSETCLOSURE0 1329 APPTERM2 4 1331 RETURN 2 - 1333 RESTART + 1333 RESTART 1334 GRAB 2 - 1336 ACC2 + 1336 ACC2 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 + 1339 ACC2 + 1340 GETFIELD1 + 1341 PUSHACC3 + 1342 GETFIELD0 + 1343 PUSHACC3 + 1344 PUSHACC3 + 1345 APPLY2 + 1346 PUSHACC2 + 1347 PUSHOFFSETCLOSURE0 1348 APPTERM3 6 - 1350 ACC1 + 1350 ACC1 1351 RETURN 3 - 1353 RESTART + 1353 RESTART 1354 GRAB 2 - 1356 ACC1 + 1356 ACC1 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 + 1359 ACC2 + 1360 PUSHACC2 + 1361 GETFIELD1 + 1362 PUSHACC2 + 1363 PUSHOFFSETCLOSURE0 + 1364 APPLY3 + 1365 PUSHACC2 + 1366 GETFIELD0 + 1367 PUSHACC2 1368 APPTERM2 5 - 1370 ACC2 + 1370 ACC2 1371 RETURN 3 - 1373 RESTART + 1373 RESTART 1374 GRAB 2 - 1376 ACC1 + 1376 ACC1 1377 BRANCHIFNOT 1400 - 1379 ACC2 + 1379 ACC2 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 + 1382 ACC2 + 1383 GETFIELD0 + 1384 PUSHACC2 + 1385 GETFIELD0 + 1386 PUSHACC2 + 1387 APPLY2 + 1388 PUSHACC3 + 1389 GETFIELD1 + 1390 PUSHACC3 + 1391 GETFIELD1 + 1392 PUSHACC3 + 1393 PUSHOFFSETCLOSURE0 + 1394 APPLY3 + 1395 PUSHACC1 1396 MAKEBLOCK2 0 1398 RETURN 4 - 1400 ACC2 + 1400 ACC2 1401 BRANCHIFNOT 1405 1403 BRANCH 1407 1405 RETURN 3 1407 GETGLOBAL "List.map2" 1409 PUSHGETGLOBALFIELD Pervasives, 2 1412 APPTERM1 4 - 1414 RESTART + 1414 RESTART 1415 GRAB 2 - 1417 ACC1 + 1417 ACC1 1418 BRANCHIFNOT 1437 - 1420 ACC2 + 1420 ACC2 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 + 1423 ACC2 + 1424 GETFIELD0 + 1425 PUSHACC2 + 1426 GETFIELD0 + 1427 PUSHACC2 + 1428 APPLY2 + 1429 ACC2 + 1430 GETFIELD1 + 1431 PUSHACC2 + 1432 GETFIELD1 + 1433 PUSHACC2 + 1434 PUSHOFFSETCLOSURE0 1435 APPTERM3 6 - 1437 ACC2 + 1437 ACC2 1438 BRANCHIFNOT 1442 1440 BRANCH 1444 1442 RETURN 3 1444 GETGLOBAL "List.iter2" 1446 PUSHGETGLOBALFIELD Pervasives, 2 1449 APPTERM1 4 - 1451 RESTART + 1451 RESTART 1452 GRAB 3 - 1454 ACC2 + 1454 ACC2 1455 BRANCHIFNOT 1476 - 1457 ACC3 + 1457 ACC3 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 + 1460 ACC3 + 1461 GETFIELD1 + 1462 PUSHACC3 + 1463 GETFIELD1 + 1464 PUSHACC5 + 1465 GETFIELD0 + 1466 PUSHACC5 + 1467 GETFIELD0 + 1468 PUSHACC5 + 1469 PUSHACC5 + 1470 APPLY3 + 1471 PUSHACC3 + 1472 PUSHOFFSETCLOSURE0 1473 APPTERM 4, 8 - 1476 ACC3 + 1476 ACC3 1477 BRANCHIF 1482 - 1479 ACC1 + 1479 ACC1 1480 RETURN 4 1482 GETGLOBAL "List.fold_left2" 1484 PUSHGETGLOBALFIELD Pervasives, 2 1487 APPTERM1 5 - 1489 RESTART + 1489 RESTART 1490 GRAB 3 - 1492 ACC1 + 1492 ACC1 1493 BRANCHIFNOT 1516 - 1495 ACC2 + 1495 ACC2 1496 BRANCHIFNOT 1522 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 + 1500 ACC6 + 1501 PUSHACC6 + 1502 GETFIELD1 + 1503 PUSHACC6 + 1504 GETFIELD1 + 1505 PUSHACC6 + 1506 PUSHOFFSETCLOSURE0 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 + 1509 PUSHACC3 + 1510 GETFIELD0 + 1511 PUSHACC3 + 1512 GETFIELD0 + 1513 PUSHACC3 1514 APPTERM3 7 - 1516 ACC2 + 1516 ACC2 1517 BRANCHIF 1522 - 1519 ACC3 + 1519 ACC3 1520 RETURN 4 1522 GETGLOBAL "List.fold_right2" 1524 PUSHGETGLOBALFIELD Pervasives, 2 1527 APPTERM1 5 - 1529 RESTART + 1529 RESTART 1530 GRAB 1 - 1532 ACC1 + 1532 ACC1 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 + 1535 ACC1 + 1536 GETFIELD0 + 1537 PUSHACC1 + 1538 APPLY1 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 + 1541 ACC1 + 1542 GETFIELD1 + 1543 PUSHACC1 + 1544 PUSHOFFSETCLOSURE0 1545 APPTERM2 4 1547 RETURN 2 - 1549 CONST1 + 1549 CONST1 1550 RETURN 2 - 1552 RESTART + 1552 RESTART 1553 GRAB 1 - 1555 ACC1 + 1555 ACC1 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 + 1558 ACC1 + 1559 GETFIELD0 + 1560 PUSHACC1 + 1561 APPLY1 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 + 1564 ACC1 + 1565 GETFIELD1 + 1566 PUSHACC1 + 1567 PUSHOFFSETCLOSURE0 1568 APPTERM2 4 1570 RETURN 2 - 1572 RESTART + 1572 RESTART 1573 GRAB 2 - 1575 ACC1 + 1575 ACC1 1576 BRANCHIFNOT 1599 - 1578 ACC2 + 1578 ACC2 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 + 1581 ACC2 + 1582 GETFIELD0 + 1583 PUSHACC2 + 1584 GETFIELD0 + 1585 PUSHACC2 + 1586 APPLY2 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 + 1589 ACC2 + 1590 GETFIELD1 + 1591 PUSHACC2 + 1592 GETFIELD1 + 1593 PUSHACC2 + 1594 PUSHOFFSETCLOSURE0 1595 APPTERM3 6 1597 RETURN 3 - 1599 ACC2 + 1599 ACC2 1600 BRANCHIF 1605 - 1602 CONST1 + 1602 CONST1 1603 RETURN 3 1605 GETGLOBAL "List.for_all2" 1607 PUSHGETGLOBALFIELD Pervasives, 2 1610 APPTERM1 4 - 1612 RESTART + 1612 RESTART 1613 GRAB 2 - 1615 ACC1 + 1615 ACC1 1616 BRANCHIFNOT 1639 - 1618 ACC2 + 1618 ACC2 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 + 1621 ACC2 + 1622 GETFIELD0 + 1623 PUSHACC2 + 1624 GETFIELD0 + 1625 PUSHACC2 + 1626 APPLY2 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 + 1629 ACC2 + 1630 GETFIELD1 + 1631 PUSHACC2 + 1632 GETFIELD1 + 1633 PUSHACC2 + 1634 PUSHOFFSETCLOSURE0 1635 APPTERM3 6 1637 RETURN 3 - 1639 ACC2 + 1639 ACC2 1640 BRANCHIFNOT 1644 1642 BRANCH 1646 1644 RETURN 3 1646 GETGLOBAL "List.exists2" 1648 PUSHGETGLOBALFIELD Pervasives, 2 1651 APPTERM1 4 - 1653 RESTART + 1653 RESTART 1654 GRAB 1 - 1656 ACC1 + 1656 ACC1 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 + 1659 ACC0 + 1660 PUSHACC2 + 1661 GETFIELD0 1662 C_CALL2 equal 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 + 1666 ACC1 + 1667 GETFIELD1 + 1668 PUSHACC1 + 1669 PUSHOFFSETCLOSURE0 1670 APPTERM2 4 1672 RETURN 2 - 1674 RESTART + 1674 RESTART 1675 GRAB 1 - 1677 ACC1 + 1677 ACC1 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ + 1680 ACC0 + 1681 PUSHACC2 + 1682 GETFIELD0 + 1683 EQ 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 + 1686 ACC1 + 1687 GETFIELD1 + 1688 PUSHACC1 + 1689 PUSHOFFSETCLOSURE0 1690 APPTERM2 4 1692 RETURN 2 - 1694 RESTART + 1694 RESTART 1695 GRAB 1 - 1697 ACC1 + 1697 ACC1 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 + 1700 ACC1 + 1701 GETFIELD0 + 1702 PUSHACC1 + 1703 PUSHACC1 + 1704 GETFIELD0 1705 C_CALL2 equal 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 + 1709 ACC0 + 1710 GETFIELD1 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 + 1713 ACC2 + 1714 GETFIELD1 + 1715 PUSHACC2 + 1716 PUSHOFFSETCLOSURE0 1717 APPTERM2 5 1719 GETGLOBAL Not_found 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART + 1723 RAISE + 1724 RESTART 1725 GRAB 1 - 1727 ACC1 + 1727 ACC1 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ + 1730 ACC1 + 1731 GETFIELD0 + 1732 PUSHACC1 + 1733 PUSHACC1 + 1734 GETFIELD0 + 1735 EQ 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 + 1738 ACC0 + 1739 GETFIELD1 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 + 1742 ACC2 + 1743 GETFIELD1 + 1744 PUSHACC2 + 1745 PUSHOFFSETCLOSURE0 1746 APPTERM2 5 1748 GETGLOBAL Not_found 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART + 1752 RAISE + 1753 RESTART 1754 GRAB 1 - 1756 ACC1 + 1756 ACC1 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 + 1759 ACC0 + 1760 PUSHACC2 + 1761 GETFIELD0 + 1762 GETFIELD0 1763 C_CALL2 equal 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 + 1767 ACC1 + 1768 GETFIELD1 + 1769 PUSHACC1 + 1770 PUSHOFFSETCLOSURE0 1771 APPTERM2 4 1773 RETURN 2 - 1775 RESTART + 1775 RESTART 1776 GRAB 1 - 1778 ACC1 + 1778 ACC1 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ + 1781 ACC0 + 1782 PUSHACC2 + 1783 GETFIELD0 + 1784 GETFIELD0 + 1785 EQ 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 + 1788 ACC1 + 1789 GETFIELD1 + 1790 PUSHACC1 + 1791 PUSHOFFSETCLOSURE0 1792 APPTERM2 4 1794 RETURN 2 - 1796 RESTART + 1796 RESTART 1797 GRAB 1 - 1799 ACC1 + 1799 ACC1 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 + 1802 ACC1 + 1803 GETFIELD0 + 1804 PUSHACC2 + 1805 GETFIELD1 + 1806 PUSHACC2 + 1807 PUSHACC2 + 1808 GETFIELD0 1809 C_CALL2 equal 1811 BRANCHIFNOT 1816 - 1813 ACC0 + 1813 ACC0 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 + 1816 ACC0 + 1817 PUSHACC3 + 1818 PUSHOFFSETCLOSURE0 + 1819 APPLY2 + 1820 PUSHACC2 1821 MAKEBLOCK2 0 1823 POP 2 1825 RETURN 2 - 1827 RESTART + 1827 RESTART 1828 GRAB 1 - 1830 ACC1 + 1830 ACC1 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ + 1833 ACC1 + 1834 GETFIELD0 + 1835 PUSHACC2 + 1836 GETFIELD1 + 1837 PUSHACC2 + 1838 PUSHACC2 + 1839 GETFIELD0 + 1840 EQ 1841 BRANCHIFNOT 1846 - 1843 ACC0 + 1843 ACC0 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 + 1846 ACC0 + 1847 PUSHACC3 + 1848 PUSHOFFSETCLOSURE0 + 1849 APPLY2 + 1850 PUSHACC2 1851 MAKEBLOCK2 0 1853 POP 2 1855 RETURN 2 - 1857 RESTART + 1857 RESTART 1858 GRAB 1 - 1860 ACC1 + 1860 ACC1 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 + 1863 ACC1 + 1864 GETFIELD0 + 1865 PUSHACC0 + 1866 PUSHACC2 + 1867 APPLY1 1868 BRANCHIFNOT 1873 - 1870 ACC0 + 1870 ACC0 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 + 1873 ACC2 + 1874 GETFIELD1 + 1875 PUSHACC2 + 1876 PUSHOFFSETCLOSURE0 1877 APPTERM2 5 1879 GETGLOBAL Not_found 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART + 1883 RAISE + 1884 RESTART 1885 GRAB 2 - 1887 ACC2 + 1887 ACC2 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 + 1890 ACC2 + 1891 GETFIELD0 + 1892 PUSHACC3 + 1893 GETFIELD1 + 1894 PUSHACC1 + 1895 PUSHENVACC2 + 1896 APPLY1 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 + 1899 ACC0 + 1900 PUSHACC4 + 1901 PUSHACC4 + 1902 PUSHACC4 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 + 1905 PUSHOFFSETCLOSURE0 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 + 1908 ACC0 + 1909 PUSHACC4 + 1910 PUSHACC3 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 + 1913 PUSHACC4 + 1914 PUSHOFFSETCLOSURE0 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 + 1917 ACC1 + 1918 PUSHENVACC1 + 1919 APPLY1 + 1920 PUSHACC1 + 1921 PUSHENVACC1 + 1922 APPLY1 1923 MAKEBLOCK2 0 1925 RETURN 3 - 1927 RESTART + 1927 RESTART 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 + 1930 ACC0 + 1931 PUSHENVACC1 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 + 1936 ACC2 + 1937 PUSHCONST0 + 1938 PUSHCONST0 + 1939 PUSHACC3 1940 APPTERM3 6 - 1942 ACC0 + 1942 ACC0 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 + 1945 ACC0 + 1946 GETFIELD0 + 1947 PUSHACC1 + 1948 GETFIELD1 + 1949 PUSHOFFSETCLOSURE0 + 1950 APPLY1 + 1951 PUSHACC0 + 1952 GETFIELD1 + 1953 PUSHACC2 + 1954 GETFIELD1 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 + 1957 PUSHACC1 + 1958 GETFIELD0 + 1959 PUSHACC3 + 1960 GETFIELD0 1961 MAKEBLOCK2 0 1963 MAKEBLOCK2 0 1965 RETURN 3 1967 GETGLOBAL <0>(0, 0) 1969 RETURN 1 - 1971 RESTART + 1971 RESTART 1972 GRAB 1 - 1974 ACC0 + 1974 ACC0 1975 BRANCHIFNOT 1996 - 1977 ACC1 + 1977 ACC1 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 + 1980 ACC1 + 1981 GETFIELD1 + 1982 PUSHACC1 + 1983 GETFIELD1 + 1984 PUSHOFFSETCLOSURE0 + 1985 APPLY2 + 1986 PUSHACC2 + 1987 GETFIELD0 + 1988 PUSHACC2 + 1989 GETFIELD0 1990 MAKEBLOCK2 0 1992 MAKEBLOCK2 0 1994 RETURN 2 - 1996 ACC1 + 1996 ACC1 1997 BRANCHIFNOT 2001 1999 BRANCH 2003 2001 RETURN 2 2003 GETGLOBAL "List.combine" 2005 PUSHGETGLOBALFIELD Pervasives, 2 2008 APPTERM1 3 - 2010 RESTART + 2010 RESTART 2011 GRAB 1 - 2013 ACC1 + 2013 ACC1 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 + 2016 ACC1 + 2017 GETFIELD0 + 2018 PUSHACC2 + 2019 GETFIELD1 + 2020 PUSHACC1 + 2021 PUSHENVACC2 + 2022 APPLY1 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 + 2025 ACC0 + 2026 PUSHACC3 + 2027 PUSHACC3 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 + 2030 PUSHOFFSETCLOSURE0 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 + 2033 ACC0 + 2034 PUSHACC3 + 2035 PUSHOFFSETCLOSURE0 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 + 2038 ACC0 + 2039 PUSHENVACC1 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 + 2042 ACC0 + 2043 PUSHENVACC1 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 + 2048 CONST0 + 2049 PUSHACC1 2050 APPTERM1 3 - 2052 RESTART + 2052 RESTART 2053 GRAB 2 - 2055 ACC1 + 2055 ACC1 2056 BRANCHIFNOT 2077 - 2058 ACC2 + 2058 ACC2 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 + 2061 ACC2 + 2062 GETFIELD1 + 2063 PUSHACC2 + 2064 GETFIELD1 + 2065 PUSHACC2 + 2066 PUSHACC5 + 2067 GETFIELD0 + 2068 PUSHACC5 + 2069 GETFIELD0 + 2070 PUSHENVACC1 + 2071 APPLY2 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 + 2074 PUSHOFFSETCLOSURE0 2075 APPTERM3 6 - 2077 ACC2 + 2077 ACC2 2078 BRANCHIFNOT 2082 2080 BRANCH 2084 2082 RETURN 3 2084 GETGLOBAL "List.rev_map2" 2086 PUSHGETGLOBALFIELD Pervasives, 2 2089 APPTERM1 4 - 2091 RESTART + 2091 RESTART 2092 GRAB 2 - 2094 ACC0 + 2094 ACC0 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 + 2099 ACC3 + 2100 PUSHACC3 + 2101 PUSHCONST0 + 2102 PUSHACC3 2103 APPTERM3 7 - 2105 RESTART + 2105 RESTART 2106 GRAB 1 - 2108 ACC1 + 2108 ACC1 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 + 2111 ACC1 + 2112 GETFIELD1 + 2113 PUSHACC1 + 2114 PUSHACC3 + 2115 GETFIELD0 + 2116 PUSHENVACC1 + 2117 APPLY1 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 + 2120 PUSHOFFSETCLOSURE0 2121 APPTERM2 4 - 2123 ACC0 + 2123 ACC0 2124 RETURN 2 - 2126 RESTART + 2126 RESTART 2127 GRAB 1 - 2129 ACC0 + 2129 ACC0 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 + 2134 ACC2 + 2135 PUSHCONST0 + 2136 PUSHACC2 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 + 2139 CONST0 + 2140 PUSHACC1 + 2141 PUSHENVACC1 2142 APPTERM2 3 - 2144 ACC0 + 2144 ACC0 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 + 2147 ACC0 + 2148 GETFIELD1 2149 RETURN 1 2151 GETGLOBAL "tl" 2153 PUSHGETGLOBALFIELD Pervasives, 3 2156 APPTERM1 2 - 2158 ACC0 + 2158 ACC0 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 + 2161 ACC0 + 2162 GETFIELD0 2163 RETURN 1 2165 GETGLOBAL "hd" 2167 PUSHGETGLOBALFIELD Pervasives, 3 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 + 2172 ACC0 + 2173 PUSHCONST0 + 2174 PUSHENVACC1 2175 APPTERM2 3 2177 CLOSUREREC 0, 1200 - 2181 ACC0 + 2181 ACC0 2182 CLOSURE 1, 2172 - 2185 PUSH + 2185 PUSH 2186 CLOSURE 0, 2158 - 2189 PUSH + 2189 PUSH 2190 CLOSURE 0, 2144 - 2193 PUSH + 2193 PUSH 2194 CLOSUREREC 0, 1217 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH + 2201 PUSH 2202 CLOSUREREC 0, 1259 - 2206 ACC0 + 2206 ACC0 2207 CLOSURE 1, 2139 - 2210 PUSH + 2210 PUSH 2211 CLOSUREREC 0, 1277 2215 CLOSUREREC 0, 1294 2219 CLOSURE 0, 2127 - 2222 PUSH + 2222 PUSH 2223 CLOSUREREC 0, 1316 2227 CLOSUREREC 0, 1334 2231 CLOSUREREC 0, 1354 2235 CLOSUREREC 0, 1374 2239 CLOSURE 0, 2092 - 2242 PUSH + 2242 PUSH 2243 CLOSUREREC 0, 1415 2247 CLOSUREREC 0, 1452 2251 CLOSUREREC 0, 1490 @@ -1502,9 +1502,9 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2314 CLOSUREREC 1, 1928 2318 CLOSUREREC 0, 1942 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 + 2326 ACC0 + 2327 PUSHACC2 + 2328 PUSHACC7 2329 PUSHACC 9 2331 PUSHACC 11 2333 PUSHACC 13 @@ -1543,47 +1543,47 @@ if List.fold_left (+) 0 l <> 301 * 150 then raise Not_found 2400 POP 36 2402 SETGLOBAL List 2404 BRANCH 2432 - 2406 CONST0 - 2407 PUSHACC1 - 2408 LEINT + 2406 CONST0 + 2407 PUSHACC1 + 2408 LEINT 2409 BRANCHIFNOT 2414 - 2411 CONST0 + 2411 CONST0 2412 RETURN 1 - 2414 ACC0 + 2414 ACC0 2415 OFFSETINT -1 - 2417 PUSHOFFSETCLOSURE0 - 2418 APPLY1 - 2419 PUSHACC1 + 2417 PUSHOFFSETCLOSURE0 + 2418 APPLY1 + 2419 PUSHACC1 2420 MAKEBLOCK2 0 2422 RETURN 1 - 2424 RESTART + 2424 RESTART 2425 GRAB 1 - 2427 ACC1 - 2428 PUSHACC1 - 2429 ADDINT + 2427 ACC1 + 2428 PUSHACC1 + 2429 ADDINT 2430 RETURN 2 2432 CLOSUREREC 0, 2406 - 2436 CONST0 + 2436 CONST0 2437 C_CALL1 gc_compaction 2439 CONSTINT 300 - 2441 PUSHACC1 - 2442 APPLY1 + 2441 PUSHACC1 + 2442 APPLY1 2443 PUSHCONSTINT 150 2445 PUSHCONSTINT 301 - 2447 MULINT - 2448 PUSHACC1 - 2449 PUSHCONST0 - 2450 PUSH + 2447 MULINT + 2448 PUSHACC1 + 2449 PUSHCONST0 + 2450 PUSH 2451 CLOSURE 0, 2425 2454 PUSHGETGLOBALFIELD List, 12 - 2457 APPLY3 - 2458 NEQ + 2457 APPLY3 + 2458 NEQ 2459 BRANCHIFNOT 2466 2461 GETGLOBAL Not_found 2463 MAKEBLOCK1 0 - 2465 RAISE + 2465 RAISE 2466 POP 2 - 2468 ATOM0 + 2468 ATOM0 2469 SETGLOBAL T330-compact-4 - 2471 STOP + 2471 STOP **) diff --git a/testsuite/tests/tool-ocaml/t340-weak.ml b/testsuite/tests/tool-ocaml/t340-weak.ml index e36dbab5..7ced585d 100644 --- a/testsuite/tests/tool-ocaml/t340-weak.ml +++ b/testsuite/tests/tool-ocaml/t340-weak.ml @@ -22,2530 +22,3 @@ for i = 0 to 19 do | _ -> raise Not_found done ;; - -(** - 0 CONSTINT 42 - 2 PUSHACC0 - 3 MAKEBLOCK1 0 - 5 POP 1 - 7 SETGLOBAL Lib - 9 BRANCH 746 - 11 RESTART - 12 GRAB 1 - 14 ACC0 - 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 - 24 MAKEBLOCK2 0 - 26 RETURN 2 - 28 ACC1 - 29 RETURN 2 - 31 RESTART - 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT - 37 BRANCHIFNOT 42 - 39 CONST0 - 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 - 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ - 51 BRANCHIFNOT 58 - 53 GETGLOBAL End_of_file - 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 - 67 APPTERM 4, 9 - 70 ACC0 - 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ - 76 BRANCHIFNOT 83 - 78 GETGLOBAL End_of_file - 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT - 86 BRANCHIFNOT 107 - 88 ACC0 - 89 OFFSETINT -1 - 91 C_CALL1 create_string - 93 PUSHACC1 - 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 - 99 C_CALL4 caml_input - 101 ACC2 - 102 C_CALL1 caml_input_char - 104 ACC0 - 105 RETURN 3 - 107 ACC0 - 108 NEGINT - 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 - 116 C_CALL4 caml_input - 118 CONST0 - 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP - 128 RETURN 3 - 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ - 135 BRANCHIFNOT 140 - 137 ACC1 - 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 - 143 C_CALL1 caml_flush - 145 RETURN 1 - 147 RESTART - 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 - 152 C_CALL2 caml_output_char - 154 RETURN 2 - 156 RESTART - 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 - 161 C_CALL2 caml_output_char - 163 RETURN 2 - 165 RESTART - 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 - 170 C_CALL2 caml_output_int - 172 RETURN 2 - 174 RESTART - 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 - 179 C_CALL2 caml_seek_out - 181 RETURN 2 - 183 ACC0 - 184 C_CALL1 caml_pos_out - 186 RETURN 1 - 188 ACC0 - 189 C_CALL1 caml_channel_size - 191 RETURN 1 - 193 RESTART - 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 - 198 C_CALL2 caml_set_binary_mode - 200 RETURN 2 - 202 ACC0 - 203 C_CALL1 caml_input_char - 205 RETURN 1 - 207 ACC0 - 208 C_CALL1 caml_input_char - 210 RETURN 1 - 212 ACC0 - 213 C_CALL1 caml_input_int - 215 RETURN 1 - 217 ACC0 - 218 C_CALL1 input_value - 220 RETURN 1 - 222 RESTART - 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 - 227 C_CALL2 caml_seek_in - 229 RETURN 2 - 231 ACC0 - 232 C_CALL1 caml_pos_in - 234 RETURN 1 - 236 ACC0 - 237 C_CALL1 caml_channel_size - 239 RETURN 1 - 241 ACC0 - 242 C_CALL1 caml_close_channel - 244 RETURN 1 - 246 RESTART - 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 - 251 C_CALL2 caml_set_binary_mode - 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 - 259 C_CALL1 sys_exit - 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 - 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 - 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 - 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 - 284 RETURN 2 - 286 ENVACC1 - 287 C_CALL1 caml_flush - 289 ENVACC2 - 290 C_CALL1 caml_flush - 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 - 297 C_CALL1 float_of_string - 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 - 304 C_CALL1 int_of_string - 306 RETURN 1 - 308 ENVACC2 - 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 - 313 APPTERM1 2 - 315 CONSTINT 13 - 317 PUSHENVACC1 - 318 C_CALL2 caml_output_char - 320 ENVACC1 - 321 C_CALL1 caml_flush - 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 - 329 CONSTINT 13 - 331 PUSHENVACC1 - 332 C_CALL2 caml_output_char - 334 ENVACC1 - 335 C_CALL1 caml_flush - 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 - 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 - 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 - 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 - 360 C_CALL2 caml_output_char - 362 RETURN 1 - 364 CONSTINT 13 - 366 PUSHENVACC1 - 367 C_CALL2 caml_output_char - 369 ENVACC1 - 370 C_CALL1 caml_flush - 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 - 378 CONSTINT 13 - 380 PUSHENVACC1 - 381 C_CALL2 caml_output_char - 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 - 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 - 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 - 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 - 406 C_CALL2 caml_output_char - 408 RETURN 1 - 410 RESTART - 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT - 416 BRANCHIF 427 - 418 ACC1 - 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT - 425 BRANCHIFNOT 432 - 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 - 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 - 437 APPTERM 4, 8 - 440 RESTART - 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT - 446 BRANCHIF 457 - 448 ACC1 - 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT - 455 BRANCHIFNOT 462 - 457 GETGLOBAL "input" - 459 PUSHENVACC1 - 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 - 466 C_CALL4 caml_input - 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 - 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 - 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 - 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 - 482 APPTERM3 4 - 484 RESTART - 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 - 490 C_CALL3 sys_open - 492 C_CALL1 caml_open_descriptor - 494 RETURN 3 - 496 ACC0 - 497 C_CALL1 caml_flush - 499 ACC0 - 500 C_CALL1 caml_close_channel - 502 RETURN 1 - 504 RESTART - 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 - 510 C_CALL3 output_value - 512 RETURN 2 - 514 RESTART - 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT - 520 BRANCHIF 531 - 522 ACC1 - 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT - 529 BRANCHIFNOT 536 - 531 GETGLOBAL "output" - 533 PUSHENVACC1 - 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 - 540 C_CALL4 caml_output - 542 RETURN 4 - 544 RESTART - 545 GRAB 1 - 547 ACC1 - 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 - 553 C_CALL4 caml_output - 555 RETURN 2 - 557 ACC0 - 558 PUSHCONSTINT 438 - 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 - 563 APPTERM3 4 - 565 ACC0 - 566 PUSHCONSTINT 438 - 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 - 571 APPTERM3 4 - 573 RESTART - 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 - 579 C_CALL3 sys_open - 581 C_CALL1 caml_open_descriptor - 583 RETURN 3 - 585 ACC0 - 586 PUSHGETGLOBAL "%.12g" - 588 C_CALL2 format_float - 590 RETURN 1 - 592 ACC0 - 593 PUSHGETGLOBAL "%d" - 595 C_CALL2 format_int - 597 RETURN 1 - 599 GETGLOBAL "false" - 601 PUSHACC1 - 602 C_CALL2 string_equal - 604 BRANCHIFNOT 609 - 606 CONST0 - 607 RETURN 1 - 609 GETGLOBAL "true" - 611 PUSHACC1 - 612 C_CALL2 string_equal - 614 BRANCHIFNOT 619 - 616 CONST1 - 617 RETURN 1 - 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 - 622 APPTERM1 2 - 624 ACC0 - 625 BRANCHIFNOT 631 - 627 GETGLOBAL "true" - 629 RETURN 1 - 631 GETGLOBAL "false" - 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT - 638 BRANCHIF 646 - 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT - 644 BRANCHIFNOT 651 - 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 - 649 APPTERM1 2 - 651 ACC0 - 652 RETURN 1 - 654 RESTART - 655 GRAB 1 - 657 ACC0 - 658 C_CALL1 ml_string_length - 660 PUSHACC2 - 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT - 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 - 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 - 679 PUSHACC 8 - 681 C_CALL5 blit_string - 683 ACC0 - 684 RETURN 5 - 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT - 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT - 695 BRANCHIFNOT 700 - 697 ACC0 - 698 RETURN 1 - 700 ACC0 - 701 NEGINT - 702 RETURN 1 - 704 RESTART - 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 - 709 C_CALL2 greaterequal - 711 BRANCHIFNOT 716 - 713 ACC0 - 714 RETURN 2 - 716 ACC1 - 717 RETURN 2 - 719 RESTART - 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 - 724 C_CALL2 lessequal - 726 BRANCHIFNOT 731 - 728 ACC0 - 729 RETURN 2 - 731 ACC1 - 732 RETURN 2 - 734 ACC0 - 735 PUSHGETGLOBAL Invalid_argument - 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 - 741 PUSHGETGLOBAL Failure - 743 MAKEBLOCK2 0 - 745 RAISE - 746 CLOSURE 0, 740 - 749 PUSH - 750 CLOSURE 0, 734 - 753 PUSHGETGLOBAL "Pervasives.Exit" - 755 MAKEBLOCK1 0 - 757 PUSHGETGLOBAL "Pervasives.Assert_failure" - 759 MAKEBLOCK1 0 - 761 PUSH - 762 CLOSURE 0, 720 - 765 PUSH - 766 CLOSURE 0, 705 - 769 PUSH - 770 CLOSURE 0, 692 - 773 PUSH - 774 CLOSURE 0, 686 - 777 PUSHCONST0 - 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ - 783 BRANCHIFNOT 789 - 785 CONSTINT 30 - 787 BRANCH 791 - 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 - 794 OFFSETINT -1 - 796 PUSH - 797 CLOSURE 0, 655 - 800 PUSHACC 9 - 802 CLOSURE 1, 635 - 805 PUSH - 806 CLOSURE 0, 624 - 809 PUSHACC 11 - 811 CLOSURE 1, 599 - 814 PUSH - 815 CLOSURE 0, 592 - 818 PUSH - 819 CLOSURE 0, 585 - 822 PUSH - 823 CLOSUREREC 0, 12 - 827 CONST0 - 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 - 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 - 834 C_CALL1 caml_open_descriptor - 836 PUSH - 837 CLOSURE 0, 574 - 840 PUSHACC0 - 841 CLOSURE 1, 565 - 844 PUSHACC1 - 845 CLOSURE 1, 557 - 848 PUSH - 849 CLOSURE 0, 545 - 852 PUSHACC 22 - 854 CLOSURE 1, 515 - 857 PUSH - 858 CLOSURE 0, 505 - 861 PUSH - 862 CLOSURE 0, 496 - 865 PUSH - 866 CLOSURE 0, 485 - 869 PUSHACC0 - 870 CLOSURE 1, 477 - 873 PUSHACC1 - 874 CLOSURE 1, 470 - 877 PUSHACC 28 - 879 CLOSURE 1, 441 - 882 PUSH - 883 CLOSUREREC 0, 32 - 887 ACC0 - 888 PUSHACC 31 - 890 CLOSURE 2, 411 - 893 PUSHACC 22 - 895 CLOSUREREC 1, 70 - 899 ACC 15 - 901 CLOSURE 1, 404 - 904 PUSHACC 11 - 906 PUSHACC 17 - 908 CLOSURE 2, 399 - 911 PUSHACC 12 - 913 PUSHACC 18 - 915 PUSHACC 23 - 917 CLOSURE 3, 392 - 920 PUSHACC 13 - 922 PUSHACC 19 - 924 PUSHACC 23 - 926 CLOSURE 3, 385 - 929 PUSHACC 14 - 931 PUSHACC 20 - 933 CLOSURE 2, 374 - 936 PUSHACC 20 - 938 CLOSURE 1, 364 - 941 PUSHACC 20 - 943 CLOSURE 1, 358 - 946 PUSHACC 17 - 948 PUSHACC 22 - 950 CLOSURE 2, 353 - 953 PUSHACC 18 - 955 PUSHACC 23 - 957 PUSHACC 29 - 959 CLOSURE 3, 346 - 962 PUSHACC 19 - 964 PUSHACC 24 - 966 PUSHACC 29 - 968 CLOSURE 3, 339 - 971 PUSHACC 20 - 973 PUSHACC 25 - 975 CLOSURE 2, 325 - 978 PUSHACC 25 - 980 CLOSURE 1, 315 - 983 PUSHACC 12 - 985 PUSHACC 28 - 987 PUSHACC 30 - 989 CLOSURE 3, 308 - 992 PUSHACC0 - 993 CLOSURE 1, 301 - 996 PUSHACC1 - 997 CLOSURE 1, 294 - 1000 PUSHACC 29 - 1002 PUSHACC 31 - 1004 CLOSURE 2, 286 - 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 - 1010 CLOSURE 1, 275 - 1013 PUSHACC1 - 1014 CLOSURE 1, 263 - 1017 PUSHACC0 - 1018 CLOSURE 1, 255 - 1021 PUSHACC1 - 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH - 1027 CLOSURE 0, 247 - 1030 PUSH - 1031 CLOSURE 0, 241 - 1034 PUSH - 1035 CLOSURE 0, 236 - 1038 PUSH - 1039 CLOSURE 0, 231 - 1042 PUSH - 1043 CLOSURE 0, 223 - 1046 PUSH - 1047 CLOSURE 0, 217 - 1050 PUSH - 1051 CLOSURE 0, 212 - 1054 PUSH - 1055 CLOSURE 0, 207 - 1058 PUSHACC 32 - 1060 PUSHACC 35 - 1062 PUSHACC 33 - 1064 PUSH - 1065 CLOSURE 0, 202 - 1068 PUSHACC 41 - 1070 PUSHACC 40 - 1072 PUSHACC 42 - 1074 PUSH - 1075 CLOSURE 0, 194 - 1078 PUSHACC 46 - 1080 PUSH - 1081 CLOSURE 0, 188 - 1084 PUSH - 1085 CLOSURE 0, 183 - 1088 PUSH - 1089 CLOSURE 0, 175 - 1092 PUSHACC 51 - 1094 PUSH - 1095 CLOSURE 0, 166 - 1098 PUSH - 1099 CLOSURE 0, 157 - 1102 PUSHACC 55 - 1104 PUSHACC 57 - 1106 PUSH - 1107 CLOSURE 0, 148 - 1110 PUSH - 1111 CLOSURE 0, 142 - 1114 PUSHACC 63 - 1116 PUSHACC 62 - 1118 PUSHACC 64 - 1120 PUSHACC 38 - 1122 PUSHACC 40 - 1124 PUSHACC 42 - 1126 PUSHACC 44 - 1128 PUSHACC 46 - 1130 PUSHACC 48 - 1132 PUSHACC 50 - 1134 PUSHACC 52 - 1136 PUSHACC 54 - 1138 PUSHACC 56 - 1140 PUSHACC 58 - 1142 PUSHACC 60 - 1144 PUSHACC 62 - 1146 PUSHACC 64 - 1148 PUSHACC 66 - 1150 PUSHACC 82 - 1152 PUSHACC 84 - 1154 PUSHACC 86 - 1156 PUSHACC 88 - 1158 PUSHACC 90 - 1160 PUSHACC 92 - 1162 PUSHACC 94 - 1164 PUSHACC 96 - 1166 PUSHACC 98 - 1168 PUSHACC 100 - 1170 PUSHACC 104 - 1172 PUSHACC 104 - 1174 PUSHACC 104 - 1176 PUSHACC 108 - 1178 PUSHACC 110 - 1180 PUSHACC 112 - 1182 PUSHACC 117 - 1184 PUSHACC 117 - 1186 PUSHACC 117 - 1188 PUSHACC 117 - 1190 MAKEBLOCK 69, 0 - 1193 POP 53 - 1195 SETGLOBAL Pervasives - 1197 BRANCH 2177 - 1199 RESTART - 1200 GRAB 1 - 1202 ACC1 - 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 - 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 - 1211 APPTERM2 4 - 1213 ACC0 - 1214 RETURN 2 - 1216 RESTART - 1217 GRAB 1 - 1219 ACC0 - 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ - 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 - 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT - 1234 BRANCHIFNOT 1244 - 1236 ACC1 - 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 - 1242 APPTERM2 4 - 1244 GETGLOBAL "List.nth" - 1246 PUSHGETGLOBALFIELD Pervasives, 2 - 1249 APPTERM1 3 - 1251 GETGLOBAL "nth" - 1253 PUSHGETGLOBALFIELD Pervasives, 3 - 1256 APPTERM1 3 - 1258 RESTART - 1259 GRAB 1 - 1261 ACC0 - 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 - 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 - 1272 APPTERM2 4 - 1274 ACC1 - 1275 RETURN 2 - 1277 ACC0 - 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 - 1286 PUSHGETGLOBALFIELD Pervasives, 16 - 1289 APPTERM2 3 - 1291 RETURN 1 - 1293 RESTART - 1294 GRAB 1 - 1296 ACC1 - 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 - 1309 MAKEBLOCK2 0 - 1311 POP 1 - 1313 RETURN 2 - 1315 RESTART - 1316 GRAB 1 - 1318 ACC1 - 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 - 1329 APPTERM2 4 - 1331 RETURN 2 - 1333 RESTART - 1334 GRAB 2 - 1336 ACC2 - 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 - 1348 APPTERM3 6 - 1350 ACC1 - 1351 RETURN 3 - 1353 RESTART - 1354 GRAB 2 - 1356 ACC1 - 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 - 1368 APPTERM2 5 - 1370 ACC2 - 1371 RETURN 3 - 1373 RESTART - 1374 GRAB 2 - 1376 ACC1 - 1377 BRANCHIFNOT 1400 - 1379 ACC2 - 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 - 1396 MAKEBLOCK2 0 - 1398 RETURN 4 - 1400 ACC2 - 1401 BRANCHIFNOT 1405 - 1403 BRANCH 1407 - 1405 RETURN 3 - 1407 GETGLOBAL "List.map2" - 1409 PUSHGETGLOBALFIELD Pervasives, 2 - 1412 APPTERM1 4 - 1414 RESTART - 1415 GRAB 2 - 1417 ACC1 - 1418 BRANCHIFNOT 1437 - 1420 ACC2 - 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 - 1435 APPTERM3 6 - 1437 ACC2 - 1438 BRANCHIFNOT 1442 - 1440 BRANCH 1444 - 1442 RETURN 3 - 1444 GETGLOBAL "List.iter2" - 1446 PUSHGETGLOBALFIELD Pervasives, 2 - 1449 APPTERM1 4 - 1451 RESTART - 1452 GRAB 3 - 1454 ACC2 - 1455 BRANCHIFNOT 1476 - 1457 ACC3 - 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 - 1473 APPTERM 4, 8 - 1476 ACC3 - 1477 BRANCHIF 1482 - 1479 ACC1 - 1480 RETURN 4 - 1482 GETGLOBAL "List.fold_left2" - 1484 PUSHGETGLOBALFIELD Pervasives, 2 - 1487 APPTERM1 5 - 1489 RESTART - 1490 GRAB 3 - 1492 ACC1 - 1493 BRANCHIFNOT 1516 - 1495 ACC2 - 1496 BRANCHIFNOT 1522 - 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 - 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 - 1514 APPTERM3 7 - 1516 ACC2 - 1517 BRANCHIF 1522 - 1519 ACC3 - 1520 RETURN 4 - 1522 GETGLOBAL "List.fold_right2" - 1524 PUSHGETGLOBALFIELD Pervasives, 2 - 1527 APPTERM1 5 - 1529 RESTART - 1530 GRAB 1 - 1532 ACC1 - 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 - 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 - 1545 APPTERM2 4 - 1547 RETURN 2 - 1549 CONST1 - 1550 RETURN 2 - 1552 RESTART - 1553 GRAB 1 - 1555 ACC1 - 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 - 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 - 1568 APPTERM2 4 - 1570 RETURN 2 - 1572 RESTART - 1573 GRAB 2 - 1575 ACC1 - 1576 BRANCHIFNOT 1599 - 1578 ACC2 - 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 - 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 - 1595 APPTERM3 6 - 1597 RETURN 3 - 1599 ACC2 - 1600 BRANCHIF 1605 - 1602 CONST1 - 1603 RETURN 3 - 1605 GETGLOBAL "List.for_all2" - 1607 PUSHGETGLOBALFIELD Pervasives, 2 - 1610 APPTERM1 4 - 1612 RESTART - 1613 GRAB 2 - 1615 ACC1 - 1616 BRANCHIFNOT 1639 - 1618 ACC2 - 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 - 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 - 1635 APPTERM3 6 - 1637 RETURN 3 - 1639 ACC2 - 1640 BRANCHIFNOT 1644 - 1642 BRANCH 1646 - 1644 RETURN 3 - 1646 GETGLOBAL "List.exists2" - 1648 PUSHGETGLOBALFIELD Pervasives, 2 - 1651 APPTERM1 4 - 1653 RESTART - 1654 GRAB 1 - 1656 ACC1 - 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 - 1662 C_CALL2 equal - 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 - 1670 APPTERM2 4 - 1672 RETURN 2 - 1674 RESTART - 1675 GRAB 1 - 1677 ACC1 - 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ - 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 - 1690 APPTERM2 4 - 1692 RETURN 2 - 1694 RESTART - 1695 GRAB 1 - 1697 ACC1 - 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 - 1705 C_CALL2 equal - 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 - 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 - 1717 APPTERM2 5 - 1719 GETGLOBAL Not_found - 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART - 1725 GRAB 1 - 1727 ACC1 - 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ - 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 - 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 - 1746 APPTERM2 5 - 1748 GETGLOBAL Not_found - 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART - 1754 GRAB 1 - 1756 ACC1 - 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 - 1763 C_CALL2 equal - 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 - 1771 APPTERM2 4 - 1773 RETURN 2 - 1775 RESTART - 1776 GRAB 1 - 1778 ACC1 - 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ - 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 - 1792 APPTERM2 4 - 1794 RETURN 2 - 1796 RESTART - 1797 GRAB 1 - 1799 ACC1 - 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 - 1809 C_CALL2 equal - 1811 BRANCHIFNOT 1816 - 1813 ACC0 - 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 - 1821 MAKEBLOCK2 0 - 1823 POP 2 - 1825 RETURN 2 - 1827 RESTART - 1828 GRAB 1 - 1830 ACC1 - 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ - 1841 BRANCHIFNOT 1846 - 1843 ACC0 - 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 - 1851 MAKEBLOCK2 0 - 1853 POP 2 - 1855 RETURN 2 - 1857 RESTART - 1858 GRAB 1 - 1860 ACC1 - 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 - 1868 BRANCHIFNOT 1873 - 1870 ACC0 - 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 - 1877 APPTERM2 5 - 1879 GETGLOBAL Not_found - 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART - 1885 GRAB 2 - 1887 ACC2 - 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 - 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 - 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 - 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 - 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 - 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 - 1923 MAKEBLOCK2 0 - 1925 RETURN 3 - 1927 RESTART - 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 - 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 - 1940 APPTERM3 6 - 1942 ACC0 - 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 - 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 - 1961 MAKEBLOCK2 0 - 1963 MAKEBLOCK2 0 - 1965 RETURN 3 - 1967 GETGLOBAL <0>(0, 0) - 1969 RETURN 1 - 1971 RESTART - 1972 GRAB 1 - 1974 ACC0 - 1975 BRANCHIFNOT 1996 - 1977 ACC1 - 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 - 1990 MAKEBLOCK2 0 - 1992 MAKEBLOCK2 0 - 1994 RETURN 2 - 1996 ACC1 - 1997 BRANCHIFNOT 2001 - 1999 BRANCH 2003 - 2001 RETURN 2 - 2003 GETGLOBAL "List.combine" - 2005 PUSHGETGLOBALFIELD Pervasives, 2 - 2008 APPTERM1 3 - 2010 RESTART - 2011 GRAB 1 - 2013 ACC1 - 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 - 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 - 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 - 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 - 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 - 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 - 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 - 2050 APPTERM1 3 - 2052 RESTART - 2053 GRAB 2 - 2055 ACC1 - 2056 BRANCHIFNOT 2077 - 2058 ACC2 - 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 - 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 - 2075 APPTERM3 6 - 2077 ACC2 - 2078 BRANCHIFNOT 2082 - 2080 BRANCH 2084 - 2082 RETURN 3 - 2084 GETGLOBAL "List.rev_map2" - 2086 PUSHGETGLOBALFIELD Pervasives, 2 - 2089 APPTERM1 4 - 2091 RESTART - 2092 GRAB 2 - 2094 ACC0 - 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 - 2103 APPTERM3 7 - 2105 RESTART - 2106 GRAB 1 - 2108 ACC1 - 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 - 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 - 2121 APPTERM2 4 - 2123 ACC0 - 2124 RETURN 2 - 2126 RESTART - 2127 GRAB 1 - 2129 ACC0 - 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 - 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 - 2142 APPTERM2 3 - 2144 ACC0 - 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 - 2149 RETURN 1 - 2151 GETGLOBAL "tl" - 2153 PUSHGETGLOBALFIELD Pervasives, 3 - 2156 APPTERM1 2 - 2158 ACC0 - 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 - 2163 RETURN 1 - 2165 GETGLOBAL "hd" - 2167 PUSHGETGLOBALFIELD Pervasives, 3 - 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 - 2175 APPTERM2 3 - 2177 CLOSUREREC 0, 1200 - 2181 ACC0 - 2182 CLOSURE 1, 2172 - 2185 PUSH - 2186 CLOSURE 0, 2158 - 2189 PUSH - 2190 CLOSURE 0, 2144 - 2193 PUSH - 2194 CLOSUREREC 0, 1217 - 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH - 2202 CLOSUREREC 0, 1259 - 2206 ACC0 - 2207 CLOSURE 1, 2139 - 2210 PUSH - 2211 CLOSUREREC 0, 1277 - 2215 CLOSUREREC 0, 1294 - 2219 CLOSURE 0, 2127 - 2222 PUSH - 2223 CLOSUREREC 0, 1316 - 2227 CLOSUREREC 0, 1334 - 2231 CLOSUREREC 0, 1354 - 2235 CLOSUREREC 0, 1374 - 2239 CLOSURE 0, 2092 - 2242 PUSH - 2243 CLOSUREREC 0, 1415 - 2247 CLOSUREREC 0, 1452 - 2251 CLOSUREREC 0, 1490 - 2255 CLOSUREREC 0, 1530 - 2259 CLOSUREREC 0, 1553 - 2263 CLOSUREREC 0, 1573 - 2267 CLOSUREREC 0, 1613 - 2271 CLOSUREREC 0, 1654 - 2275 CLOSUREREC 0, 1675 - 2279 CLOSUREREC 0, 1695 - 2283 CLOSUREREC 0, 1725 - 2287 CLOSUREREC 0, 1754 - 2291 CLOSUREREC 0, 1776 - 2295 CLOSUREREC 0, 1797 - 2299 CLOSUREREC 0, 1828 - 2303 CLOSUREREC 0, 1858 - 2307 ACC 24 - 2309 CLOSURE 1, 2042 - 2312 PUSHACC 25 - 2314 CLOSUREREC 1, 1928 - 2318 CLOSUREREC 0, 1942 - 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 - 2329 PUSHACC 9 - 2331 PUSHACC 11 - 2333 PUSHACC 13 - 2335 PUSHACC 15 - 2337 PUSHACC 17 - 2339 PUSHACC 10 - 2341 PUSHACC 12 - 2343 PUSHACC 13 - 2345 PUSHACC 15 - 2347 PUSHACC 23 - 2349 PUSHACC 25 - 2351 PUSHACC 27 - 2353 PUSHACC 29 - 2355 PUSHACC 31 - 2357 PUSHACC 33 - 2359 PUSHACC 35 - 2361 PUSHACC 37 - 2363 PUSHACC 40 - 2365 PUSHACC 42 - 2367 PUSHACC 41 - 2369 PUSHACC 45 - 2371 PUSHACC 47 - 2373 PUSHACC 50 - 2375 PUSHACC 52 - 2377 PUSHACC 51 - 2379 PUSHACC 55 - 2381 PUSHACC 56 - 2383 PUSHACC 59 - 2385 PUSHACC 61 - 2387 PUSHACC 60 - 2389 PUSHACC 64 - 2391 PUSHACC 66 - 2393 PUSHACC 68 - 2395 PUSHACC 70 - 2397 MAKEBLOCK 37, 0 - 2400 POP 36 - 2402 SETGLOBAL List - 2404 BRANCH 2622 - 2406 CONSTINT 97 - 2408 PUSHACC1 - 2409 GEINT - 2410 BRANCHIFNOT 2418 - 2412 CONSTINT 122 - 2414 PUSHACC1 - 2415 LEINT - 2416 BRANCHIF 2442 - 2418 CONSTINT 224 - 2420 PUSHACC1 - 2421 GEINT - 2422 BRANCHIFNOT 2430 - 2424 CONSTINT 246 - 2426 PUSHACC1 - 2427 LEINT - 2428 BRANCHIF 2442 - 2430 CONSTINT 248 - 2432 PUSHACC1 - 2433 GEINT - 2434 BRANCHIFNOT 2447 - 2436 CONSTINT 254 - 2438 PUSHACC1 - 2439 LEINT - 2440 BRANCHIFNOT 2447 - 2442 ACC0 - 2443 OFFSETINT -32 - 2445 RETURN 1 - 2447 ACC0 - 2448 RETURN 1 - 2450 CONSTINT 65 - 2452 PUSHACC1 - 2453 GEINT - 2454 BRANCHIFNOT 2462 - 2456 CONSTINT 90 - 2458 PUSHACC1 - 2459 LEINT - 2460 BRANCHIF 2486 - 2462 CONSTINT 192 - 2464 PUSHACC1 - 2465 GEINT - 2466 BRANCHIFNOT 2474 - 2468 CONSTINT 214 - 2470 PUSHACC1 - 2471 LEINT - 2472 BRANCHIF 2486 - 2474 CONSTINT 216 - 2476 PUSHACC1 - 2477 GEINT - 2478 BRANCHIFNOT 2491 - 2480 CONSTINT 222 - 2482 PUSHACC1 - 2483 LEINT - 2484 BRANCHIFNOT 2491 - 2486 ACC0 - 2487 OFFSETINT 32 - 2489 RETURN 1 - 2491 ACC0 - 2492 RETURN 1 - 2494 CONSTINT 39 - 2496 PUSHACC1 - 2497 LTINT - 2498 BRANCHIFNOT 2520 - 2500 CONSTINT 9 - 2502 PUSHACC1 - 2503 EQ - 2504 BRANCHIFNOT 2510 - 2506 GETGLOBAL "\\t" - 2508 RETURN 1 - 2510 CONSTINT 13 - 2512 PUSHACC1 - 2513 EQ - 2514 BRANCHIFNOT 2540 - 2516 GETGLOBAL "\\n" - 2518 RETURN 1 - 2520 CONSTINT 39 - 2522 PUSHACC1 - 2523 EQ - 2524 BRANCHIFNOT 2530 - 2526 GETGLOBAL "\\'" - 2528 RETURN 1 - 2530 CONSTINT 92 - 2532 PUSHACC1 - 2533 EQ - 2534 BRANCHIFNOT 2540 - 2536 GETGLOBAL "\\\\" - 2538 RETURN 1 - 2540 ACC0 - 2541 C_CALL1 is_printable - 2543 BRANCHIFNOT 2555 - 2545 CONST1 - 2546 C_CALL1 create_string - 2548 PUSHACC1 - 2549 PUSHCONST0 - 2550 PUSHACC2 - 2551 SETSTRINGCHAR - 2552 ACC0 - 2553 RETURN 2 - 2555 ACC0 - 2556 PUSHCONSTINT 4 - 2558 C_CALL1 create_string - 2560 PUSHCONSTINT 92 - 2562 PUSHCONST0 - 2563 PUSHACC2 - 2564 SETSTRINGCHAR - 2565 CONSTINT 100 - 2567 PUSHACC2 - 2568 DIVINT - 2569 PUSHCONSTINT 48 - 2571 ADDINT - 2572 PUSHCONST1 - 2573 PUSHACC2 - 2574 SETSTRINGCHAR - 2575 CONSTINT 10 - 2577 PUSHCONSTINT 10 - 2579 PUSHACC3 - 2580 DIVINT - 2581 MODINT - 2582 PUSHCONSTINT 48 - 2584 ADDINT - 2585 PUSHCONST2 - 2586 PUSHACC2 - 2587 SETSTRINGCHAR - 2588 CONSTINT 10 - 2590 PUSHACC2 - 2591 MODINT - 2592 PUSHCONSTINT 48 - 2594 ADDINT - 2595 PUSHCONST3 - 2596 PUSHACC2 - 2597 SETSTRINGCHAR - 2598 ACC0 - 2599 RETURN 3 - 2601 CONST0 - 2602 PUSHACC1 - 2603 LTINT - 2604 BRANCHIF 2612 - 2606 CONSTINT 255 - 2608 PUSHACC1 - 2609 GTINT - 2610 BRANCHIFNOT 2619 - 2612 GETGLOBAL "Char.chr" - 2614 PUSHGETGLOBALFIELD Pervasives, 2 - 2617 APPTERM1 2 - 2619 ACC0 - 2620 RETURN 1 - 2622 CLOSURE 0, 2601 - 2625 PUSH - 2626 CLOSURE 0, 2494 - 2629 PUSH - 2630 CLOSURE 0, 2450 - 2633 PUSH - 2634 CLOSURE 0, 2406 - 2637 PUSHACC0 - 2638 PUSHACC2 - 2639 PUSHACC4 - 2640 PUSHACC6 - 2641 MAKEBLOCK 4, 0 - 2644 POP 4 - 2646 SETGLOBAL Char - 2648 BRANCH 3540 - 2650 RESTART - 2651 GRAB 3 - 2653 ACC1 - 2654 PUSHACC3 - 2655 GEINT - 2656 BRANCHIFNOT 2663 - 2658 GETGLOBAL Not_found - 2660 MAKEBLOCK1 0 - 2662 RAISE - 2663 ACC3 - 2664 PUSHACC3 - 2665 PUSHACC2 - 2666 GETSTRINGCHAR - 2667 EQ - 2668 BRANCHIFNOT 2673 - 2670 ACC2 - 2671 RETURN 4 - 2673 ACC3 - 2674 PUSHACC3 - 2675 OFFSETINT 1 - 2677 PUSHACC3 - 2678 PUSHACC3 - 2679 PUSHOFFSETCLOSURE0 - 2680 APPTERM 4, 8 - 2683 RESTART - 2684 GRAB 2 - 2686 CONST0 - 2687 PUSHACC2 - 2688 LTINT - 2689 BRANCHIFNOT 2696 - 2691 GETGLOBAL Not_found - 2693 MAKEBLOCK1 0 - 2695 RAISE - 2696 ACC2 - 2697 PUSHACC2 - 2698 PUSHACC2 - 2699 GETSTRINGCHAR - 2700 EQ - 2701 BRANCHIFNOT 2706 - 2703 ACC1 - 2704 RETURN 3 - 2706 ACC2 - 2707 PUSHACC2 - 2708 OFFSETINT -1 - 2710 PUSHACC2 - 2711 PUSHOFFSETCLOSURE0 - 2712 APPTERM3 6 - 2714 RESTART - 2715 GRAB 1 - 2717 ACC1 - 2718 PUSHCONST0 - 2719 PUSHACC2 - 2720 PUSHENVACC1 - 2721 APPTERM3 5 - 2723 RESTART - 2724 GRAB 2 - 2726 CONST0 - 2727 PUSHACC2 - 2728 LTINT - 2729 BRANCHIF 2738 - 2731 ACC0 - 2732 C_CALL1 ml_string_length - 2734 PUSHACC2 - 2735 GEINT - 2736 BRANCHIFNOT 2745 - 2738 GETGLOBAL "String.rcontains_from" - 2740 PUSHGETGLOBALFIELD Pervasives, 2 - 2743 APPTERM1 4 - 2745 PUSHTRAP 2756 - 2747 ACC6 - 2748 PUSHACC6 - 2749 PUSHACC6 - 2750 PUSHENVACC1 - 2751 APPLY3 - 2752 CONST1 - 2753 POPTRAP - 2754 RETURN 3 - 2756 PUSHGETGLOBAL Not_found - 2758 PUSHACC1 - 2759 GETFIELD0 - 2760 EQ - 2761 BRANCHIFNOT 2766 - 2763 CONST0 - 2764 RETURN 4 - 2766 ACC0 - 2767 RAISE - 2768 RESTART - 2769 GRAB 2 - 2771 CONST0 - 2772 PUSHACC2 - 2773 LTINT - 2774 BRANCHIF 2783 - 2776 ACC0 - 2777 C_CALL1 ml_string_length - 2779 PUSHACC2 - 2780 GTINT - 2781 BRANCHIFNOT 2790 - 2783 GETGLOBAL "String.contains_from" - 2785 PUSHGETGLOBALFIELD Pervasives, 2 - 2788 APPTERM1 4 - 2790 PUSHTRAP 2811 - 2792 PUSH_RETADDR 2807 - 2794 ACC 9 - 2796 PUSHACC 9 - 2798 PUSHACC 9 - 2800 C_CALL1 ml_string_length - 2802 PUSHACC 10 - 2804 PUSHENVACC1 - 2805 APPLY 4 - 2807 CONST1 - 2808 POPTRAP - 2809 RETURN 3 - 2811 PUSHGETGLOBAL Not_found - 2813 PUSHACC1 - 2814 GETFIELD0 - 2815 EQ - 2816 BRANCHIFNOT 2821 - 2818 CONST0 - 2819 RETURN 4 - 2821 ACC0 - 2822 RAISE - 2823 RESTART - 2824 GRAB 2 - 2826 CONST0 - 2827 PUSHACC2 - 2828 LTINT - 2829 BRANCHIF 2838 - 2831 ACC0 - 2832 C_CALL1 ml_string_length - 2834 PUSHACC2 - 2835 GEINT - 2836 BRANCHIFNOT 2845 - 2838 GETGLOBAL "String.rindex_from" - 2840 PUSHGETGLOBALFIELD Pervasives, 2 - 2843 APPTERM1 4 - 2845 ACC2 - 2846 PUSHACC2 - 2847 PUSHACC2 - 2848 PUSHENVACC1 - 2849 APPTERM3 6 - 2851 RESTART - 2852 GRAB 1 - 2854 ACC1 - 2855 PUSHACC1 - 2856 C_CALL1 ml_string_length - 2858 OFFSETINT -1 - 2860 PUSHACC2 - 2861 PUSHENVACC1 - 2862 APPTERM3 5 - 2864 RESTART - 2865 GRAB 2 - 2867 CONST0 - 2868 PUSHACC2 - 2869 LTINT - 2870 BRANCHIF 2879 - 2872 ACC0 - 2873 C_CALL1 ml_string_length - 2875 PUSHACC2 - 2876 GTINT - 2877 BRANCHIFNOT 2886 - 2879 GETGLOBAL "String.index_from" - 2881 PUSHGETGLOBALFIELD Pervasives, 2 - 2884 APPTERM1 4 - 2886 ACC2 - 2887 PUSHACC2 - 2888 PUSHACC2 - 2889 C_CALL1 ml_string_length - 2891 PUSHACC3 - 2892 PUSHENVACC1 - 2893 APPTERM 4, 7 - 2896 RESTART - 2897 GRAB 1 - 2899 ACC1 - 2900 PUSHCONST0 - 2901 PUSHACC2 - 2902 C_CALL1 ml_string_length - 2904 PUSHACC3 - 2905 PUSHENVACC1 - 2906 APPTERM 4, 6 - 2909 ACC0 - 2910 PUSHGETGLOBALFIELD Char, 2 - 2913 PUSHENVACC1 - 2914 APPTERM2 3 - 2916 ACC0 - 2917 PUSHGETGLOBALFIELD Char, 3 - 2920 PUSHENVACC1 - 2921 APPTERM2 3 - 2923 RESTART - 2924 GRAB 1 - 2926 CONST0 - 2927 PUSHACC2 - 2928 C_CALL1 ml_string_length - 2930 EQ - 2931 BRANCHIFNOT 2936 - 2933 ACC1 - 2934 RETURN 2 - 2936 ACC1 - 2937 PUSHENVACC1 - 2938 APPLY1 - 2939 PUSHCONST0 - 2940 PUSHACC3 - 2941 GETSTRINGCHAR - 2942 PUSHACC2 - 2943 APPLY1 - 2944 PUSHCONST0 - 2945 PUSHACC2 - 2946 SETSTRINGCHAR - 2947 ACC0 - 2948 RETURN 3 - 2950 ACC0 - 2951 PUSHGETGLOBALFIELD Char, 2 - 2954 PUSHENVACC1 - 2955 APPTERM2 3 - 2957 ACC0 - 2958 PUSHGETGLOBALFIELD Char, 3 - 2961 PUSHENVACC1 - 2962 APPTERM2 3 - 2964 RESTART - 2965 GRAB 1 - 2967 ACC1 - 2968 C_CALL1 ml_string_length - 2970 PUSHCONST0 - 2971 PUSHACC1 - 2972 EQ - 2973 BRANCHIFNOT 2978 - 2975 ACC2 - 2976 RETURN 3 - 2978 ACC0 - 2979 C_CALL1 create_string - 2981 PUSHCONST0 - 2982 PUSHACC2 - 2983 OFFSETINT -1 - 2985 PUSH - 2986 BRANCH 3002 - 2988 CHECK_SIGNALS - 2989 ACC1 - 2990 PUSHACC6 - 2991 GETSTRINGCHAR - 2992 PUSHACC5 - 2993 APPLY1 - 2994 PUSHACC2 - 2995 PUSHACC4 - 2996 SETSTRINGCHAR - 2997 ACC1 - 2998 OFFSETINT 1 - 3000 ASSIGN 1 - 3002 ACC0 - 3003 PUSHACC2 - 3004 LEINT - 3005 BRANCHIF 2988 - 3007 CONST0 - 3008 POP 2 - 3010 ACC0 - 3011 RETURN 4 - 3013 CONST0 - 3014 PUSHCONST0 - 3015 PUSHACC2 - 3016 C_CALL1 ml_string_length - 3018 OFFSETINT -1 - 3020 PUSH - 3021 BRANCH 3059 - 3023 CHECK_SIGNALS - 3024 ACC1 - 3025 PUSHACC4 - 3026 GETSTRINGCHAR - 3027 PUSHACC0 - 3028 PUSHGETGLOBAL "\000\"\000\000\004\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - 3030 C_CALL2 bitvect_test - 3032 BRANCHIFNOT 3038 - 3034 CONST0 - 3035 CONST2 - 3036 BRANCH 3048 - 3038 ACC0 - 3039 C_CALL1 is_printable - 3041 BRANCHIFNOT 3046 - 3043 CONST1 - 3044 BRANCH 3048 - 3046 CONSTINT 4 - 3048 POP 1 - 3050 PUSHACC3 - 3051 ADDINT - 3052 ASSIGN 2 - 3054 ACC1 - 3055 OFFSETINT 1 - 3057 ASSIGN 1 - 3059 ACC0 - 3060 PUSHACC2 - 3061 LEINT - 3062 BRANCHIF 3023 - 3064 CONST0 - 3065 POP 2 - 3067 ACC1 - 3068 C_CALL1 ml_string_length - 3070 PUSHACC1 - 3071 EQ - 3072 BRANCHIFNOT 3077 - 3074 ACC1 - 3075 RETURN 2 - 3077 ACC0 - 3078 C_CALL1 create_string - 3080 PUSHCONST0 - 3081 ASSIGN 1 - 3083 CONST0 - 3084 PUSHACC3 - 3085 C_CALL1 ml_string_length - 3087 OFFSETINT -1 - 3089 PUSH - 3090 BRANCH 3245 - 3092 CHECK_SIGNALS - 3093 ACC1 - 3094 PUSHACC5 - 3095 GETSTRINGCHAR - 3096 PUSHACC0 - 3097 PUSHGETGLOBAL "\000\000\000\000\004\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - 3099 C_CALL2 bitvect_test - 3101 BRANCHIFNOT 3120 - 3103 CONST0 - 3104 CONSTINT 92 - 3106 PUSHACC5 - 3107 PUSHACC5 - 3108 SETSTRINGCHAR - 3109 ACC4 - 3110 OFFSETINT 1 - 3112 ASSIGN 4 - 3114 ACC0 - 3115 PUSHACC5 - 3116 PUSHACC5 - 3117 SETSTRINGCHAR - 3118 BRANCH 3233 - 3120 CONSTINT 9 - 3122 PUSHACC1 - 3123 EQ - 3124 BRANCHIFNOT 3143 - 3126 CONSTINT 92 - 3128 PUSHACC5 - 3129 PUSHACC5 - 3130 SETSTRINGCHAR - 3131 ACC4 - 3132 OFFSETINT 1 - 3134 ASSIGN 4 - 3136 CONSTINT 116 - 3138 PUSHACC5 - 3139 PUSHACC5 - 3140 SETSTRINGCHAR - 3141 BRANCH 3233 - 3143 CONSTINT 13 - 3145 PUSHACC1 - 3146 EQ - 3147 BRANCHIFNOT 3166 - 3149 CONSTINT 92 - 3151 PUSHACC5 - 3152 PUSHACC5 - 3153 SETSTRINGCHAR - 3154 ACC4 - 3155 OFFSETINT 1 - 3157 ASSIGN 4 - 3159 CONSTINT 110 - 3161 PUSHACC5 - 3162 PUSHACC5 - 3163 SETSTRINGCHAR - 3164 BRANCH 3233 - 3166 ACC0 - 3167 C_CALL1 is_printable - 3169 BRANCHIFNOT 3177 - 3171 ACC0 - 3172 PUSHACC5 - 3173 PUSHACC5 - 3174 SETSTRINGCHAR - 3175 BRANCH 3233 - 3177 ACC0 - 3178 PUSHCONSTINT 92 - 3180 PUSHACC6 - 3181 PUSHACC6 - 3182 SETSTRINGCHAR - 3183 ACC5 - 3184 OFFSETINT 1 - 3186 ASSIGN 5 - 3188 CONSTINT 100 - 3190 PUSHACC1 - 3191 DIVINT - 3192 PUSHCONSTINT 48 - 3194 ADDINT - 3195 PUSHACC6 - 3196 PUSHACC6 - 3197 SETSTRINGCHAR - 3198 ACC5 - 3199 OFFSETINT 1 - 3201 ASSIGN 5 - 3203 CONSTINT 10 - 3205 PUSHCONSTINT 10 - 3207 PUSHACC2 - 3208 DIVINT - 3209 MODINT - 3210 PUSHCONSTINT 48 - 3212 ADDINT - 3213 PUSHACC6 - 3214 PUSHACC6 - 3215 SETSTRINGCHAR - 3216 ACC5 - 3217 OFFSETINT 1 - 3219 ASSIGN 5 - 3221 CONSTINT 10 - 3223 PUSHACC1 - 3224 MODINT - 3225 PUSHCONSTINT 48 - 3227 ADDINT - 3228 PUSHACC6 - 3229 PUSHACC6 - 3230 SETSTRINGCHAR - 3231 POP 1 - 3233 POP 1 - 3235 ACC3 - 3236 OFFSETINT 1 - 3238 ASSIGN 3 - 3240 ACC1 - 3241 OFFSETINT 1 - 3243 ASSIGN 1 - 3245 ACC0 - 3246 PUSHACC2 - 3247 LEINT - 3248 BRANCHIF 3092 - 3250 CONST0 - 3251 POP 2 - 3253 ACC0 - 3254 RETURN 3 - 3256 ENVACC1 - 3257 C_CALL1 ml_string_length - 3259 PUSHENVACC3 - 3260 GETFIELD0 - 3261 PUSHENVACC2 - 3262 PUSHCONST0 - 3263 PUSHENVACC1 - 3264 C_CALL5 blit_string - 3266 ENVACC1 - 3267 C_CALL1 ml_string_length - 3269 PUSHENVACC3 - 3270 GETFIELD0 - 3271 ADDINT - 3272 PUSHENVACC3 - 3273 SETFIELD0 - 3274 ACC0 - 3275 C_CALL1 ml_string_length - 3277 PUSHENVACC3 - 3278 GETFIELD0 - 3279 PUSHENVACC2 - 3280 PUSHCONST0 - 3281 PUSHACC4 - 3282 C_CALL5 blit_string - 3284 ACC0 - 3285 C_CALL1 ml_string_length - 3287 PUSHENVACC3 - 3288 GETFIELD0 - 3289 ADDINT - 3290 PUSHENVACC3 - 3291 SETFIELD0 - 3292 RETURN 1 - 3294 ENVACC1 - 3295 OFFSETREF 1 - 3297 ACC0 - 3298 C_CALL1 ml_string_length - 3300 PUSHENVACC2 - 3301 GETFIELD0 - 3302 ADDINT - 3303 PUSHENVACC2 - 3304 SETFIELD0 - 3305 RETURN 1 - 3307 RESTART - 3308 GRAB 1 - 3310 ACC1 - 3311 BRANCHIFNOT 3374 - 3313 ACC1 - 3314 GETFIELD0 - 3315 PUSHCONST0 - 3316 MAKEBLOCK1 0 - 3318 PUSHCONST0 - 3319 MAKEBLOCK1 0 - 3321 PUSHACC4 - 3322 PUSHACC1 - 3323 PUSHACC3 - 3324 CLOSURE 2, 3294 - 3327 PUSHGETGLOBALFIELD List, 9 - 3330 APPLY2 - 3331 ACC1 - 3332 GETFIELD0 - 3333 OFFSETINT -1 - 3335 PUSHACC4 - 3336 C_CALL1 ml_string_length - 3338 MULINT - 3339 PUSHACC1 - 3340 GETFIELD0 - 3341 ADDINT - 3342 C_CALL1 create_string - 3344 PUSHACC3 - 3345 C_CALL1 ml_string_length - 3347 PUSHCONST0 - 3348 PUSHACC2 - 3349 PUSHCONST0 - 3350 PUSHACC7 - 3351 C_CALL5 blit_string - 3353 ACC3 - 3354 C_CALL1 ml_string_length - 3356 MAKEBLOCK1 0 - 3358 PUSHACC6 - 3359 GETFIELD1 - 3360 PUSHACC1 - 3361 PUSHACC3 - 3362 PUSHACC 8 - 3364 CLOSURE 3, 3256 - 3367 PUSHGETGLOBALFIELD List, 9 - 3370 APPLY2 - 3371 ACC1 - 3372 RETURN 7 - 3374 GETGLOBAL "" - 3376 RETURN 2 - 3378 RESTART - 3379 GRAB 4 - 3381 CONST0 - 3382 PUSHACC5 - 3383 LTINT - 3384 BRANCHIF 3414 - 3386 CONST0 - 3387 PUSHACC2 - 3388 LTINT - 3389 BRANCHIF 3414 - 3391 ACC0 - 3392 C_CALL1 ml_string_length - 3394 PUSHACC5 - 3395 PUSHACC3 - 3396 ADDINT - 3397 GTINT - 3398 BRANCHIF 3414 - 3400 CONST0 - 3401 PUSHACC4 - 3402 LTINT - 3403 BRANCHIF 3414 - 3405 ACC2 - 3406 C_CALL1 ml_string_length - 3408 PUSHACC5 - 3409 PUSHACC5 - 3410 ADDINT - 3411 GTINT - 3412 BRANCHIFNOT 3421 - 3414 GETGLOBAL "String.blit" - 3416 PUSHGETGLOBALFIELD Pervasives, 2 - 3419 APPTERM1 6 - 3421 ACC4 - 3422 PUSHACC4 - 3423 PUSHACC4 - 3424 PUSHACC4 - 3425 PUSHACC4 - 3426 C_CALL5 blit_string - 3428 RETURN 5 - 3430 RESTART - 3431 GRAB 3 - 3433 CONST0 - 3434 PUSHACC2 - 3435 LTINT - 3436 BRANCHIF 3452 - 3438 CONST0 - 3439 PUSHACC3 - 3440 LTINT - 3441 BRANCHIF 3452 - 3443 ACC0 - 3444 C_CALL1 ml_string_length - 3446 PUSHACC3 - 3447 PUSHACC3 - 3448 ADDINT - 3449 GTINT - 3450 BRANCHIFNOT 3459 - 3452 GETGLOBAL "String.fill" - 3454 PUSHGETGLOBALFIELD Pervasives, 2 - 3457 APPTERM1 5 - 3459 ACC3 - 3460 PUSHACC3 - 3461 PUSHACC3 - 3462 PUSHACC3 - 3463 C_CALL4 fill_string - 3465 RETURN 4 - 3467 RESTART - 3468 GRAB 2 - 3470 CONST0 - 3471 PUSHACC2 - 3472 LTINT - 3473 BRANCHIF 3489 - 3475 CONST0 - 3476 PUSHACC3 - 3477 LTINT - 3478 BRANCHIF 3489 - 3480 ACC0 - 3481 C_CALL1 ml_string_length - 3483 PUSHACC3 - 3484 PUSHACC3 - 3485 ADDINT - 3486 GTINT - 3487 BRANCHIFNOT 3496 - 3489 GETGLOBAL "String.sub" - 3491 PUSHGETGLOBALFIELD Pervasives, 2 - 3494 APPTERM1 4 - 3496 ACC2 - 3497 C_CALL1 create_string - 3499 PUSHACC3 - 3500 PUSHCONST0 - 3501 PUSHACC2 - 3502 PUSHACC5 - 3503 PUSHACC5 - 3504 C_CALL5 blit_string - 3506 ACC0 - 3507 RETURN 4 - 3509 ACC0 - 3510 C_CALL1 ml_string_length - 3512 PUSHACC0 - 3513 C_CALL1 create_string - 3515 PUSHACC1 - 3516 PUSHCONST0 - 3517 PUSHACC2 - 3518 PUSHCONST0 - 3519 PUSHACC6 - 3520 C_CALL5 blit_string - 3522 ACC0 - 3523 RETURN 3 - 3525 RESTART - 3526 GRAB 1 - 3528 ACC0 - 3529 C_CALL1 create_string - 3531 PUSHACC2 - 3532 PUSHACC2 - 3533 PUSHCONST0 - 3534 PUSHACC3 - 3535 C_CALL4 fill_string - 3537 ACC0 - 3538 RETURN 3 - 3540 CLOSURE 0, 3526 - 3543 PUSH - 3544 CLOSURE 0, 3509 - 3547 PUSH - 3548 CLOSURE 0, 3468 - 3551 PUSH - 3552 CLOSURE 0, 3431 - 3555 PUSH - 3556 CLOSURE 0, 3379 - 3559 PUSH - 3560 CLOSURE 0, 3308 - 3563 PUSH - 3564 CLOSURE 0, 3013 - 3567 PUSH - 3568 CLOSURE 0, 2965 - 3571 PUSHACC0 - 3572 CLOSURE 1, 2957 - 3575 PUSHACC1 - 3576 CLOSURE 1, 2950 - 3579 PUSHACC 8 - 3581 CLOSURE 1, 2924 - 3584 PUSHACC0 - 3585 CLOSURE 1, 2916 - 3588 PUSHACC1 - 3589 CLOSURE 1, 2909 - 3592 PUSH - 3593 CLOSUREREC 0, 2651 - 3597 ACC0 - 3598 CLOSURE 1, 2897 - 3601 PUSHACC1 - 3602 CLOSURE 1, 2865 - 3605 PUSH - 3606 CLOSUREREC 0, 2684 - 3610 ACC0 - 3611 CLOSURE 1, 2852 - 3614 PUSHACC1 - 3615 CLOSURE 1, 2824 - 3618 PUSHACC5 - 3619 CLOSURE 1, 2769 - 3622 PUSHACC3 - 3623 CLOSURE 1, 2724 - 3626 PUSHACC1 - 3627 CLOSURE 1, 2715 - 3630 PUSHACC 9 - 3632 PUSHACC 11 - 3634 PUSHACC 14 - 3636 PUSHACC 16 - 3638 PUSHACC5 - 3639 PUSHACC7 - 3640 PUSHACC6 - 3641 PUSHACC 10 - 3643 PUSHACC 14 - 3645 PUSHACC 13 - 3647 PUSHACC 17 - 3649 PUSHACC 26 - 3651 PUSHACC 28 - 3653 PUSHACC 30 - 3655 PUSHACC 32 - 3657 PUSHACC 34 - 3659 PUSHACC 36 - 3661 PUSHACC 38 - 3663 MAKEBLOCK 18, 0 - 3666 POP 22 - 3668 SETGLOBAL String - 3670 GETGLOBAL "" - 3672 PUSHCONSTINT 20 - 3674 C_CALL2 make_vect - 3676 PUSHCONSTINT 20 - 3678 C_CALL1 weak_create - 3680 PUSHCONST0 - 3681 PUSHCONSTINT 19 - 3683 PUSH - 3684 BRANCH 3712 - 3686 CHECK_SIGNALS - 3687 CONSTINT 115 - 3689 PUSHCONSTINT 20 - 3691 PUSHGETGLOBALFIELD String, 0 - 3694 APPLY2 - 3695 PUSHACC2 - 3696 PUSHACC5 - 3697 SETVECTITEM - 3698 ACC1 - 3699 PUSHACC4 - 3700 GETVECTITEM - 3701 MAKEBLOCK1 0 - 3703 PUSHACC2 - 3704 PUSHACC4 - 3705 C_CALL3 weak_set - 3707 ACC1 - 3708 OFFSETINT 1 - 3710 ASSIGN 1 - 3712 ACC0 - 3713 PUSHACC2 - 3714 LEINT - 3715 BRANCHIF 3686 - 3717 CONST0 - 3718 POP 2 - 3720 CONST0 - 3721 C_CALL1 gc_full_major - 3723 CONST0 - 3724 PUSHCONSTINT 19 - 3726 PUSH - 3727 BRANCH 3750 - 3729 CHECK_SIGNALS - 3730 ACC1 - 3731 PUSHACC3 - 3732 C_CALL2 weak_get - 3734 PUSHACC0 - 3735 BRANCHIF 3742 - 3737 GETGLOBAL Not_found - 3739 MAKEBLOCK1 0 - 3741 RAISE - 3742 CONST0 - 3743 POP 1 - 3745 ACC1 - 3746 OFFSETINT 1 - 3748 ASSIGN 1 - 3750 ACC0 - 3751 PUSHACC2 - 3752 LEINT - 3753 BRANCHIF 3729 - 3755 CONST0 - 3756 POP 2 - 3758 CONST0 - 3759 PUSHCONSTINT 19 - 3761 PUSH - 3762 BRANCH 3782 - 3764 CHECK_SIGNALS - 3765 CONST0 - 3766 PUSHCONST2 - 3767 PUSHACC3 - 3768 MODINT - 3769 EQ - 3770 BRANCHIFNOT 3777 - 3772 GETGLOBAL "" - 3774 PUSHACC2 - 3775 PUSHACC5 - 3776 SETVECTITEM - 3777 ACC1 - 3778 OFFSETINT 1 - 3780 ASSIGN 1 - 3782 ACC0 - 3783 PUSHACC2 - 3784 LEINT - 3785 BRANCHIF 3764 - 3787 CONST0 - 3788 POP 2 - 3790 CONST0 - 3791 C_CALL1 gc_full_major - 3793 CONST0 - 3794 PUSHCONSTINT 19 - 3796 PUSH - 3797 BRANCH 3851 - 3799 CHECK_SIGNALS - 3800 ACC1 - 3801 PUSHACC3 - 3802 C_CALL2 weak_get - 3804 PUSHACC0 - 3805 BRANCHIFNOT 3829 - 3807 CONST1 - 3808 PUSHCONST2 - 3809 PUSHACC4 - 3810 MODINT - 3811 EQ - 3812 BRANCHIFNOT 3839 - 3814 CONSTINT 115 - 3816 PUSHCONSTINT 5 - 3818 PUSHACC2 - 3819 GETFIELD0 - 3820 GETSTRINGCHAR - 3821 NEQ - 3822 BRANCHIFNOT 3844 - 3824 GETGLOBAL Not_found - 3826 MAKEBLOCK1 0 - 3828 RAISE - 3829 CONST0 - 3830 PUSHCONST2 - 3831 PUSHACC4 - 3832 MODINT - 3833 EQ - 3834 BRANCHIFNOT 3839 - 3836 CONST0 - 3837 BRANCH 3844 - 3839 GETGLOBAL Not_found - 3841 MAKEBLOCK1 0 - 3843 RAISE - 3844 POP 1 - 3846 ACC1 - 3847 OFFSETINT 1 - 3849 ASSIGN 1 - 3851 ACC0 - 3852 PUSHACC2 - 3853 LEINT - 3854 BRANCHIF 3799 - 3856 CONST0 - 3857 POP 4 - 3859 ATOM0 - 3860 SETGLOBAL T340-weak - 3862 STOP -**) diff --git a/testsuite/tests/tool-ocaml/t350-heapcheck.ml b/testsuite/tests/tool-ocaml/t350-heapcheck.ml index ef4557cd..45295eaa 100644 --- a/testsuite/tests/tool-ocaml/t350-heapcheck.ml +++ b/testsuite/tests/tool-ocaml/t350-heapcheck.ml @@ -23,2532 +23,3 @@ for i = 0 to 19 do | _ -> raise Not_found done ;; - -(** - 0 CONSTINT 42 - 2 PUSHACC0 - 3 MAKEBLOCK1 0 - 5 POP 1 - 7 SETGLOBAL Lib - 9 BRANCH 746 - 11 RESTART - 12 GRAB 1 - 14 ACC0 - 15 BRANCHIFNOT 28 - 17 ACC1 - 18 PUSHACC1 - 19 GETFIELD1 - 20 PUSHOFFSETCLOSURE0 - 21 APPLY2 - 22 PUSHACC1 - 23 GETFIELD0 - 24 MAKEBLOCK2 0 - 26 RETURN 2 - 28 ACC1 - 29 RETURN 2 - 31 RESTART - 32 GRAB 3 - 34 CONST0 - 35 PUSHACC4 - 36 LEINT - 37 BRANCHIFNOT 42 - 39 CONST0 - 40 RETURN 4 - 42 ACC3 - 43 PUSHACC3 - 44 PUSHACC3 - 45 PUSHACC3 - 46 C_CALL4 caml_input - 48 PUSHCONST0 - 49 PUSHACC1 - 50 EQ - 51 BRANCHIFNOT 58 - 53 GETGLOBAL End_of_file - 55 MAKEBLOCK1 0 - 57 RAISE - 58 ACC0 - 59 PUSHACC5 - 60 SUBINT - 61 PUSHACC1 - 62 PUSHACC5 - 63 ADDINT - 64 PUSHACC4 - 65 PUSHACC4 - 66 PUSHOFFSETCLOSURE0 - 67 APPTERM 4, 9 - 70 ACC0 - 71 C_CALL1 caml_input_scan_line - 73 PUSHCONST0 - 74 PUSHACC1 - 75 EQ - 76 BRANCHIFNOT 83 - 78 GETGLOBAL End_of_file - 80 MAKEBLOCK1 0 - 82 RAISE - 83 CONST0 - 84 PUSHACC1 - 85 GTINT - 86 BRANCHIFNOT 107 - 88 ACC0 - 89 OFFSETINT -1 - 91 C_CALL1 create_string - 93 PUSHACC1 - 94 OFFSETINT -1 - 96 PUSHCONST0 - 97 PUSHACC2 - 98 PUSHACC5 - 99 C_CALL4 caml_input - 101 ACC2 - 102 C_CALL1 caml_input_char - 104 ACC0 - 105 RETURN 3 - 107 ACC0 - 108 NEGINT - 109 C_CALL1 create_string - 111 PUSHACC1 - 112 NEGINT - 113 PUSHCONST0 - 114 PUSHACC2 - 115 PUSHACC5 - 116 C_CALL4 caml_input - 118 CONST0 - 119 PUSHTRAP 130 - 121 ACC6 - 122 PUSHOFFSETCLOSURE0 - 123 APPLY1 - 124 PUSHACC5 - 125 PUSHENVACC1 - 126 APPLY2 - 127 POPTRAP - 128 RETURN 3 - 130 PUSHGETGLOBAL End_of_file - 132 PUSHACC1 - 133 GETFIELD0 - 134 EQ - 135 BRANCHIFNOT 140 - 137 ACC1 - 138 RETURN 4 - 140 ACC0 - 141 RAISE - 142 ACC0 - 143 C_CALL1 caml_flush - 145 RETURN 1 - 147 RESTART - 148 GRAB 1 - 150 ACC1 - 151 PUSHACC1 - 152 C_CALL2 caml_output_char - 154 RETURN 2 - 156 RESTART - 157 GRAB 1 - 159 ACC1 - 160 PUSHACC1 - 161 C_CALL2 caml_output_char - 163 RETURN 2 - 165 RESTART - 166 GRAB 1 - 168 ACC1 - 169 PUSHACC1 - 170 C_CALL2 caml_output_int - 172 RETURN 2 - 174 RESTART - 175 GRAB 1 - 177 ACC1 - 178 PUSHACC1 - 179 C_CALL2 caml_seek_out - 181 RETURN 2 - 183 ACC0 - 184 C_CALL1 caml_pos_out - 186 RETURN 1 - 188 ACC0 - 189 C_CALL1 caml_channel_size - 191 RETURN 1 - 193 RESTART - 194 GRAB 1 - 196 ACC1 - 197 PUSHACC1 - 198 C_CALL2 caml_set_binary_mode - 200 RETURN 2 - 202 ACC0 - 203 C_CALL1 caml_input_char - 205 RETURN 1 - 207 ACC0 - 208 C_CALL1 caml_input_char - 210 RETURN 1 - 212 ACC0 - 213 C_CALL1 caml_input_int - 215 RETURN 1 - 217 ACC0 - 218 C_CALL1 input_value - 220 RETURN 1 - 222 RESTART - 223 GRAB 1 - 225 ACC1 - 226 PUSHACC1 - 227 C_CALL2 caml_seek_in - 229 RETURN 2 - 231 ACC0 - 232 C_CALL1 caml_pos_in - 234 RETURN 1 - 236 ACC0 - 237 C_CALL1 caml_channel_size - 239 RETURN 1 - 241 ACC0 - 242 C_CALL1 caml_close_channel - 244 RETURN 1 - 246 RESTART - 247 GRAB 1 - 249 ACC1 - 250 PUSHACC1 - 251 C_CALL2 caml_set_binary_mode - 253 RETURN 2 - 255 CONST0 - 256 PUSHENVACC1 - 257 APPLY1 - 258 ACC0 - 259 C_CALL1 sys_exit - 261 RETURN 1 - 263 CONST0 - 264 PUSHENVACC1 - 265 GETFIELD0 - 266 APPTERM1 2 - 268 CONST0 - 269 PUSHENVACC1 - 270 APPLY1 - 271 CONST0 - 272 PUSHENVACC2 - 273 APPTERM1 2 - 275 ENVACC1 - 276 GETFIELD0 - 277 PUSHACC0 - 278 PUSHACC2 - 279 CLOSURE 2, 268 - 282 PUSHENVACC1 - 283 SETFIELD0 - 284 RETURN 2 - 286 ENVACC1 - 287 C_CALL1 caml_flush - 289 ENVACC2 - 290 C_CALL1 caml_flush - 292 RETURN 1 - 294 CONST0 - 295 PUSHENVACC1 - 296 APPLY1 - 297 C_CALL1 float_of_string - 299 RETURN 1 - 301 CONST0 - 302 PUSHENVACC1 - 303 APPLY1 - 304 C_CALL1 int_of_string - 306 RETURN 1 - 308 ENVACC2 - 309 C_CALL1 caml_flush - 311 ENVACC1 - 312 PUSHENVACC3 - 313 APPTERM1 2 - 315 CONSTINT 13 - 317 PUSHENVACC1 - 318 C_CALL2 caml_output_char - 320 ENVACC1 - 321 C_CALL1 caml_flush - 323 RETURN 1 - 325 ACC0 - 326 PUSHENVACC1 - 327 PUSHENVACC2 - 328 APPLY2 - 329 CONSTINT 13 - 331 PUSHENVACC1 - 332 C_CALL2 caml_output_char - 334 ENVACC1 - 335 C_CALL1 caml_flush - 337 RETURN 1 - 339 ACC0 - 340 PUSHENVACC1 - 341 APPLY1 - 342 PUSHENVACC2 - 343 PUSHENVACC3 - 344 APPTERM2 3 - 346 ACC0 - 347 PUSHENVACC1 - 348 APPLY1 - 349 PUSHENVACC2 - 350 PUSHENVACC3 - 351 APPTERM2 3 - 353 ACC0 - 354 PUSHENVACC1 - 355 PUSHENVACC2 - 356 APPTERM2 3 - 358 ACC0 - 359 PUSHENVACC1 - 360 C_CALL2 caml_output_char - 362 RETURN 1 - 364 CONSTINT 13 - 366 PUSHENVACC1 - 367 C_CALL2 caml_output_char - 369 ENVACC1 - 370 C_CALL1 caml_flush - 372 RETURN 1 - 374 ACC0 - 375 PUSHENVACC1 - 376 PUSHENVACC2 - 377 APPLY2 - 378 CONSTINT 13 - 380 PUSHENVACC1 - 381 C_CALL2 caml_output_char - 383 RETURN 1 - 385 ACC0 - 386 PUSHENVACC1 - 387 APPLY1 - 388 PUSHENVACC2 - 389 PUSHENVACC3 - 390 APPTERM2 3 - 392 ACC0 - 393 PUSHENVACC1 - 394 APPLY1 - 395 PUSHENVACC2 - 396 PUSHENVACC3 - 397 APPTERM2 3 - 399 ACC0 - 400 PUSHENVACC1 - 401 PUSHENVACC2 - 402 APPTERM2 3 - 404 ACC0 - 405 PUSHENVACC1 - 406 C_CALL2 caml_output_char - 408 RETURN 1 - 410 RESTART - 411 GRAB 3 - 413 CONST0 - 414 PUSHACC3 - 415 LTINT - 416 BRANCHIF 427 - 418 ACC1 - 419 C_CALL1 ml_string_length - 421 PUSHACC4 - 422 PUSHACC4 - 423 ADDINT - 424 GTINT - 425 BRANCHIFNOT 432 - 427 GETGLOBAL "really_input" - 429 PUSHENVACC1 - 430 APPTERM1 5 - 432 ACC3 - 433 PUSHACC3 - 434 PUSHACC3 - 435 PUSHACC3 - 436 PUSHENVACC2 - 437 APPTERM 4, 8 - 440 RESTART - 441 GRAB 3 - 443 CONST0 - 444 PUSHACC3 - 445 LTINT - 446 BRANCHIF 457 - 448 ACC1 - 449 C_CALL1 ml_string_length - 451 PUSHACC4 - 452 PUSHACC4 - 453 ADDINT - 454 GTINT - 455 BRANCHIFNOT 462 - 457 GETGLOBAL "input" - 459 PUSHENVACC1 - 460 APPTERM1 5 - 462 ACC3 - 463 PUSHACC3 - 464 PUSHACC3 - 465 PUSHACC3 - 466 C_CALL4 caml_input - 468 RETURN 4 - 470 ACC0 - 471 PUSHCONST0 - 472 PUSHGETGLOBAL <0>(0, <0>(6, 0)) - 474 PUSHENVACC1 - 475 APPTERM3 4 - 477 ACC0 - 478 PUSHCONST0 - 479 PUSHGETGLOBAL <0>(0, <0>(7, 0)) - 481 PUSHENVACC1 - 482 APPTERM3 4 - 484 RESTART - 485 GRAB 2 - 487 ACC1 - 488 PUSHACC1 - 489 PUSHACC4 - 490 C_CALL3 sys_open - 492 C_CALL1 caml_open_descriptor - 494 RETURN 3 - 496 ACC0 - 497 C_CALL1 caml_flush - 499 ACC0 - 500 C_CALL1 caml_close_channel - 502 RETURN 1 - 504 RESTART - 505 GRAB 1 - 507 CONST0 - 508 PUSHACC2 - 509 PUSHACC2 - 510 C_CALL3 output_value - 512 RETURN 2 - 514 RESTART - 515 GRAB 3 - 517 CONST0 - 518 PUSHACC3 - 519 LTINT - 520 BRANCHIF 531 - 522 ACC1 - 523 C_CALL1 ml_string_length - 525 PUSHACC4 - 526 PUSHACC4 - 527 ADDINT - 528 GTINT - 529 BRANCHIFNOT 536 - 531 GETGLOBAL "output" - 533 PUSHENVACC1 - 534 APPTERM1 5 - 536 ACC3 - 537 PUSHACC3 - 538 PUSHACC3 - 539 PUSHACC3 - 540 C_CALL4 caml_output - 542 RETURN 4 - 544 RESTART - 545 GRAB 1 - 547 ACC1 - 548 C_CALL1 ml_string_length - 550 PUSHCONST0 - 551 PUSHACC3 - 552 PUSHACC3 - 553 C_CALL4 caml_output - 555 RETURN 2 - 557 ACC0 - 558 PUSHCONSTINT 438 - 560 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(6, 0)))) - 562 PUSHENVACC1 - 563 APPTERM3 4 - 565 ACC0 - 566 PUSHCONSTINT 438 - 568 PUSHGETGLOBAL <0>(1, <0>(3, <0>(4, <0>(7, 0)))) - 570 PUSHENVACC1 - 571 APPTERM3 4 - 573 RESTART - 574 GRAB 2 - 576 ACC1 - 577 PUSHACC1 - 578 PUSHACC4 - 579 C_CALL3 sys_open - 581 C_CALL1 caml_open_descriptor - 583 RETURN 3 - 585 ACC0 - 586 PUSHGETGLOBAL "%.12g" - 588 C_CALL2 format_float - 590 RETURN 1 - 592 ACC0 - 593 PUSHGETGLOBAL "%d" - 595 C_CALL2 format_int - 597 RETURN 1 - 599 GETGLOBAL "false" - 601 PUSHACC1 - 602 C_CALL2 string_equal - 604 BRANCHIFNOT 609 - 606 CONST0 - 607 RETURN 1 - 609 GETGLOBAL "true" - 611 PUSHACC1 - 612 C_CALL2 string_equal - 614 BRANCHIFNOT 619 - 616 CONST1 - 617 RETURN 1 - 619 GETGLOBAL "bool_of_string" - 621 PUSHENVACC1 - 622 APPTERM1 2 - 624 ACC0 - 625 BRANCHIFNOT 631 - 627 GETGLOBAL "true" - 629 RETURN 1 - 631 GETGLOBAL "false" - 633 RETURN 1 - 635 CONST0 - 636 PUSHACC1 - 637 LTINT - 638 BRANCHIF 646 - 640 CONSTINT 255 - 642 PUSHACC1 - 643 GTINT - 644 BRANCHIFNOT 651 - 646 GETGLOBAL "char_of_int" - 648 PUSHENVACC1 - 649 APPTERM1 2 - 651 ACC0 - 652 RETURN 1 - 654 RESTART - 655 GRAB 1 - 657 ACC0 - 658 C_CALL1 ml_string_length - 660 PUSHACC2 - 661 C_CALL1 ml_string_length - 663 PUSHACC0 - 664 PUSHACC2 - 665 ADDINT - 666 C_CALL1 create_string - 668 PUSHACC2 - 669 PUSHCONST0 - 670 PUSHACC2 - 671 PUSHCONST0 - 672 PUSHACC7 - 673 C_CALL5 blit_string - 675 ACC1 - 676 PUSHACC3 - 677 PUSHACC2 - 678 PUSHCONST0 - 679 PUSHACC 8 - 681 C_CALL5 blit_string - 683 ACC0 - 684 RETURN 5 - 686 CONSTINT -1 - 688 PUSHACC1 - 689 XORINT - 690 RETURN 1 - 692 CONST0 - 693 PUSHACC1 - 694 GEINT - 695 BRANCHIFNOT 700 - 697 ACC0 - 698 RETURN 1 - 700 ACC0 - 701 NEGINT - 702 RETURN 1 - 704 RESTART - 705 GRAB 1 - 707 ACC1 - 708 PUSHACC1 - 709 C_CALL2 greaterequal - 711 BRANCHIFNOT 716 - 713 ACC0 - 714 RETURN 2 - 716 ACC1 - 717 RETURN 2 - 719 RESTART - 720 GRAB 1 - 722 ACC1 - 723 PUSHACC1 - 724 C_CALL2 lessequal - 726 BRANCHIFNOT 731 - 728 ACC0 - 729 RETURN 2 - 731 ACC1 - 732 RETURN 2 - 734 ACC0 - 735 PUSHGETGLOBAL Invalid_argument - 737 MAKEBLOCK2 0 - 739 RAISE - 740 ACC0 - 741 PUSHGETGLOBAL Failure - 743 MAKEBLOCK2 0 - 745 RAISE - 746 CLOSURE 0, 740 - 749 PUSH - 750 CLOSURE 0, 734 - 753 PUSHGETGLOBAL "Pervasives.Exit" - 755 MAKEBLOCK1 0 - 757 PUSHGETGLOBAL "Pervasives.Assert_failure" - 759 MAKEBLOCK1 0 - 761 PUSH - 762 CLOSURE 0, 720 - 765 PUSH - 766 CLOSURE 0, 705 - 769 PUSH - 770 CLOSURE 0, 692 - 773 PUSH - 774 CLOSURE 0, 686 - 777 PUSHCONST0 - 778 PUSHCONSTINT 31 - 780 PUSHCONST1 - 781 LSLINT - 782 EQ - 783 BRANCHIFNOT 789 - 785 CONSTINT 30 - 787 BRANCH 791 - 789 CONSTINT 62 - 791 PUSHCONST1 - 792 LSLINT - 793 PUSHACC0 - 794 OFFSETINT -1 - 796 PUSH - 797 CLOSURE 0, 655 - 800 PUSHACC 9 - 802 CLOSURE 1, 635 - 805 PUSH - 806 CLOSURE 0, 624 - 809 PUSHACC 11 - 811 CLOSURE 1, 599 - 814 PUSH - 815 CLOSURE 0, 592 - 818 PUSH - 819 CLOSURE 0, 585 - 822 PUSH - 823 CLOSUREREC 0, 12 - 827 CONST0 - 828 C_CALL1 caml_open_descriptor - 830 PUSHCONST1 - 831 C_CALL1 caml_open_descriptor - 833 PUSHCONST2 - 834 C_CALL1 caml_open_descriptor - 836 PUSH - 837 CLOSURE 0, 574 - 840 PUSHACC0 - 841 CLOSURE 1, 565 - 844 PUSHACC1 - 845 CLOSURE 1, 557 - 848 PUSH - 849 CLOSURE 0, 545 - 852 PUSHACC 22 - 854 CLOSURE 1, 515 - 857 PUSH - 858 CLOSURE 0, 505 - 861 PUSH - 862 CLOSURE 0, 496 - 865 PUSH - 866 CLOSURE 0, 485 - 869 PUSHACC0 - 870 CLOSURE 1, 477 - 873 PUSHACC1 - 874 CLOSURE 1, 470 - 877 PUSHACC 28 - 879 CLOSURE 1, 441 - 882 PUSH - 883 CLOSUREREC 0, 32 - 887 ACC0 - 888 PUSHACC 31 - 890 CLOSURE 2, 411 - 893 PUSHACC 22 - 895 CLOSUREREC 1, 70 - 899 ACC 15 - 901 CLOSURE 1, 404 - 904 PUSHACC 11 - 906 PUSHACC 17 - 908 CLOSURE 2, 399 - 911 PUSHACC 12 - 913 PUSHACC 18 - 915 PUSHACC 23 - 917 CLOSURE 3, 392 - 920 PUSHACC 13 - 922 PUSHACC 19 - 924 PUSHACC 23 - 926 CLOSURE 3, 385 - 929 PUSHACC 14 - 931 PUSHACC 20 - 933 CLOSURE 2, 374 - 936 PUSHACC 20 - 938 CLOSURE 1, 364 - 941 PUSHACC 20 - 943 CLOSURE 1, 358 - 946 PUSHACC 17 - 948 PUSHACC 22 - 950 CLOSURE 2, 353 - 953 PUSHACC 18 - 955 PUSHACC 23 - 957 PUSHACC 29 - 959 CLOSURE 3, 346 - 962 PUSHACC 19 - 964 PUSHACC 24 - 966 PUSHACC 29 - 968 CLOSURE 3, 339 - 971 PUSHACC 20 - 973 PUSHACC 25 - 975 CLOSURE 2, 325 - 978 PUSHACC 25 - 980 CLOSURE 1, 315 - 983 PUSHACC 12 - 985 PUSHACC 28 - 987 PUSHACC 30 - 989 CLOSURE 3, 308 - 992 PUSHACC0 - 993 CLOSURE 1, 301 - 996 PUSHACC1 - 997 CLOSURE 1, 294 - 1000 PUSHACC 29 - 1002 PUSHACC 31 - 1004 CLOSURE 2, 286 - 1007 MAKEBLOCK1 0 - 1009 PUSHACC0 - 1010 CLOSURE 1, 275 - 1013 PUSHACC1 - 1014 CLOSURE 1, 263 - 1017 PUSHACC0 - 1018 CLOSURE 1, 255 - 1021 PUSHACC1 - 1022 PUSHACC 22 - 1024 PUSHACC4 - 1025 PUSHACC3 - 1026 PUSH - 1027 CLOSURE 0, 247 - 1030 PUSH - 1031 CLOSURE 0, 241 - 1034 PUSH - 1035 CLOSURE 0, 236 - 1038 PUSH - 1039 CLOSURE 0, 231 - 1042 PUSH - 1043 CLOSURE 0, 223 - 1046 PUSH - 1047 CLOSURE 0, 217 - 1050 PUSH - 1051 CLOSURE 0, 212 - 1054 PUSH - 1055 CLOSURE 0, 207 - 1058 PUSHACC 32 - 1060 PUSHACC 35 - 1062 PUSHACC 33 - 1064 PUSH - 1065 CLOSURE 0, 202 - 1068 PUSHACC 41 - 1070 PUSHACC 40 - 1072 PUSHACC 42 - 1074 PUSH - 1075 CLOSURE 0, 194 - 1078 PUSHACC 46 - 1080 PUSH - 1081 CLOSURE 0, 188 - 1084 PUSH - 1085 CLOSURE 0, 183 - 1088 PUSH - 1089 CLOSURE 0, 175 - 1092 PUSHACC 51 - 1094 PUSH - 1095 CLOSURE 0, 166 - 1098 PUSH - 1099 CLOSURE 0, 157 - 1102 PUSHACC 55 - 1104 PUSHACC 57 - 1106 PUSH - 1107 CLOSURE 0, 148 - 1110 PUSH - 1111 CLOSURE 0, 142 - 1114 PUSHACC 63 - 1116 PUSHACC 62 - 1118 PUSHACC 64 - 1120 PUSHACC 38 - 1122 PUSHACC 40 - 1124 PUSHACC 42 - 1126 PUSHACC 44 - 1128 PUSHACC 46 - 1130 PUSHACC 48 - 1132 PUSHACC 50 - 1134 PUSHACC 52 - 1136 PUSHACC 54 - 1138 PUSHACC 56 - 1140 PUSHACC 58 - 1142 PUSHACC 60 - 1144 PUSHACC 62 - 1146 PUSHACC 64 - 1148 PUSHACC 66 - 1150 PUSHACC 82 - 1152 PUSHACC 84 - 1154 PUSHACC 86 - 1156 PUSHACC 88 - 1158 PUSHACC 90 - 1160 PUSHACC 92 - 1162 PUSHACC 94 - 1164 PUSHACC 96 - 1166 PUSHACC 98 - 1168 PUSHACC 100 - 1170 PUSHACC 104 - 1172 PUSHACC 104 - 1174 PUSHACC 104 - 1176 PUSHACC 108 - 1178 PUSHACC 110 - 1180 PUSHACC 112 - 1182 PUSHACC 117 - 1184 PUSHACC 117 - 1186 PUSHACC 117 - 1188 PUSHACC 117 - 1190 MAKEBLOCK 69, 0 - 1193 POP 53 - 1195 SETGLOBAL Pervasives - 1197 BRANCH 2177 - 1199 RESTART - 1200 GRAB 1 - 1202 ACC1 - 1203 BRANCHIFNOT 1213 - 1205 ACC1 - 1206 GETFIELD1 - 1207 PUSHACC1 - 1208 OFFSETINT 1 - 1210 PUSHOFFSETCLOSURE0 - 1211 APPTERM2 4 - 1213 ACC0 - 1214 RETURN 2 - 1216 RESTART - 1217 GRAB 1 - 1219 ACC0 - 1220 BRANCHIFNOT 1251 - 1222 CONST0 - 1223 PUSHACC2 - 1224 EQ - 1225 BRANCHIFNOT 1231 - 1227 ACC0 - 1228 GETFIELD0 - 1229 RETURN 2 - 1231 CONST0 - 1232 PUSHACC2 - 1233 GTINT - 1234 BRANCHIFNOT 1244 - 1236 ACC1 - 1237 OFFSETINT -1 - 1239 PUSHACC1 - 1240 GETFIELD1 - 1241 PUSHOFFSETCLOSURE0 - 1242 APPTERM2 4 - 1244 GETGLOBAL "List.nth" - 1246 PUSHGETGLOBALFIELD Pervasives, 2 - 1249 APPTERM1 3 - 1251 GETGLOBAL "nth" - 1253 PUSHGETGLOBALFIELD Pervasives, 3 - 1256 APPTERM1 3 - 1258 RESTART - 1259 GRAB 1 - 1261 ACC0 - 1262 BRANCHIFNOT 1274 - 1264 ACC1 - 1265 PUSHACC1 - 1266 GETFIELD0 - 1267 MAKEBLOCK2 0 - 1269 PUSHACC1 - 1270 GETFIELD1 - 1271 PUSHOFFSETCLOSURE0 - 1272 APPTERM2 4 - 1274 ACC1 - 1275 RETURN 2 - 1277 ACC0 - 1278 BRANCHIFNOT 1291 - 1280 ACC0 - 1281 GETFIELD1 - 1282 PUSHOFFSETCLOSURE0 - 1283 APPLY1 - 1284 PUSHACC1 - 1285 GETFIELD0 - 1286 PUSHGETGLOBALFIELD Pervasives, 16 - 1289 APPTERM2 3 - 1291 RETURN 1 - 1293 RESTART - 1294 GRAB 1 - 1296 ACC1 - 1297 BRANCHIFNOT 1313 - 1299 ACC1 - 1300 GETFIELD0 - 1301 PUSHACC1 - 1302 APPLY1 - 1303 PUSHACC2 - 1304 GETFIELD1 - 1305 PUSHACC2 - 1306 PUSHOFFSETCLOSURE0 - 1307 APPLY2 - 1308 PUSHACC1 - 1309 MAKEBLOCK2 0 - 1311 POP 1 - 1313 RETURN 2 - 1315 RESTART - 1316 GRAB 1 - 1318 ACC1 - 1319 BRANCHIFNOT 1331 - 1321 ACC1 - 1322 GETFIELD0 - 1323 PUSHACC1 - 1324 APPLY1 - 1325 ACC1 - 1326 GETFIELD1 - 1327 PUSHACC1 - 1328 PUSHOFFSETCLOSURE0 - 1329 APPTERM2 4 - 1331 RETURN 2 - 1333 RESTART - 1334 GRAB 2 - 1336 ACC2 - 1337 BRANCHIFNOT 1350 - 1339 ACC2 - 1340 GETFIELD1 - 1341 PUSHACC3 - 1342 GETFIELD0 - 1343 PUSHACC3 - 1344 PUSHACC3 - 1345 APPLY2 - 1346 PUSHACC2 - 1347 PUSHOFFSETCLOSURE0 - 1348 APPTERM3 6 - 1350 ACC1 - 1351 RETURN 3 - 1353 RESTART - 1354 GRAB 2 - 1356 ACC1 - 1357 BRANCHIFNOT 1370 - 1359 ACC2 - 1360 PUSHACC2 - 1361 GETFIELD1 - 1362 PUSHACC2 - 1363 PUSHOFFSETCLOSURE0 - 1364 APPLY3 - 1365 PUSHACC2 - 1366 GETFIELD0 - 1367 PUSHACC2 - 1368 APPTERM2 5 - 1370 ACC2 - 1371 RETURN 3 - 1373 RESTART - 1374 GRAB 2 - 1376 ACC1 - 1377 BRANCHIFNOT 1400 - 1379 ACC2 - 1380 BRANCHIFNOT 1407 - 1382 ACC2 - 1383 GETFIELD0 - 1384 PUSHACC2 - 1385 GETFIELD0 - 1386 PUSHACC2 - 1387 APPLY2 - 1388 PUSHACC3 - 1389 GETFIELD1 - 1390 PUSHACC3 - 1391 GETFIELD1 - 1392 PUSHACC3 - 1393 PUSHOFFSETCLOSURE0 - 1394 APPLY3 - 1395 PUSHACC1 - 1396 MAKEBLOCK2 0 - 1398 RETURN 4 - 1400 ACC2 - 1401 BRANCHIFNOT 1405 - 1403 BRANCH 1407 - 1405 RETURN 3 - 1407 GETGLOBAL "List.map2" - 1409 PUSHGETGLOBALFIELD Pervasives, 2 - 1412 APPTERM1 4 - 1414 RESTART - 1415 GRAB 2 - 1417 ACC1 - 1418 BRANCHIFNOT 1437 - 1420 ACC2 - 1421 BRANCHIFNOT 1444 - 1423 ACC2 - 1424 GETFIELD0 - 1425 PUSHACC2 - 1426 GETFIELD0 - 1427 PUSHACC2 - 1428 APPLY2 - 1429 ACC2 - 1430 GETFIELD1 - 1431 PUSHACC2 - 1432 GETFIELD1 - 1433 PUSHACC2 - 1434 PUSHOFFSETCLOSURE0 - 1435 APPTERM3 6 - 1437 ACC2 - 1438 BRANCHIFNOT 1442 - 1440 BRANCH 1444 - 1442 RETURN 3 - 1444 GETGLOBAL "List.iter2" - 1446 PUSHGETGLOBALFIELD Pervasives, 2 - 1449 APPTERM1 4 - 1451 RESTART - 1452 GRAB 3 - 1454 ACC2 - 1455 BRANCHIFNOT 1476 - 1457 ACC3 - 1458 BRANCHIFNOT 1482 - 1460 ACC3 - 1461 GETFIELD1 - 1462 PUSHACC3 - 1463 GETFIELD1 - 1464 PUSHACC5 - 1465 GETFIELD0 - 1466 PUSHACC5 - 1467 GETFIELD0 - 1468 PUSHACC5 - 1469 PUSHACC5 - 1470 APPLY3 - 1471 PUSHACC3 - 1472 PUSHOFFSETCLOSURE0 - 1473 APPTERM 4, 8 - 1476 ACC3 - 1477 BRANCHIF 1482 - 1479 ACC1 - 1480 RETURN 4 - 1482 GETGLOBAL "List.fold_left2" - 1484 PUSHGETGLOBALFIELD Pervasives, 2 - 1487 APPTERM1 5 - 1489 RESTART - 1490 GRAB 3 - 1492 ACC1 - 1493 BRANCHIFNOT 1516 - 1495 ACC2 - 1496 BRANCHIFNOT 1522 - 1498 PUSH_RETADDR 1509 - 1500 ACC6 - 1501 PUSHACC6 - 1502 GETFIELD1 - 1503 PUSHACC6 - 1504 GETFIELD1 - 1505 PUSHACC6 - 1506 PUSHOFFSETCLOSURE0 - 1507 APPLY 4 - 1509 PUSHACC3 - 1510 GETFIELD0 - 1511 PUSHACC3 - 1512 GETFIELD0 - 1513 PUSHACC3 - 1514 APPTERM3 7 - 1516 ACC2 - 1517 BRANCHIF 1522 - 1519 ACC3 - 1520 RETURN 4 - 1522 GETGLOBAL "List.fold_right2" - 1524 PUSHGETGLOBALFIELD Pervasives, 2 - 1527 APPTERM1 5 - 1529 RESTART - 1530 GRAB 1 - 1532 ACC1 - 1533 BRANCHIFNOT 1549 - 1535 ACC1 - 1536 GETFIELD0 - 1537 PUSHACC1 - 1538 APPLY1 - 1539 BRANCHIFNOT 1547 - 1541 ACC1 - 1542 GETFIELD1 - 1543 PUSHACC1 - 1544 PUSHOFFSETCLOSURE0 - 1545 APPTERM2 4 - 1547 RETURN 2 - 1549 CONST1 - 1550 RETURN 2 - 1552 RESTART - 1553 GRAB 1 - 1555 ACC1 - 1556 BRANCHIFNOT 1570 - 1558 ACC1 - 1559 GETFIELD0 - 1560 PUSHACC1 - 1561 APPLY1 - 1562 BRANCHIF 1570 - 1564 ACC1 - 1565 GETFIELD1 - 1566 PUSHACC1 - 1567 PUSHOFFSETCLOSURE0 - 1568 APPTERM2 4 - 1570 RETURN 2 - 1572 RESTART - 1573 GRAB 2 - 1575 ACC1 - 1576 BRANCHIFNOT 1599 - 1578 ACC2 - 1579 BRANCHIFNOT 1605 - 1581 ACC2 - 1582 GETFIELD0 - 1583 PUSHACC2 - 1584 GETFIELD0 - 1585 PUSHACC2 - 1586 APPLY2 - 1587 BRANCHIFNOT 1597 - 1589 ACC2 - 1590 GETFIELD1 - 1591 PUSHACC2 - 1592 GETFIELD1 - 1593 PUSHACC2 - 1594 PUSHOFFSETCLOSURE0 - 1595 APPTERM3 6 - 1597 RETURN 3 - 1599 ACC2 - 1600 BRANCHIF 1605 - 1602 CONST1 - 1603 RETURN 3 - 1605 GETGLOBAL "List.for_all2" - 1607 PUSHGETGLOBALFIELD Pervasives, 2 - 1610 APPTERM1 4 - 1612 RESTART - 1613 GRAB 2 - 1615 ACC1 - 1616 BRANCHIFNOT 1639 - 1618 ACC2 - 1619 BRANCHIFNOT 1646 - 1621 ACC2 - 1622 GETFIELD0 - 1623 PUSHACC2 - 1624 GETFIELD0 - 1625 PUSHACC2 - 1626 APPLY2 - 1627 BRANCHIF 1637 - 1629 ACC2 - 1630 GETFIELD1 - 1631 PUSHACC2 - 1632 GETFIELD1 - 1633 PUSHACC2 - 1634 PUSHOFFSETCLOSURE0 - 1635 APPTERM3 6 - 1637 RETURN 3 - 1639 ACC2 - 1640 BRANCHIFNOT 1644 - 1642 BRANCH 1646 - 1644 RETURN 3 - 1646 GETGLOBAL "List.exists2" - 1648 PUSHGETGLOBALFIELD Pervasives, 2 - 1651 APPTERM1 4 - 1653 RESTART - 1654 GRAB 1 - 1656 ACC1 - 1657 BRANCHIFNOT 1672 - 1659 ACC0 - 1660 PUSHACC2 - 1661 GETFIELD0 - 1662 C_CALL2 equal - 1664 BRANCHIF 1672 - 1666 ACC1 - 1667 GETFIELD1 - 1668 PUSHACC1 - 1669 PUSHOFFSETCLOSURE0 - 1670 APPTERM2 4 - 1672 RETURN 2 - 1674 RESTART - 1675 GRAB 1 - 1677 ACC1 - 1678 BRANCHIFNOT 1692 - 1680 ACC0 - 1681 PUSHACC2 - 1682 GETFIELD0 - 1683 EQ - 1684 BRANCHIF 1692 - 1686 ACC1 - 1687 GETFIELD1 - 1688 PUSHACC1 - 1689 PUSHOFFSETCLOSURE0 - 1690 APPTERM2 4 - 1692 RETURN 2 - 1694 RESTART - 1695 GRAB 1 - 1697 ACC1 - 1698 BRANCHIFNOT 1719 - 1700 ACC1 - 1701 GETFIELD0 - 1702 PUSHACC1 - 1703 PUSHACC1 - 1704 GETFIELD0 - 1705 C_CALL2 equal - 1707 BRANCHIFNOT 1713 - 1709 ACC0 - 1710 GETFIELD1 - 1711 RETURN 3 - 1713 ACC2 - 1714 GETFIELD1 - 1715 PUSHACC2 - 1716 PUSHOFFSETCLOSURE0 - 1717 APPTERM2 5 - 1719 GETGLOBAL Not_found - 1721 MAKEBLOCK1 0 - 1723 RAISE - 1724 RESTART - 1725 GRAB 1 - 1727 ACC1 - 1728 BRANCHIFNOT 1748 - 1730 ACC1 - 1731 GETFIELD0 - 1732 PUSHACC1 - 1733 PUSHACC1 - 1734 GETFIELD0 - 1735 EQ - 1736 BRANCHIFNOT 1742 - 1738 ACC0 - 1739 GETFIELD1 - 1740 RETURN 3 - 1742 ACC2 - 1743 GETFIELD1 - 1744 PUSHACC2 - 1745 PUSHOFFSETCLOSURE0 - 1746 APPTERM2 5 - 1748 GETGLOBAL Not_found - 1750 MAKEBLOCK1 0 - 1752 RAISE - 1753 RESTART - 1754 GRAB 1 - 1756 ACC1 - 1757 BRANCHIFNOT 1773 - 1759 ACC0 - 1760 PUSHACC2 - 1761 GETFIELD0 - 1762 GETFIELD0 - 1763 C_CALL2 equal - 1765 BRANCHIF 1773 - 1767 ACC1 - 1768 GETFIELD1 - 1769 PUSHACC1 - 1770 PUSHOFFSETCLOSURE0 - 1771 APPTERM2 4 - 1773 RETURN 2 - 1775 RESTART - 1776 GRAB 1 - 1778 ACC1 - 1779 BRANCHIFNOT 1794 - 1781 ACC0 - 1782 PUSHACC2 - 1783 GETFIELD0 - 1784 GETFIELD0 - 1785 EQ - 1786 BRANCHIF 1794 - 1788 ACC1 - 1789 GETFIELD1 - 1790 PUSHACC1 - 1791 PUSHOFFSETCLOSURE0 - 1792 APPTERM2 4 - 1794 RETURN 2 - 1796 RESTART - 1797 GRAB 1 - 1799 ACC1 - 1800 BRANCHIFNOT 1825 - 1802 ACC1 - 1803 GETFIELD0 - 1804 PUSHACC2 - 1805 GETFIELD1 - 1806 PUSHACC2 - 1807 PUSHACC2 - 1808 GETFIELD0 - 1809 C_CALL2 equal - 1811 BRANCHIFNOT 1816 - 1813 ACC0 - 1814 RETURN 4 - 1816 ACC0 - 1817 PUSHACC3 - 1818 PUSHOFFSETCLOSURE0 - 1819 APPLY2 - 1820 PUSHACC2 - 1821 MAKEBLOCK2 0 - 1823 POP 2 - 1825 RETURN 2 - 1827 RESTART - 1828 GRAB 1 - 1830 ACC1 - 1831 BRANCHIFNOT 1855 - 1833 ACC1 - 1834 GETFIELD0 - 1835 PUSHACC2 - 1836 GETFIELD1 - 1837 PUSHACC2 - 1838 PUSHACC2 - 1839 GETFIELD0 - 1840 EQ - 1841 BRANCHIFNOT 1846 - 1843 ACC0 - 1844 RETURN 4 - 1846 ACC0 - 1847 PUSHACC3 - 1848 PUSHOFFSETCLOSURE0 - 1849 APPLY2 - 1850 PUSHACC2 - 1851 MAKEBLOCK2 0 - 1853 POP 2 - 1855 RETURN 2 - 1857 RESTART - 1858 GRAB 1 - 1860 ACC1 - 1861 BRANCHIFNOT 1879 - 1863 ACC1 - 1864 GETFIELD0 - 1865 PUSHACC0 - 1866 PUSHACC2 - 1867 APPLY1 - 1868 BRANCHIFNOT 1873 - 1870 ACC0 - 1871 RETURN 3 - 1873 ACC2 - 1874 GETFIELD1 - 1875 PUSHACC2 - 1876 PUSHOFFSETCLOSURE0 - 1877 APPTERM2 5 - 1879 GETGLOBAL Not_found - 1881 MAKEBLOCK1 0 - 1883 RAISE - 1884 RESTART - 1885 GRAB 2 - 1887 ACC2 - 1888 BRANCHIFNOT 1917 - 1890 ACC2 - 1891 GETFIELD0 - 1892 PUSHACC3 - 1893 GETFIELD1 - 1894 PUSHACC1 - 1895 PUSHENVACC2 - 1896 APPLY1 - 1897 BRANCHIFNOT 1908 - 1899 ACC0 - 1900 PUSHACC4 - 1901 PUSHACC4 - 1902 PUSHACC4 - 1903 MAKEBLOCK2 0 - 1905 PUSHOFFSETCLOSURE0 - 1906 APPTERM3 8 - 1908 ACC0 - 1909 PUSHACC4 - 1910 PUSHACC3 - 1911 MAKEBLOCK2 0 - 1913 PUSHACC4 - 1914 PUSHOFFSETCLOSURE0 - 1915 APPTERM3 8 - 1917 ACC1 - 1918 PUSHENVACC1 - 1919 APPLY1 - 1920 PUSHACC1 - 1921 PUSHENVACC1 - 1922 APPLY1 - 1923 MAKEBLOCK2 0 - 1925 RETURN 3 - 1927 RESTART - 1928 GRAB 1 - 1930 ACC0 - 1931 PUSHENVACC1 - 1932 CLOSUREREC 2, 1885 - 1936 ACC2 - 1937 PUSHCONST0 - 1938 PUSHCONST0 - 1939 PUSHACC3 - 1940 APPTERM3 6 - 1942 ACC0 - 1943 BRANCHIFNOT 1967 - 1945 ACC0 - 1946 GETFIELD0 - 1947 PUSHACC1 - 1948 GETFIELD1 - 1949 PUSHOFFSETCLOSURE0 - 1950 APPLY1 - 1951 PUSHACC0 - 1952 GETFIELD1 - 1953 PUSHACC2 - 1954 GETFIELD1 - 1955 MAKEBLOCK2 0 - 1957 PUSHACC1 - 1958 GETFIELD0 - 1959 PUSHACC3 - 1960 GETFIELD0 - 1961 MAKEBLOCK2 0 - 1963 MAKEBLOCK2 0 - 1965 RETURN 3 - 1967 GETGLOBAL <0>(0, 0) - 1969 RETURN 1 - 1971 RESTART - 1972 GRAB 1 - 1974 ACC0 - 1975 BRANCHIFNOT 1996 - 1977 ACC1 - 1978 BRANCHIFNOT 2003 - 1980 ACC1 - 1981 GETFIELD1 - 1982 PUSHACC1 - 1983 GETFIELD1 - 1984 PUSHOFFSETCLOSURE0 - 1985 APPLY2 - 1986 PUSHACC2 - 1987 GETFIELD0 - 1988 PUSHACC2 - 1989 GETFIELD0 - 1990 MAKEBLOCK2 0 - 1992 MAKEBLOCK2 0 - 1994 RETURN 2 - 1996 ACC1 - 1997 BRANCHIFNOT 2001 - 1999 BRANCH 2003 - 2001 RETURN 2 - 2003 GETGLOBAL "List.combine" - 2005 PUSHGETGLOBALFIELD Pervasives, 2 - 2008 APPTERM1 3 - 2010 RESTART - 2011 GRAB 1 - 2013 ACC1 - 2014 BRANCHIFNOT 2038 - 2016 ACC1 - 2017 GETFIELD0 - 2018 PUSHACC2 - 2019 GETFIELD1 - 2020 PUSHACC1 - 2021 PUSHENVACC2 - 2022 APPLY1 - 2023 BRANCHIFNOT 2033 - 2025 ACC0 - 2026 PUSHACC3 - 2027 PUSHACC3 - 2028 MAKEBLOCK2 0 - 2030 PUSHOFFSETCLOSURE0 - 2031 APPTERM2 6 - 2033 ACC0 - 2034 PUSHACC3 - 2035 PUSHOFFSETCLOSURE0 - 2036 APPTERM2 6 - 2038 ACC0 - 2039 PUSHENVACC1 - 2040 APPTERM1 3 - 2042 ACC0 - 2043 PUSHENVACC1 - 2044 CLOSUREREC 2, 2011 - 2048 CONST0 - 2049 PUSHACC1 - 2050 APPTERM1 3 - 2052 RESTART - 2053 GRAB 2 - 2055 ACC1 - 2056 BRANCHIFNOT 2077 - 2058 ACC2 - 2059 BRANCHIFNOT 2084 - 2061 ACC2 - 2062 GETFIELD1 - 2063 PUSHACC2 - 2064 GETFIELD1 - 2065 PUSHACC2 - 2066 PUSHACC5 - 2067 GETFIELD0 - 2068 PUSHACC5 - 2069 GETFIELD0 - 2070 PUSHENVACC1 - 2071 APPLY2 - 2072 MAKEBLOCK2 0 - 2074 PUSHOFFSETCLOSURE0 - 2075 APPTERM3 6 - 2077 ACC2 - 2078 BRANCHIFNOT 2082 - 2080 BRANCH 2084 - 2082 RETURN 3 - 2084 GETGLOBAL "List.rev_map2" - 2086 PUSHGETGLOBALFIELD Pervasives, 2 - 2089 APPTERM1 4 - 2091 RESTART - 2092 GRAB 2 - 2094 ACC0 - 2095 CLOSUREREC 1, 2053 - 2099 ACC3 - 2100 PUSHACC3 - 2101 PUSHCONST0 - 2102 PUSHACC3 - 2103 APPTERM3 7 - 2105 RESTART - 2106 GRAB 1 - 2108 ACC1 - 2109 BRANCHIFNOT 2123 - 2111 ACC1 - 2112 GETFIELD1 - 2113 PUSHACC1 - 2114 PUSHACC3 - 2115 GETFIELD0 - 2116 PUSHENVACC1 - 2117 APPLY1 - 2118 MAKEBLOCK2 0 - 2120 PUSHOFFSETCLOSURE0 - 2121 APPTERM2 4 - 2123 ACC0 - 2124 RETURN 2 - 2126 RESTART - 2127 GRAB 1 - 2129 ACC0 - 2130 CLOSUREREC 1, 2106 - 2134 ACC2 - 2135 PUSHCONST0 - 2136 PUSHACC2 - 2137 APPTERM2 5 - 2139 CONST0 - 2140 PUSHACC1 - 2141 PUSHENVACC1 - 2142 APPTERM2 3 - 2144 ACC0 - 2145 BRANCHIFNOT 2151 - 2147 ACC0 - 2148 GETFIELD1 - 2149 RETURN 1 - 2151 GETGLOBAL "tl" - 2153 PUSHGETGLOBALFIELD Pervasives, 3 - 2156 APPTERM1 2 - 2158 ACC0 - 2159 BRANCHIFNOT 2165 - 2161 ACC0 - 2162 GETFIELD0 - 2163 RETURN 1 - 2165 GETGLOBAL "hd" - 2167 PUSHGETGLOBALFIELD Pervasives, 3 - 2170 APPTERM1 2 - 2172 ACC0 - 2173 PUSHCONST0 - 2174 PUSHENVACC1 - 2175 APPTERM2 3 - 2177 CLOSUREREC 0, 1200 - 2181 ACC0 - 2182 CLOSURE 1, 2172 - 2185 PUSH - 2186 CLOSURE 0, 2158 - 2189 PUSH - 2190 CLOSURE 0, 2144 - 2193 PUSH - 2194 CLOSUREREC 0, 1217 - 2198 GETGLOBALFIELD Pervasives, 16 - 2201 PUSH - 2202 CLOSUREREC 0, 1259 - 2206 ACC0 - 2207 CLOSURE 1, 2139 - 2210 PUSH - 2211 CLOSUREREC 0, 1277 - 2215 CLOSUREREC 0, 1294 - 2219 CLOSURE 0, 2127 - 2222 PUSH - 2223 CLOSUREREC 0, 1316 - 2227 CLOSUREREC 0, 1334 - 2231 CLOSUREREC 0, 1354 - 2235 CLOSUREREC 0, 1374 - 2239 CLOSURE 0, 2092 - 2242 PUSH - 2243 CLOSUREREC 0, 1415 - 2247 CLOSUREREC 0, 1452 - 2251 CLOSUREREC 0, 1490 - 2255 CLOSUREREC 0, 1530 - 2259 CLOSUREREC 0, 1553 - 2263 CLOSUREREC 0, 1573 - 2267 CLOSUREREC 0, 1613 - 2271 CLOSUREREC 0, 1654 - 2275 CLOSUREREC 0, 1675 - 2279 CLOSUREREC 0, 1695 - 2283 CLOSUREREC 0, 1725 - 2287 CLOSUREREC 0, 1754 - 2291 CLOSUREREC 0, 1776 - 2295 CLOSUREREC 0, 1797 - 2299 CLOSUREREC 0, 1828 - 2303 CLOSUREREC 0, 1858 - 2307 ACC 24 - 2309 CLOSURE 1, 2042 - 2312 PUSHACC 25 - 2314 CLOSUREREC 1, 1928 - 2318 CLOSUREREC 0, 1942 - 2322 CLOSUREREC 0, 1972 - 2326 ACC0 - 2327 PUSHACC2 - 2328 PUSHACC7 - 2329 PUSHACC 9 - 2331 PUSHACC 11 - 2333 PUSHACC 13 - 2335 PUSHACC 15 - 2337 PUSHACC 17 - 2339 PUSHACC 10 - 2341 PUSHACC 12 - 2343 PUSHACC 13 - 2345 PUSHACC 15 - 2347 PUSHACC 23 - 2349 PUSHACC 25 - 2351 PUSHACC 27 - 2353 PUSHACC 29 - 2355 PUSHACC 31 - 2357 PUSHACC 33 - 2359 PUSHACC 35 - 2361 PUSHACC 37 - 2363 PUSHACC 40 - 2365 PUSHACC 42 - 2367 PUSHACC 41 - 2369 PUSHACC 45 - 2371 PUSHACC 47 - 2373 PUSHACC 50 - 2375 PUSHACC 52 - 2377 PUSHACC 51 - 2379 PUSHACC 55 - 2381 PUSHACC 56 - 2383 PUSHACC 59 - 2385 PUSHACC 61 - 2387 PUSHACC 60 - 2389 PUSHACC 64 - 2391 PUSHACC 66 - 2393 PUSHACC 68 - 2395 PUSHACC 70 - 2397 MAKEBLOCK 37, 0 - 2400 POP 36 - 2402 SETGLOBAL List - 2404 BRANCH 2622 - 2406 CONSTINT 97 - 2408 PUSHACC1 - 2409 GEINT - 2410 BRANCHIFNOT 2418 - 2412 CONSTINT 122 - 2414 PUSHACC1 - 2415 LEINT - 2416 BRANCHIF 2442 - 2418 CONSTINT 224 - 2420 PUSHACC1 - 2421 GEINT - 2422 BRANCHIFNOT 2430 - 2424 CONSTINT 246 - 2426 PUSHACC1 - 2427 LEINT - 2428 BRANCHIF 2442 - 2430 CONSTINT 248 - 2432 PUSHACC1 - 2433 GEINT - 2434 BRANCHIFNOT 2447 - 2436 CONSTINT 254 - 2438 PUSHACC1 - 2439 LEINT - 2440 BRANCHIFNOT 2447 - 2442 ACC0 - 2443 OFFSETINT -32 - 2445 RETURN 1 - 2447 ACC0 - 2448 RETURN 1 - 2450 CONSTINT 65 - 2452 PUSHACC1 - 2453 GEINT - 2454 BRANCHIFNOT 2462 - 2456 CONSTINT 90 - 2458 PUSHACC1 - 2459 LEINT - 2460 BRANCHIF 2486 - 2462 CONSTINT 192 - 2464 PUSHACC1 - 2465 GEINT - 2466 BRANCHIFNOT 2474 - 2468 CONSTINT 214 - 2470 PUSHACC1 - 2471 LEINT - 2472 BRANCHIF 2486 - 2474 CONSTINT 216 - 2476 PUSHACC1 - 2477 GEINT - 2478 BRANCHIFNOT 2491 - 2480 CONSTINT 222 - 2482 PUSHACC1 - 2483 LEINT - 2484 BRANCHIFNOT 2491 - 2486 ACC0 - 2487 OFFSETINT 32 - 2489 RETURN 1 - 2491 ACC0 - 2492 RETURN 1 - 2494 CONSTINT 39 - 2496 PUSHACC1 - 2497 LTINT - 2498 BRANCHIFNOT 2520 - 2500 CONSTINT 9 - 2502 PUSHACC1 - 2503 EQ - 2504 BRANCHIFNOT 2510 - 2506 GETGLOBAL "\\t" - 2508 RETURN 1 - 2510 CONSTINT 13 - 2512 PUSHACC1 - 2513 EQ - 2514 BRANCHIFNOT 2540 - 2516 GETGLOBAL "\\n" - 2518 RETURN 1 - 2520 CONSTINT 39 - 2522 PUSHACC1 - 2523 EQ - 2524 BRANCHIFNOT 2530 - 2526 GETGLOBAL "\\'" - 2528 RETURN 1 - 2530 CONSTINT 92 - 2532 PUSHACC1 - 2533 EQ - 2534 BRANCHIFNOT 2540 - 2536 GETGLOBAL "\\\\" - 2538 RETURN 1 - 2540 ACC0 - 2541 C_CALL1 is_printable - 2543 BRANCHIFNOT 2555 - 2545 CONST1 - 2546 C_CALL1 create_string - 2548 PUSHACC1 - 2549 PUSHCONST0 - 2550 PUSHACC2 - 2551 SETSTRINGCHAR - 2552 ACC0 - 2553 RETURN 2 - 2555 ACC0 - 2556 PUSHCONSTINT 4 - 2558 C_CALL1 create_string - 2560 PUSHCONSTINT 92 - 2562 PUSHCONST0 - 2563 PUSHACC2 - 2564 SETSTRINGCHAR - 2565 CONSTINT 100 - 2567 PUSHACC2 - 2568 DIVINT - 2569 PUSHCONSTINT 48 - 2571 ADDINT - 2572 PUSHCONST1 - 2573 PUSHACC2 - 2574 SETSTRINGCHAR - 2575 CONSTINT 10 - 2577 PUSHCONSTINT 10 - 2579 PUSHACC3 - 2580 DIVINT - 2581 MODINT - 2582 PUSHCONSTINT 48 - 2584 ADDINT - 2585 PUSHCONST2 - 2586 PUSHACC2 - 2587 SETSTRINGCHAR - 2588 CONSTINT 10 - 2590 PUSHACC2 - 2591 MODINT - 2592 PUSHCONSTINT 48 - 2594 ADDINT - 2595 PUSHCONST3 - 2596 PUSHACC2 - 2597 SETSTRINGCHAR - 2598 ACC0 - 2599 RETURN 3 - 2601 CONST0 - 2602 PUSHACC1 - 2603 LTINT - 2604 BRANCHIF 2612 - 2606 CONSTINT 255 - 2608 PUSHACC1 - 2609 GTINT - 2610 BRANCHIFNOT 2619 - 2612 GETGLOBAL "Char.chr" - 2614 PUSHGETGLOBALFIELD Pervasives, 2 - 2617 APPTERM1 2 - 2619 ACC0 - 2620 RETURN 1 - 2622 CLOSURE 0, 2601 - 2625 PUSH - 2626 CLOSURE 0, 2494 - 2629 PUSH - 2630 CLOSURE 0, 2450 - 2633 PUSH - 2634 CLOSURE 0, 2406 - 2637 PUSHACC0 - 2638 PUSHACC2 - 2639 PUSHACC4 - 2640 PUSHACC6 - 2641 MAKEBLOCK 4, 0 - 2644 POP 4 - 2646 SETGLOBAL Char - 2648 BRANCH 3540 - 2650 RESTART - 2651 GRAB 3 - 2653 ACC1 - 2654 PUSHACC3 - 2655 GEINT - 2656 BRANCHIFNOT 2663 - 2658 GETGLOBAL Not_found - 2660 MAKEBLOCK1 0 - 2662 RAISE - 2663 ACC3 - 2664 PUSHACC3 - 2665 PUSHACC2 - 2666 GETSTRINGCHAR - 2667 EQ - 2668 BRANCHIFNOT 2673 - 2670 ACC2 - 2671 RETURN 4 - 2673 ACC3 - 2674 PUSHACC3 - 2675 OFFSETINT 1 - 2677 PUSHACC3 - 2678 PUSHACC3 - 2679 PUSHOFFSETCLOSURE0 - 2680 APPTERM 4, 8 - 2683 RESTART - 2684 GRAB 2 - 2686 CONST0 - 2687 PUSHACC2 - 2688 LTINT - 2689 BRANCHIFNOT 2696 - 2691 GETGLOBAL Not_found - 2693 MAKEBLOCK1 0 - 2695 RAISE - 2696 ACC2 - 2697 PUSHACC2 - 2698 PUSHACC2 - 2699 GETSTRINGCHAR - 2700 EQ - 2701 BRANCHIFNOT 2706 - 2703 ACC1 - 2704 RETURN 3 - 2706 ACC2 - 2707 PUSHACC2 - 2708 OFFSETINT -1 - 2710 PUSHACC2 - 2711 PUSHOFFSETCLOSURE0 - 2712 APPTERM3 6 - 2714 RESTART - 2715 GRAB 1 - 2717 ACC1 - 2718 PUSHCONST0 - 2719 PUSHACC2 - 2720 PUSHENVACC1 - 2721 APPTERM3 5 - 2723 RESTART - 2724 GRAB 2 - 2726 CONST0 - 2727 PUSHACC2 - 2728 LTINT - 2729 BRANCHIF 2738 - 2731 ACC0 - 2732 C_CALL1 ml_string_length - 2734 PUSHACC2 - 2735 GEINT - 2736 BRANCHIFNOT 2745 - 2738 GETGLOBAL "String.rcontains_from" - 2740 PUSHGETGLOBALFIELD Pervasives, 2 - 2743 APPTERM1 4 - 2745 PUSHTRAP 2756 - 2747 ACC6 - 2748 PUSHACC6 - 2749 PUSHACC6 - 2750 PUSHENVACC1 - 2751 APPLY3 - 2752 CONST1 - 2753 POPTRAP - 2754 RETURN 3 - 2756 PUSHGETGLOBAL Not_found - 2758 PUSHACC1 - 2759 GETFIELD0 - 2760 EQ - 2761 BRANCHIFNOT 2766 - 2763 CONST0 - 2764 RETURN 4 - 2766 ACC0 - 2767 RAISE - 2768 RESTART - 2769 GRAB 2 - 2771 CONST0 - 2772 PUSHACC2 - 2773 LTINT - 2774 BRANCHIF 2783 - 2776 ACC0 - 2777 C_CALL1 ml_string_length - 2779 PUSHACC2 - 2780 GTINT - 2781 BRANCHIFNOT 2790 - 2783 GETGLOBAL "String.contains_from" - 2785 PUSHGETGLOBALFIELD Pervasives, 2 - 2788 APPTERM1 4 - 2790 PUSHTRAP 2811 - 2792 PUSH_RETADDR 2807 - 2794 ACC 9 - 2796 PUSHACC 9 - 2798 PUSHACC 9 - 2800 C_CALL1 ml_string_length - 2802 PUSHACC 10 - 2804 PUSHENVACC1 - 2805 APPLY 4 - 2807 CONST1 - 2808 POPTRAP - 2809 RETURN 3 - 2811 PUSHGETGLOBAL Not_found - 2813 PUSHACC1 - 2814 GETFIELD0 - 2815 EQ - 2816 BRANCHIFNOT 2821 - 2818 CONST0 - 2819 RETURN 4 - 2821 ACC0 - 2822 RAISE - 2823 RESTART - 2824 GRAB 2 - 2826 CONST0 - 2827 PUSHACC2 - 2828 LTINT - 2829 BRANCHIF 2838 - 2831 ACC0 - 2832 C_CALL1 ml_string_length - 2834 PUSHACC2 - 2835 GEINT - 2836 BRANCHIFNOT 2845 - 2838 GETGLOBAL "String.rindex_from" - 2840 PUSHGETGLOBALFIELD Pervasives, 2 - 2843 APPTERM1 4 - 2845 ACC2 - 2846 PUSHACC2 - 2847 PUSHACC2 - 2848 PUSHENVACC1 - 2849 APPTERM3 6 - 2851 RESTART - 2852 GRAB 1 - 2854 ACC1 - 2855 PUSHACC1 - 2856 C_CALL1 ml_string_length - 2858 OFFSETINT -1 - 2860 PUSHACC2 - 2861 PUSHENVACC1 - 2862 APPTERM3 5 - 2864 RESTART - 2865 GRAB 2 - 2867 CONST0 - 2868 PUSHACC2 - 2869 LTINT - 2870 BRANCHIF 2879 - 2872 ACC0 - 2873 C_CALL1 ml_string_length - 2875 PUSHACC2 - 2876 GTINT - 2877 BRANCHIFNOT 2886 - 2879 GETGLOBAL "String.index_from" - 2881 PUSHGETGLOBALFIELD Pervasives, 2 - 2884 APPTERM1 4 - 2886 ACC2 - 2887 PUSHACC2 - 2888 PUSHACC2 - 2889 C_CALL1 ml_string_length - 2891 PUSHACC3 - 2892 PUSHENVACC1 - 2893 APPTERM 4, 7 - 2896 RESTART - 2897 GRAB 1 - 2899 ACC1 - 2900 PUSHCONST0 - 2901 PUSHACC2 - 2902 C_CALL1 ml_string_length - 2904 PUSHACC3 - 2905 PUSHENVACC1 - 2906 APPTERM 4, 6 - 2909 ACC0 - 2910 PUSHGETGLOBALFIELD Char, 2 - 2913 PUSHENVACC1 - 2914 APPTERM2 3 - 2916 ACC0 - 2917 PUSHGETGLOBALFIELD Char, 3 - 2920 PUSHENVACC1 - 2921 APPTERM2 3 - 2923 RESTART - 2924 GRAB 1 - 2926 CONST0 - 2927 PUSHACC2 - 2928 C_CALL1 ml_string_length - 2930 EQ - 2931 BRANCHIFNOT 2936 - 2933 ACC1 - 2934 RETURN 2 - 2936 ACC1 - 2937 PUSHENVACC1 - 2938 APPLY1 - 2939 PUSHCONST0 - 2940 PUSHACC3 - 2941 GETSTRINGCHAR - 2942 PUSHACC2 - 2943 APPLY1 - 2944 PUSHCONST0 - 2945 PUSHACC2 - 2946 SETSTRINGCHAR - 2947 ACC0 - 2948 RETURN 3 - 2950 ACC0 - 2951 PUSHGETGLOBALFIELD Char, 2 - 2954 PUSHENVACC1 - 2955 APPTERM2 3 - 2957 ACC0 - 2958 PUSHGETGLOBALFIELD Char, 3 - 2961 PUSHENVACC1 - 2962 APPTERM2 3 - 2964 RESTART - 2965 GRAB 1 - 2967 ACC1 - 2968 C_CALL1 ml_string_length - 2970 PUSHCONST0 - 2971 PUSHACC1 - 2972 EQ - 2973 BRANCHIFNOT 2978 - 2975 ACC2 - 2976 RETURN 3 - 2978 ACC0 - 2979 C_CALL1 create_string - 2981 PUSHCONST0 - 2982 PUSHACC2 - 2983 OFFSETINT -1 - 2985 PUSH - 2986 BRANCH 3002 - 2988 CHECK_SIGNALS - 2989 ACC1 - 2990 PUSHACC6 - 2991 GETSTRINGCHAR - 2992 PUSHACC5 - 2993 APPLY1 - 2994 PUSHACC2 - 2995 PUSHACC4 - 2996 SETSTRINGCHAR - 2997 ACC1 - 2998 OFFSETINT 1 - 3000 ASSIGN 1 - 3002 ACC0 - 3003 PUSHACC2 - 3004 LEINT - 3005 BRANCHIF 2988 - 3007 CONST0 - 3008 POP 2 - 3010 ACC0 - 3011 RETURN 4 - 3013 CONST0 - 3014 PUSHCONST0 - 3015 PUSHACC2 - 3016 C_CALL1 ml_string_length - 3018 OFFSETINT -1 - 3020 PUSH - 3021 BRANCH 3059 - 3023 CHECK_SIGNALS - 3024 ACC1 - 3025 PUSHACC4 - 3026 GETSTRINGCHAR - 3027 PUSHACC0 - 3028 PUSHGETGLOBAL "\000\"\000\000\004\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - 3030 C_CALL2 bitvect_test - 3032 BRANCHIFNOT 3038 - 3034 CONST0 - 3035 CONST2 - 3036 BRANCH 3048 - 3038 ACC0 - 3039 C_CALL1 is_printable - 3041 BRANCHIFNOT 3046 - 3043 CONST1 - 3044 BRANCH 3048 - 3046 CONSTINT 4 - 3048 POP 1 - 3050 PUSHACC3 - 3051 ADDINT - 3052 ASSIGN 2 - 3054 ACC1 - 3055 OFFSETINT 1 - 3057 ASSIGN 1 - 3059 ACC0 - 3060 PUSHACC2 - 3061 LEINT - 3062 BRANCHIF 3023 - 3064 CONST0 - 3065 POP 2 - 3067 ACC1 - 3068 C_CALL1 ml_string_length - 3070 PUSHACC1 - 3071 EQ - 3072 BRANCHIFNOT 3077 - 3074 ACC1 - 3075 RETURN 2 - 3077 ACC0 - 3078 C_CALL1 create_string - 3080 PUSHCONST0 - 3081 ASSIGN 1 - 3083 CONST0 - 3084 PUSHACC3 - 3085 C_CALL1 ml_string_length - 3087 OFFSETINT -1 - 3089 PUSH - 3090 BRANCH 3245 - 3092 CHECK_SIGNALS - 3093 ACC1 - 3094 PUSHACC5 - 3095 GETSTRINGCHAR - 3096 PUSHACC0 - 3097 PUSHGETGLOBAL "\000\000\000\000\004\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - 3099 C_CALL2 bitvect_test - 3101 BRANCHIFNOT 3120 - 3103 CONST0 - 3104 CONSTINT 92 - 3106 PUSHACC5 - 3107 PUSHACC5 - 3108 SETSTRINGCHAR - 3109 ACC4 - 3110 OFFSETINT 1 - 3112 ASSIGN 4 - 3114 ACC0 - 3115 PUSHACC5 - 3116 PUSHACC5 - 3117 SETSTRINGCHAR - 3118 BRANCH 3233 - 3120 CONSTINT 9 - 3122 PUSHACC1 - 3123 EQ - 3124 BRANCHIFNOT 3143 - 3126 CONSTINT 92 - 3128 PUSHACC5 - 3129 PUSHACC5 - 3130 SETSTRINGCHAR - 3131 ACC4 - 3132 OFFSETINT 1 - 3134 ASSIGN 4 - 3136 CONSTINT 116 - 3138 PUSHACC5 - 3139 PUSHACC5 - 3140 SETSTRINGCHAR - 3141 BRANCH 3233 - 3143 CONSTINT 13 - 3145 PUSHACC1 - 3146 EQ - 3147 BRANCHIFNOT 3166 - 3149 CONSTINT 92 - 3151 PUSHACC5 - 3152 PUSHACC5 - 3153 SETSTRINGCHAR - 3154 ACC4 - 3155 OFFSETINT 1 - 3157 ASSIGN 4 - 3159 CONSTINT 110 - 3161 PUSHACC5 - 3162 PUSHACC5 - 3163 SETSTRINGCHAR - 3164 BRANCH 3233 - 3166 ACC0 - 3167 C_CALL1 is_printable - 3169 BRANCHIFNOT 3177 - 3171 ACC0 - 3172 PUSHACC5 - 3173 PUSHACC5 - 3174 SETSTRINGCHAR - 3175 BRANCH 3233 - 3177 ACC0 - 3178 PUSHCONSTINT 92 - 3180 PUSHACC6 - 3181 PUSHACC6 - 3182 SETSTRINGCHAR - 3183 ACC5 - 3184 OFFSETINT 1 - 3186 ASSIGN 5 - 3188 CONSTINT 100 - 3190 PUSHACC1 - 3191 DIVINT - 3192 PUSHCONSTINT 48 - 3194 ADDINT - 3195 PUSHACC6 - 3196 PUSHACC6 - 3197 SETSTRINGCHAR - 3198 ACC5 - 3199 OFFSETINT 1 - 3201 ASSIGN 5 - 3203 CONSTINT 10 - 3205 PUSHCONSTINT 10 - 3207 PUSHACC2 - 3208 DIVINT - 3209 MODINT - 3210 PUSHCONSTINT 48 - 3212 ADDINT - 3213 PUSHACC6 - 3214 PUSHACC6 - 3215 SETSTRINGCHAR - 3216 ACC5 - 3217 OFFSETINT 1 - 3219 ASSIGN 5 - 3221 CONSTINT 10 - 3223 PUSHACC1 - 3224 MODINT - 3225 PUSHCONSTINT 48 - 3227 ADDINT - 3228 PUSHACC6 - 3229 PUSHACC6 - 3230 SETSTRINGCHAR - 3231 POP 1 - 3233 POP 1 - 3235 ACC3 - 3236 OFFSETINT 1 - 3238 ASSIGN 3 - 3240 ACC1 - 3241 OFFSETINT 1 - 3243 ASSIGN 1 - 3245 ACC0 - 3246 PUSHACC2 - 3247 LEINT - 3248 BRANCHIF 3092 - 3250 CONST0 - 3251 POP 2 - 3253 ACC0 - 3254 RETURN 3 - 3256 ENVACC1 - 3257 C_CALL1 ml_string_length - 3259 PUSHENVACC3 - 3260 GETFIELD0 - 3261 PUSHENVACC2 - 3262 PUSHCONST0 - 3263 PUSHENVACC1 - 3264 C_CALL5 blit_string - 3266 ENVACC1 - 3267 C_CALL1 ml_string_length - 3269 PUSHENVACC3 - 3270 GETFIELD0 - 3271 ADDINT - 3272 PUSHENVACC3 - 3273 SETFIELD0 - 3274 ACC0 - 3275 C_CALL1 ml_string_length - 3277 PUSHENVACC3 - 3278 GETFIELD0 - 3279 PUSHENVACC2 - 3280 PUSHCONST0 - 3281 PUSHACC4 - 3282 C_CALL5 blit_string - 3284 ACC0 - 3285 C_CALL1 ml_string_length - 3287 PUSHENVACC3 - 3288 GETFIELD0 - 3289 ADDINT - 3290 PUSHENVACC3 - 3291 SETFIELD0 - 3292 RETURN 1 - 3294 ENVACC1 - 3295 OFFSETREF 1 - 3297 ACC0 - 3298 C_CALL1 ml_string_length - 3300 PUSHENVACC2 - 3301 GETFIELD0 - 3302 ADDINT - 3303 PUSHENVACC2 - 3304 SETFIELD0 - 3305 RETURN 1 - 3307 RESTART - 3308 GRAB 1 - 3310 ACC1 - 3311 BRANCHIFNOT 3374 - 3313 ACC1 - 3314 GETFIELD0 - 3315 PUSHCONST0 - 3316 MAKEBLOCK1 0 - 3318 PUSHCONST0 - 3319 MAKEBLOCK1 0 - 3321 PUSHACC4 - 3322 PUSHACC1 - 3323 PUSHACC3 - 3324 CLOSURE 2, 3294 - 3327 PUSHGETGLOBALFIELD List, 9 - 3330 APPLY2 - 3331 ACC1 - 3332 GETFIELD0 - 3333 OFFSETINT -1 - 3335 PUSHACC4 - 3336 C_CALL1 ml_string_length - 3338 MULINT - 3339 PUSHACC1 - 3340 GETFIELD0 - 3341 ADDINT - 3342 C_CALL1 create_string - 3344 PUSHACC3 - 3345 C_CALL1 ml_string_length - 3347 PUSHCONST0 - 3348 PUSHACC2 - 3349 PUSHCONST0 - 3350 PUSHACC7 - 3351 C_CALL5 blit_string - 3353 ACC3 - 3354 C_CALL1 ml_string_length - 3356 MAKEBLOCK1 0 - 3358 PUSHACC6 - 3359 GETFIELD1 - 3360 PUSHACC1 - 3361 PUSHACC3 - 3362 PUSHACC 8 - 3364 CLOSURE 3, 3256 - 3367 PUSHGETGLOBALFIELD List, 9 - 3370 APPLY2 - 3371 ACC1 - 3372 RETURN 7 - 3374 GETGLOBAL "" - 3376 RETURN 2 - 3378 RESTART - 3379 GRAB 4 - 3381 CONST0 - 3382 PUSHACC5 - 3383 LTINT - 3384 BRANCHIF 3414 - 3386 CONST0 - 3387 PUSHACC2 - 3388 LTINT - 3389 BRANCHIF 3414 - 3391 ACC0 - 3392 C_CALL1 ml_string_length - 3394 PUSHACC5 - 3395 PUSHACC3 - 3396 ADDINT - 3397 GTINT - 3398 BRANCHIF 3414 - 3400 CONST0 - 3401 PUSHACC4 - 3402 LTINT - 3403 BRANCHIF 3414 - 3405 ACC2 - 3406 C_CALL1 ml_string_length - 3408 PUSHACC5 - 3409 PUSHACC5 - 3410 ADDINT - 3411 GTINT - 3412 BRANCHIFNOT 3421 - 3414 GETGLOBAL "String.blit" - 3416 PUSHGETGLOBALFIELD Pervasives, 2 - 3419 APPTERM1 6 - 3421 ACC4 - 3422 PUSHACC4 - 3423 PUSHACC4 - 3424 PUSHACC4 - 3425 PUSHACC4 - 3426 C_CALL5 blit_string - 3428 RETURN 5 - 3430 RESTART - 3431 GRAB 3 - 3433 CONST0 - 3434 PUSHACC2 - 3435 LTINT - 3436 BRANCHIF 3452 - 3438 CONST0 - 3439 PUSHACC3 - 3440 LTINT - 3441 BRANCHIF 3452 - 3443 ACC0 - 3444 C_CALL1 ml_string_length - 3446 PUSHACC3 - 3447 PUSHACC3 - 3448 ADDINT - 3449 GTINT - 3450 BRANCHIFNOT 3459 - 3452 GETGLOBAL "String.fill" - 3454 PUSHGETGLOBALFIELD Pervasives, 2 - 3457 APPTERM1 5 - 3459 ACC3 - 3460 PUSHACC3 - 3461 PUSHACC3 - 3462 PUSHACC3 - 3463 C_CALL4 fill_string - 3465 RETURN 4 - 3467 RESTART - 3468 GRAB 2 - 3470 CONST0 - 3471 PUSHACC2 - 3472 LTINT - 3473 BRANCHIF 3489 - 3475 CONST0 - 3476 PUSHACC3 - 3477 LTINT - 3478 BRANCHIF 3489 - 3480 ACC0 - 3481 C_CALL1 ml_string_length - 3483 PUSHACC3 - 3484 PUSHACC3 - 3485 ADDINT - 3486 GTINT - 3487 BRANCHIFNOT 3496 - 3489 GETGLOBAL "String.sub" - 3491 PUSHGETGLOBALFIELD Pervasives, 2 - 3494 APPTERM1 4 - 3496 ACC2 - 3497 C_CALL1 create_string - 3499 PUSHACC3 - 3500 PUSHCONST0 - 3501 PUSHACC2 - 3502 PUSHACC5 - 3503 PUSHACC5 - 3504 C_CALL5 blit_string - 3506 ACC0 - 3507 RETURN 4 - 3509 ACC0 - 3510 C_CALL1 ml_string_length - 3512 PUSHACC0 - 3513 C_CALL1 create_string - 3515 PUSHACC1 - 3516 PUSHCONST0 - 3517 PUSHACC2 - 3518 PUSHCONST0 - 3519 PUSHACC6 - 3520 C_CALL5 blit_string - 3522 ACC0 - 3523 RETURN 3 - 3525 RESTART - 3526 GRAB 1 - 3528 ACC0 - 3529 C_CALL1 create_string - 3531 PUSHACC2 - 3532 PUSHACC2 - 3533 PUSHCONST0 - 3534 PUSHACC3 - 3535 C_CALL4 fill_string - 3537 ACC0 - 3538 RETURN 3 - 3540 CLOSURE 0, 3526 - 3543 PUSH - 3544 CLOSURE 0, 3509 - 3547 PUSH - 3548 CLOSURE 0, 3468 - 3551 PUSH - 3552 CLOSURE 0, 3431 - 3555 PUSH - 3556 CLOSURE 0, 3379 - 3559 PUSH - 3560 CLOSURE 0, 3308 - 3563 PUSH - 3564 CLOSURE 0, 3013 - 3567 PUSH - 3568 CLOSURE 0, 2965 - 3571 PUSHACC0 - 3572 CLOSURE 1, 2957 - 3575 PUSHACC1 - 3576 CLOSURE 1, 2950 - 3579 PUSHACC 8 - 3581 CLOSURE 1, 2924 - 3584 PUSHACC0 - 3585 CLOSURE 1, 2916 - 3588 PUSHACC1 - 3589 CLOSURE 1, 2909 - 3592 PUSH - 3593 CLOSUREREC 0, 2651 - 3597 ACC0 - 3598 CLOSURE 1, 2897 - 3601 PUSHACC1 - 3602 CLOSURE 1, 2865 - 3605 PUSH - 3606 CLOSUREREC 0, 2684 - 3610 ACC0 - 3611 CLOSURE 1, 2852 - 3614 PUSHACC1 - 3615 CLOSURE 1, 2824 - 3618 PUSHACC5 - 3619 CLOSURE 1, 2769 - 3622 PUSHACC3 - 3623 CLOSURE 1, 2724 - 3626 PUSHACC1 - 3627 CLOSURE 1, 2715 - 3630 PUSHACC 9 - 3632 PUSHACC 11 - 3634 PUSHACC 14 - 3636 PUSHACC 16 - 3638 PUSHACC5 - 3639 PUSHACC7 - 3640 PUSHACC6 - 3641 PUSHACC 10 - 3643 PUSHACC 14 - 3645 PUSHACC 13 - 3647 PUSHACC 17 - 3649 PUSHACC 26 - 3651 PUSHACC 28 - 3653 PUSHACC 30 - 3655 PUSHACC 32 - 3657 PUSHACC 34 - 3659 PUSHACC 36 - 3661 PUSHACC 38 - 3663 MAKEBLOCK 18, 0 - 3666 POP 22 - 3668 SETGLOBAL String - 3670 CONST0 - 3671 C_CALL1 gc_stat - 3673 GETGLOBAL "" - 3675 PUSHCONSTINT 20 - 3677 C_CALL2 make_vect - 3679 PUSHCONSTINT 20 - 3681 C_CALL1 weak_create - 3683 PUSHCONST0 - 3684 PUSHCONSTINT 19 - 3686 PUSH - 3687 BRANCH 3715 - 3689 CHECK_SIGNALS - 3690 CONSTINT 115 - 3692 PUSHCONSTINT 20 - 3694 PUSHGETGLOBALFIELD String, 0 - 3697 APPLY2 - 3698 PUSHACC2 - 3699 PUSHACC5 - 3700 SETVECTITEM - 3701 ACC1 - 3702 PUSHACC4 - 3703 GETVECTITEM - 3704 MAKEBLOCK1 0 - 3706 PUSHACC2 - 3707 PUSHACC4 - 3708 C_CALL3 weak_set - 3710 ACC1 - 3711 OFFSETINT 1 - 3713 ASSIGN 1 - 3715 ACC0 - 3716 PUSHACC2 - 3717 LEINT - 3718 BRANCHIF 3689 - 3720 CONST0 - 3721 POP 2 - 3723 CONST0 - 3724 C_CALL1 gc_full_major - 3726 CONST0 - 3727 PUSHCONSTINT 19 - 3729 PUSH - 3730 BRANCH 3753 - 3732 CHECK_SIGNALS - 3733 ACC1 - 3734 PUSHACC3 - 3735 C_CALL2 weak_get - 3737 PUSHACC0 - 3738 BRANCHIF 3745 - 3740 GETGLOBAL Not_found - 3742 MAKEBLOCK1 0 - 3744 RAISE - 3745 CONST0 - 3746 POP 1 - 3748 ACC1 - 3749 OFFSETINT 1 - 3751 ASSIGN 1 - 3753 ACC0 - 3754 PUSHACC2 - 3755 LEINT - 3756 BRANCHIF 3732 - 3758 CONST0 - 3759 POP 2 - 3761 CONST0 - 3762 PUSHCONSTINT 19 - 3764 PUSH - 3765 BRANCH 3785 - 3767 CHECK_SIGNALS - 3768 CONST0 - 3769 PUSHCONST2 - 3770 PUSHACC3 - 3771 MODINT - 3772 EQ - 3773 BRANCHIFNOT 3780 - 3775 GETGLOBAL "" - 3777 PUSHACC2 - 3778 PUSHACC5 - 3779 SETVECTITEM - 3780 ACC1 - 3781 OFFSETINT 1 - 3783 ASSIGN 1 - 3785 ACC0 - 3786 PUSHACC2 - 3787 LEINT - 3788 BRANCHIF 3767 - 3790 CONST0 - 3791 POP 2 - 3793 CONST0 - 3794 C_CALL1 gc_full_major - 3796 CONST0 - 3797 PUSHCONSTINT 19 - 3799 PUSH - 3800 BRANCH 3854 - 3802 CHECK_SIGNALS - 3803 ACC1 - 3804 PUSHACC3 - 3805 C_CALL2 weak_get - 3807 PUSHACC0 - 3808 BRANCHIFNOT 3832 - 3810 CONST1 - 3811 PUSHCONST2 - 3812 PUSHACC4 - 3813 MODINT - 3814 EQ - 3815 BRANCHIFNOT 3842 - 3817 CONSTINT 115 - 3819 PUSHCONSTINT 5 - 3821 PUSHACC2 - 3822 GETFIELD0 - 3823 GETSTRINGCHAR - 3824 NEQ - 3825 BRANCHIFNOT 3847 - 3827 GETGLOBAL Not_found - 3829 MAKEBLOCK1 0 - 3831 RAISE - 3832 CONST0 - 3833 PUSHCONST2 - 3834 PUSHACC4 - 3835 MODINT - 3836 EQ - 3837 BRANCHIFNOT 3842 - 3839 CONST0 - 3840 BRANCH 3847 - 3842 GETGLOBAL Not_found - 3844 MAKEBLOCK1 0 - 3846 RAISE - 3847 POP 1 - 3849 ACC1 - 3850 OFFSETINT 1 - 3852 ASSIGN 1 - 3854 ACC0 - 3855 PUSHACC2 - 3856 LEINT - 3857 BRANCHIF 3802 - 3859 CONST0 - 3860 POP 4 - 3862 ATOM0 - 3863 SETGLOBAL T350-heapcheck - 3865 STOP -**) diff --git a/testsuite/tests/tool-ocaml/t360-stacks-1.ml b/testsuite/tests/tool-ocaml/t360-stacks-1.ml index 100fbabb..2c257a79 100644 --- a/testsuite/tests/tool-ocaml/t360-stacks-1.ml +++ b/testsuite/tests/tool-ocaml/t360-stacks-1.ml @@ -8,36 +8,36 @@ if f 30000 <> 30012 then raise Not_found (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 29 - 11 CONST0 - 12 PUSHACC1 - 13 LEINT + 11 CONST0 + 12 PUSHACC1 + 13 LEINT 14 BRANCHIFNOT 20 16 CONSTINT 12 18 RETURN 1 - 20 ACC0 + 20 ACC0 21 OFFSETINT -1 - 23 PUSHOFFSETCLOSURE0 - 24 APPLY1 - 25 PUSHCONST1 - 26 ADDINT + 23 PUSHOFFSETCLOSURE0 + 24 APPLY1 + 25 PUSHCONST1 + 26 ADDINT 27 RETURN 1 29 CLOSUREREC 0, 11 33 CONSTINT 30012 35 PUSHCONSTINT 30000 - 37 PUSHACC2 - 38 APPLY1 - 39 NEQ + 37 PUSHACC2 + 38 APPLY1 + 39 NEQ 40 BRANCHIFNOT 47 42 GETGLOBAL Not_found 44 MAKEBLOCK1 0 - 46 RAISE + 46 RAISE 47 POP 1 - 49 ATOM0 + 49 ATOM0 50 SETGLOBAL T360-stacks-1 - 52 STOP + 52 STOP **) diff --git a/testsuite/tests/tool-ocaml/t360-stacks-2.ml b/testsuite/tests/tool-ocaml/t360-stacks-2.ml index 8d13c7d7..88a884c7 100644 --- a/testsuite/tests/tool-ocaml/t360-stacks-2.ml +++ b/testsuite/tests/tool-ocaml/t360-stacks-2.ml @@ -11,44 +11,44 @@ with Stack_overflow -> () (** 0 CONSTINT 42 - 2 PUSHACC0 + 2 PUSHACC0 3 MAKEBLOCK1 0 5 POP 1 7 SETGLOBAL Lib 9 BRANCH 29 - 11 CONST0 - 12 PUSHACC1 - 13 LEINT + 11 CONST0 + 12 PUSHACC1 + 13 LEINT 14 BRANCHIFNOT 20 16 CONSTINT 12 18 RETURN 1 - 20 ACC0 + 20 ACC0 21 OFFSETINT -1 - 23 PUSHOFFSETCLOSURE0 - 24 APPLY1 - 25 PUSHCONST1 - 26 ADDINT + 23 PUSHOFFSETCLOSURE0 + 24 APPLY1 + 25 PUSHCONST1 + 26 ADDINT 27 RETURN 1 29 CLOSUREREC 0, 11 33 PUSHTRAP 44 35 CONSTINT 3000000 - 37 PUSHACC5 - 38 APPLY1 + 37 PUSHACC5 + 38 APPLY1 39 GETGLOBAL Not_found 41 MAKEBLOCK1 0 - 43 RAISE + 43 RAISE 44 PUSHGETGLOBAL Stack_overflow - 46 PUSHACC1 - 47 GETFIELD0 - 48 EQ + 46 PUSHACC1 + 47 GETFIELD0 + 48 EQ 49 BRANCHIFNOT 54 - 51 CONST0 + 51 CONST0 52 BRANCH 56 - 54 ACC0 - 55 RAISE + 54 ACC0 + 55 RAISE 56 POP 1 58 POP 1 - 60 ATOM0 + 60 ATOM0 61 SETGLOBAL T360-stacks-2 - 63 STOP + 63 STOP **) diff --git a/testsuite/tests/tool-ocamldep-modalias/A.ml b/testsuite/tests/tool-ocamldep-modalias/A.ml new file mode 100644 index 00000000..9faa225a --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/A.ml @@ -0,0 +1 @@ +let f x = x +1 diff --git a/testsuite/tests/tool-ocamldep-modalias/B.ml b/testsuite/tests/tool-ocamldep-modalias/B.ml new file mode 100644 index 00000000..17d27a3e --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/B.ml @@ -0,0 +1,2 @@ +open Packed +let g = A.f diff --git a/testsuite/tests/tool-ocamldep-modalias/C.ml b/testsuite/tests/tool-ocamldep-modalias/C.ml new file mode 100644 index 00000000..87cb814d --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/C.ml @@ -0,0 +1,2 @@ +open Lib +let h x = A.f x + B.g x diff --git a/testsuite/tests/tool-ocamldep-modalias/D.ml b/testsuite/tests/tool-ocamldep-modalias/D.ml new file mode 100644 index 00000000..9f192def --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/D.ml @@ -0,0 +1 @@ +let z x = imp (x*2) diff --git a/testsuite/tests/tool-ocamldep-modalias/Makefile b/testsuite/tests/tool-ocamldep-modalias/Makefile new file mode 100644 index 00000000..476a8ace --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/Makefile @@ -0,0 +1,73 @@ +# Test for ocamldep and -no-alias-deps +# There are two versions: +# Makefile.build uses -no-alias-deps only for lib.ml/mli +# Makefile.build2 has no lib.ml, and uses -no-alias-deps for components too + +OCAMLDEP=$(OCAMLRUN) $(OTOPDIR)/tools/ocamldep +SOURCES = A.ml B.ml C.ml D.ml +LINKS = $(SOURCES:%=Lib%) +DEPENDS = depend.mk depend.mk2 depend.mod depend.mod2 depend.mod3 + +all: clean + @$(MAKE) build > /dev/null + @$(MAKE) $(DEPENDS) > /dev/null + @$(MAKE) compare + +build: depend.mk depend.mk2 + rm -f $(LINKS) + if $(NATIVECODE_ONLY); then : ; else \ + $(MAKE) -f Makefile.build byte; \ + rm -f *.cm* lib.ml; \ + $(MAKE) -f Makefile.build2 byte; fi + if $(BYTECODE_ONLY); then :; else \ + $(MAKE) -f Makefile.build opt; \ + rm -f *.cm* lib.ml; \ + $(MAKE) -f Makefile.build2 opt; fi + +# Create links for prefixed versions of the components +Lib%.ml: %.ml + cp $< $@ + +# Dependencies for Makefile.build, compiling and linking lib.cmo +depend.mk: $(LINKS) + cp lib_impl.ml lib.ml + $(OCAMLDEP) -as-map lib.ml lib.mli > $@ + $(OCAMLDEP) -map lib.ml -open Lib $(LINKS) >> $@ + +# Dependencies for Makefile.build2, not compiling lib.cmo +depend.mk2: $(LINKS) + rm -f lib.ml + $(OCAMLDEP) -map lib.mli -open Lib \ + $(LINKS) > $@ + +# Others tests for ocamldep +depend.mod: $(LINKS) + cp lib_impl.ml lib.ml + $(OCAMLDEP) -as-map -modules lib.ml lib.mli > $@ + $(OCAMLDEP) -modules -map lib.ml -open Lib $(LINKS) >> $@ + +depend.mod2: $(LINKS) + rm -f lib.ml + $(OCAMLDEP) -modules -map lib.mli $(LINKS) > $@ + +depend.mod3: $(LINKS) + rm -f lib.ml + $(OCAMLDEP) -modules -as-map -map lib.mli -open Lib \ + $(LINKS) > $@ + +promote: + for i in $(DEPENDS); do cp $$i $$i.reference; done + +compare: $(DEPENDS) + @rm -f $(LINKS) lib.ml + @for i in $(DEPENDS); do \ + printf " ... testing '$$i':"; \ + $(DIFF) $$i.reference $$i > /dev/null \ + && echo " => passed" || echo " => failed"; \ + done + +clean: + @rm -f *.cm* *.$(O) *.$(A) $(DEPENDS) $(LINKS) lib.ml *~ *.byt* *.opt* + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-ocamldep-modalias/Makefile.build b/testsuite/tests/tool-ocamldep-modalias/Makefile.build new file mode 100644 index 00000000..17c61dfb --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/Makefile.build @@ -0,0 +1,43 @@ +# Makefile using -no-alias-deps only for lib.ml/mli + +SOURCES = A.ml B.ml C.ml D.ml +OBJECTS = lib.cmo $(SOURCES:%.ml=Lib%.cmo) +NOBJECTS = $(OBJECTS:%.cmo=%.cmx) + +byte: main.byt +opt: main.opt + +main.byt: lib.cma main.cmo + $(OCAMLC) lib.cma main.cmo -o $@ + +lib.ml: lib_impl.ml + cp $< $@ + +lib.cma: $(OBJECTS) + $(OCAMLC) -a -o $@ $(OBJECTS) + +lib.cmi: lib.mli + $(OCAMLC) -c -no-alias-deps -w -49 $< + +lib.cmo: lib.ml + $(OCAMLC) -c -no-alias-deps -w -49 $< + +Lib%.cmo: %.ml + $(OCAMLC) -c -open Lib -o $@ $< + +main.opt: lib.cmxa main.cmx + $(OCAMLOPT) lib.cmxa main.cmx -o $@ + +lib.cmxa: $(NOBJECTS) + $(OCAMLOPT) -a -o $@ $(NOBJECTS) + +lib.cmx: lib.ml + $(OCAMLOPT) -c -no-alias-deps -w -49 $< + +Lib%.cmx: %.ml + $(OCAMLOPT) -c -open Lib -o $@ $< + +include depend.mk + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 b/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 new file mode 100644 index 00000000..a75477b9 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/Makefile.build2 @@ -0,0 +1,38 @@ +# Makefile using -no-alias-deps for all files, no need to link lib.cmo + +SOURCES = A.ml B.ml C.ml +OBJECTS = $(SOURCES:%.ml=Lib%.cmo) +NOBJECTS = $(OBJECTS:%.cmo=%.cmx) + +byte: main.byt2 +opt: main.opt2 + +main.byt2: lib2.cma main.cmo + $(OCAMLC) lib2.cma main.cmo -o $@ + +lib2.cma: $(OBJECTS) + $(OCAMLC) -a -o $@ $(OBJECTS) + +lib.cmi: lib.mli + $(OCAMLC) -c -w -49 $< + +Lib%.cmo: %.ml + $(OCAMLC) -c -open Lib -o $@ $< + +main.opt2: lib.cmxa main.cmx + $(OCAMLOPT) lib.cmxa main.cmx -o $@ + +lib.cmxa: $(NOBJECTS) + $(OCAMLOPT) -a -o $@ $(NOBJECTS) + +lib.cmx: lib.ml + $(OCAMLOPT) -c -no-alias-deps -w -49 $< + +Lib%.cmx: %.ml + $(OCAMLOPT) -c -open Lib -o $@ $< + +include depend.mk2 + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common +COMPFLAGS = -no-alias-deps # Used by $(OCAMLC) diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference new file mode 100644 index 00000000..951b5d26 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mk.reference @@ -0,0 +1,11 @@ +lib.cmo : lib.cmi +lib.cmx : lib.cmi +lib.cmi : +LibA.cmo : lib.cmi +LibA.cmx : lib.cmx +LibB.cmo : LibA.cmo lib.cmi +LibB.cmx : LibA.cmx lib.cmx +LibC.cmo : LibB.cmo LibA.cmo lib.cmi +LibC.cmx : LibB.cmx LibA.cmx lib.cmx +LibD.cmo : lib.cmi +LibD.cmx : lib.cmx diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference new file mode 100644 index 00000000..a3f73b5e --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mk2.reference @@ -0,0 +1,8 @@ +LibA.cmo : lib.cmi +LibA.cmx : lib.cmi +LibB.cmo : LibA.cmo lib.cmi +LibB.cmx : LibA.cmx lib.cmi +LibC.cmo : LibB.cmo LibA.cmo lib.cmi +LibC.cmx : LibB.cmx LibA.cmx lib.cmi +LibD.cmo : lib.cmi +LibD.cmx : lib.cmi diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mod.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mod.reference new file mode 100644 index 00000000..37a3cea2 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mod.reference @@ -0,0 +1,6 @@ +lib.ml: +lib.mli: +LibA.ml: Lib +LibB.ml: Lib LibA +LibC.ml: Lib LibA LibB +LibD.ml: Lib diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mod2.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mod2.reference new file mode 100644 index 00000000..7ec54741 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mod2.reference @@ -0,0 +1,4 @@ +LibA.ml: +LibB.ml: A Packed +LibC.ml: Lib LibA LibB +LibD.ml: diff --git a/testsuite/tests/tool-ocamldep-modalias/depend.mod3.reference b/testsuite/tests/tool-ocamldep-modalias/depend.mod3.reference new file mode 100644 index 00000000..8ab7ed95 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/depend.mod3.reference @@ -0,0 +1,4 @@ +LibA.ml: Lib +LibB.ml: Lib LibA +LibC.ml: Lib LibA LibB +LibD.ml: Lib diff --git a/testsuite/tests/tool-ocamldep-modalias/lib.mli b/testsuite/tests/tool-ocamldep-modalias/lib.mli new file mode 100644 index 00000000..2334c2b6 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/lib.mli @@ -0,0 +1,8 @@ +module Packed : sig + module A = LibA + module B = LibB + module C = LibC +end +include (module type of struct include Packed end) + +val imp : int -> int diff --git a/testsuite/tests/tool-ocamldep-modalias/lib_impl.ml b/testsuite/tests/tool-ocamldep-modalias/lib_impl.ml new file mode 100644 index 00000000..fc8581ad --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/lib_impl.ml @@ -0,0 +1,8 @@ +module Packed = struct + module A = LibA + module B = LibB + module C = LibC +end +include Packed + +let imp x = x+1 diff --git a/testsuite/tests/tool-ocamldep-modalias/main.ml b/testsuite/tests/tool-ocamldep-modalias/main.ml new file mode 100644 index 00000000..94668912 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-modalias/main.ml @@ -0,0 +1,3 @@ +open Lib + +let () = Printf.printf "B.g 3 = %d\n%!" (B.g 3) diff --git a/testsuite/tests/tool-ocamldoc-2/Makefile b/testsuite/tests/tool-ocamldoc-2/Makefile new file mode 100644 index 00000000..372041d5 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/Makefile @@ -0,0 +1,53 @@ +#************************************************************************** +#* * +#* 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=../.. +COMPFLAGS=-I $(OTOPDIR)/ocamldoc +LD_PATH=$(TOPDIR)/otherlibs/$(UNIXLIBVAR)unix:$(TOPDIR)/otherlibs/str +DOCFLAGS=-I $(OTOPDIR)/stdlib $(COMPFLAGS)\ + -latextitle "6,subsection*" \ + -latextitle "7,subsubsection*" \ + -latex-type-prefix "TYP" \ + -latex-module-prefix "" \ + -latex-module-type-prefix "" \ + -latex-value-prefix "" + +.PHONY: default +default: + @if ! $(SUPPORTS_SHARED_LIBRARIES); then \ + echo 'skipped (shared libraries not available)'; \ + else \ + $(SET_LD_PATH) $(MAKE) run; \ + fi + +.PHONY: run +run: *.mli + @for file in *.mli; do \ + printf " ... testing '$$file'"; \ + F="`basename $$file .mli`"; \ + $(OCAMLDOC) $(DOCFLAGS) -hide-warnings -latex $ \ + -o $$F.result $$file; \ + $(DIFF) $$F.reference $$F.result >/dev/null \ + && echo " => passed" || echo " => failed"; \ + done + +.PHONY: promote +promote: defaultpromote + +.PHONY: clean +clean: defaultclean + @rm -f *.result *.html *.tex *.log *.out *.sty *.toc *.css *.aux + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/tool-ocamldoc-2/test.mli b/testsuite/tests/tool-ocamldoc-2/test.mli new file mode 100644 index 00000000..3c4ec154 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/test.mli @@ -0,0 +1,30 @@ + +(** Ten comments for tests *) + +(** {6 A first comments for title } *) + +(** {7 A subsection for ocamldoc *} *) + +(** {7 Bis } *) + +(** {7 Ter } *) + +(** {6 A new section } *) + +(** {7 And its subsection } *) + +(** {7 Encore } *) + +(** Encore! Encore! *) + + +(**/**) +module Silence : sig + (** At last *) +end + +(**/**) + +(** {7 With strange aeons } *) + +module End : sig end diff --git a/testsuite/tests/tool-ocamldoc-2/test.reference b/testsuite/tests/tool-ocamldoc-2/test.reference new file mode 100644 index 00000000..55afe977 --- /dev/null +++ b/testsuite/tests/tool-ocamldoc-2/test.reference @@ -0,0 +1,74 @@ +\documentclass[11pt]{article} +\usepackage[latin1]{inputenc} +\usepackage[T1]{fontenc} +\usepackage{textcomp} +\usepackage{fullpage} +\usepackage{url} +\usepackage{ocamldoc} +\begin{document} +\tableofcontents +\section{Module {\tt{Test}} : Ten comments for tests} +\label{Test}\index{Test@\verb`Test`} + + + + +\ocamldocvspace{0.5cm} + + + +\subsection*{A first comments for title } + + + + +\subsubsection*{A subsection for ocamldoc *} + + + + +\subsubsection*{Bis } + + + + +\subsubsection*{Ter } + + + + +\subsection*{A new section } + + + + +\subsubsection*{And its subsection } + + + + +\subsubsection*{Encore } + + + + +Encore! Encore! + + + +\subsubsection*{With strange aeons } + + + + +\begin{ocamldoccode} +{\tt{module }}{\tt{End}}{\tt{ : }}\end{ocamldoccode} +\label{Test.End}\index{End@\verb`End`} + +\begin{ocamldocsigend} +\end{ocamldocsigend} + + + + +\end{document} \ No newline at end of file diff --git a/testsuite/tests/tool-ocamldoc/.ignore b/testsuite/tests/tool-ocamldoc/.ignore deleted file mode 100644 index 866d4be8..00000000 --- a/testsuite/tests/tool-ocamldoc/.ignore +++ /dev/null @@ -1,4 +0,0 @@ -*.html -*.sty -*.css -ocamldoc.out diff --git a/testsuite/tests/tool-ocamldoc/Makefile b/testsuite/tests/tool-ocamldoc/Makefile index 976010e5..e28c62f1 100644 --- a/testsuite/tests/tool-ocamldoc/Makefile +++ b/testsuite/tests/tool-ocamldoc/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. CUSTOM_MODULE=odoc_test diff --git a/testsuite/tests/tool-ocamldoc/t03.ml b/testsuite/tests/tool-ocamldoc/t03.ml index 3d06cc59..9d9e1593 100644 --- a/testsuite/tests/tool-ocamldoc/t03.ml +++ b/testsuite/tests/tool-ocamldoc/t03.ml @@ -4,4 +4,9 @@ module Bar = struct type t = int let x = 2 end;; module type MT2 = sig type t val x : t end;; module type Gee = MT2 with type t = float ;; -module T = (val (if true then (module Foo:MT2 with type t = int) else (module Bar: MT2 with type t = int)) : MT2 with type t = int);; +module T = (val + (if true + then (module Foo:MT2 with type t = int) + else (module Bar: MT2 with type t = int)) + : MT2 with type t = int) +;; diff --git a/testsuite/tests/tool-toplevel/Makefile b/testsuite/tests/tool-toplevel/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/tool-toplevel/Makefile +++ b/testsuite/tests/tool-toplevel/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/translprim/Makefile b/testsuite/tests/translprim/Makefile new file mode 100644 index 00000000..c4223d45 --- /dev/null +++ b/testsuite/tests/translprim/Makefile @@ -0,0 +1,4 @@ +BASEDIR=../.. +TOPFLAGS+=-dlambda +include $(BASEDIR)/makefiles/Makefile.dlambda +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/translprim/array_spec.ml b/testsuite/tests/translprim/array_spec.ml new file mode 100644 index 00000000..e78c9634 --- /dev/null +++ b/testsuite/tests/translprim/array_spec.ml @@ -0,0 +1,62 @@ +external len : 'a array -> int = "%array_length" +external safe_get : 'a array -> int -> 'a = "%array_safe_get" +external unsafe_get : 'a array -> int -> 'a = "%array_unsafe_get" +external safe_set : 'a array -> int -> 'a -> unit = "%array_safe_set" +external unsafe_set : 'a array -> int -> 'a -> unit = "%array_unsafe_set" + +(* Specialization in application *) + +let int_a = [|1;2;3|];; +let float_a = [|1.;2.;3.|];; +let addr_a = [|"a";"b";"c"|];; + +len int_a;; +len float_a;; +len addr_a;; +(fun a -> len a);; + +safe_get int_a 0;; +safe_get float_a 0;; +safe_get addr_a 0;; +(fun a -> safe_get a 0);; + +unsafe_get int_a 0;; +unsafe_get float_a 0;; +unsafe_get addr_a 0;; +(fun a -> unsafe_get a 0);; + +safe_set int_a 0 1;; +safe_set float_a 0 1.;; +safe_set addr_a 0 "a";; +(fun a x -> safe_set a 0 x);; + +unsafe_set int_a 0 1;; +unsafe_set float_a 0 1.;; +unsafe_set addr_a 0 "a";; +(fun a x -> unsafe_set a 0 x);; + +(* Specialization during eta-expansion *) + +let eta_gen_len : 'a array -> _ = len;; +let eta_gen_safe_get : 'a array -> int -> 'a = safe_get;; +let eta_gen_unsafe_get : 'a array -> int -> 'a = unsafe_get;; +let eta_gen_safe_set : 'a array -> int -> 'a -> unit = safe_set;; +let eta_gen_unsafe_set : 'a array -> int -> 'a -> unit = unsafe_set;; + +let eta_int_len : int array -> _ = len;; +let eta_int_safe_get : int array -> int -> int = safe_get;; +let eta_int_unsafe_get : int array -> int -> int = unsafe_get;; +let eta_int_safe_set : int array -> int -> int -> unit = safe_set;; +let eta_int_unsafe_set : int array -> int -> int -> unit = unsafe_set;; + +let eta_float_len : float array -> _ = len;; +let eta_float_safe_get : float array -> int -> float = safe_get;; +let eta_float_unsafe_get : float array -> int -> float = unsafe_get;; +let eta_float_safe_set : float array -> int -> float -> unit = safe_set;; +let eta_float_unsafe_set : float array -> int -> float -> unit = unsafe_set;; + +let eta_addr_len : string array -> _ = len;; +let eta_addr_safe_get : string array -> int -> string = safe_get;; +let eta_addr_unsafe_get : string array -> int -> string = unsafe_get;; +let eta_addr_safe_set : string array -> int -> string -> unit = safe_set;; +let eta_addr_unsafe_set : string array -> int -> string -> unit = unsafe_set;; diff --git a/testsuite/tests/translprim/array_spec.ml.reference b/testsuite/tests/translprim/array_spec.ml.reference new file mode 100644 index 00000000..7b48cfdd --- /dev/null +++ b/testsuite/tests/translprim/array_spec.ml.reference @@ -0,0 +1,88 @@ +(setglobal Array_spec! + (let + (int_a = (makearray[int] 1 2 3) + float_a = (makearray[float] 1. 2. 3.) + addr_a = (makearray[addr] "a" "b" "c")) + (seq (array.length[int] int_a) (array.length[float] float_a) + (array.length[addr] addr_a) + (function a (array.length[gen] a)) + (array.get[int] int_a 0) (array.get[float] float_a 0) + (array.get[addr] addr_a 0) + (function a (array.get[gen] a 0)) + (array.unsafe_get[int] int_a 0) + (array.unsafe_get[float] float_a 0) + (array.unsafe_get[addr] addr_a 0) + (function a (array.unsafe_get[gen] a 0)) + (array.set[int] int_a 0 1) (array.set[float] float_a 0 1.) + (array.set[addr] addr_a 0 "a") + (function a x (array.set[gen] a 0 x)) + (array.unsafe_set[int] int_a 0 1) + (array.unsafe_set[float] float_a 0 1.) + (array.unsafe_set[addr] addr_a 0 "a") + (function a x (array.unsafe_set[gen] a 0 x)) + (let + (eta_gen_len = + (function prim (array.length[gen] prim)) + eta_gen_safe_get = + (function prim prim + (array.get[gen] prim prim)) + eta_gen_unsafe_get = + (function prim prim + (array.unsafe_get[gen] prim prim)) + eta_gen_safe_set = + (function prim prim prim + (array.set[gen] prim prim prim)) + eta_gen_unsafe_set = + (function prim prim prim + (array.unsafe_set[gen] prim prim prim)) + eta_int_len = + (function prim (array.length[int] prim)) + eta_int_safe_get = + (function prim prim + (array.get[int] prim prim)) + eta_int_unsafe_get = + (function prim prim + (array.unsafe_get[int] prim prim)) + eta_int_safe_set = + (function prim prim prim + (array.set[int] prim prim prim)) + eta_int_unsafe_set = + (function prim prim prim + (array.unsafe_set[int] prim prim prim)) + eta_float_len = + (function prim (array.length[float] prim)) + eta_float_safe_get = + (function prim prim + (array.get[float] prim prim)) + eta_float_unsafe_get = + (function prim prim + (array.unsafe_get[float] prim prim)) + eta_float_safe_set = + (function prim prim prim + (array.set[float] prim prim prim)) + eta_float_unsafe_set = + (function prim prim prim + (array.unsafe_set[float] prim prim prim)) + eta_addr_len = + (function prim (array.length[addr] prim)) + eta_addr_safe_get = + (function prim prim + (array.get[addr] prim prim)) + eta_addr_unsafe_get = + (function prim prim + (array.unsafe_get[addr] prim prim)) + eta_addr_safe_set = + (function prim prim prim + (array.set[addr] prim prim prim)) + eta_addr_unsafe_set = + (function prim prim prim + (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 + eta_gen_unsafe_set eta_int_len eta_int_safe_get + eta_int_unsafe_get eta_int_safe_set + eta_int_unsafe_set eta_float_len eta_float_safe_get + eta_float_unsafe_get eta_float_safe_set + eta_float_unsafe_set eta_addr_len eta_addr_safe_get + eta_addr_unsafe_get eta_addr_safe_set + eta_addr_unsafe_set))))) diff --git a/testsuite/tests/translprim/comparison_table.ml b/testsuite/tests/translprim/comparison_table.ml new file mode 100644 index 00000000..129ea5c5 --- /dev/null +++ b/testsuite/tests/translprim/comparison_table.ml @@ -0,0 +1,239 @@ +external cmp : 'a -> 'a -> int = "%compare";; +external eq : 'a -> 'a -> bool = "%equal";; +external ne : 'a -> 'a -> bool = "%notequal";; +external lt : 'a -> 'a -> bool = "%lessthan";; +external gt : 'a -> 'a -> bool = "%greaterthan";; +external le : 'a -> 'a -> bool = "%lessequal";; +external ge : 'a -> 'a -> bool = "%greaterequal";; + +type intlike = A | B | C | D + +(* Check specialization in explicit application *) + +let gen_cmp x y = cmp x y;; +let int_cmp (x : int) y = cmp x y;; +let bool_cmp (x : bool) y = cmp x y;; +let intlike_cmp (x : intlike) y = cmp x y;; +let float_cmp (x : float) y = cmp x y;; +let string_cmp (x : string) y = cmp x y;; +let int32_cmp (x : int32) y = cmp x y;; +let int64_cmp (x : int64) y = cmp x y;; +let nativeint_cmp (x : nativeint) y = cmp x y;; + +let gen_eq x y = eq x y;; +let int_eq (x : int) y = eq x y;; +let bool_eq (x : bool) y = eq x y;; +let intlike_eq (x : intlike) y = eq x y;; +let float_eq (x : float) y = eq x y;; +let string_eq (x : string) y = eq x y;; +let int32_eq (x : int32) y = eq x y;; +let int64_eq (x : int64) y = eq x y;; +let nativeint_eq (x : nativeint) y = eq x y;; + +let gen_ne x y = ne x y;; +let int_ne (x : int) y = ne x y;; +let bool_ne (x : bool) y = ne x y;; +let intlike_ne (x : intlike) y = ne x y;; +let float_ne (x : float) y = ne x y;; +let string_ne (x : string) y = ne x y;; +let int32_ne (x : int32) y = ne x y;; +let int64_ne (x : int64) y = ne x y;; +let nativeint_ne (x : nativeint) y = ne x y;; + +let gen_lt x y = lt x y;; +let int_lt (x : int) y = lt x y;; +let bool_lt (x : bool) y = lt x y;; +let intlike_lt (x : intlike) y = lt x y;; +let float_lt (x : float) y = lt x y;; +let string_lt (x : string) y = lt x y;; +let int32_lt (x : int32) y = lt x y;; +let int64_lt (x : int64) y = lt x y;; +let nativeint_lt (x : nativeint) y = lt x y;; + +let gen_gt x y = gt x y;; +let int_gt (x : int) y = gt x y;; +let bool_gt (x : bool) y = gt x y;; +let intlike_gt (x : intlike) y = gt x y;; +let float_gt (x : float) y = gt x y;; +let string_gt (x : string) y = gt x y;; +let int32_gt (x : int32) y = gt x y;; +let int64_gt (x : int64) y = gt x y;; +let nativeint_gt (x : nativeint) y = gt x y;; + +let gen_le x y = le x y;; +let int_le (x : int) y = le x y;; +let bool_le (x : bool) y = le x y;; +let intlike_le (x : intlike) y = le x y;; +let float_le (x : float) y = le x y;; +let string_le (x : string) y = le x y;; +let int32_le (x : int32) y = le x y;; +let int64_le (x : int64) y = le x y;; +let nativeint_le (x : nativeint) y = le x y;; + +let gen_ge x y = ge x y;; +let int_ge (x : int) y = ge x y;; +let bool_ge (x : bool) y = ge x y;; +let intlike_ge (x : intlike) y = ge x y;; +let float_ge (x : float) y = ge x y;; +let string_ge (x : string) y = ge x y;; +let int32_ge (x : int32) y = ge x y;; +let int64_ge (x : int64) y = ge x y;; +let nativeint_ge (x : nativeint) y = ge x y;; + +(* Check specialization in eta-expansion *) + +let eta_gen_cmp : 'a -> _ = cmp;; +let eta_int_cmp : int -> _ = cmp;; +let eta_bool_cmp : bool -> _ = cmp;; +let eta_intlike_cmp : intlike -> _ = cmp;; +let eta_float_cmp : float -> _ = cmp;; +let eta_string_cmp : string -> _ = cmp;; +let eta_int32_cmp : int32 -> _ = cmp;; +let eta_int64_cmp : int64 -> _ = cmp;; +let eta_nativeint_cmp : nativeint -> _ = cmp;; + +let eta_gen_eq : 'a -> _ = eq;; +let eta_int_eq : int -> _ = eq;; +let eta_bool_eq : bool -> _ = eq;; +let eta_intlike_eq : intlike -> _ = eq;; +let eta_float_eq : float -> _ = eq;; +let eta_string_eq : string -> _ = eq;; +let eta_int32_eq : int32 -> _ = eq;; +let eta_int64_eq : int64 -> _ = eq;; +let eta_nativeint_eq : nativeint -> _ = eq;; + +let eta_gen_ne : 'a -> _ = ne;; +let eta_int_ne : int -> _ = ne;; +let eta_bool_ne : bool -> _ = ne;; +let eta_intlike_ne : intlike -> _ = ne;; +let eta_float_ne : float -> _ = ne;; +let eta_string_ne : string -> _ = ne;; +let eta_int32_ne : int32 -> _ = ne;; +let eta_int64_ne : int64 -> _ = ne;; +let eta_nativeint_ne : nativeint -> _ = ne;; + +let eta_gen_lt : 'a -> _ = lt;; +let eta_int_lt : int -> _ = lt;; +let eta_bool_lt : bool -> _ = lt;; +let eta_intlike_lt : intlike -> _ = lt;; +let eta_float_lt : float -> _ = lt;; +let eta_string_lt : string -> _ = lt;; +let eta_int32_lt : int32 -> _ = lt;; +let eta_int64_lt : int64 -> _ = lt;; +let eta_nativeint_lt : nativeint -> _ = lt;; + +let eta_gen_gt : 'a -> _ = gt;; +let eta_int_gt : int -> _ = gt;; +let eta_bool_gt : bool -> _ = gt;; +let eta_intlike_gt : intlike -> _ = gt;; +let eta_float_gt : float -> _ = gt;; +let eta_string_gt : string -> _ = gt;; +let eta_int32_gt : int32 -> _ = gt;; +let eta_int64_gt : int64 -> _ = gt;; +let eta_nativeint_gt : nativeint -> _ = gt;; + +let eta_gen_le : 'a -> _ = le;; +let eta_int_le : int -> _ = le;; +let eta_bool_le : bool -> _ = le;; +let eta_intlike_le : intlike -> _ = le;; +let eta_float_le : float -> _ = le;; +let eta_string_le : string -> _ = le;; +let eta_int32_le : int32 -> _ = le;; +let eta_int64_le : int64 -> _ = le;; +let eta_nativeint_le : nativeint -> _ = le;; + +let eta_gen_ge : 'a -> _ = ge;; +let eta_int_ge : int -> _ = ge;; +let eta_bool_ge : bool -> _ = ge;; +let eta_intlike_ge : intlike -> _ = ge;; +let eta_float_ge : float -> _ = ge;; +let eta_string_ge : string -> _ = ge;; +let eta_int32_ge : int32 -> _ = ge;; +let eta_int64_ge : int64 -> _ = ge;; +let eta_nativeint_ge : nativeint -> _ = ge;; + +(* Check results of computations *) + +let int_vec = [(1,1);(1,2);(2,1)];; +let bool_vec = [(false,false);(false,true);(true,false)];; +let intlike_vec = [(A,A);(A,B);(B,A)];; +let float_vec = [(1.,1.);(1.,2.);(2.,1.)];; +let string_vec = [("1","1");("1","2");("2","1")];; +let int32_vec = [(1l,1l);(1l,2l);(2l,1l)];; +let int64_vec = [(1L,1L);(1L,2L);(2L,1L)];; +let nativeint_vec = [(1n,1n);(1n,2n);(2n,1n)];; + +let test_vec cmp eq ne lt gt le ge vec = + let uncurry f (x,y) = f x y in + let map f l = List.map (uncurry f) l in + (map gen_cmp vec, map cmp vec), + (map (fun gen spec -> map gen vec, map spec vec) + [gen_eq,eq; gen_ne,ne; gen_lt,lt; gen_gt,gt; gen_le,le; gen_ge,ge]) +;; + +test_vec + int_cmp int_eq int_ne int_lt int_gt int_le int_ge + int_vec;; +test_vec + bool_cmp bool_eq bool_ne bool_lt bool_gt bool_le bool_ge + bool_vec;; +test_vec + intlike_cmp intlike_eq intlike_ne intlike_lt intlike_gt intlike_le intlike_ge + intlike_vec;; +test_vec + float_cmp float_eq float_ne float_lt float_gt float_le float_ge + float_vec;; +test_vec + string_cmp string_eq string_ne string_lt string_gt string_le string_ge + string_vec;; +test_vec + int32_cmp int32_eq int32_ne int32_lt int32_gt int32_le int32_ge + int32_vec;; +test_vec + int64_cmp int64_eq int64_ne int64_lt int64_gt int64_le int64_ge + int64_vec;; +test_vec + nativeint_cmp nativeint_eq nativeint_ne + nativeint_lt nativeint_gt nativeint_le nativeint_ge + nativeint_vec;; + +let eta_test_vec cmp eq ne lt gt le ge vec = + let uncurry f (x,y) = f x y in + let map f l = List.map (uncurry f) l in + (map eta_gen_cmp vec, map cmp vec), + (map (fun gen spec -> map gen vec, map spec vec) + [eta_gen_eq,eq; eta_gen_ne,ne; eta_gen_lt,lt; + eta_gen_gt,gt; eta_gen_le,le; eta_gen_ge,ge]) +;; + +eta_test_vec + eta_int_cmp eta_int_eq eta_int_ne eta_int_lt eta_int_gt eta_int_le eta_int_ge + int_vec;; +eta_test_vec + eta_bool_cmp eta_bool_eq eta_bool_ne eta_bool_lt eta_bool_gt + eta_bool_le eta_bool_ge + bool_vec;; +eta_test_vec + eta_intlike_cmp eta_intlike_eq eta_intlike_ne eta_intlike_lt eta_intlike_gt + eta_intlike_le eta_intlike_ge + intlike_vec;; +eta_test_vec + eta_float_cmp eta_float_eq eta_float_ne eta_float_lt eta_float_gt + eta_float_le eta_float_ge + float_vec;; +eta_test_vec + eta_string_cmp eta_string_eq eta_string_ne eta_string_lt eta_string_gt + eta_string_le eta_string_ge + string_vec;; +eta_test_vec + eta_int32_cmp eta_int32_eq eta_int32_ne eta_int32_lt eta_int32_gt + eta_int32_le eta_int32_ge + int32_vec;; +eta_test_vec + eta_int64_cmp eta_int64_eq eta_int64_ne eta_int64_lt eta_int64_gt + eta_int64_le eta_int64_ge + int64_vec;; +eta_test_vec + eta_nativeint_cmp eta_nativeint_eq eta_nativeint_ne + eta_nativeint_lt eta_nativeint_gt eta_nativeint_le eta_nativeint_ge + nativeint_vec;; diff --git a/testsuite/tests/translprim/comparison_table.ml.reference b/testsuite/tests/translprim/comparison_table.ml.reference new file mode 100644 index 00000000..22d533ec --- /dev/null +++ b/testsuite/tests/translprim/comparison_table.ml.reference @@ -0,0 +1,381 @@ +(setglobal Comparison_table! + (seq (opaque (global List!)) + (let + (gen_cmp = (function x y (caml_compare x y)) + int_cmp = + (function x y (caml_int_compare x y)) + bool_cmp = + (function x y (caml_int_compare x y)) + intlike_cmp = + (function x y (caml_int_compare x y)) + float_cmp = + (function x y (caml_float_compare x y)) + string_cmp = + (function x y (caml_string_compare x y)) + int32_cmp = + (function x y (caml_int32_compare x y)) + int64_cmp = + (function x y (caml_int64_compare x y)) + nativeint_cmp = + (function x y (caml_nativeint_compare x y)) + gen_eq = (function x y (caml_equal x y)) + int_eq = (function x y (== x y)) + bool_eq = (function x y (== x y)) + intlike_eq = (function x y (== x y)) + float_eq = (function x y (==. x y)) + string_eq = + (function x y (caml_string_equal x y)) + int32_eq = (function x y (Int32.== x y)) + int64_eq = (function x y (Int64.== x y)) + nativeint_eq = + (function x y (Nativeint.== x y)) + gen_ne = (function x y (caml_notequal x y)) + int_ne = (function x y (!= x y)) + bool_ne = (function x y (!= x y)) + intlike_ne = (function x y (!= x y)) + float_ne = (function x y (!=. x y)) + string_ne = + (function x y (caml_string_notequal x y)) + int32_ne = (function x y (Int32.!= x y)) + int64_ne = (function x y (Int64.!= x y)) + nativeint_ne = + (function x y (Nativeint.!= x y)) + gen_lt = (function x y (caml_lessthan x y)) + int_lt = (function x y (< x y)) + bool_lt = (function x y (< x y)) + intlike_lt = (function x y (< x y)) + float_lt = (function x y (<. x y)) + string_lt = + (function x y (caml_string_lessthan x y)) + int32_lt = (function x y (Int32.< x y)) + int64_lt = (function x y (Int64.< x y)) + nativeint_lt = + (function x y (Nativeint.< x y)) + gen_gt = + (function x y (caml_greaterthan x y)) + int_gt = (function x y (> x y)) + bool_gt = (function x y (> x y)) + intlike_gt = (function x y (> x y)) + float_gt = (function x y (>. x y)) + string_gt = + (function x y (caml_string_greaterthan x y)) + int32_gt = (function x y (Int32.> x y)) + int64_gt = (function x y (Int64.> x y)) + nativeint_gt = + (function x y (Nativeint.> x y)) + gen_le = (function x y (caml_lessequal x y)) + int_le = (function x y (<= x y)) + bool_le = (function x y (<= x y)) + intlike_le = (function x y (<= x y)) + float_le = (function x y (<=. x y)) + string_le = + (function x y (caml_string_lessequal x y)) + int32_le = (function x y (Int32.<= x y)) + int64_le = (function x y (Int64.<= x y)) + nativeint_le = + (function x y (Nativeint.<= x y)) + gen_ge = + (function x y (caml_greaterequal x y)) + int_ge = (function x y (>= x y)) + bool_ge = (function x y (>= x y)) + intlike_ge = (function x y (>= x y)) + float_ge = (function x y (>=. x y)) + string_ge = + (function x y (caml_string_greaterequal x y)) + int32_ge = (function x y (Int32.>= x y)) + int64_ge = (function x y (Int64.>= x y)) + nativeint_ge = + (function x y (Nativeint.>= x y)) + eta_gen_cmp = + (function prim prim (caml_compare prim prim)) + eta_int_cmp = + (function prim prim + (caml_int_compare prim prim)) + eta_bool_cmp = + (function prim prim + (caml_int_compare prim prim)) + eta_intlike_cmp = + (function prim prim + (caml_int_compare prim prim)) + eta_float_cmp = + (function prim prim + (caml_float_compare prim prim)) + eta_string_cmp = + (function prim prim + (caml_string_compare prim prim)) + eta_int32_cmp = + (function prim prim + (caml_int32_compare prim prim)) + eta_int64_cmp = + (function prim prim + (caml_int64_compare prim prim)) + eta_nativeint_cmp = + (function prim prim + (caml_nativeint_compare prim prim)) + eta_gen_eq = + (function prim prim (caml_equal prim prim)) + eta_int_eq = + (function prim prim (== prim prim)) + eta_bool_eq = + (function prim prim (== prim prim)) + eta_intlike_eq = + (function prim prim (== prim prim)) + eta_float_eq = + (function prim prim (==. prim prim)) + eta_string_eq = + (function prim prim + (caml_string_equal prim prim)) + eta_int32_eq = + (function prim prim (Int32.== prim prim)) + eta_int64_eq = + (function prim prim (Int64.== prim prim)) + eta_nativeint_eq = + (function prim prim (Nativeint.== prim prim)) + eta_gen_ne = + (function prim prim (caml_notequal prim prim)) + eta_int_ne = + (function prim prim (!= prim prim)) + eta_bool_ne = + (function prim prim (!= prim prim)) + eta_intlike_ne = + (function prim prim (!= prim prim)) + eta_float_ne = + (function prim prim (!=. prim prim)) + eta_string_ne = + (function prim prim + (caml_string_notequal prim prim)) + eta_int32_ne = + (function prim prim (Int32.!= prim prim)) + eta_int64_ne = + (function prim prim (Int64.!= prim prim)) + eta_nativeint_ne = + (function prim prim (Nativeint.!= prim prim)) + eta_gen_lt = + (function prim prim (caml_lessthan prim prim)) + eta_int_lt = + (function prim prim (< prim prim)) + eta_bool_lt = + (function prim prim (< prim prim)) + eta_intlike_lt = + (function prim prim (< prim prim)) + eta_float_lt = + (function prim prim (<. prim prim)) + eta_string_lt = + (function prim prim + (caml_string_lessthan prim prim)) + eta_int32_lt = + (function prim prim (Int32.< prim prim)) + eta_int64_lt = + (function prim prim (Int64.< prim prim)) + eta_nativeint_lt = + (function prim prim (Nativeint.< prim prim)) + eta_gen_gt = + (function prim prim + (caml_greaterthan prim prim)) + eta_int_gt = + (function prim prim (> prim prim)) + eta_bool_gt = + (function prim prim (> prim prim)) + eta_intlike_gt = + (function prim prim (> prim prim)) + eta_float_gt = + (function prim prim (>. prim prim)) + eta_string_gt = + (function prim prim + (caml_string_greaterthan prim prim)) + eta_int32_gt = + (function prim prim (Int32.> prim prim)) + eta_int64_gt = + (function prim prim (Int64.> prim prim)) + eta_nativeint_gt = + (function prim prim (Nativeint.> prim prim)) + eta_gen_le = + (function prim prim (caml_lessequal prim prim)) + eta_int_le = + (function prim prim (<= prim prim)) + eta_bool_le = + (function prim prim (<= prim prim)) + eta_intlike_le = + (function prim prim (<= prim prim)) + eta_float_le = + (function prim prim (<=. prim prim)) + eta_string_le = + (function prim prim + (caml_string_lessequal prim prim)) + eta_int32_le = + (function prim prim (Int32.<= prim prim)) + eta_int64_le = + (function prim prim (Int64.<= prim prim)) + eta_nativeint_le = + (function prim prim (Nativeint.<= prim prim)) + eta_gen_ge = + (function prim prim + (caml_greaterequal prim prim)) + eta_int_ge = + (function prim prim (>= prim prim)) + eta_bool_ge = + (function prim prim (>= prim prim)) + eta_intlike_ge = + (function prim prim (>= prim prim)) + eta_float_ge = + (function prim prim (>=. prim prim)) + eta_string_ge = + (function prim prim + (caml_string_greaterequal prim prim)) + eta_int32_ge = + (function prim prim (Int32.>= prim prim)) + eta_int64_ge = + (function prim prim (Int64.>= prim prim)) + eta_nativeint_ge = + (function prim prim (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]]] + float_vec = [0: [0: 1. 1.] [0: [0: 1. 2.] [0: [0: 2. 1.] 0a]]] + string_vec = + [0: [0: "1" "1"] [0: [0: "1" "2"] [0: [0: "2" "1"] 0a]]] + int32_vec = [0: [0: 1l 1l] [0: [0: 1l 2l] [0: [0: 2l 1l] 0a]]] + int64_vec = [0: [0: 1L 1L] [0: [0: 1L 2L] [0: [0: 2L 1L] 0a]]] + nativeint_vec = + [0: [0: 1n 1n] [0: [0: 1n 2n] [0: [0: 2n 1n] 0a]]] + test_vec = + (function cmp eq ne lt gt le ge + vec + (let + (uncurry = + (function f param + (apply f (field 0 param) (field 1 param))) + map = + (function f l + (apply (field 12 (global List!)) + (apply uncurry f) l))) + (makeblock 0 + (makeblock 0 (apply map gen_cmp vec) + (apply map cmp vec)) + (apply map + (function gen spec + (makeblock 0 (apply map gen vec) + (apply map spec vec))) + (makeblock 0 (makeblock 0 gen_eq eq) + (makeblock 0 (makeblock 0 gen_ne ne) + (makeblock 0 (makeblock 0 gen_lt lt) + (makeblock 0 (makeblock 0 gen_gt gt) + (makeblock 0 (makeblock 0 gen_le le) + (makeblock 0 (makeblock 0 gen_ge ge) 0a))))))))))) + (seq + (apply test_vec int_cmp int_eq int_ne int_lt + int_gt int_le int_ge int_vec) + (apply test_vec bool_cmp bool_eq bool_ne + bool_lt bool_gt bool_le bool_ge bool_vec) + (apply test_vec intlike_cmp intlike_eq intlike_ne + intlike_lt intlike_gt intlike_le intlike_ge + intlike_vec) + (apply test_vec float_cmp float_eq float_ne + float_lt float_gt float_le float_ge + float_vec) + (apply test_vec string_cmp string_eq string_ne + string_lt string_gt string_le string_ge + string_vec) + (apply test_vec int32_cmp int32_eq int32_ne + int32_lt int32_gt int32_le int32_ge + int32_vec) + (apply test_vec int64_cmp int64_eq int64_ne + int64_lt int64_gt int64_le int64_ge + int64_vec) + (apply test_vec nativeint_cmp nativeint_eq + nativeint_ne nativeint_lt nativeint_gt + nativeint_le nativeint_ge nativeint_vec) + (let + (eta_test_vec = + (function cmp eq ne lt gt le + ge vec + (let + (uncurry = + (function f param + (apply f (field 0 param) + (field 1 param))) + map = + (function f l + (apply (field 12 (global List!)) + (apply uncurry f) l))) + (makeblock 0 + (makeblock 0 (apply map eta_gen_cmp vec) + (apply map cmp vec)) + (apply map + (function gen spec + (makeblock 0 (apply map gen vec) + (apply map spec vec))) + (makeblock 0 (makeblock 0 eta_gen_eq eq) + (makeblock 0 (makeblock 0 eta_gen_ne ne) + (makeblock 0 (makeblock 0 eta_gen_lt lt) + (makeblock 0 (makeblock 0 eta_gen_gt gt) + (makeblock 0 + (makeblock 0 eta_gen_le le) + (makeblock 0 + (makeblock 0 eta_gen_ge ge) 0a))))))))))) + (seq + (apply eta_test_vec eta_int_cmp eta_int_eq + eta_int_ne eta_int_lt eta_int_gt eta_int_le + eta_int_ge int_vec) + (apply eta_test_vec eta_bool_cmp eta_bool_eq + eta_bool_ne eta_bool_lt eta_bool_gt + eta_bool_le eta_bool_ge bool_vec) + (apply eta_test_vec eta_intlike_cmp eta_intlike_eq + eta_intlike_ne eta_intlike_lt eta_intlike_gt + eta_intlike_le eta_intlike_ge intlike_vec) + (apply eta_test_vec eta_float_cmp eta_float_eq + eta_float_ne eta_float_lt eta_float_gt + eta_float_le eta_float_ge float_vec) + (apply eta_test_vec eta_string_cmp eta_string_eq + eta_string_ne eta_string_lt eta_string_gt + eta_string_le eta_string_ge string_vec) + (apply eta_test_vec eta_int32_cmp eta_int32_eq + eta_int32_ne eta_int32_lt eta_int32_gt + eta_int32_le eta_int32_ge int32_vec) + (apply eta_test_vec eta_int64_cmp eta_int64_eq + eta_int64_ne eta_int64_lt eta_int64_gt + eta_int64_le eta_int64_ge int64_vec) + (apply eta_test_vec eta_nativeint_cmp + eta_nativeint_eq eta_nativeint_ne + eta_nativeint_lt eta_nativeint_gt + eta_nativeint_le eta_nativeint_ge nativeint_vec) + (makeblock 0 gen_cmp int_cmp bool_cmp + intlike_cmp float_cmp string_cmp int32_cmp + int64_cmp nativeint_cmp gen_eq int_eq + bool_eq intlike_eq float_eq string_eq + int32_eq int64_eq nativeint_eq gen_ne + int_ne bool_ne intlike_ne float_ne + string_ne int32_ne int64_ne nativeint_ne + gen_lt int_lt bool_lt intlike_lt + float_lt string_lt int32_lt int64_lt + nativeint_lt gen_gt int_gt bool_gt + intlike_gt float_gt string_gt int32_gt + int64_gt nativeint_gt gen_le int_le + bool_le intlike_le float_le string_le + int32_le int64_le nativeint_le gen_ge + int_ge bool_ge intlike_ge float_ge + string_ge int32_ge int64_ge nativeint_ge + eta_gen_cmp eta_int_cmp eta_bool_cmp + eta_intlike_cmp eta_float_cmp eta_string_cmp + eta_int32_cmp eta_int64_cmp eta_nativeint_cmp + eta_gen_eq eta_int_eq eta_bool_eq + eta_intlike_eq eta_float_eq eta_string_eq + eta_int32_eq eta_int64_eq eta_nativeint_eq + eta_gen_ne eta_int_ne eta_bool_ne + eta_intlike_ne eta_float_ne eta_string_ne + eta_int32_ne eta_int64_ne eta_nativeint_ne + eta_gen_lt eta_int_lt eta_bool_lt + eta_intlike_lt eta_float_lt eta_string_lt + eta_int32_lt eta_int64_lt eta_nativeint_lt + eta_gen_gt eta_int_gt eta_bool_gt + eta_intlike_gt eta_float_gt eta_string_gt + eta_int32_gt eta_int64_gt eta_nativeint_gt + eta_gen_le eta_int_le eta_bool_le + eta_intlike_le eta_float_le eta_string_le + eta_int32_le eta_int64_le eta_nativeint_le + eta_gen_ge eta_int_ge eta_bool_ge + eta_intlike_ge eta_float_ge eta_string_ge + eta_int32_ge eta_int64_ge eta_nativeint_ge + int_vec bool_vec intlike_vec float_vec + string_vec int32_vec int64_vec + nativeint_vec test_vec eta_test_vec))))))) diff --git a/testsuite/tests/translprim/module_coercion.ml b/testsuite/tests/translprim/module_coercion.ml new file mode 100644 index 00000000..041b3034 --- /dev/null +++ b/testsuite/tests/translprim/module_coercion.ml @@ -0,0 +1,37 @@ +module M = struct + external len : 'a array -> int = "%array_length" + external safe_get : 'a array -> int -> 'a = "%array_safe_get" + external unsafe_get : 'a array -> int -> 'a = "%array_unsafe_get" + external safe_set : 'a array -> int -> 'a -> unit = "%array_safe_set" + external unsafe_set : 'a array -> int -> 'a -> unit = "%array_unsafe_set" + external cmp : 'a -> 'a -> int = "%compare";; + external eq : 'a -> 'a -> bool = "%equal";; + external ne : 'a -> 'a -> bool = "%notequal";; + external lt : 'a -> 'a -> bool = "%lessthan";; + external gt : 'a -> 'a -> bool = "%greaterthan";; + external le : 'a -> 'a -> bool = "%lessequal";; + external ge : 'a -> 'a -> bool = "%greaterequal";; +end;; + +module type T = sig + type t + val len : t array -> int + val safe_get : t array -> int -> t + val unsafe_get : t array -> int -> t + val safe_set : t array -> int -> t -> unit + val unsafe_set : t array -> int -> t -> unit + val cmp : t -> t -> int + val eq : t -> t -> bool + val ne : t -> t -> bool + val lt : t -> t -> bool + val gt : t -> t -> bool + val le : t -> t -> bool + val ge : t -> t -> bool +end;; + +module M_int : T with type t := int = M;; +module M_float : T with type t := float = M;; +module M_string : T with type t := string = M;; +module M_int32 : T with type t := int32 = M;; +module M_int64 : T with type t := int64 = M;; +module M_nativeint : T with type t := nativeint = M;; diff --git a/testsuite/tests/translprim/module_coercion.ml.reference b/testsuite/tests/translprim/module_coercion.ml.reference new file mode 100644 index 00000000..b84637f4 --- /dev/null +++ b/testsuite/tests/translprim/module_coercion.ml.reference @@ -0,0 +1,104 @@ +(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 + (array.unsafe_get[int] prim prim)) + (function prim prim prim + (array.set[int] prim prim prim)) + (function prim prim prim + (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 + (array.unsafe_get[float] prim prim)) + (function prim prim prim + (array.set[float] prim prim prim)) + (function prim prim prim + (array.unsafe_set[float] prim prim prim)) + (function prim prim + (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 + (array.unsafe_get[addr] prim prim)) + (function prim prim prim + (array.set[addr] prim prim prim)) + (function prim prim prim + (array.unsafe_set[addr] prim prim prim)) + (function prim prim + (caml_string_compare prim prim)) + (function prim prim + (caml_string_equal prim prim)) + (function prim prim + (caml_string_notequal prim prim)) + (function prim prim + (caml_string_lessthan prim prim)) + (function prim prim + (caml_string_greaterthan prim prim)) + (function prim prim + (caml_string_lessequal prim prim)) + (function prim prim + (caml_string_greaterequal prim prim))) + (makeblock 0 (function prim (array.length[addr] prim)) + (function prim prim (array.get[addr] prim prim)) + (function prim prim + (array.unsafe_get[addr] prim prim)) + (function prim prim prim + (array.set[addr] prim prim prim)) + (function prim prim prim + (array.unsafe_set[addr] prim prim prim)) + (function prim prim + (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 + (array.unsafe_get[addr] prim prim)) + (function prim prim prim + (array.set[addr] prim prim prim)) + (function prim prim prim + (array.unsafe_set[addr] prim prim prim)) + (function prim prim + (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 + (array.unsafe_get[addr] prim prim)) + (function prim prim prim + (array.set[addr] prim prim prim)) + (function prim prim prim + (array.unsafe_set[addr] prim prim prim)) + (function prim prim + (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)))))) diff --git a/testsuite/tests/translprim/ref_spec.ml b/testsuite/tests/translprim/ref_spec.ml new file mode 100644 index 00000000..068fa884 --- /dev/null +++ b/testsuite/tests/translprim/ref_spec.ml @@ -0,0 +1,54 @@ +type 'a custom_rec = { x : unit; mutable y : 'a } +type float_rec = { w : float; mutable z : float } + +type cst = A | B +type gen = C | D of string + +type var = [ `A | `B ] +type vargen = [ `A | `B of int | `C ] + +let int_ref = ref 1;; +let var_ref : var ref = ref `A;; +let vargen_ref : vargen ref = ref `A;; +let cst_ref = ref A;; +let gen_ref = ref C;; +let flt_ref = ref 0.;; + +int_ref := 2;; +var_ref := `B;; +vargen_ref := `B 0;; +vargen_ref := `C;; +cst_ref := B;; +gen_ref := D "foo";; +gen_ref := C;; +flt_ref := 1.;; + +let int_rec = { x = (); y = 1 };; +let var_rec : var custom_rec = { x = (); y = `A };; +let vargen_rec : vargen custom_rec = { x = (); y = `A };; +let cst_rec = { x = (); y = A };; +let gen_rec = { x = (); y = C };; +let flt_rec = { x = (); y = 0. };; +let flt_rec' = { w = 0.; z = 0. };; + +int_rec.y <- 2;; +var_rec.y <- `B;; +vargen_rec.y <- `B 0;; +vargen_rec.y <- `C;; +cst_rec.y <- B;; +gen_rec.y <- D "foo";; +gen_rec.y <- C;; +flt_rec.y <- 1.;; +flt_rec'.z <- 1.;; + +(* must use a write barrier, type is open *) +let set_open_poly (r:[>`Foo] ref) y = r := y ;; +let set_open_poly (r:[<`Foo] ref) y = r := y ;; +let set_open_poly (r:[`Foo] ref) y = r := y ;; +let set_open_poly (r:[< `Bar | `Foo | `Baz > `Foo `Bar] ref) y = r := y ;; +let set_open_poly (r:[>`Foo of int] ref) y = r := y ;; +let set_open_poly (r:[<`Foo of int] ref) y = r := y ;; +let set_open_poly (r:[`Foo of int] ref) y = r := y ;; +let set_open_poly (r:[< `Bar | `Foo of float | `Baz > `Foo `Bar] ref) y = + r := y +;; diff --git a/testsuite/tests/translprim/ref_spec.ml.reference b/testsuite/tests/translprim/ref_spec.ml.reference new file mode 100644 index 00000000..ed1784ad --- /dev/null +++ b/testsuite/tests/translprim/ref_spec.ml.reference @@ -0,0 +1,50 @@ +(setglobal Ref_spec! + (let + (int_ref = (makemutable 0 1) + var_ref = (makemutable 0 65a) + vargen_ref = (makemutable 0 65a) + cst_ref = (makemutable 0 0a) + gen_ref = (makemutable 0 0a) + flt_ref = (makemutable 0 0.)) + (seq (setfield_imm 0 int_ref 2) (setfield_imm 0 var_ref 66a) + (setfield_ptr 0 vargen_ref [0: 66 0]) + (setfield_ptr 0 vargen_ref 67a) (setfield_imm 0 cst_ref 1a) + (setfield_ptr 0 gen_ref [0: "foo"]) + (setfield_ptr 0 gen_ref 0a) (setfield_ptr 0 flt_ref 1.) + (let + (int_rec = (makemutable 0 0a 1) + var_rec = (makemutable 0 0a 65a) + vargen_rec = (makemutable 0 0a 65a) + cst_rec = (makemutable 0 0a 0a) + gen_rec = (makemutable 0 0a 0a) + flt_rec = (makemutable 0 0a 0.) + flt_rec' = (makearray[float] 0. 0.)) + (seq (setfield_imm 1 int_rec 2) + (setfield_imm 1 var_rec 66a) + (setfield_ptr 1 vargen_rec [0: 66 0]) + (setfield_ptr 1 vargen_rec 67a) + (setfield_imm 1 cst_rec 1a) + (setfield_ptr 1 gen_rec [0: "foo"]) + (setfield_ptr 1 gen_rec 0a) (setfield_ptr 1 flt_rec 1.) + (setfloatfield 1 flt_rec' 1.) + (let + (set_open_poly = + (function r y (setfield_ptr 0 r y)) + set_open_poly = + (function r y (setfield_imm 0 r y)) + set_open_poly = + (function r y (setfield_imm 0 r y)) + set_open_poly = + (function r y (setfield_imm 0 r y)) + set_open_poly = + (function r y (setfield_ptr 0 r y)) + set_open_poly = + (function r y (setfield_ptr 0 r y)) + set_open_poly = + (function r y (setfield_ptr 0 r y)) + set_open_poly = + (function r y (setfield_ptr 0 r y))) + (makeblock 0 int_ref var_ref vargen_ref + cst_ref gen_ref flt_ref int_rec + var_rec vargen_rec cst_rec gen_rec + flt_rec flt_rec' set_open_poly))))))) diff --git a/testsuite/tests/typing-extension-constructor/Makefile b/testsuite/tests/typing-extension-constructor/Makefile new file mode 100644 index 00000000..7fc00661 --- /dev/null +++ b/testsuite/tests/typing-extension-constructor/Makefile @@ -0,0 +1,18 @@ +#************************************************************************** +#* * +#* 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=../.. +include $(BASEDIR)/makefiles/Makefile.toplevel +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-extension-constructor/test.ml b/testsuite/tests/typing-extension-constructor/test.ml new file mode 100644 index 00000000..4c73807f --- /dev/null +++ b/testsuite/tests/typing-extension-constructor/test.ml @@ -0,0 +1,14 @@ + +type t = ..;; +type t += A;; + +[%extension_constructor A];; +([%extension_constructor A] : extension_constructor);; + +module M = struct + type extension_constructor = int +end;; + +open M;; + +([%extension_constructor A] : extension_constructor);; diff --git a/testsuite/tests/typing-extension-constructor/test.ml.reference b/testsuite/tests/typing-extension-constructor/test.ml.reference new file mode 100644 index 00000000..5fc7ac41 --- /dev/null +++ b/testsuite/tests/typing-extension-constructor/test.ml.reference @@ -0,0 +1,12 @@ + +# type t = .. +# type t += A +# - : extension_constructor = +# - : extension_constructor = +# module M : sig type extension_constructor = int end +# # Characters 2-28: + ([%extension_constructor A] : extension_constructor);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type extension_constructor + but an expression was expected of type M.extension_constructor = int +# diff --git a/testsuite/tests/typing-extensions/Makefile b/testsuite/tests/typing-extensions/Makefile index 5f42b705..9625a3fb 100644 --- a/testsuite/tests/typing-extensions/Makefile +++ b/testsuite/tests/typing-extensions/Makefile @@ -1,4 +1,3 @@ BASEDIR=../.. include $(BASEDIR)/makefiles/Makefile.toplevel include $(BASEDIR)/makefiles/Makefile.common - diff --git a/testsuite/tests/typing-extensions/cast.ml b/testsuite/tests/typing-extensions/cast.ml index afcc2080..855f4df7 100644 --- a/testsuite/tests/typing-extensions/cast.ml +++ b/testsuite/tests/typing-extensions/cast.ml @@ -1,7 +1,8 @@ (* By using two types we can have a recursive constraint *) type 'a class_name = .. constraint 'a = < cast: 'a. 'a name -> 'a; ..> -and 'a name = Class : 'a class_name -> (< cast: 'a. 'a name -> 'a; ..> as 'a) name +and 'a name = + Class : 'a class_name -> (< cast: 'a. 'a name -> 'a; ..> as 'a) name ;; exception Bad_cast @@ -29,7 +30,7 @@ class foo: foo_t = object(self) method cast: type a. a name -> a = function - Class Foo -> (self :> foo_t) + Class Foo -> (self :> foo_t) | _ -> ((raise Bad_cast) : a) method foo = "foo" end diff --git a/testsuite/tests/typing-extensions/cast.ml.reference b/testsuite/tests/typing-extensions/cast.ml.reference index c2297416..468a7c94 100644 --- a/testsuite/tests/typing-extensions/cast.ml.reference +++ b/testsuite/tests/typing-extensions/cast.ml.reference @@ -1,5 +1,5 @@ -# type 'b class_name = .. constraint 'b = < cast : 'a. 'a name -> 'a; .. > +# 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 # exception Bad_cast diff --git a/testsuite/tests/typing-extensions/extensions.ml b/testsuite/tests/typing-extensions/extensions.ml index 59a23db9..edb14c8b 100644 --- a/testsuite/tests/typing-extensions/extensions.ml +++ b/testsuite/tests/typing-extensions/extensions.ml @@ -200,10 +200,12 @@ type +'a foo = .. type 'a foo += A of (int -> 'a) ;; -type 'a foo += B of ('a -> int) (* ERROR: Parameter variances are not satisfied *) +type 'a foo += B of ('a -> int) + (* ERROR: Parameter variances are not satisfied *) ;; -type _ foo += C : ('a -> int) -> 'a foo (* ERROR: Parameter variances are not satisfied *) +type _ foo += C : ('a -> int) -> 'a foo + (* ERROR: Parameter variances are not satisfied *) ;; type 'a bar = .. @@ -294,19 +296,22 @@ type foo += | Bar of int ;; -let n1 = Obj.extension_name Foo +let extension_name e = Obj.extension_name (Obj.extension_constructor e);; +let extension_id e = Obj.extension_id (Obj.extension_constructor e);; + +let n1 = extension_name Foo ;; -let n2 = Obj.extension_name (Bar 1) +let n2 = extension_name (Bar 1) ;; -let t = (Obj.extension_id (Bar 2)) = (Obj.extension_id (Bar 3)) (* true *) +let t = (extension_id (Bar 2)) = (extension_id (Bar 3)) (* true *) ;; -let f = (Obj.extension_id (Bar 2)) = (Obj.extension_id Foo) (* false *) +let f = (extension_id (Bar 2)) = (extension_id Foo) (* false *) ;; -let is_foo x = (Obj.extension_id Foo) = (Obj.extension_id x) +let is_foo x = (extension_id Foo) = (extension_id x) type foo += Foo ;; @@ -314,8 +319,8 @@ type foo += Foo let f = is_foo Foo ;; -let _ = Obj.extension_name 7 (* Invald_arg *) +let _ = Obj.extension_constructor 7 (* Invald_arg *) ;; -let _ = Obj.extension_id (object method m = 3 end) (* Invald_arg *) +let _ = Obj.extension_constructor (object method m = 3 end) (* Invald_arg *) ;; diff --git a/testsuite/tests/typing-extensions/extensions.ml.reference b/testsuite/tests/typing-extensions/extensions.ml.reference index 25af292d..2a9183f7 100644 --- a/testsuite/tests/typing-extensions/extensions.ml.reference +++ b/testsuite/tests/typing-extensions/extensions.ml.reference @@ -83,14 +83,14 @@ type 'a foo = .. # type 'a foo2 += D of int | E of 'a | F : int foo2 # type +'a foo = .. # type 'a foo += A of (int -> 'a) -# Characters 1-32: - type 'a foo += B of ('a -> int) (* ERROR: Parameter variances are not satisfied *) +# Characters 1-32: + type 'a foo += B of ('a -> int) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, expected parameter variances are not satisfied. The 1st type parameter was expected to be covariant, but it is injective contravariant. -# Characters 1-40: - type _ foo += C : ('a -> int) -> 'a foo (* ERROR: Parameter variances are not satisfied *) +# Characters 1-40: + type _ foo += C : ('a -> int) -> 'a foo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In this definition, expected parameter variances are not satisfied. The 1st type parameter was expected to be covariant, @@ -119,6 +119,8 @@ Error: This extension does not match the definition of type bar # val y : exn * exn = (Foo (3, _), Bar (Some 5)) # type foo = .. # type foo += Foo | Bar of int +# val extension_name : 'a -> string = +# val extension_id : 'a -> int = # val n1 : string = "Foo" # val n2 : string = "Bar" # val t : bool = true @@ -126,6 +128,6 @@ Error: This extension does not match the definition of type bar # val is_foo : 'a -> bool = type foo += Foo # val f : bool = false -# Exception: Invalid_argument "Obj.extension_name". -# Exception: Invalid_argument "Obj.extension_id". +# Exception: Invalid_argument "Obj.extension_constructor". +# Exception: Invalid_argument "Obj.extension_constructor". # diff --git a/testsuite/tests/typing-extensions/open_types.ml b/testsuite/tests/typing-extensions/open_types.ml index e7632cac..766bee04 100644 --- a/testsuite/tests/typing-extensions/open_types.ml +++ b/testsuite/tests/typing-extensions/open_types.ml @@ -107,3 +107,11 @@ type foo = .. type foo += Foo let f = function Foo -> () ;; (* warn *) + +(* More complex exhaustiveness *) + +let f = function + | [Foo] -> 1 + | _::_::_ -> 3 + | [] -> 2 +;; (* warn *) diff --git a/testsuite/tests/typing-extensions/open_types.ml.reference b/testsuite/tests/typing-extensions/open_types.ml.reference index e639c9df..8e86ec09 100644 --- a/testsuite/tests/typing-extensions/open_types.ml.reference +++ b/testsuite/tests/typing-extensions/open_types.ml.reference @@ -76,10 +76,21 @@ Error: Signature mismatch: ^^^^^^^^^^^^^^^^^^ Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: -_ -Matching over values of extensible variant types must include -a wild card pattern in order to be exhaustive. +*extension* +Matching over values of extensible variant types (the *extension* above) +must include a wild card pattern in order to be exhaustive. type foo = .. type foo += Foo val f : foo -> unit = +# Characters 44-96: + ........function + | [Foo] -> 1 + | _::_::_ -> 3 + | [] -> 2 +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +*extension*::[] +Matching over values of extensible variant types (the *extension* above) +must include a wild card pattern in order to be exhaustive. +val f : foo list -> int = # diff --git a/testsuite/tests/typing-fstclassmod/Makefile b/testsuite/tests/typing-fstclassmod/Makefile index e7791836..3f32b3dc 100644 --- a/testsuite/tests/typing-fstclassmod/Makefile +++ b/testsuite/tests/typing-fstclassmod/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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= diff --git a/testsuite/tests/typing-fstclassmod/fstclassmod.ml b/testsuite/tests/typing-fstclassmod/fstclassmod.ml index bc8d66e5..a291a4c7 100644 --- a/testsuite/tests/typing-fstclassmod/fstclassmod.ml +++ b/testsuite/tests/typing-fstclassmod/fstclassmod.ml @@ -17,7 +17,8 @@ let both l = [ make_set compare; make_set (fun x y -> compare y x) ] let () = - print_endline (String.concat " " (List.map (String.concat "/") (both ["abc";"xyz";"def"]))) + print_endline (String.concat " " (List.map (String.concat "/") + (both ["abc";"xyz";"def"]))) (* Hiding the internal representation *) @@ -133,7 +134,8 @@ end = struct | Pair p -> let module P = (val p : PAIR with type t = s) in let (x1, x2) = TypEq.apply P.eq x in - Printf.sprintf "(%s,%s)" (Print.to_string P.t1 x1) (Print.to_string P.t2 x2) + Printf.sprintf "(%s,%s)" (Print.to_string P.t1 x1) + (Print.to_string P.t2 x2) end let () = diff --git a/testsuite/tests/typing-gadts/Makefile b/testsuite/tests/typing-gadts/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-gadts/Makefile +++ b/testsuite/tests/typing-gadts/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-gadts/didier.ml b/testsuite/tests/typing-gadts/didier.ml index 8091375c..f34ecb67 100644 --- a/testsuite/tests/typing-gadts/didier.ml +++ b/testsuite/tests/typing-gadts/didier.ml @@ -1,31 +1,31 @@ -type 'a ty = +type 'a ty = | Int : int ty | Bool : bool ty -let fbool (type t) (x : t) (tag : t ty) = - match tag with +let fbool (type t) (x : t) (tag : t ty) = + match tag with | Bool -> x ;; (* val fbool : 'a -> 'a ty -> 'a = *) (** OK: the return value is x of type t **) -let fint (type t) (x : t) (tag : t ty) = - match tag with +let fint (type t) (x : t) (tag : t ty) = + match tag with | Int -> x > 0 ;; (* val fint : 'a -> 'a ty -> bool = *) (** OK: the return value is x > 0 of type bool; This has used the equation t = bool, not visible in the return type **) -let f (type t) (x : t) (tag : t ty) = - match tag with +let f (type t) (x : t) (tag : t ty) = + match tag with | Int -> x > 0 | Bool -> x (* val f : 'a -> 'a ty -> bool = *) -let g (type t) (x : t) (tag : t ty) = - match tag with +let g (type t) (x : t) (tag : t ty) = + match tag with | Bool -> x | Int -> x > 0 (* Error: This expression has type bool but an expression was expected of type @@ -45,4 +45,3 @@ let g (type t) (x : t) (tag : t ty) = match tag with | Bool -> idb2 x | Int -> x > 0 - diff --git a/testsuite/tests/typing-gadts/didier.ml.reference b/testsuite/tests/typing-gadts/didier.ml.reference new file mode 100644 index 00000000..295d38bb --- /dev/null +++ b/testsuite/tests/typing-gadts/didier.ml.reference @@ -0,0 +1,34 @@ + +# Characters 94-122: + ..match tag with + | Bool -> x +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Int +type 'a ty = Int : int ty | Bool : bool ty +val fbool : 'a -> 'a ty -> 'a = +# Characters 132-163: + ..match tag with + | Int -> x > 0 +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Bool +val fint : 'a -> 'a ty -> bool = +# * * Characters 376-381: + | Int -> x > 0 + ^^^^^ +Error: This expression has type bool but an expression was expected of type + t = int +# Characters 45-47: + let idb1 = (fun id -> let _ = id true in id) id;; + ^^ +Error: Unbound value id +# Characters 26-28: + let idb2 : bool -> bool = id;; + ^^ +Error: Unbound value id +# val idb3 : bool -> bool = +# +Characters 184-184: + Error: Syntax error +# diff --git a/testsuite/tests/typing-gadts/dynamic_frisch.ml b/testsuite/tests/typing-gadts/dynamic_frisch.ml index 2636d5b4..7018bbc1 100644 --- a/testsuite/tests/typing-gadts/dynamic_frisch.ml +++ b/testsuite/tests/typing-gadts/dynamic_frisch.ml @@ -444,7 +444,6 @@ let ty_abc : ([`A of int | `B of string | `C] as 'a, 'e) ty = Thd, v -> `A v | Ttl Thd, v -> `B v | Ttl (Ttl Thd), Noarg -> `C - | _ -> assert false end) type 'a vlist = [`Nil | `Cons of 'a * 'a vlist] diff --git a/testsuite/tests/typing-gadts/dynamic_frisch.ml.principal.reference b/testsuite/tests/typing-gadts/dynamic_frisch.ml.principal.reference index a894b22d..894b553a 100644 --- a/testsuite/tests/typing-gadts/dynamic_frisch.ml.principal.reference +++ b/testsuite/tests/typing-gadts/dynamic_frisch.ml.principal.reference @@ -148,8 +148,8 @@ val ty_abc : ([ `A of int | `B of string | `C ], 'e) ty = Sum (, ) ^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type a * a vlist but a pattern was expected which matches values of type - a#5 = ex#34 * ex#35 - Type a is not compatible with type ex#34 + $Tdyn_'a = $0 * $1 + Type a is not compatible with type $0 # type (_, _) ty = Int : (int, 'd) ty | String : (string, 'f) ty @@ -171,7 +171,7 @@ and (_, _) ty_sel = and (_, _) ty_case = TCarg : ('b, 'a) ty_sel * ('a, 'e) ty -> ('e, 'b) ty_case | TCnoarg : ('b, noarg) ty_sel -> ('e, 'b) ty_case -# val ty_abc : ([ `A of int | `B of string | `C ], 'e) ty = Sum +# val ty_abc : ([ `A of int | `B of string | `C ], 'e) ty = Sum type 'a vlist = [ `Cons of 'a * 'a vlist | `Nil ] val ty_list : ('a, 'e) ty -> ('a vlist, 'e) ty = # * * * * * * * * * diff --git a/testsuite/tests/typing-gadts/dynamic_frisch.ml.reference b/testsuite/tests/typing-gadts/dynamic_frisch.ml.reference index a894b22d..894b553a 100644 --- a/testsuite/tests/typing-gadts/dynamic_frisch.ml.reference +++ b/testsuite/tests/typing-gadts/dynamic_frisch.ml.reference @@ -148,8 +148,8 @@ val ty_abc : ([ `A of int | `B of string | `C ], 'e) ty = Sum (, ) ^^^^^^^^^^^^^^^^^ Error: This pattern matches values of type a * a vlist but a pattern was expected which matches values of type - a#5 = ex#34 * ex#35 - Type a is not compatible with type ex#34 + $Tdyn_'a = $0 * $1 + Type a is not compatible with type $0 # type (_, _) ty = Int : (int, 'd) ty | String : (string, 'f) ty @@ -171,7 +171,7 @@ and (_, _) ty_sel = and (_, _) ty_case = TCarg : ('b, 'a) ty_sel * ('a, 'e) ty -> ('e, 'b) ty_case | TCnoarg : ('b, noarg) ty_sel -> ('e, 'b) ty_case -# val ty_abc : ([ `A of int | `B of string | `C ], 'e) ty = Sum +# val ty_abc : ([ `A of int | `B of string | `C ], 'e) ty = Sum type 'a vlist = [ `Cons of 'a * 'a vlist | `Nil ] val ty_list : ('a, 'e) ty -> ('a vlist, 'e) ty = # * * * * * * * * * diff --git a/testsuite/tests/typing-gadts/omega07.ml b/testsuite/tests/typing-gadts/omega07.ml index 9b3bd7e2..ddd7133c 100644 --- a/testsuite/tests/typing-gadts/omega07.ml +++ b/testsuite/tests/typing-gadts/omega07.ml @@ -203,7 +203,8 @@ let rec diff : type a b. (a,b) le -> a nat -> b nat -> (a,b) diff = match a, b,le with (* warning *) | NZ, m, LeZ _ -> Diff (m, PlusZ m) | NS x, NS y, LeS q -> - match diff q x y with Diff (m, p) -> Diff (m, PlusS p) + (match diff q x y with Diff (m, p) -> Diff (m, PlusS p)) + | _ -> . ;; let rec diff : type a b. (a,b) le -> b nat -> (a,b) diff = diff --git a/testsuite/tests/typing-gadts/omega07.ml.principal.reference b/testsuite/tests/typing-gadts/omega07.ml.principal.reference index 47565e3a..6ae426a5 100644 --- a/testsuite/tests/typing-gadts/omega07.ml.principal.reference +++ b/testsuite/tests/typing-gadts/omega07.ml.principal.reference @@ -63,15 +63,7 @@ val plus_assoc : # val smaller : ('a succ, 'b succ) le -> ('a, 'b) le = # type (_, _) diff = Diff : 'c nat * ('a, 'c, 'b) plus -> ('a, 'b) diff # * * * * * * * * * val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = -# Characters 87-243: - ..match a, b,le with (* warning *) - | NZ, m, LeZ _ -> Diff (m, PlusZ m) - | NS x, NS y, LeS q -> - match diff q x y with Diff (m, p) -> Diff (m, PlusS p) -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a value that is not matched: -(NS _, NZ, _) -val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = +# val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = # val diff : ('a, 'b) le -> 'b nat -> ('a, 'b) diff = # type (_, _) filter = Filter : ('m, 'n) le * ('a, 'm) seq -> ('a, 'n) filter val leS' : ('m, 'n) le -> ('m, 'n succ) le = diff --git a/testsuite/tests/typing-gadts/omega07.ml.reference b/testsuite/tests/typing-gadts/omega07.ml.reference index 47565e3a..6ae426a5 100644 --- a/testsuite/tests/typing-gadts/omega07.ml.reference +++ b/testsuite/tests/typing-gadts/omega07.ml.reference @@ -63,15 +63,7 @@ val plus_assoc : # val smaller : ('a succ, 'b succ) le -> ('a, 'b) le = # type (_, _) diff = Diff : 'c nat * ('a, 'c, 'b) plus -> ('a, 'b) diff # * * * * * * * * * val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = -# Characters 87-243: - ..match a, b,le with (* warning *) - | NZ, m, LeZ _ -> Diff (m, PlusZ m) - | NS x, NS y, LeS q -> - match diff q x y with Diff (m, p) -> Diff (m, PlusS p) -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a value that is not matched: -(NS _, NZ, _) -val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = +# val diff : ('a, 'b) le -> 'a nat -> 'b nat -> ('a, 'b) diff = # val diff : ('a, 'b) le -> 'b nat -> ('a, 'b) diff = # type (_, _) filter = Filter : ('m, 'n) le * ('a, 'm) seq -> ('a, 'n) filter val leS' : ('m, 'n) le -> ('m, 'n succ) le = diff --git a/testsuite/tests/typing-gadts/pr5332.ml b/testsuite/tests/typing-gadts/pr5332.ml index ef70e5a1..700e37b1 100644 --- a/testsuite/tests/typing-gadts/pr5332.ml +++ b/testsuite/tests/typing-gadts/pr5332.ml @@ -12,6 +12,6 @@ let f : type env a. (env, a) typ -> (env, a) typ -> int = fun ta tb -> | Tint, Tint -> 0 | Tbool, Tbool -> 1 | Tvar var, tb -> 2 + | _ -> . (* error *) ;; -let x = f Tint (Tvar Zero) -;; +(* let x = f Tint (Tvar Zero) ;; *) diff --git a/testsuite/tests/typing-gadts/pr5332.ml.reference b/testsuite/tests/typing-gadts/pr5332.ml.reference index 4cf48a22..3abbcfff 100644 --- a/testsuite/tests/typing-gadts/pr5332.ml.reference +++ b/testsuite/tests/typing-gadts/pr5332.ml.reference @@ -6,14 +6,9 @@ Tint : ('env, int) typ | Tbool : ('env, bool) typ | Tvar : ('env, 'a) var -> ('env, 'a) typ -# Characters 72-156: - .match ta, tb with - | Tint, Tint -> 0 - | Tbool, Tbool -> 1 - | Tvar var, tb -> 2 -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a value that is not matched: -(Tbool, Tvar _) -val f : ('env, 'a) typ -> ('env, 'a) typ -> int = -# Exception: Match_failure ("//toplevel//", 9, 1). -# +# Characters 162-163: + | _ -> . (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: (Tint, Tvar Zero) +# diff --git a/testsuite/tests/typing-gadts/pr5689.ml b/testsuite/tests/typing-gadts/pr5689.ml index 304f8e6c..856ddc27 100644 --- a/testsuite/tests/typing-gadts/pr5689.ml +++ b/testsuite/tests/typing-gadts/pr5689.ml @@ -9,7 +9,7 @@ type _ inline_t = let uppercase seq = let rec process: type a. a inline_t -> a inline_t = function - | Text txt -> Text (String.uppercase txt) + | Text txt -> Text (String.uppercase_ascii txt) | Bold xs -> Bold (List.map process xs) | Link lnk -> Link lnk | Mref (lnk, xs) -> Mref (lnk, List.map process xs) diff --git a/testsuite/tests/typing-gadts/pr5906.ml b/testsuite/tests/typing-gadts/pr5906.ml index 7b53c5c9..f0b2f0b0 100644 --- a/testsuite/tests/typing-gadts/pr5906.ml +++ b/testsuite/tests/typing-gadts/pr5906.ml @@ -7,7 +7,8 @@ type (_, _, _) binop = | Leq: ('a, 'a, bool) binop | Add: (int, int, int) binop -let eval (type a) (type b) (type c) (bop:(a,b,c) binop) (x:a constant) (y:b constant) : c constant = +let eval (type a) (type b) (type c) (bop:(a,b,c) binop) (x:a constant) + (y:b constant) : c constant = match bop, x, y with | Eq, Bool x, Bool y -> Bool (if x then y else not y) | Leq, Int x, Int y -> Bool (x <= y) diff --git a/testsuite/tests/typing-gadts/pr5906.ml.reference b/testsuite/tests/typing-gadts/pr5906.ml.reference index 85c13297..28a103c7 100644 --- a/testsuite/tests/typing-gadts/pr5906.ml.reference +++ b/testsuite/tests/typing-gadts/pr5906.ml.reference @@ -1,5 +1,5 @@ -# -Characters 524-524: +# +Characters 533-533: Error: Syntax error # diff --git a/testsuite/tests/typing-gadts/pr5948.ml.reference b/testsuite/tests/typing-gadts/pr5948.ml.reference index 7d774212..597cbfa6 100644 --- a/testsuite/tests/typing-gadts/pr5948.ml.reference +++ b/testsuite/tests/typing-gadts/pr5948.ml.reference @@ -13,7 +13,8 @@ val intB : [< `TagB ] -> int = ^^^^ Error: This expression has type ([< `TagA of 'b ] as 'a) -> 'b but an expression was expected of type a -> int - Type 'a is not compatible with type a = [< `TagA of int | `TagB ] + Type [< `TagA of 'b ] as 'a is not compatible with type + a = [< `TagA of int | `TagB ] The first variant type does not allow tag(s) `TagB # Characters 10-18: let _ = example6 (WrapPoly AandBTags) `TagB (* This causes a seg fault *) diff --git a/testsuite/tests/typing-gadts/pr6158.ml.principal.reference b/testsuite/tests/typing-gadts/pr6158.ml.principal.reference index e7d54587..c022a461 100644 --- a/testsuite/tests/typing-gadts/pr6158.ml.principal.reference +++ b/testsuite/tests/typing-gadts/pr6158.ml.principal.reference @@ -12,8 +12,8 @@ Error: This pattern matches values of type (int s, int s) eq # Characters 120-124: struct let f : ('a S.s, 'a S.t) eq -> unit = function Refl -> () end;; ^^^^ -Error: This pattern matches values of type (ex#0 S.s, ex#1 S.t) eq +Error: This pattern matches values of type ($0 S.s, $1 S.t) eq but a pattern was expected which matches values of type - (ex#0 S.s, ex#0 S.t) eq - The type constructor ex#0 would escape its scope + ('a S.s, 'a S.t) eq + The type constructor $0 would escape its scope # diff --git a/testsuite/tests/typing-gadts/pr6158.ml.reference b/testsuite/tests/typing-gadts/pr6158.ml.reference index c7d5c1ec..692130f3 100644 --- a/testsuite/tests/typing-gadts/pr6158.ml.reference +++ b/testsuite/tests/typing-gadts/pr6158.ml.reference @@ -9,7 +9,11 @@ Error: This pattern matches values of type (int s, int s) eq but a pattern was expected which matches values of type (int s, int t) eq Type int s is not compatible with type int t -# module M : - functor (S : sig type 'a t = T of 'a type 'a s = T of 'a end) -> - sig val f : (a#0 S.s, a#0 S.t) eq -> unit end +# Characters 120-124: + struct let f : ('a S.s, 'a S.t) eq -> unit = function Refl -> () end;; + ^^^^ +Error: This pattern matches values of type ($'a S.s, $'a S.s) eq + but a pattern was expected which matches values of type + ($'a S.s, $'a S.t) eq + The type constructor $'a would escape its scope # diff --git a/testsuite/tests/typing-gadts/pr6163.ml b/testsuite/tests/typing-gadts/pr6163.ml index ad5e8eda..dc5bb8c6 100644 --- a/testsuite/tests/typing-gadts/pr6163.ml +++ b/testsuite/tests/typing-gadts/pr6163.ml @@ -11,4 +11,5 @@ let f (Aux x) = | Succ (Succ Zero) -> "2" | Succ (Succ (Succ Zero)) -> "3" | Succ (Succ (Succ (Succ Zero))) -> "4" + | _ -> . (* error *) ;; diff --git a/testsuite/tests/typing-gadts/pr6163.ml.principal.reference b/testsuite/tests/typing-gadts/pr6163.ml.principal.reference index 0b771dc7..c1ac7bd1 100644 --- a/testsuite/tests/typing-gadts/pr6163.ml.principal.reference +++ b/testsuite/tests/typing-gadts/pr6163.ml.principal.reference @@ -5,14 +5,10 @@ Aux : [ `Succ of [< [< [< [ `Zero ] pre_nat ] pre_nat ] pre_nat ] ] nat -> aux -# Characters 19-157: - ..match x with - | Succ Zero -> "1" - | Succ (Succ Zero) -> "2" - | Succ (Succ (Succ Zero)) -> "3" - | Succ (Succ (Succ (Succ Zero))) -> "4" -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a value that is not matched: -Succ (Succ (Succ (Succ (Succ _)))) -val f : aux -> string = +# Characters 162-163: + | _ -> . (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: + Succ (Succ (Succ (Succ (Succ Zero)))) # diff --git a/testsuite/tests/typing-gadts/pr6163.ml.reference b/testsuite/tests/typing-gadts/pr6163.ml.reference index 0b771dc7..c1ac7bd1 100644 --- a/testsuite/tests/typing-gadts/pr6163.ml.reference +++ b/testsuite/tests/typing-gadts/pr6163.ml.reference @@ -5,14 +5,10 @@ Aux : [ `Succ of [< [< [< [ `Zero ] pre_nat ] pre_nat ] pre_nat ] ] nat -> aux -# Characters 19-157: - ..match x with - | Succ Zero -> "1" - | Succ (Succ Zero) -> "2" - | Succ (Succ (Succ Zero)) -> "3" - | Succ (Succ (Succ (Succ Zero))) -> "4" -Warning 8: this pattern-matching is not exhaustive. -Here is an example of a value that is not matched: -Succ (Succ (Succ (Succ (Succ _)))) -val f : aux -> string = +# Characters 162-163: + | _ -> . (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: + Succ (Succ (Succ (Succ (Succ Zero)))) # diff --git a/testsuite/tests/typing-gadts/pr6174.ml.principal.reference b/testsuite/tests/typing-gadts/pr6174.ml.principal.reference index 8f2be525..e47a32fa 100644 --- a/testsuite/tests/typing-gadts/pr6174.ml.principal.reference +++ b/testsuite/tests/typing-gadts/pr6174.ml.principal.reference @@ -2,6 +2,6 @@ # Characters 137-138: fun C k -> k (fun x -> x);; ^ -Error: This expression has type ex#0 but an expression was expected of type - ex#1 = (ex#2 -> ex#1) -> ex#1 +Error: This expression has type $0 but an expression was expected of type + $1 = ($2 -> $1) -> $1 # diff --git a/testsuite/tests/typing-gadts/pr6174.ml.reference b/testsuite/tests/typing-gadts/pr6174.ml.reference index 8f2be525..e47a32fa 100644 --- a/testsuite/tests/typing-gadts/pr6174.ml.reference +++ b/testsuite/tests/typing-gadts/pr6174.ml.reference @@ -2,6 +2,6 @@ # Characters 137-138: fun C k -> k (fun x -> x);; ^ -Error: This expression has type ex#0 but an expression was expected of type - ex#1 = (ex#2 -> ex#1) -> ex#1 +Error: This expression has type $0 but an expression was expected of type + $1 = ($2 -> $1) -> $1 # diff --git a/testsuite/tests/typing-gadts/pr6690.ml b/testsuite/tests/typing-gadts/pr6690.ml index 46ece4b2..151e9955 100644 --- a/testsuite/tests/typing-gadts/pr6690.ml +++ b/testsuite/tests/typing-gadts/pr6690.ml @@ -9,19 +9,22 @@ type ('a, 'result, 'visit_action) context = | Global : ('a, 'a, 'a visit_action) context ;; -let vexpr (type visit_action) : (_, _, visit_action) context -> _ -> visit_action = +let vexpr (type visit_action) + : (_, _, visit_action) context -> _ -> visit_action = function | Local -> fun _ -> raise Exit | Global -> fun _ -> raise Exit ;; -let vexpr (type visit_action) : ('a, 'result, visit_action) context -> 'a -> visit_action = +let vexpr (type visit_action) + : ('a, 'result, visit_action) context -> 'a -> visit_action = function | Local -> fun _ -> raise Exit | Global -> fun _ -> raise Exit ;; -let vexpr (type result) (type visit_action) : (unit, result, visit_action) context -> unit -> visit_action = +let vexpr (type result) (type visit_action) + : (unit, result, visit_action) context -> unit -> visit_action = function | Local -> fun _ -> raise Exit | Global -> fun _ -> raise Exit diff --git a/testsuite/tests/typing-gadts/pr6690.ml.principal.reference b/testsuite/tests/typing-gadts/pr6690.ml.principal.reference index 2ff16245..5c9215bf 100644 --- a/testsuite/tests/typing-gadts/pr6690.ml.principal.reference +++ b/testsuite/tests/typing-gadts/pr6690.ml.principal.reference @@ -5,19 +5,19 @@ type 'a local_visit_action type ('a, 'result, 'visit_action) context = Local : ('a, 'a * insert, 'a local_visit_action) context | Global : ('a, 'a, 'a visit_action) context -# Characters 133-139: +# Characters 137-143: | Global -> fun _ -> raise Exit ^^^^^^ -Error: This pattern matches values of type (ex#1, ex#1, visit_action) context +Error: This pattern matches values of type ($1, $1, visit_action) context but a pattern was expected which matches values of type - (ex#0, ex#0 * insert, visit_action) context - Type ex#1 is not compatible with type ex#0 -# Characters 141-147: + ($0, $0 * insert, visit_action) context + Type $1 is not compatible with type $0 +# Characters 145-151: | Global -> fun _ -> raise Exit ^^^^^^ -Error: This pattern matches values of type (ex#3, ex#3, visit_action) context +Error: This pattern matches values of type ($1, $1, visit_action) context but a pattern was expected which matches values of type - (ex#2, ex#2 * insert, visit_action) context - Type ex#3 is not compatible with type ex#2 -# val vexpr : (unit, 'a, 'b) context -> unit -> 'b = + ($0, $0 * insert, visit_action) context + Type $1 is not compatible with type $0 +# val vexpr : (unit, 'a, 'b) context -> unit -> 'b = # diff --git a/testsuite/tests/typing-gadts/pr6690.ml.reference b/testsuite/tests/typing-gadts/pr6690.ml.reference index 086f3237..ee67a095 100644 --- a/testsuite/tests/typing-gadts/pr6690.ml.reference +++ b/testsuite/tests/typing-gadts/pr6690.ml.reference @@ -5,23 +5,21 @@ type 'a local_visit_action type ('a, 'result, 'visit_action) context = Local : ('a, 'a * insert, 'a local_visit_action) context | Global : ('a, 'a, 'a visit_action) context -# Characters 11-162: - ..........(type visit_action) : (_, _, visit_action) context -> _ -> visit_action = - function +# Characters 104-109: | Local -> fun _ -> raise Exit - | Global -> fun _ -> raise Exit -Error: This expression has type (ex#0, ex#0 * insert, 'a) context -> 'b -> 'a - but an expression was expected of type - (ex#0, ex#0 * insert, 'a) context -> 'b -> 'a - The type constructor ex#0 would escape its scope -# Characters 11-170: - ..........(type visit_action) : ('a, 'result, visit_action) context -> 'a -> visit_action = - function + ^^^^^ +Error: This pattern matches values of type + ($0, $0 * insert, $0 local_visit_action) context + but a pattern was expected which matches values of type + ($0, $0 * insert, visit_action) context + The type constructor $0 would escape its scope +# Characters 112-117: | Local -> fun _ -> raise Exit - | Global -> fun _ -> raise Exit -Error: This expression has type (a#0, a#0 * insert, 'a) context -> a#0 -> 'a - but an expression was expected of type - (a#0, a#0 * insert, 'a) context -> a#0 -> 'a - The type constructor a#0 would escape its scope -# val vexpr : (unit, 'a, 'b) context -> unit -> 'b = + ^^^^^ +Error: This pattern matches values of type + ($'a, $'a * insert, $'a local_visit_action) context + but a pattern was expected which matches values of type + ($'a, $'a * insert, visit_action) context + The type constructor $'a would escape its scope +# val vexpr : (unit, 'a, 'b) context -> unit -> 'b = # diff --git a/testsuite/tests/typing-gadts/pr6980.ml b/testsuite/tests/typing-gadts/pr6980.ml new file mode 100644 index 00000000..7538b25f --- /dev/null +++ b/testsuite/tests/typing-gadts/pr6980.ml @@ -0,0 +1,11 @@ +type 'a t = [< `Foo | `Bar] as 'a;; +type 'a s = [< `Foo | `Bar | `Baz > `Bar] as 'a;; + +type 'a first = First : 'a second -> ('b t as 'a) first +and 'a second = Second : ('b s as 'a) second;; + +type aux = Aux : 'a t second * ('a -> int) -> aux;; + +let it : 'a. [< `Bar | `Foo > `Bar ] as 'a = `Bar;; + +let g (Aux(Second, f)) = f it;; diff --git a/testsuite/tests/typing-gadts/pr6980.ml.reference b/testsuite/tests/typing-gadts/pr6980.ml.reference new file mode 100644 index 00000000..5fd89921 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr6980.ml.reference @@ -0,0 +1,14 @@ + +# type 'a t = 'a constraint 'a = [< `Bar | `Foo ] +# type 'a s = 'a constraint 'a = [< `Bar | `Baz | `Foo > `Bar ] +# type 'a first = First : 'b t second -> ([< `Bar | `Foo ] as 'b) t first +and 'a second = Second : [< `Bar | `Baz | `Foo > `Bar ] s second +# type aux = Aux : ([< `Bar | `Foo ] as 'a) t second * ('a -> int) -> aux +# val it : [< `Bar | `Foo > `Bar ] = `Bar +# Characters 28-30: + let g (Aux(Second, f)) = f it;; + ^^ +Error: This expression has type [< `Bar | `Foo > `Bar ] + but an expression was expected of type [< `Bar | `Foo ] + Types for tag `Bar are incompatible +# diff --git a/testsuite/tests/typing-gadts/pr6993_bad.ml b/testsuite/tests/typing-gadts/pr6993_bad.ml new file mode 100644 index 00000000..122b50f3 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr6993_bad.ml @@ -0,0 +1,12 @@ +type (_, _) eqp = Y : ('a, 'a) eqp | N : string -> ('a, 'b) eqp +let f : ('a list, 'a) eqp -> unit = function N s -> print_string s;; + +module rec A : sig type t = B.t list end = + struct type t = B.t list end +and B : sig type t val eq : (B.t list, t) eqp end = + struct + type t = A.t + let eq = Y + end;; + +f B.eq;; diff --git a/testsuite/tests/typing-gadts/pr6993_bad.ml.reference b/testsuite/tests/typing-gadts/pr6993_bad.ml.reference new file mode 100644 index 00000000..cda1b16a --- /dev/null +++ b/testsuite/tests/typing-gadts/pr6993_bad.ml.reference @@ -0,0 +1,13 @@ + +# Characters 100-130: + let f : ('a list, 'a) eqp -> unit = function N s -> print_string s;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Y +type (_, _) eqp = Y : ('a, 'a) eqp | N : string -> ('a, 'b) eqp +val f : ('a list, 'a) eqp -> unit = +# module rec A : sig type t = B.t list end +and B : sig type t val eq : (B.t list, t) eqp end +# Exception: Match_failure ("//toplevel//", 2, 36). +# diff --git a/testsuite/tests/typing-gadts/pr7016.ml b/testsuite/tests/typing-gadts/pr7016.ml new file mode 100644 index 00000000..2b2eefbb --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7016.ml @@ -0,0 +1,9 @@ +type (_, _) t = + | Nil : ('tl, 'tl) t + | Cons : 'a * ('b, 'tl) t -> ('a * 'b, 'tl) t;; + +let get1 (Cons (x, _) : (_ * 'a, 'a) t) = x ;; (* warn, cf PR#6993 *) + +let get1' = function + | (Cons (x, _) : (_ * 'a, 'a) t) -> x + | Nil -> assert false ;; (* ok *) diff --git a/testsuite/tests/typing-gadts/pr7016.ml.reference b/testsuite/tests/typing-gadts/pr7016.ml.reference new file mode 100644 index 00000000..1176287e --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7016.ml.reference @@ -0,0 +1,13 @@ + +# type (_, _) t = + Nil : ('tl, 'tl) t + | Cons : 'a * ('b, 'tl) t -> ('a * 'b, 'tl) t +# Characters 10-44: + let get1 (Cons (x, _) : (_ * 'a, 'a) t) = x ;; (* warn, cf PR#6993 *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Nil +val get1 : ('b * 'a, 'a) t -> 'b = +# val get1' : ('b * 'a as 'a, 'a) t -> 'b = +# diff --git a/testsuite/tests/typing-gadts/pr7160.ml b/testsuite/tests/typing-gadts/pr7160.ml new file mode 100644 index 00000000..91263dc0 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7160.ml @@ -0,0 +1,5 @@ +type _ t = + Int : int -> int t | String : string -> string t | Same : 'l t -> 'l t;; +let rec f = function Int x -> x | Same s -> f s;; +type 'a tt = 'a t = + Int : int -> int tt | String : string -> string tt | Same : 'l1 t -> 'l2 tt;; diff --git a/testsuite/tests/typing-gadts/pr7160.ml.reference b/testsuite/tests/typing-gadts/pr7160.ml.reference new file mode 100644 index 00000000..5d5e9254 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7160.ml.reference @@ -0,0 +1,12 @@ + +# type _ t = + Int : int -> int t + | String : string -> string t + | Same : 'l t -> 'l t +# val f : int t -> int = +# Characters 0-97: + type 'a tt = 'a t = + Int : int -> int tt | String : string -> string tt | Same : 'l1 t -> 'l2 tt.. +Error: This variant or record definition does not match that of type 'a t + The types for field Same are not equal. +# diff --git a/testsuite/tests/typing-gadts/pr7214.ml b/testsuite/tests/typing-gadts/pr7214.ml new file mode 100644 index 00000000..ff077b4f --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7214.ml @@ -0,0 +1,8 @@ +type _ t = I : int t;; + +let f (type a) (x : a t) = + let module M = struct + let (I : a t) = x (* fail because of toplevel let *) + let x = (I : a t) + end in + () ;; diff --git a/testsuite/tests/typing-gadts/pr7214.ml.reference b/testsuite/tests/typing-gadts/pr7214.ml.reference new file mode 100644 index 00000000..b0211233 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7214.ml.reference @@ -0,0 +1,9 @@ + +# type _ t = I : int t +# Characters 61-62: + let (I : a t) = x (* fail because of toplevel let *) + ^ +Error: This pattern matches values of type int t + but a pattern was expected which matches values of type a t + Type int is not compatible with type a +# diff --git a/testsuite/tests/typing-gadts/pr7222.ml b/testsuite/tests/typing-gadts/pr7222.ml new file mode 100644 index 00000000..26b8a037 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7222.ml @@ -0,0 +1,10 @@ +type +'a n = private int +type nil = private Nil_type +type (_,_) elt = + | Elt_fine: 'nat n -> ('l,'nat * 'l) elt + | Elt: 'nat n -> ('l,'nat -> 'l) elt +type _ t = Nil : nil t | Cons : ('x, 'fx) elt * 'x t -> 'fx t;; + +let undetected: ('a -> 'b -> nil) t -> 'a n -> 'b n -> unit = fun sh i j -> + let Cons(Elt dim, _) = sh in () +;; diff --git a/testsuite/tests/typing-gadts/pr7222.ml.principal.reference b/testsuite/tests/typing-gadts/pr7222.ml.principal.reference new file mode 100644 index 00000000..3f28c3b2 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7222.ml.principal.reference @@ -0,0 +1,15 @@ + +# type +'a n = private int +type nil = private Nil_type +type (_, _) elt = + Elt_fine : 'nat n -> ('l, 'nat * 'l) elt + | Elt : 'nat n -> ('l, 'nat -> 'l) elt +type _ t = Nil : nil t | Cons : ('x, 'fx) elt * 'x t -> 'fx t +# Characters 83-99: + let Cons(Elt dim, _) = sh in () + ^^^^^^^^^^^^^^^^ +Error: This pattern matches values of type ('a -> $0 -> nil) t + but a pattern was expected which matches values of type + ('a -> 'b -> nil) t + The type constructor $0 would escape its scope +# diff --git a/testsuite/tests/typing-gadts/pr7222.ml.reference b/testsuite/tests/typing-gadts/pr7222.ml.reference new file mode 100644 index 00000000..15025953 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7222.ml.reference @@ -0,0 +1,15 @@ + +# type +'a n = private int +type nil = private Nil_type +type (_, _) elt = + Elt_fine : 'nat n -> ('l, 'nat * 'l) elt + | Elt : 'nat n -> ('l, 'nat -> 'l) elt +type _ t = Nil : nil t | Cons : ('x, 'fx) elt * 'x t -> 'fx t +# Characters 88-95: + let Cons(Elt dim, _) = sh in () + ^^^^^^^ +Error: This pattern matches values of type ($Cons_'x, 'a -> $Cons_'x) elt + but a pattern was expected which matches values of type + ($Cons_'x, 'a -> $'b -> nil) elt + The type constructor $'b would escape its scope +# diff --git a/testsuite/tests/typing-gadts/pr7230.ml b/testsuite/tests/typing-gadts/pr7230.ml new file mode 100644 index 00000000..6e588b64 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7230.ml @@ -0,0 +1,4 @@ +type _ t = T : int t;; + +(* Should raise Not_found *) +let _ = match (raise Not_found : float t) with _ -> .;; diff --git a/testsuite/tests/typing-gadts/pr7230.ml.reference b/testsuite/tests/typing-gadts/pr7230.ml.reference new file mode 100644 index 00000000..a05bcdf1 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7230.ml.reference @@ -0,0 +1,4 @@ + +# type _ t = T : int t +# Exception: Not_found. +# diff --git a/testsuite/tests/typing-gadts/pr7234.ml b/testsuite/tests/typing-gadts/pr7234.ml new file mode 100644 index 00000000..a8a06d2a --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7234.ml @@ -0,0 +1,7 @@ +type (_, _) eq = Eq : ('a, 'a) eq | Neq : int -> ('a, 'b) eq;; +type 'a t;; +let f (type a) (Neq n : (a, a t) eq) = n;; (* warn! *) + +module F (T : sig type _ t end) = struct + let f (type a) (Neq n : (a, a T.t) eq) = n (* warn! *) +end;; diff --git a/testsuite/tests/typing-gadts/pr7234.ml.principal.reference b/testsuite/tests/typing-gadts/pr7234.ml.principal.reference new file mode 100644 index 00000000..6210e218 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7234.ml.principal.reference @@ -0,0 +1,19 @@ + +# type (_, _) eq = Eq : ('a, 'a) eq | Neq : int -> ('a, 'b) eq +# type 'a t +# Characters 15-40: + let f (type a) (Neq n : (a, a t) eq) = n;; (* warn! *) + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Eq +val f : ('a, 'a t) eq -> int = +# Characters 58-85: + let f (type a) (Neq n : (a, a T.t) eq) = n (* warn! *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Eq +module F : + functor (T : sig type _ t end) -> sig val f : ('a, 'a T.t) eq -> int end +# diff --git a/testsuite/tests/typing-gadts/pr7234.ml.reference b/testsuite/tests/typing-gadts/pr7234.ml.reference new file mode 100644 index 00000000..6210e218 --- /dev/null +++ b/testsuite/tests/typing-gadts/pr7234.ml.reference @@ -0,0 +1,19 @@ + +# type (_, _) eq = Eq : ('a, 'a) eq | Neq : int -> ('a, 'b) eq +# type 'a t +# Characters 15-40: + let f (type a) (Neq n : (a, a t) eq) = n;; (* warn! *) + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Eq +val f : ('a, 'a t) eq -> int = +# Characters 58-85: + let f (type a) (Neq n : (a, a T.t) eq) = n (* warn! *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Eq +module F : + functor (T : sig type _ t end) -> sig val f : ('a, 'a T.t) eq -> int end +# diff --git a/testsuite/tests/typing-gadts/test.ml b/testsuite/tests/typing-gadts/test.ml index f4f23e0e..61cfd39f 100644 --- a/testsuite/tests/typing-gadts/test.ml +++ b/testsuite/tests/typing-gadts/test.ml @@ -97,6 +97,53 @@ module PR6862 = struct class d (Just x) = object method x : int = x end end;; +module Exhaustive2 = struct + type _ t = Int : int t + let f (x : bool t option) = match x with None -> () +end;; + +module PR6220 = struct + type 'a t = I : int t | F : float t + let f : int t -> int = function I -> 1 + let g : int t -> int = function I -> 1 | _ -> 2 (* no warning *) +end;; + +module PR6403 = struct + type (_, _) eq = Refl : ('a, 'a) eq + type empty = { bottom : 'a . 'a } + type ('a, 'b) sum = Left of 'a | Right of 'b + + let notequal : ((int, bool) eq, empty) sum -> empty = function + | Right empty -> empty +end;; + +module PR6437 = struct + type ('a, 'b) ctx = + | Nil : (unit, unit) ctx + | Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx + + type 'a var = + | O : ('a * unit) var + | S : 'a var -> ('a * unit) var + + let rec f : type g1 g2. (g1, g2) ctx * g1 var -> g2 var = function + | Cons g, O -> O + | Cons g, S n -> S (f (g, n)) + | _ -> . + (*| Nil, _ -> (assert false) *) (* warns, but shouldn't *) +end;; + +module PR6801 = struct + type _ value = + | String : string -> string value + | Float : float -> float value + | Any + + let print_string_value (x : string value) = + match x with + | String s -> print_endline s (* warn : Any *) +end;; + module Existential_escape = struct type _ t = C : int -> int t @@ -114,7 +161,7 @@ module Rectype = ;; module Or_patterns = -struct + struct type _ t = | IntLit : int -> int t | BoolLit : bool -> bool t @@ -350,7 +397,7 @@ let f : type a b. (a,b) eq -> < m : a; .. > -> < m : b > = let f : type a b. (a,b) eq -> [> `A of a] -> [> `A of b] = fun Eq o -> o ;; (* fail *) -let f (type a) (type b) (eq : (a,b) eq) (v : [> `A of a]) : [> `A of b] = +let f (type a b) (eq : (a,b) eq) (v : [> `A of a]) : [> `A of b] = match eq with Eq -> v ;; (* should fail *) let f : type a b. (a,b) eq -> [< `A of a | `B] -> [< `A of b | `B] = diff --git a/testsuite/tests/typing-gadts/test.ml.principal.reference b/testsuite/tests/typing-gadts/test.ml.principal.reference index cba7f347..b69bb6b6 100644 --- a/testsuite/tests/typing-gadts/test.ml.principal.reference +++ b/testsuite/tests/typing-gadts/test.ml.principal.reference @@ -65,15 +65,57 @@ module PR6862 : type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt class d : int opt -> object method x : int end end +# module Exhaustive2 : + sig type _ t = Int : int t val f : bool t option -> unit end +# Characters 146-147: + let g : int t -> int = function I -> 1 | _ -> 2 (* no warning *) + ^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +module PR6220 : + sig + type 'a t = I : int t | F : float t + val f : int t -> int + val g : int t -> int + end +# module PR6403 : + sig + type (_, _) eq = Refl : ('a, 'a) eq + type empty = { bottom : 'a. 'a; } + type ('a, 'b) sum = Left of 'a | Right of 'b + val notequal : ((int, bool) eq, empty) sum -> empty + end +# module PR6437 : + sig + type ('a, 'b) ctx = + Nil : (unit, unit) ctx + | Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx + type 'a var = O : ('a * unit) var | S : 'a var -> ('a * unit) var + val f : ('g1, 'g2) ctx * 'g1 var -> 'g2 var + end +# Characters 175-221: + ....match x with + | String s -> print_endline s................. +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Any +module PR6801 : + sig + type _ value = + String : string -> string value + | Float : float -> float value + | Any + val print_string_value : string value -> unit + end # Characters 118-119: let eval (D x) = x ^ -Error: This expression has type a#2 t but an expression was expected of type - a#2 t - The type constructor a#2 would escape its scope +Error: This expression has type $D_'a t + but an expression was expected of type 'a + The type constructor $D_'a would escape its scope # module Rectype : sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end -# Characters 178-186: +# Characters 180-188: | (IntLit _ | BoolLit _) -> () ^^^^^^^^ Error: This pattern matches values of type int t @@ -106,21 +148,21 @@ Error: This pattern matches values of type 'a t function Int -> ky (1 : a) 1 (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # Characters 70-82: let r = match x with Int -> ky (1 : a) 1 (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # Characters 69-81: let r = match x with Int -> ky 1 (1 : a) (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # val test : 'a t -> int = @@ -144,7 +186,7 @@ Error: This expression has type int option match v with Int -> let y = either 1 x in y ^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # val f : 'a t -> 'a -> 'a = @@ -215,7 +257,7 @@ Error: This expression has type [> `A of a ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation -# Characters 97-98: +# Characters 90-91: match eq with Eq -> v ;; (* should fail *) ^ Error: This expression has type [> `A of a ] @@ -265,7 +307,7 @@ val f : 'a ty -> 'a t -> int = | TA, D z -> z Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: -(TE TC, D [| |]) +(TE TC, D [| 0. |]) val f : 'a ty -> 'a t -> int = # Characters 147-154: | D [|1.0|], TE TC -> 14 @@ -287,7 +329,7 @@ Error: This pattern matches values of type 'a array | {left=TA; right=D z} -> z Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: -{left=TE TC; right=D [| |]} +{left=TE TC; right=D [| 0. |]} type ('a, 'b) pair = { left : 'a; right : 'b; } val f : 'a ty -> 'a t -> int = # module M : sig type 'a t val eq : ('a t, 'b t) eq end @@ -309,22 +351,21 @@ type _ int_bar = IB_constr : < bar : int; .. > int_bar ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < foo : int > - Type ex#17 = < bar : int; .. > is not compatible with type < > + Type $0 = < bar : int; .. > is not compatible with type < > The second object type has no method bar # Characters 98-99: (x:) ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < bar : int; foo : int > - Type ex#19 = < bar : int; .. > is not compatible with type - < bar : int > + Type $0 = < bar : int; .. > is not compatible with type < bar : int > The first object type has an abstract row, it cannot be closed -# Characters 98-99: +# Characters 97-121: (x:) - ^ -Error: This expression has type < bar : int; foo : int; .. > as 'a + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type < bar : int; foo : int; .. > but an expression was expected of type 'a - The type constructor ex#22 would escape its scope + The type constructor $1 would escape its scope # val g : 'a -> 'a int_foo -> 'a int_bar -> 'a = # val g : 'a -> 'a int_foo -> 'a int_bar -> 'a * int * int = # type 'a ty = Int : int -> int ty diff --git a/testsuite/tests/typing-gadts/test.ml.reference b/testsuite/tests/typing-gadts/test.ml.reference index a3ea98d1..2ef37155 100644 --- a/testsuite/tests/typing-gadts/test.ml.reference +++ b/testsuite/tests/typing-gadts/test.ml.reference @@ -65,15 +65,57 @@ module PR6862 : type _ opt = Just : 'a -> 'a opt | Nothing : 'a opt class d : int opt -> object method x : int end end +# module Exhaustive2 : + sig type _ t = Int : int t val f : bool t option -> unit end +# Characters 146-147: + let g : int t -> int = function I -> 1 | _ -> 2 (* no warning *) + ^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +module PR6220 : + sig + type 'a t = I : int t | F : float t + val f : int t -> int + val g : int t -> int + end +# module PR6403 : + sig + type (_, _) eq = Refl : ('a, 'a) eq + type empty = { bottom : 'a. 'a; } + type ('a, 'b) sum = Left of 'a | Right of 'b + val notequal : ((int, bool) eq, empty) sum -> empty + end +# module PR6437 : + sig + type ('a, 'b) ctx = + Nil : (unit, unit) ctx + | Cons : ('a, 'b) ctx -> ('a * unit, 'b * unit) ctx + type 'a var = O : ('a * unit) var | S : 'a var -> ('a * unit) var + val f : ('g1, 'g2) ctx * 'g1 var -> 'g2 var + end +# Characters 175-221: + ....match x with + | String s -> print_endline s................. +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Any +module PR6801 : + sig + type _ value = + String : string -> string value + | Float : float -> float value + | Any + val print_string_value : string value -> unit + end # Characters 118-119: let eval (D x) = x ^ -Error: This expression has type a#2 t but an expression was expected of type - a#2 t - The type constructor a#2 would escape its scope +Error: This expression has type $D_'a t + but an expression was expected of type 'a + The type constructor $D_'a would escape its scope # module Rectype : sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end -# Characters 178-186: +# Characters 180-188: | (IntLit _ | BoolLit _) -> () ^^^^^^^^ Error: This pattern matches values of type int t @@ -107,21 +149,21 @@ Error: This pattern matches values of type 'a t function Int -> ky (1 : a) 1 (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # Characters 70-82: let r = match x with Int -> ky (1 : a) 1 (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # Characters 69-81: let r = match x with Int -> ky 1 (1 : a) (* fails *) ^^^^^^^^^^^^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # val test : 'a t -> int = @@ -145,7 +187,7 @@ Error: This expression has type int option match v with Int -> let y = either 1 x in y ^ Error: This expression has type a = int - but an expression was expected of type a = int + but an expression was expected of type 'a This instance of int is ambiguous: it would escape the scope of its equation # val f : 'a t -> 'a -> 'a = @@ -209,7 +251,7 @@ Error: This expression has type [> `A of a ] Type a is not compatible with type b = a This instance of a is ambiguous: it would escape the scope of its equation -# Characters 97-98: +# Characters 90-91: match eq with Eq -> v ;; (* should fail *) ^ Error: This expression has type [> `A of a ] @@ -252,7 +294,7 @@ val f : 'a ty -> 'a t -> int = | TA, D z -> z Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: -(TE TC, D [| |]) +(TE TC, D [| 0. |]) val f : 'a ty -> 'a t -> int = # Characters 147-154: | D [|1.0|], TE TC -> 14 @@ -274,7 +316,7 @@ Error: This pattern matches values of type 'a array | {left=TA; right=D z} -> z Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: -{left=TE TC; right=D [| |]} +{left=TE TC; right=D [| 0. |]} type ('a, 'b) pair = { left : 'a; right : 'b; } val f : 'a ty -> 'a t -> int = # module M : sig type 'a t val eq : ('a t, 'b t) eq end @@ -296,22 +338,21 @@ type _ int_bar = IB_constr : < bar : int; .. > int_bar ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < foo : int > - Type ex#17 = < bar : int; .. > is not compatible with type < > + Type $0 = < bar : int; .. > is not compatible with type < > The second object type has no method bar # Characters 98-99: (x:) ^ Error: This expression has type t = < foo : int; .. > but an expression was expected of type < bar : int; foo : int > - Type ex#19 = < bar : int; .. > is not compatible with type - < bar : int > + Type $0 = < bar : int; .. > is not compatible with type < bar : int > The first object type has an abstract row, it cannot be closed -# Characters 98-99: +# Characters 97-121: (x:) - ^ -Error: This expression has type < bar : int; foo : int; .. > as 'a + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type < bar : int; foo : int; .. > but an expression was expected of type 'a - The type constructor ex#22 would escape its scope + The type constructor $1 would escape its scope # val g : 'a -> 'a int_foo -> 'a int_bar -> 'a = # val g : 'a -> 'a int_foo -> 'a int_bar -> 'a * int * int = # type 'a ty = Int : int -> int ty diff --git a/testsuite/tests/typing-gadts/yallop_bugs.ml b/testsuite/tests/typing-gadts/yallop_bugs.ml index 08708a67..983822bc 100644 --- a/testsuite/tests/typing-gadts/yallop_bugs.ml +++ b/testsuite/tests/typing-gadts/yallop_bugs.ml @@ -3,7 +3,7 @@ type (_, _) eq = Refl : ('a, 'a) eq let magic : 'a 'b. 'a -> 'b = - fun (type a) (type b) (x : a) -> + fun (type a b) (x : a) -> let module M = (functor (T : sig type 'a t end) -> struct diff --git a/testsuite/tests/typing-gadts/yallop_bugs.ml.principal.reference b/testsuite/tests/typing-gadts/yallop_bugs.ml.principal.reference index b9f0cac9..accbebf4 100644 --- a/testsuite/tests/typing-gadts/yallop_bugs.ml.principal.reference +++ b/testsuite/tests/typing-gadts/yallop_bugs.ml.principal.reference @@ -1,5 +1,5 @@ -# Characters 240-248: +# Characters 233-241: let f (Refl : (a T.t, b T.t) eq) = (x :> b) ^^^^^^^^ Error: Type a is not a subtype of b diff --git a/testsuite/tests/typing-gadts/yallop_bugs.ml.reference b/testsuite/tests/typing-gadts/yallop_bugs.ml.reference index b9f0cac9..accbebf4 100644 --- a/testsuite/tests/typing-gadts/yallop_bugs.ml.reference +++ b/testsuite/tests/typing-gadts/yallop_bugs.ml.reference @@ -1,5 +1,5 @@ -# Characters 240-248: +# Characters 233-241: let f (Refl : (a T.t, b T.t) eq) = (x :> b) ^^^^^^^^ Error: Type a is not a subtype of b diff --git a/testsuite/tests/typing-immediate/Makefile b/testsuite/tests/typing-immediate/Makefile new file mode 100644 index 00000000..7fc00661 --- /dev/null +++ b/testsuite/tests/typing-immediate/Makefile @@ -0,0 +1,18 @@ +#************************************************************************** +#* * +#* 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=../.. +include $(BASEDIR)/makefiles/Makefile.toplevel +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-immediate/immediate.ml b/testsuite/tests/typing-immediate/immediate.ml new file mode 100644 index 00000000..996469f9 --- /dev/null +++ b/testsuite/tests/typing-immediate/immediate.ml @@ -0,0 +1,86 @@ +module type S = sig type t [@@immediate] end;; +module F (M : S) : S = M;; + +(* VALID DECLARATIONS *) + +module A = struct + (* Abstract types can be immediate *) + type t [@@immediate] + + (* [@@immediate] tag here is unnecessary but valid since t has it *) + type s = t [@@immediate] + + (* Again, valid alias even without tag *) + type r = s + + (* Mutually recursive declarations work as well *) + type p = q [@@immediate] + and q = int +end;; + +(* Valid using with constraints *) +module type X = sig type t end;; +module Y = struct type t = int end;; +module Z = ((Y : X with type t = int) : sig type t [@@immediate] end);; + +(* Valid using an explicit signature *) +module M_valid : S = struct type t = int end;; +module FM_valid = F (struct type t = int end);; + +(* Practical usage over modules *) +module Foo : sig type t val x : t ref end = struct + type t = int + let x = ref 0 +end;; + +module Bar : sig type t [@@immediate] val x : t ref end = struct + type t = int + let x = ref 0 +end;; + +let test f = + let start = Sys.time() in f (); + (Sys.time() -. start);; + +let test_foo () = + for i = 0 to 100_000_000 do + Foo.x := !Foo.x + done;; + +let test_bar () = + for i = 0 to 100_000_000 do + Bar.x := !Bar.x + done;; + +(* Uncomment these to test. Should see substantial speedup! +let () = Printf.printf "No @@immediate: %fs\n" (test test_foo) +let () = Printf.printf "With @@immediate: %fs\n" (test test_bar) *) + + +(* INVALID DECLARATIONS *) + +(* Cannot directly declare a non-immediate type as immediate *) +module B = struct + type t = string [@@immediate] +end;; + +(* Not guaranteed that t is immediate, so this is an invalid declaration *) +module C = struct + type t + type s = t [@@immediate] +end;; + +(* Can't ascribe to an immediate type signature with a non-immediate type *) +module D : sig type t [@@immediate] end = struct + type t = string +end;; + +(* Same as above but with explicit signature *) +module M_invalid : S = struct type t = string end;; +module FM_invalid = F (struct type t = string end);; + +(* Can't use a non-immediate type even if mutually recursive *) +module E = struct + type t = s [@@immediate] + and s = string +end;; diff --git a/testsuite/tests/typing-immediate/immediate.ml.reference b/testsuite/tests/typing-immediate/immediate.ml.reference new file mode 100644 index 00000000..d62a7061 --- /dev/null +++ b/testsuite/tests/typing-immediate/immediate.ml.reference @@ -0,0 +1,71 @@ + +# module type S = sig type t [@@immediate] end +# module F : functor (M : S) -> S +# module A : + sig + type t [@@immediate] + type s = t [@@immediate] + type r = s + type p = q [@@immediate] + and q = int + end +# module type X = sig type t end +# module Y : sig type t = int end +# module Z : sig type t [@@immediate] end +# module M_valid : S +# module FM_valid : S +# module Foo : sig type t val x : t ref end +# module Bar : sig type t [@@immediate] val x : t ref end +# val test : (unit -> 'a) -> float = +# val test_foo : unit -> unit = +# val test_bar : unit -> unit = +# * * Characters 306-335: + type t = string [@@immediate] + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Types marked with the immediate attribute must be + non-pointer types like int or bool +# Characters 106-130: + type s = t [@@immediate] + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Types marked with the immediate attribute must be + non-pointer types like int or bool +# Characters 120-148: + ..........................................struct + type t = string + end.. +Error: Signature mismatch: + Modules do not match: + sig type t = string end + is not included in + sig type t [@@immediate] end + Type declarations do not match: + type t = string + is not included in + type t [@@immediate] + the first is not an immediate type. +# Characters 72-98: + module M_invalid : S = struct type t = string end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: sig type t = string end is not included in S + Type declarations do not match: + type t = string + is not included in + type t [@@immediate] + the first is not an immediate type. +# Characters 23-49: + module FM_invalid = F (struct type t = string end);; + ^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Signature mismatch: + Modules do not match: sig type t = string end is not included in S + Type declarations do not match: + type t = string + is not included in + type t [@@immediate] + the first is not an immediate type. +# Characters 85-109: + type t = s [@@immediate] + ^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Types marked with the immediate attribute must be + non-pointer types like int or bool +# diff --git a/testsuite/tests/typing-implicit_unpack/Makefile b/testsuite/tests/typing-implicit_unpack/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-implicit_unpack/Makefile +++ b/testsuite/tests/typing-implicit_unpack/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference index 32c49a29..8f2d22b3 100644 --- a/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference +++ b/testsuite/tests/typing-implicit_unpack/implicit_unpack.ml.reference @@ -86,6 +86,7 @@ module type MapT = val remove : key -> 'a t -> 'a t val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t + val union : (key -> 'a -> 'a -> 'a option) -> 'a t -> 'a t -> 'a t val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val iter : (key -> 'a -> unit) -> 'a t -> unit @@ -123,6 +124,7 @@ module SSMap : val remove : key -> 'a t -> 'a t val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t + val union : (key -> 'a -> 'a -> 'a option) -> 'a t -> 'a t -> 'a t val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val iter : (key -> 'a -> unit) -> 'a t -> unit diff --git a/testsuite/tests/typing-labels/Makefile b/testsuite/tests/typing-labels/Makefile index 299656b2..c11a415f 100644 --- a/testsuite/tests/typing-labels/Makefile +++ b/testsuite/tests/typing-labels/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.several diff --git a/testsuite/tests/typing-misc-bugs/Makefile b/testsuite/tests/typing-misc-bugs/Makefile index 04ded445..994943bc 100644 --- a/testsuite/tests/typing-misc-bugs/Makefile +++ b/testsuite/tests/typing-misc-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** include ../../makefiles/Makefile.okbad include ../../makefiles/Makefile.common diff --git a/testsuite/tests/typing-misc-bugs/core_array_reduced_ok.ml b/testsuite/tests/typing-misc-bugs/core_array_reduced_ok.ml new file mode 100644 index 00000000..bd55cc0a --- /dev/null +++ b/testsuite/tests/typing-misc-bugs/core_array_reduced_ok.ml @@ -0,0 +1,94 @@ +type sexp = A of string | L of sexp list +type 'a t = 'a array +let _ = fun (_ : 'a t) -> () + +let array_of_sexp _ _ = [| |] +let sexp_of_array _ _ = A "foo" +let sexp_of_int _ = A "42" +let int_of_sexp _ = 42 + +let t_of_sexp : 'a . (sexp -> 'a) -> sexp -> 'a t= + let _tp_loc = "core_array.ml.t" in + fun _of_a -> fun t -> (array_of_sexp _of_a) t +let _ = t_of_sexp +let sexp_of_t : 'a . ('a -> sexp) -> 'a t -> sexp= + fun _of_a -> fun v -> (sexp_of_array _of_a) v +let _ = sexp_of_t +module T = + struct + module Int = + struct + type t_ = int array + let _ = fun (_ : t_) -> () + + let t__of_sexp: sexp -> t_ = + let _tp_loc = "core_array.ml.T.Int.t_" in + fun t -> (array_of_sexp int_of_sexp) t + let _ = t__of_sexp + let sexp_of_t_: t_ -> sexp = + fun v -> (sexp_of_array sexp_of_int) v + let _ = sexp_of_t_ + end + end +module type Permissioned = + sig + type ('a,-'perms) t + end +module Permissioned : + sig + type ('a,-'perms) t + include + sig + val t_of_sexp : + (sexp -> 'a) -> + (sexp -> 'perms) -> sexp -> ('a,'perms) t + val sexp_of_t : + ('a -> sexp) -> + ('perms -> sexp) -> ('a,'perms) t -> sexp + end + module Int : + sig + type nonrec -'perms t = (int,'perms) t + include + sig + val t_of_sexp : + (sexp -> 'perms) -> sexp -> 'perms t + val sexp_of_t : + ('perms -> sexp) -> 'perms t -> sexp + end + end + end = + struct + type ('a,-'perms) t = 'a array + let _ = fun (_ : ('a,'perms) t) -> () + + let t_of_sexp : + 'a 'perms . + (sexp -> 'a) -> + (sexp -> 'perms) -> sexp -> ('a,'perms) t= + let _tp_loc = "core_array.ml.Permissioned.t" in + fun _of_a -> fun _of_perms -> fun t -> (array_of_sexp _of_a) t + let _ = t_of_sexp + let sexp_of_t : + 'a 'perms . + ('a -> sexp) -> + ('perms -> sexp) -> ('a,'perms) t -> sexp= + fun _of_a -> fun _of_perms -> fun v -> (sexp_of_array _of_a) v + let _ = sexp_of_t + module Int = + struct + include T.Int + type -'perms t = t_ + let _ = fun (_ : 'perms t) -> () + + let t_of_sexp : + 'perms . (sexp -> 'perms) -> sexp -> 'perms t= + let _tp_loc = "core_array.ml.Permissioned.Int.t" in + fun _of_perms -> fun t -> t__of_sexp t + let _ = t_of_sexp + let sexp_of_t : + 'perms . ('perms -> sexp) -> 'perms t -> sexp= + fun _of_perms -> fun v -> sexp_of_t_ v + let _ = sexp_of_t + end + end diff --git a/testsuite/tests/typing-misc-bugs/pr6946_bad.ml b/testsuite/tests/typing-misc-bugs/pr6946_bad.ml new file mode 100644 index 00000000..bbaefe90 --- /dev/null +++ b/testsuite/tests/typing-misc-bugs/pr6946_bad.ml @@ -0,0 +1,2 @@ +external foo : int = "%ignore";; +let _ = foo ();; diff --git a/testsuite/tests/typing-misc/Makefile b/testsuite/tests/typing-misc/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-misc/Makefile +++ b/testsuite/tests/typing-misc/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-misc/pr6939.ml b/testsuite/tests/typing-misc/pr6939.ml new file mode 100755 index 00000000..0ed82035 --- /dev/null +++ b/testsuite/tests/typing-misc/pr6939.ml @@ -0,0 +1,4 @@ + +let rec x = [| x |]; 1.;; + +let rec x = let u = [|y|] in 10. and y = 1.;; diff --git a/testsuite/tests/typing-misc/pr6939.ml.reference b/testsuite/tests/typing-misc/pr6939.ml.reference new file mode 100644 index 00000000..3a452cce --- /dev/null +++ b/testsuite/tests/typing-misc/pr6939.ml.reference @@ -0,0 +1,18 @@ + +# Characters 13-20: + let rec x = [| x |]; 1.;; + ^^^^^^^ +Warning 10: this expression should have type unit. +Characters 13-24: + let rec x = [| x |]; 1.;; + ^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +# Characters 17-18: + let rec x = let u = [|y|] in 10. and y = 1.;; + ^ +Warning 26: unused variable u. +Characters 13-33: + let rec x = let u = [|y|] in 10. and y = 1.;; + ^^^^^^^^^^^^^^^^^^^^ +Error: This kind of expression is not allowed as right-hand side of `let rec' +# diff --git a/testsuite/tests/typing-misc/pr7103.ml b/testsuite/tests/typing-misc/pr7103.ml new file mode 100644 index 00000000..bdca4b34 --- /dev/null +++ b/testsuite/tests/typing-misc/pr7103.ml @@ -0,0 +1,14 @@ +type 'a t +type a + +let f : < .. > t -> unit = fun _ -> ();; + +let g : [< `b] t -> unit = fun _ -> ();; + +let h : [> `b] t -> unit = fun _ -> ();; + +let _ = fun (x : a t) -> f x;; + +let _ = fun (x : a t) -> g x;; + +let _ = fun (x : a t) -> h x;; diff --git a/testsuite/tests/typing-misc/pr7103.ml.reference b/testsuite/tests/typing-misc/pr7103.ml.reference new file mode 100644 index 00000000..e7457063 --- /dev/null +++ b/testsuite/tests/typing-misc/pr7103.ml.reference @@ -0,0 +1,25 @@ + +# type 'a t +type a +val f : < .. > t -> unit = +# val g : [< `b ] t -> unit = +# val h : [> `b ] t -> unit = +# Characters 28-29: + let _ = fun (x : a t) -> f x;; + ^ +Error: This expression has type a t but an expression was expected of type + (< .. > as 'a) t + Type a is not compatible with type < .. > as 'a +# Characters 28-29: + let _ = fun (x : a t) -> g x;; + ^ +Error: This expression has type a t but an expression was expected of type + ([< `b ] as 'a) t + Type a is not compatible with type [< `b ] as 'a +# Characters 28-29: + let _ = fun (x : a t) -> h x;; + ^ +Error: This expression has type a t but an expression was expected of type + ([> `b ] as 'a) t + Type a is not compatible with type [> `b ] as 'a +# diff --git a/testsuite/tests/typing-misc/printing.ml b/testsuite/tests/typing-misc/printing.ml new file mode 100644 index 00000000..8a9c2310 --- /dev/null +++ b/testsuite/tests/typing-misc/printing.ml @@ -0,0 +1,7 @@ +(* PR#7012 *) + +type t = [ 'A_name | `Hi ];; + +let f (x:'id_arg) = x;; + +let f (x:'Id_arg) = x;; diff --git a/testsuite/tests/typing-misc/printing.ml.reference b/testsuite/tests/typing-misc/printing.ml.reference new file mode 100644 index 00000000..21763b2d --- /dev/null +++ b/testsuite/tests/typing-misc/printing.ml.reference @@ -0,0 +1,9 @@ + +# Characters 26-33: + type t = [ 'A_name | `Hi ];; + ^^^^^^^ +Error: The type 'A_name is not a polymorphic variant type +Hint: Did you mean `A_name? +# val f : 'id_arg -> 'id_arg = +# val f : 'Id_arg -> 'Id_arg = +# diff --git a/testsuite/tests/typing-missing-cmi/Makefile b/testsuite/tests/typing-missing-cmi/Makefile new file mode 100644 index 00000000..6a18f649 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi/Makefile @@ -0,0 +1,17 @@ + +.PHONY: default +default: subdir/m.ml a.ml b.ml main.ml + @printf " ... testing 'main.ml'"; + @$(OCAMLC) -c subdir/m.ml; + @$(OCAMLC) -c -I subdir a.ml; + @$(OCAMLC) -c -I subdir b.ml; + @$(OCAMLC) -c main.ml > main.ml.result 2>&1 || : + @$(DIFF) main.ml.result main.ml.reference >/dev/null \ + && echo " => passed" || echo " => failed" + +.PHONY: clean +clean: + @rm -f subdir/m.cm[io] *.cm[io] main.ml.result + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-missing-cmi/a.ml b/testsuite/tests/typing-missing-cmi/a.ml new file mode 100644 index 00000000..0631d439 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi/a.ml @@ -0,0 +1 @@ +let (a : M.a) = 2 diff --git a/testsuite/tests/typing-missing-cmi/b.ml b/testsuite/tests/typing-missing-cmi/b.ml new file mode 100644 index 00000000..eb1e004a --- /dev/null +++ b/testsuite/tests/typing-missing-cmi/b.ml @@ -0,0 +1 @@ +let (b : M.b) = 2 diff --git a/testsuite/tests/typing-missing-cmi/main.ml b/testsuite/tests/typing-missing-cmi/main.ml new file mode 100644 index 00000000..1bf8c991 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi/main.ml @@ -0,0 +1 @@ +let _ = A.a = B.b diff --git a/testsuite/tests/typing-missing-cmi/main.ml.reference b/testsuite/tests/typing-missing-cmi/main.ml.reference new file mode 100644 index 00000000..dfcfd020 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi/main.ml.reference @@ -0,0 +1,5 @@ +File "main.ml", line 1, characters 14-17: +Error: This expression has type M.b but an expression was expected of type + M.a +M.b is abstract because no corresponding cmi file was found in path. +M.a is abstract because no corresponding cmi file was found in path. diff --git a/testsuite/tests/typing-missing-cmi/subdir/m.ml b/testsuite/tests/typing-missing-cmi/subdir/m.ml new file mode 100644 index 00000000..32870c88 --- /dev/null +++ b/testsuite/tests/typing-missing-cmi/subdir/m.ml @@ -0,0 +1,2 @@ +type a = int +type b = a diff --git a/testsuite/tests/typing-modules-bugs/Makefile b/testsuite/tests/typing-modules-bugs/Makefile index 04ded445..994943bc 100644 --- a/testsuite/tests/typing-modules-bugs/Makefile +++ b/testsuite/tests/typing-modules-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** include ../../makefiles/Makefile.okbad include ../../makefiles/Makefile.common diff --git a/testsuite/tests/typing-modules-bugs/pr51_ok.ml b/testsuite/tests/typing-modules-bugs/pr51_ok.ml new file mode 100644 index 00000000..0826fa31 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr51_ok.ml @@ -0,0 +1,18 @@ +module X=struct + module type SIG=sig type t=int val x:t end + module F(Y:SIG) : SIG = struct type t=Y.t let x=Y.x end +end;; +module DUMMY=struct type t=int let x=2 end;; +let x = (3 : X.F(DUMMY).t);; + +module X2=struct + module type SIG=sig type t=int val x:t end + module F(Y:SIG)(Z:SIG) = struct + type t=Y.t + let x=Y.x + type t'=Z.t + let x'=Z.x + end +end;; +let x = (3 : X2.F(DUMMY)(DUMMY).t);; +let x = (3 : X2.F(DUMMY)(DUMMY).t');; diff --git a/testsuite/tests/typing-modules-bugs/pr5663_ok.ml b/testsuite/tests/typing-modules-bugs/pr5663_ok.ml new file mode 100644 index 00000000..ce791f90 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr5663_ok.ml @@ -0,0 +1,7 @@ +module F (M : sig + type 'a t + type 'a u = string + val f : unit -> _ u t + end) = struct + let t = M.f () + end diff --git a/testsuite/tests/typing-modules-bugs/pr6513_ok.ml b/testsuite/tests/typing-modules-bugs/pr6513_ok.ml index f23fc599..7474ba93 100644 --- a/testsuite/tests/typing-modules-bugs/pr6513_ok.ml +++ b/testsuite/tests/typing-modules-bugs/pr6513_ok.ml @@ -18,8 +18,11 @@ sig type u end -module Make: functor (Html5: Html5_sigs.T with type 'a Xml.wrap = 'a and type 'a wrap = 'a and type 'a list_wrap = 'a list) -> S with - type t = Html5_types.div Html5.elt and - type u = < foo: Html5.uri > +module Make: functor (Html5: Html5_sigs.T + with type 'a Xml.wrap = 'a and + type 'a wrap = 'a and + type 'a list_wrap = 'a list) + -> S with type t = Html5_types.div Html5.elt and + type u = < foo: Html5.uri > end *) diff --git a/testsuite/tests/typing-modules-bugs/pr6651_ok.ml b/testsuite/tests/typing-modules-bugs/pr6651_ok.ml new file mode 100644 index 00000000..9c430051 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6651_ok.ml @@ -0,0 +1,13 @@ +module type S = sig + module type T + module X : T +end + +module F (X : S) = X.X + +module M = struct + module type T = sig type t end + module X = struct type t = int end +end + +type t = F(M).t diff --git a/testsuite/tests/typing-modules-bugs/pr6752_ok.ml b/testsuite/tests/typing-modules-bugs/pr6752_ok.ml new file mode 100644 index 00000000..846af0d1 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6752_ok.ml @@ -0,0 +1,43 @@ +module Common0 = + struct + type msg = Msg + + let handle_msg = ref (function _ -> failwith "Unable to handle message") + let extend_handle f = + let old = !handle_msg in + handle_msg := f old + + let q : _ Queue.t = Queue.create () + let add msg = Queue.add msg q + let handle_queue_messages () = Queue.iter !handle_msg q + end + +let q' : Common0.msg Queue.t = Common0.q + +module Common = + struct + type msg = .. + + let handle_msg = ref (function _ -> failwith "Unable to handle message") + let extend_handle f = + let old = !handle_msg in + handle_msg := f old + + let q : _ Queue.t = Queue.create () + let add msg = Queue.add msg q + let handle_queue_messages () = Queue.iter !handle_msg q + end + +module M1 = + struct + type Common.msg += Reload of string | Alert of string + + let handle fallback = function + Reload s -> print_endline ("Reload "^s) + | Alert s -> print_endline ("Alert "^s) + | x -> fallback x + + let () = Common.extend_handle handle + let () = Common.add (Reload "config.file") + let () = Common.add (Alert "Initialisation done") + end diff --git a/testsuite/tests/typing-modules-bugs/pr6899_first_bad.ml b/testsuite/tests/typing-modules-bugs/pr6899_first_bad.ml new file mode 100644 index 00000000..07435e11 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6899_first_bad.ml @@ -0,0 +1,3 @@ +let should_reject = + let table = Hashtbl.create 1 in + fun x y -> Hashtbl.add table x y diff --git a/testsuite/tests/typing-modules-bugs/pr6899_ok.ml b/testsuite/tests/typing-modules-bugs/pr6899_ok.ml new file mode 100644 index 00000000..e049534d --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6899_ok.ml @@ -0,0 +1,6 @@ +type 'a t = 'a option +let is_some = function + | None -> false + | Some _ -> true + +let should_accept ?x () = is_some x diff --git a/testsuite/tests/typing-modules-bugs/pr6899_second_bad.ml b/testsuite/tests/typing-modules-bugs/pr6899_second_bad.ml new file mode 100644 index 00000000..4d49fe1e --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6899_second_bad.ml @@ -0,0 +1,5 @@ +include struct + let foo `Test = () + let wrap f `Test = f + let bar = wrap () +end diff --git a/testsuite/tests/typing-modules-bugs/pr6944_ok.ml b/testsuite/tests/typing-modules-bugs/pr6944_ok.ml new file mode 100644 index 00000000..dffba4e9 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6944_ok.ml @@ -0,0 +1,4 @@ +let f () = + let module S = String in + let module N = Map.Make(S) in + N.add "sum" 41 N.empty;; diff --git a/testsuite/tests/typing-modules-bugs/pr6954_ok.ml b/testsuite/tests/typing-modules-bugs/pr6954_ok.ml new file mode 100644 index 00000000..0e13489b --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6954_ok.ml @@ -0,0 +1,11 @@ +module X = struct module Y = struct module type S = sig type t end end end + +(* open X (* works! *) *) +module Y = X.Y + +type 'a arg_t = 'at constraint 'a = (module Y.S with type t = 'at) +type t = (module X.Y.S with type t = unit) + +let f (x : t arg_t) = () + +let () = f () diff --git a/testsuite/tests/typing-modules-bugs/pr6981_ok.ml b/testsuite/tests/typing-modules-bugs/pr6981_ok.ml new file mode 100644 index 00000000..e2b285b9 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6981_ok.ml @@ -0,0 +1,10 @@ +module type S = +sig + type a + type b +end +module Foo + (Bar : S with type a = private [> `A]) + (Baz : S with type b = private < b : Bar.b ; .. >) = +struct +end diff --git a/testsuite/tests/typing-modules-bugs/pr6982_ok.ml b/testsuite/tests/typing-modules-bugs/pr6982_ok.ml new file mode 100644 index 00000000..7e24940a --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6982_ok.ml @@ -0,0 +1,26 @@ +module A = struct + module type A_S = sig + end + + type t = (module A_S) +end + +module type S = sig type t end + +let f (type a) (module X : S with type t = a) = () + +let _ = f (module A) (* ok *) + +module A_annotated_alias : S with type t = (module A.A_S) = A + +let _ = f (module A_annotated_alias) (* ok *) +let _ = f (module A_annotated_alias : S with type t = (module A.A_S)) (* ok *) + +module A_alias = A +module A_alias_expanded = struct include A_alias end + +let _ = f (module A_alias_expanded : S with type t = (module A.A_S)) (* ok *) +let _ = f (module A_alias_expanded) (* ok *) + +let _ = f (module A_alias : S with type t = (module A.A_S)) (* doesn't type *) +let _ = f (module A_alias) (* doesn't type either *) diff --git a/testsuite/tests/typing-modules-bugs/pr6985_ok.ml b/testsuite/tests/typing-modules-bugs/pr6985_ok.ml new file mode 100644 index 00000000..f6078c97 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6985_ok.ml @@ -0,0 +1,7 @@ +module Foo + (Bar : sig type a = private [> `A ] end) + (Baz : module type of struct include Bar end) = +struct +end +module Bazoinks = struct type a = [ `A ] end +module Bug = Foo(Bazoinks)(Bazoinks) diff --git a/testsuite/tests/typing-modules-bugs/pr6992_bad.ml b/testsuite/tests/typing-modules-bugs/pr6992_bad.ml new file mode 100644 index 00000000..c2814d44 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr6992_bad.ml @@ -0,0 +1,15 @@ +(* PR#6992, reported by Stephen Dolan *) + +type (_, _) eq = Eq : ('a, 'a) eq +let cast : type a b . (a, b) eq -> a -> b = fun Eq x -> x + +module Fix (F : sig type 'a f end) = struct + type 'a fix = ('a, 'a F.f) eq + let uniq (type a) (type b) (Eq : a fix) (Eq : b fix) : (a, b) eq = Eq +end + +(* This would allow: +module FixId = Fix (struct type 'a f = 'a end) + let bad : (int, string) eq = FixId.uniq Eq Eq + let _ = Printf.printf "Oh dear: %s" (cast bad 42) +*) diff --git a/testsuite/tests/typing-modules-bugs/pr7036_ok.ml b/testsuite/tests/typing-modules-bugs/pr7036_ok.ml new file mode 100644 index 00000000..8a646035 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr7036_ok.ml @@ -0,0 +1,21 @@ +module M = struct + module type S = sig type a val v : a end + type 'a s = (module S with type a = 'a) +end + +module B = struct + class type a = object method a : 'a. 'a M.s -> 'a end +end + +module M' = M +module B' = B + +class b : B.a = object + method a : 'a. 'a M.s -> 'a = fun (type a) ((module X) : (module M.S with type +a = a)) -> X.v +end + +class b' : B.a = object + method a : 'a. 'a M'.s -> 'a = fun (type a) ((module X) : (module M'.S with +type a = a)) -> X.v +end diff --git a/testsuite/tests/typing-modules-bugs/pr7082_ok.ml b/testsuite/tests/typing-modules-bugs/pr7082_ok.ml new file mode 100644 index 00000000..c3132dae --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr7082_ok.ml @@ -0,0 +1,7 @@ +module type FOO = sig type t end +module type BAR = +sig + (* Works: module rec A : (sig include FOO with type t = < b:B.t > end) *) + module rec A : (FOO with type t = < b:B.t >) + and B : FOO +end diff --git a/testsuite/tests/typing-modules-bugs/pr7152_ok.ml b/testsuite/tests/typing-modules-bugs/pr7152_ok.ml new file mode 100644 index 00000000..59491f35 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr7152_ok.ml @@ -0,0 +1,72 @@ +module M : sig + type make_dec + val add_dec: make_dec -> unit +end = struct + type u + + module Fast: sig + type 'd t + val create: unit -> 'd t + module type S = sig + module Data: sig type t end + val key: Data.t t + end + module Register (D:S): sig end + val attach: 'd t -> 'd -> unit + end = struct + type 'd t = unit + let create () = () + module type S = sig + module Data: sig type t end + val key: Data.t t + end + module Register (D:S) = struct end + let attach _ _ = () + end + + type make_dec + + module Dem = struct + module Data = struct + type t = make_dec + end + let key = Fast.create () + end + + module EDem = Fast.Register(Dem) + + let add_dec dec = + Fast.attach Dem.key dec +end + +(* simpler version *) + +module Simple = struct + type 'a t + module type S = sig + module Data: sig type t end + val key: Data.t t + end + module Register (D:S) = struct let key = D.key end + module M = struct + module Data = struct type t = int end + let key : _ t = Obj.magic () + end +end;; +module EM = Simple.Register(Simple.M);; +Simple.M.key;; + +module Simple2 = struct + type 'a t + module type S = sig + module Data: sig type t end + val key: Data.t t + end + module M = struct + module Data = struct type t = int end + let key : _ t = Obj.magic () + end + module Register (D:S) = struct let key = D.key end + module EM = Simple.Register(Simple.M) + let k : M.Data.t t = M.key +end;; diff --git a/testsuite/tests/typing-modules-bugs/pr7182_ok.ml b/testsuite/tests/typing-modules-bugs/pr7182_ok.ml new file mode 100644 index 00000000..e7d01956 --- /dev/null +++ b/testsuite/tests/typing-modules-bugs/pr7182_ok.ml @@ -0,0 +1,3 @@ +module rec M + : sig external f : int -> int = "%identity" end + = struct external f : int -> int = "%identity" end diff --git a/testsuite/tests/typing-modules/Makefile b/testsuite/tests/typing-modules/Makefile index 02fc5fb0..7fc00661 100644 --- a/testsuite/tests/typing-modules/Makefile +++ b/testsuite/tests/typing-modules/Makefile @@ -1,14 +1,18 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** -include ../../makefiles/Makefile.toplevel -include ../../makefiles/Makefile.common +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.toplevel +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-modules/Test.ml b/testsuite/tests/typing-modules/Test.ml index 97ef3f16..640655eb 100644 --- a/testsuite/tests/typing-modules/Test.ml +++ b/testsuite/tests/typing-modules/Test.ml @@ -52,6 +52,7 @@ type u = X of bool;; module type B = A with type t = u;; (* fail *) (* PR#5815 *) +(* ---> duplicated exception name is now an error *) module type S = sig exception Foo of int exception Foo of bool end;; diff --git a/testsuite/tests/typing-modules/Test.ml.principal.reference b/testsuite/tests/typing-modules/Test.ml.principal.reference index d99e9a3c..9646d3d0 100644 --- a/testsuite/tests/typing-modules/Test.ml.principal.reference +++ b/testsuite/tests/typing-modules/Test.ml.principal.reference @@ -28,7 +28,11 @@ Error: Signature mismatch: ^^^^^^^^^^ Error: This variant or record definition does not match that of type u The types for field X are not equal. -# module type S = sig exception Foo of bool end +# Characters 121-124: + module type S = sig exception Foo of int exception Foo of bool end;; + ^^^ +Error: Multiple definition of the extension constructor name Foo. + Names must be unique in a given structure or signature. # module F : functor (X : sig end) -> sig val x : int end # Characters 0-3: F.x;; (* fail *) diff --git a/testsuite/tests/typing-modules/Test.ml.reference b/testsuite/tests/typing-modules/Test.ml.reference index d99e9a3c..9646d3d0 100644 --- a/testsuite/tests/typing-modules/Test.ml.reference +++ b/testsuite/tests/typing-modules/Test.ml.reference @@ -28,7 +28,11 @@ Error: Signature mismatch: ^^^^^^^^^^ Error: This variant or record definition does not match that of type u The types for field X are not equal. -# module type S = sig exception Foo of bool end +# Characters 121-124: + module type S = sig exception Foo of int exception Foo of bool end;; + ^^^ +Error: Multiple definition of the extension constructor name Foo. + Names must be unique in a given structure or signature. # module F : functor (X : sig end) -> sig val x : int end # Characters 0-3: F.x;; (* fail *) diff --git a/testsuite/tests/typing-modules/aliases.ml.reference b/testsuite/tests/typing-modules/aliases.ml.reference index 6f0fe745..724f0138 100644 --- a/testsuite/tests/typing-modules/aliases.ml.reference +++ b/testsuite/tests/typing-modules/aliases.ml.reference @@ -8,8 +8,11 @@ val escaped : char -> string val lowercase : char -> char val uppercase : char -> char + val lowercase_ascii : char -> char + val uppercase_ascii : char -> char type t = char val compare : t -> t -> int + val equal : t -> t -> bool external unsafe_chr : int -> char = "%identity" end # - : char = 'B' @@ -20,8 +23,11 @@ val escaped : char -> string val lowercase : char -> char val uppercase : char -> char + val lowercase_ascii : char -> char + val uppercase_ascii : char -> char type t = char val compare : t -> t -> int + val equal : t -> t -> bool external unsafe_chr : int -> char = "%identity" end # - : char = 'B' @@ -35,8 +41,11 @@ val escaped : char -> string val lowercase : char -> char val uppercase : char -> char + val lowercase_ascii : char -> char + val uppercase_ascii : char -> char type t = char val compare : t -> t -> int + val equal : t -> t -> bool external unsafe_chr : int -> char = "%identity" end # module C4 : @@ -46,8 +55,11 @@ val escaped : char -> string val lowercase : char -> char val uppercase : char -> char + val lowercase_ascii : char -> char + val uppercase_ascii : char -> char type t = char val compare : t -> t -> int + val equal : t -> t -> bool external unsafe_chr : int -> char = "%identity" end # - : char = 'B' @@ -368,19 +380,7 @@ Error: Unbound module type A module K : sig module E = B module N = E.O end # val x : K.N.t = "foo" # module M : sig type t = A module B : sig type u = B end end -# Characters 53-54: - module P : sig type t = M.t = A module B = M.B end = M;; (* should be ok *) - ^ -Error: Signature mismatch: - Modules do not match: - sig type t = M.t = A module B : sig type u = M.B.u = B end end - is not included in - sig type t = M.t = A module B = M.B end - In module B: - Modules do not match: - sig type u = M.B.u = B end - is not included in - (module M.B) +# module P : sig type t = M.t = A module B = M.B end # module P : sig type t = M.t = A module B = M.B end # module type S = sig module M : sig module P : sig end end module Q = M end # module type S = @@ -393,24 +393,7 @@ Error: Signature mismatch: module M : sig module N : sig end module P : sig end end module Q = M end -# Characters 16-17: - module R' : S = R;; (* should be ok *) - ^ -Error: Signature mismatch: - Modules do not match: - sig - module M : sig module N : sig end module P : sig end end - module Q = M - end - is not included in - S - In module Q: - Modules do not match: - sig module N : sig end module P : sig end end - is not included in - sig module N = M.N module P = M.P end - In module Q.N: - Modules do not match: sig end is not included in (module M.N) +# module R' : S # module M : sig val f : 'a -> 'a end module rec R : sig module M : sig val f : 'a -> 'a end end # - : int = 3 diff --git a/testsuite/tests/typing-modules/b.ml.reference b/testsuite/tests/typing-modules/b.ml.reference new file mode 100644 index 00000000..9faafbf6 --- /dev/null +++ b/testsuite/tests/typing-modules/b.ml.reference @@ -0,0 +1,5 @@ + +# * * * * * +Characters 352-352: + Error: Syntax error +# diff --git a/testsuite/tests/typing-modules/b2.ml.reference b/testsuite/tests/typing-modules/b2.ml.reference new file mode 100644 index 00000000..9b455862 --- /dev/null +++ b/testsuite/tests/typing-modules/b2.ml.reference @@ -0,0 +1,5 @@ + +# * * +Characters 312-312: + Error: Syntax error +# diff --git a/testsuite/tests/typing-modules/d.ml.reference b/testsuite/tests/typing-modules/d.ml.reference new file mode 100644 index 00000000..06308c78 --- /dev/null +++ b/testsuite/tests/typing-modules/d.ml.reference @@ -0,0 +1,5 @@ + +# +Characters 42-42: + Error: Syntax error +# diff --git a/testsuite/tests/typing-modules/generative.ml.reference b/testsuite/tests/typing-modules/generative.ml.reference index a6aa1002..0f892d43 100644 --- a/testsuite/tests/typing-modules/generative.ml.reference +++ b/testsuite/tests/typing-modules/generative.ml.reference @@ -39,6 +39,6 @@ Error: Signature mismatch: functor (X : sig end) -> sig end # module X : functor (X : sig end) (Y : sig end) (Z : sig end) -> sig end # module Y : functor (X : sig end) (Y : sig end) (Z : sig end) -> sig end -# module Z : functor (_ : sig end) (_ : sig end) (_ : sig end) -> sig end +# module Z : sig end -> sig end -> sig end -> sig end # module GZ : functor (X : sig end) () (Z : sig end) -> sig end # diff --git a/testsuite/tests/typing-modules/pr7207.ml b/testsuite/tests/typing-modules/pr7207.ml new file mode 100644 index 00000000..c0ac33d5 --- /dev/null +++ b/testsuite/tests/typing-modules/pr7207.ml @@ -0,0 +1,2 @@ +module F (X : sig end) = struct type t = int end;; +type t = F(Does_not_exist).t;; diff --git a/testsuite/tests/typing-modules/pr7207.ml.reference b/testsuite/tests/typing-modules/pr7207.ml.reference new file mode 100644 index 00000000..4fe8e21e --- /dev/null +++ b/testsuite/tests/typing-modules/pr7207.ml.reference @@ -0,0 +1,7 @@ + +# module F : functor (X : sig end) -> sig type t = int end +# Characters 9-28: + type t = F(Does_not_exist).t;; + ^^^^^^^^^^^^^^^^^^^ +Error: Unbound module Does_not_exist +# diff --git a/testsuite/tests/typing-modules/printing.ml b/testsuite/tests/typing-modules/printing.ml new file mode 100644 index 00000000..77dd8c70 --- /dev/null +++ b/testsuite/tests/typing-modules/printing.ml @@ -0,0 +1,14 @@ +(* PR#6650 *) + +module type S = sig + class type c = object method m : int end + module M : sig + class type d = c + end +end;; +module F (X : S) = X.M;; + +(* PR#6648 *) + +module M = struct module N = struct let x = 1 end end;; +#show_module M;; diff --git a/testsuite/tests/typing-modules/printing.ml.reference b/testsuite/tests/typing-modules/printing.ml.reference new file mode 100644 index 00000000..c5a9a773 --- /dev/null +++ b/testsuite/tests/typing-modules/printing.ml.reference @@ -0,0 +1,10 @@ + +# module type S = + sig + class type c = object method m : int end + module M : sig class type d = c end + end +# module F : functor (X : S) -> sig class type d = X.c end +# module M : sig module N : sig val x : int end end +# module M : sig module N : sig ... end end +# diff --git a/testsuite/tests/typing-objects-bugs/Makefile b/testsuite/tests/typing-objects-bugs/Makefile index 1103dbff..69e2ee7b 100644 --- a/testsuite/tests/typing-objects-bugs/Makefile +++ b/testsuite/tests/typing-objects-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.okbad diff --git a/testsuite/tests/typing-objects/Exemples.ml b/testsuite/tests/typing-objects/Exemples.ml index 5ffc6498..f0ab4d53 100644 --- a/testsuite/tests/typing-objects/Exemples.ml +++ b/testsuite/tests/typing-objects/Exemples.ml @@ -78,7 +78,7 @@ let c'' = new color_circle p;; let c'' = new color_circle p';; (c'' :> color_point circle);; -(c'' :> point circle);; (* Echec *) +(c'' :> point circle);; (* Fail *) fun x -> (x : color_point color_circle :> point circle);; class printable_point y = object (s) @@ -204,7 +204,7 @@ let c = new int_comparable 10;; l#add c;; let c2 = new int_comparable2 15;; -l#add (c2 :> int_comparable);; (* Echec : 'a comp2 n'est un sous-type *) +l#add (c2 :> int_comparable);; (* Fail : 'a comp2 is not a subtype *) (new sorted_list ())#add c2;; class int_comparable3 (x : int) = object diff --git a/testsuite/tests/typing-objects/Exemples.ml.principal.reference b/testsuite/tests/typing-objects/Exemples.ml.principal.reference index f0f3812e..67090461 100644 --- a/testsuite/tests/typing-objects/Exemples.ml.principal.reference +++ b/testsuite/tests/typing-objects/Exemples.ml.principal.reference @@ -84,7 +84,7 @@ Error: This expression has type point but an expression was expected of type # val c'' : color_point color_circle = # - : color_point circle = # Characters 0-21: - (c'' :> point circle);; (* Echec *) + (c'' :> point circle);; (* Fail *) ^^^^^^^^^^^^^^^^^^^^^ Error: Type color_point color_circle = @@ -208,7 +208,7 @@ and ['a] cons : # - : unit = () # val c2 : int_comparable2 = # Characters 6-28: - l#add (c2 :> int_comparable);; (* Echec : 'a comp2 n'est un sous-type *) + l#add (c2 :> int_comparable);; (* Fail : 'a comp2 is not a subtype *) ^^^^^^^^^^^^^^^^^^^^^^ Error: Type int_comparable2 = diff --git a/testsuite/tests/typing-objects/Exemples.ml.reference b/testsuite/tests/typing-objects/Exemples.ml.reference index 085a9e92..cfd13603 100644 --- a/testsuite/tests/typing-objects/Exemples.ml.reference +++ b/testsuite/tests/typing-objects/Exemples.ml.reference @@ -84,7 +84,7 @@ Error: This expression has type point but an expression was expected of type # val c'' : color_point color_circle = # - : color_point circle = # Characters 0-21: - (c'' :> point circle);; (* Echec *) + (c'' :> point circle);; (* Fail *) ^^^^^^^^^^^^^^^^^^^^^ Error: Type color_point color_circle = @@ -208,7 +208,7 @@ and ['a] cons : # - : unit = () # val c2 : int_comparable2 = # Characters 6-28: - l#add (c2 :> int_comparable);; (* Echec : 'a comp2 n'est un sous-type *) + l#add (c2 :> int_comparable);; (* Fail : 'a comp2 is not a subtype *) ^^^^^^^^^^^^^^^^^^^^^^ Error: Type int_comparable2 = diff --git a/testsuite/tests/typing-objects/Makefile b/testsuite/tests/typing-objects/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-objects/Makefile +++ b/testsuite/tests/typing-objects/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-objects/Tests.ml b/testsuite/tests/typing-objects/Tests.ml index 917474f9..c52fe909 100644 --- a/testsuite/tests/typing-objects/Tests.ml +++ b/testsuite/tests/typing-objects/Tests.ml @@ -1,8 +1,8 @@ -(* Le sous-typage est "syntaxique" *) +(* Subtyping is "syntactic" *) fun (x : < x : int >) y z -> (y :> 'a), (x :> 'a), (z :> 'a);; (* - : (< x : int > as 'a) -> 'a -> 'a * 'a = *) -(* Bizarrerie du typage des classes *) +(* Quirks of class typing. *) class ['a] c () = object method f = (new c (): int c) end and ['a] d () = object @@ -11,14 +11,14 @@ end;; (* class ['a] c : unit -> object constraint 'a = int method f : 'a c end *) (* and ['a] d : unit -> object constraint 'a = int method f : 'a c end *) -(* 'a libre dans classe d *) +(* 'a free in class d *) class ['a] c () = object method f (x : 'a) = () end and d () = object inherit ['a] c () end;; -(* Instancie #c *) +(* Create instance #c *) class virtual c () = object end and ['a] d () = object constraint 'a = #c @@ -36,7 +36,7 @@ end;; (* class ['a] c : unit -> object constraint 'a = int end and ['a] d : unit -> object constraint 'a = int #c end *) -(* Self en parametre *) +(* Self as parameter *) class ['a] c (x : 'a) = object (self : 'b) constraint 'a = 'b method f = self @@ -51,20 +51,20 @@ class x () = object end;; (* The class x should be virtual: its methods f is undefined *) -(* Methode g en trop *) +(* Supplementary method g *) class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end and virtual d x = object (_ : 'a) inherit c x method g = true end;; -(* Contrainte non respectee *) +(* Constraint not respected *) class ['a] c () = object constraint 'a = int method f x = (x : bool c) end;; -(* Differentes contraintes *) +(* Different constraints *) class ['a, 'b] c () = object constraint 'a = int -> 'c constraint 'b = 'a * * 'c * 'd @@ -74,13 +74,13 @@ class ['a, 'b] d () = object inherit ['a, 'b] c () end;; -(* Contrainte non generique *) +(* Non-generic constraint *) let x = ref [];; class ['a] c () = object method f = (x : 'a) end;; -(* Abreviations *) +(* Abbreviations *) type 'a c = and 'a d = ;; type 'a c = @@ -129,7 +129,7 @@ class ['a, 'b] e () y = object inherit ['a, 'b] M'.c 1 y end;; open M;; (new c 5 true)#g;; -(* #cl quand cl est fermee *) +(* #cl when cl is closed *) module M = struct class ['a] c () = object method f (x : 'a) = () end end;; module M' = (M : sig class ['a] c : unit -> object method f : 'a -> unit end end);; @@ -138,7 +138,7 @@ fun x -> (x :> 'a #M'.c);; class ['a] c (x : 'b #c) = object end;; class ['a] c (x : 'b #c) = object end;; -(* Ordre de calcul *) +(* Computation order *) class c () = object method f = 1 end and d () = object method f = 2 end;; class e () = object inherit c () inherit d () end;; (new e ())#f;; @@ -187,11 +187,11 @@ class d x y = object inherit c x y end;; let c = new c 1 2 in c#x, c#y;; let d = new d 1 2 in d#x, d#y;; -(* Parametres n'apparaissant pas dans le type de l'objet *) +(* Parameters which does not appear in the object type *) class ['a] c (x : 'a) = object end;; new c;; -(* Variables privees *) +(* Private variables *) (* module type M = sig class c : unit -> object val x : int end @@ -215,7 +215,7 @@ end;; let e = new e () in e#x, e#y, e#c, e#d;; *) -(* Oubli de variables dans l'interface *) +(* Forgotten variables in interfaces *) module M : sig class c : unit -> object diff --git a/testsuite/tests/typing-objects/Tests.ml.principal.reference b/testsuite/tests/typing-objects/Tests.ml.principal.reference index 6c944944..d39a70dc 100644 --- a/testsuite/tests/typing-objects/Tests.ml.principal.reference +++ b/testsuite/tests/typing-objects/Tests.ml.principal.reference @@ -4,7 +4,7 @@ = # class ['a] c : unit -> object constraint 'a = int method f : int c end and ['a] d : unit -> object constraint 'a = int method f : int c end -# Characters 234-275: +# Characters 230-271: ....and d () = object inherit ['a] c () end.. @@ -24,7 +24,7 @@ and ['a] d : unit -> object constraint 'a = int #c end method virtual f : int end.. Error: This class should be virtual. The following methods are undefined : f -# Characters 139-147: +# Characters 144-152: class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end ^^^^^^^^ Error: This pattern cannot match self: it only matches values of type @@ -59,7 +59,7 @@ Error: The type of this class, class ['a] c : unit -> object constraint 'a = '_b list ref method f : 'a end, contains type variables that cannot be generalized -# Characters 20-52: +# Characters 21-53: type 'a c = ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of d, type int c should be 'a c diff --git a/testsuite/tests/typing-objects/Tests.ml.reference b/testsuite/tests/typing-objects/Tests.ml.reference index 57628351..d39a70dc 100644 --- a/testsuite/tests/typing-objects/Tests.ml.reference +++ b/testsuite/tests/typing-objects/Tests.ml.reference @@ -2,9 +2,9 @@ # - : < x : int > -> < x : int > -> < x : int > -> < x : int > * < x : int > * < x : int > = -# class ['a] c : unit -> object constraint 'a = int method f : 'a c end -and ['a] d : unit -> object constraint 'a = int method f : 'a c end -# Characters 234-275: +# class ['a] c : unit -> object constraint 'a = int method f : int c end +and ['a] d : unit -> object constraint 'a = int method f : int c end +# Characters 230-271: ....and d () = object inherit ['a] c () end.. @@ -24,7 +24,7 @@ and ['a] d : unit -> object constraint 'a = int #c end method virtual f : int end.. Error: This class should be virtual. The following methods are undefined : f -# Characters 139-147: +# Characters 144-152: class virtual c ((x : 'a): < f : int >) = object (_ : 'a) end ^^^^^^^^ Error: This pattern cannot match self: it only matches values of type @@ -59,7 +59,7 @@ Error: The type of this class, class ['a] c : unit -> object constraint 'a = '_b list ref method f : 'a end, contains type variables that cannot be generalized -# Characters 20-52: +# Characters 21-53: type 'a c = ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error: In the definition of d, type int c should be 'a c @@ -285,7 +285,8 @@ Error: This expression has type 'a t but an expression was expected of type Warning 10: this expression should have type unit. - : ('a t as 'a) t -> unit = # class ['a] c : - unit -> object constraint 'a = (< .. > as 'b) -> unit method m : 'a end + unit -> + object constraint 'a = (< .. > as 'b) -> unit method m : 'b -> unit end # class ['a] c : unit -> object constraint 'a = unit -> (< .. > as 'b) method m : 'a -> 'b end diff --git a/testsuite/tests/typing-objects/pr5545.ml b/testsuite/tests/typing-objects/pr5545.ml new file mode 100644 index 00000000..1273e6f0 --- /dev/null +++ b/testsuite/tests/typing-objects/pr5545.ml @@ -0,0 +1,22 @@ +type foo = int;; + +class o = + object(this) + method x : foo = 10 + method y : int = this # x + end;; + + +class o = + object(this) + method x : foo = 10 + method y = (this # x : int) + end;; + + + +class o = + object(this) + method x : int = (10 : int) + method y = (this # x : foo) + end;; diff --git a/testsuite/tests/typing-objects/pr5545.ml.principal.reference b/testsuite/tests/typing-objects/pr5545.ml.principal.reference new file mode 100644 index 00000000..4f7fda96 --- /dev/null +++ b/testsuite/tests/typing-objects/pr5545.ml.principal.reference @@ -0,0 +1,6 @@ + +# type foo = int +# class o : object method x : foo method y : int end +# class o : object method x : foo method y : int end +# class o : object method x : int method y : foo end +# diff --git a/testsuite/tests/typing-objects/pr5545.ml.reference b/testsuite/tests/typing-objects/pr5545.ml.reference new file mode 100644 index 00000000..4f7fda96 --- /dev/null +++ b/testsuite/tests/typing-objects/pr5545.ml.reference @@ -0,0 +1,6 @@ + +# type foo = int +# class o : object method x : foo method y : int end +# class o : object method x : foo method y : int end +# class o : object method x : int method y : foo end +# diff --git a/testsuite/tests/typing-objects/pr5619_bad.ml b/testsuite/tests/typing-objects/pr5619_bad.ml index 2dd3eaaa..8608dd02 100644 --- a/testsuite/tests/typing-objects/pr5619_bad.ml +++ b/testsuite/tests/typing-objects/pr5619_bad.ml @@ -14,7 +14,6 @@ class foo = method cast = function Foo -> (self :> ) - | _ -> raise Exit end ;; @@ -24,6 +23,6 @@ class foo: foo_t = method cast: type a. a name -> a = function Foo -> (self :> foo_t) - | _ -> ((raise Exit) : a) + | _ -> raise Exit end ;; diff --git a/testsuite/tests/typing-objects/pr5619_bad.ml.principal.reference b/testsuite/tests/typing-objects/pr5619_bad.ml.principal.reference index 48777229..0b50417a 100644 --- a/testsuite/tests/typing-objects/pr5619_bad.ml.principal.reference +++ b/testsuite/tests/typing-objects/pr5619_bad.ml.principal.reference @@ -1,15 +1,15 @@ # class type foo_t = object method foo : string end type 'a name = Foo : foo_t name | Int : int name -# class foo : +# class foo : object method cast : foo_t name -> < foo : string > method foo : string end -# Characters 22-184: +# Characters 22-176: ..object(self) method foo = "foo" method cast: type a. a name -> a = function Foo -> (self :> foo_t) - | _ -> ((raise Exit) : a) + | _ -> raise Exit end Error: The class type object method cast : 'a name -> 'a method foo : string end diff --git a/testsuite/tests/typing-objects/pr5619_bad.ml.reference b/testsuite/tests/typing-objects/pr5619_bad.ml.reference index 48777229..0b50417a 100644 --- a/testsuite/tests/typing-objects/pr5619_bad.ml.reference +++ b/testsuite/tests/typing-objects/pr5619_bad.ml.reference @@ -1,15 +1,15 @@ # class type foo_t = object method foo : string end type 'a name = Foo : foo_t name | Int : int name -# class foo : +# class foo : object method cast : foo_t name -> < foo : string > method foo : string end -# Characters 22-184: +# Characters 22-176: ..object(self) method foo = "foo" method cast: type a. a name -> a = function Foo -> (self :> foo_t) - | _ -> ((raise Exit) : a) + | _ -> raise Exit end Error: The class type object method cast : 'a name -> 'a method foo : string end diff --git a/testsuite/tests/typing-objects/pr6123_bad.ml.principal.reference b/testsuite/tests/typing-objects/pr6123_bad.ml.principal.reference index a7e48182..eb3b05c0 100644 --- a/testsuite/tests/typing-objects/pr6123_bad.ml.principal.reference +++ b/testsuite/tests/typing-objects/pr6123_bad.ml.principal.reference @@ -2,7 +2,7 @@ # Characters 253-257: let args = List.map (fun ty -> new argument(self, ty)) args_ty in ^^^^ -Error: This expression has type < arguments : 'b; .. > as 'a - but an expression was expected of type 'a +Error: This expression has type < arguments : 'a; .. > + but an expression was expected of type 'b Self type cannot escape its class # diff --git a/testsuite/tests/typing-objects/pr6123_bad.ml.reference b/testsuite/tests/typing-objects/pr6123_bad.ml.reference index a7e48182..eb3b05c0 100644 --- a/testsuite/tests/typing-objects/pr6123_bad.ml.reference +++ b/testsuite/tests/typing-objects/pr6123_bad.ml.reference @@ -2,7 +2,7 @@ # Characters 253-257: let args = List.map (fun ty -> new argument(self, ty)) args_ty in ^^^^ -Error: This expression has type < arguments : 'b; .. > as 'a - but an expression was expected of type 'a +Error: This expression has type < arguments : 'a; .. > + but an expression was expected of type 'b Self type cannot escape its class # diff --git a/testsuite/tests/typing-objects/pr6907_bad.ml b/testsuite/tests/typing-objects/pr6907_bad.ml new file mode 100644 index 00000000..0a9a7a1d --- /dev/null +++ b/testsuite/tests/typing-objects/pr6907_bad.ml @@ -0,0 +1,7 @@ +class type ['e] t = object('s) + method update : 'e -> 's +end;; + +module type S = sig + class base : 'e -> ['e] t +end;; diff --git a/testsuite/tests/typing-objects/pr6907_bad.ml.reference b/testsuite/tests/typing-objects/pr6907_bad.ml.reference new file mode 100644 index 00000000..3a4ef9af --- /dev/null +++ b/testsuite/tests/typing-objects/pr6907_bad.ml.reference @@ -0,0 +1,10 @@ + +# class type ['e] t = object ('a) method update : 'e -> 'a end +# Characters 23-48: + class base : 'e -> ['e] t + ^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Some type variables are unbound in this type: + class base : 'e -> ['e] t + The method update has type 'e -> < update : 'a; .. > as 'a where 'e + is unbound +# diff --git a/testsuite/tests/typing-poly-bugs/Makefile b/testsuite/tests/typing-poly-bugs/Makefile index 1103dbff..69e2ee7b 100644 --- a/testsuite/tests/typing-poly-bugs/Makefile +++ b/testsuite/tests/typing-poly-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.okbad diff --git a/testsuite/tests/typing-poly-bugs/pr5673_bad.ml b/testsuite/tests/typing-poly-bugs/pr5673_bad.ml index 454ab1b4..99088000 100644 --- a/testsuite/tests/typing-poly-bugs/pr5673_bad.ml +++ b/testsuite/tests/typing-poly-bugs/pr5673_bad.ml @@ -1,7 +1,7 @@ module Classdef = struct class virtual ['a, 'b, 'c] cl0 = - object - constraint 'c = < m : 'a -> 'b -> int; .. > + object + constraint 'c = < m : 'a -> 'b -> int; .. > end class virtual ['a, 'b] cl1 = diff --git a/testsuite/tests/typing-poly-bugs/pr5673_ok.ml b/testsuite/tests/typing-poly-bugs/pr5673_ok.ml index df9fd215..26ad1606 100644 --- a/testsuite/tests/typing-poly-bugs/pr5673_ok.ml +++ b/testsuite/tests/typing-poly-bugs/pr5673_ok.ml @@ -1,7 +1,7 @@ module Classdef = struct class virtual ['a, 'b, 'c] cl0 = - object - constraint 'c = < m : 'a -> 'b -> int; .. > + object + constraint 'c = < m : 'a -> 'b -> int; .. > end class virtual ['a, 'b] cl1 = diff --git a/testsuite/tests/typing-poly/Makefile b/testsuite/tests/typing-poly/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-poly/Makefile +++ b/testsuite/tests/typing-poly/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-poly/poly.ml b/testsuite/tests/typing-poly/poly.ml index 36dc76a4..1ddc6d6c 100644 --- a/testsuite/tests/typing-poly/poly.ml +++ b/testsuite/tests/typing-poly/poly.ml @@ -378,7 +378,7 @@ class c = object (self) method m : 'a. ([> 'a t] as 'a) -> 'a = fun x -> self#m x end;; -(* usage avant instance *) +(* use before instancing *) class c = object method m : 'a. 'a option -> ([> `A] as 'a) = fun x -> `A end;; (* various old bugs *) @@ -459,10 +459,10 @@ class type ['a, 'b] a = object end and ['a, 'b] b = object method a: ('a, 'b) #a as 'a method as_b: ('a, 'b) b -end +end;; -class type ['b] ca = object ('s) inherit ['s, 'b] a end -class type ['a] cb = object ('s) inherit ['a, 's] b end +class type ['b] ca = object ('s) inherit ['s, 'b] a end;; +class type ['a] cb = object ('s) inherit ['a, 's] b end;; type bt = 'b ca cb as 'b ;; @@ -667,3 +667,23 @@ let using_match b = match (fun x -> x), fun x -> x with x, y -> x, y;; match fun x -> x with x -> x, x;; + +(* PR#6747 *) +(* ok *) +let n = object + method m : 'x 'o. ([< `Foo of 'x] as 'o) -> 'x = fun x -> assert false +end;; +(* ok, but not with -principal *) +let n = + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; +(* fail *) +let (n : < m : 'a. [< `Foo of int] -> 'a >) = + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; +(* fail *) +let (n : 'b -> < m : 'a . ([< `Foo of int] as 'b) -> 'a >) = fun x -> + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + +(* PR#6171 *) +let f b (x: 'x) = + let module M = struct type t = A end in + if b then x else M.A;; diff --git a/testsuite/tests/typing-poly/poly.ml.principal.reference b/testsuite/tests/typing-poly/poly.ml.principal.reference index 4de2912d..d8525934 100644 --- a/testsuite/tests/typing-poly/poly.ml.principal.reference +++ b/testsuite/tests/typing-poly/poly.ml.principal.reference @@ -74,7 +74,11 @@ method empty : bool method fold : f:('a -> 'c -> 'c) -> init:'c -> 'c end -# class ['a] ostream1 : +# Characters 166-178: + self#tl#fold ~f ~init:(f self#hd init) + ^^^^^^^^^^^^ +Warning 18: this use of a polymorphic method is not principal. +class ['a] ostream1 : hd:'a -> tl:'b -> object ('b) @@ -354,7 +358,7 @@ Error: Constraints are not satisfied in this type. ([> `B of 'a ], 'a) b as 'a should be an instance of (('b, [> `A of ('d, 'c) a as 'd ] as 'c) a as 'b, 'c) b -# * class type ['a, 'b] a = +# * class type ['a, 'b] a = object constraint 'a = < as_a : ('a, 'b) a as 'c; b : 'b; .. > constraint 'b = < a : 'a; as_b : ('a, 'b) b; .. > @@ -368,19 +372,19 @@ and ['a, 'b] b = method a : 'a method as_b : ('a, 'b) b end -class type ['a] ca = +# class type ['a] ca = object ('b) constraint 'a = < a : 'b; as_b : ('b, 'a) b; .. > method as_a : ('b, 'a) a method b : 'a end -class type ['a] cb = +# class type ['a] cb = object ('b) constraint 'a = < as_a : ('a, 'b) a; b : 'b; .. > method a : 'a method as_b : ('a, 'b) b end -type bt = 'a ca cb as 'a +# type bt = 'a ca cb as 'a # class c : object method m : int end # val f : unit -> c = # val f : unit -> c = @@ -647,4 +651,25 @@ Error: In the definition of t, type 'y t should be 'x t # val using_match : bool -> int * ('a -> 'a) = # - : ('a -> 'a) * ('b -> 'b) = (, ) # - : ('a -> 'a) * ('b -> 'b) = (, ) +# val n : < m : 'x 'a. ([< `Foo of 'x ] as 'a) -> 'x > = +# Characters 89-110: + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^ +Error: This method has type ([< `Foo of 'b ] as 'a) -> 'b + which is less general than 'x. 'a -> 'x +# Characters 104-125: + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^ +Error: This method has type ([< `Foo of 'b ] as 'a) -> 'b + which is less general than 'x. 'a -> 'x +# Characters 128-149: + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^ +Error: This method has type ([< `Foo of 'b ] as 'a) -> 'b + which is less general than 'x. 'a -> 'x +# Characters 94-97: + if b then x else M.A;; + ^^^ +Error: This expression has type M.t but an expression was expected of type 'x + The type constructor M.t would escape its scope # diff --git a/testsuite/tests/typing-poly/poly.ml.reference b/testsuite/tests/typing-poly/poly.ml.reference index 8855c1f6..fd968116 100644 --- a/testsuite/tests/typing-poly/poly.ml.reference +++ b/testsuite/tests/typing-poly/poly.ml.reference @@ -337,7 +337,7 @@ Error: Constraints are not satisfied in this type. ([> `B of 'a ], 'a) b as 'a should be an instance of (('b, [> `A of 'b ] as 'c) a as 'b, 'c) b -# * class type ['a, 'b] a = +# * class type ['a, 'b] a = object constraint 'a = < as_a : ('a, 'b) a as 'c; b : 'b; .. > constraint 'b = < a : 'a; as_b : ('a, 'b) b; .. > @@ -351,19 +351,19 @@ and ['a, 'b] b = method a : 'a method as_b : ('a, 'b) b end -class type ['a] ca = +# class type ['a] ca = object ('b) constraint 'a = < a : 'b; as_b : ('b, 'a) b; .. > method as_a : ('b, 'a) a method b : 'a end -class type ['a] cb = +# class type ['a] cb = object ('b) constraint 'a = < as_a : ('a, 'b) a; b : 'b; .. > method a : 'a method as_b : ('a, 'b) b end -type bt = 'a ca cb as 'a +# type bt = 'a ca cb as 'a # class c : object method m : int end # val f : unit -> c = # val f : unit -> c = @@ -605,4 +605,25 @@ Error: In the definition of t, type 'y t should be 'x t # val using_match : bool -> int * ('a -> 'a) = # - : ('a -> 'a) * ('b -> 'b) = (, ) # - : ('a -> 'a) * ('b -> 'b) = (, ) +# val n : < m : 'x 'a. ([< `Foo of 'x ] as 'a) -> 'x > = +# val n : < m : 'x. [< `Foo of 'x ] -> 'x > = +# Characters 59-129: + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type < m : 'x. [< `Foo of 'x ] -> 'x > + but an expression was expected of type + < m : 'a. [< `Foo of int ] -> 'a > + The universal variable 'x would escape its scope +# Characters 83-153: + object method m : 'x. [< `Foo of 'x] -> 'x = fun x -> assert false end;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: This expression has type < m : 'x. [< `Foo of 'x ] -> 'x > + but an expression was expected of type + < m : 'a. [< `Foo of int ] -> 'a > + The universal variable 'x would escape its scope +# Characters 94-97: + if b then x else M.A;; + ^^^ +Error: This expression has type M.t but an expression was expected of type 'x + The type constructor M.t would escape its scope # diff --git a/testsuite/tests/typing-polyvariants-bugs-2/Makefile b/testsuite/tests/typing-polyvariants-bugs-2/Makefile index 4cf35f3c..2775418c 100644 --- a/testsuite/tests/typing-polyvariants-bugs-2/Makefile +++ b/testsuite/tests/typing-polyvariants-bugs-2/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. default: diff --git a/testsuite/tests/typing-polyvariants-bugs/Makefile b/testsuite/tests/typing-polyvariants-bugs/Makefile index 1103dbff..69e2ee7b 100644 --- a/testsuite/tests/typing-polyvariants-bugs/Makefile +++ b/testsuite/tests/typing-polyvariants-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.okbad diff --git a/testsuite/tests/typing-polyvariants-bugs/pr7199_ok.ml b/testsuite/tests/typing-polyvariants-bugs/pr7199_ok.ml new file mode 100644 index 00000000..dd1d05c1 --- /dev/null +++ b/testsuite/tests/typing-polyvariants-bugs/pr7199_ok.ml @@ -0,0 +1,13 @@ +module type S = sig + type +'a t + + val foo : [`A] t -> unit + val bar : [< `A | `B] t -> unit +end + +module Make(T : S) = struct + let f x = + T.foo x; + T.bar x; + (x :> [`A | `C] T.t) +end diff --git a/testsuite/tests/typing-private-bugs/Makefile b/testsuite/tests/typing-private-bugs/Makefile index 1103dbff..69e2ee7b 100644 --- a/testsuite/tests/typing-private-bugs/Makefile +++ b/testsuite/tests/typing-private-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.okbad diff --git a/testsuite/tests/typing-private/Makefile b/testsuite/tests/typing-private/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-private/Makefile +++ b/testsuite/tests/typing-private/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-recmod/Makefile b/testsuite/tests/typing-recmod/Makefile index 1103dbff..69e2ee7b 100644 --- a/testsuite/tests/typing-recmod/Makefile +++ b/testsuite/tests/typing-recmod/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.okbad diff --git a/testsuite/tests/typing-recordarg/Makefile b/testsuite/tests/typing-recordarg/Makefile new file mode 100644 index 00000000..7fc00661 --- /dev/null +++ b/testsuite/tests/typing-recordarg/Makefile @@ -0,0 +1,18 @@ +#************************************************************************** +#* * +#* 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=../.. +include $(BASEDIR)/makefiles/Makefile.toplevel +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-recordarg/recordarg.ml b/testsuite/tests/typing-recordarg/recordarg.ml new file mode 100644 index 00000000..ebd8d056 --- /dev/null +++ b/testsuite/tests/typing-recordarg/recordarg.ml @@ -0,0 +1,92 @@ +type t = A of {x:int; mutable y:int};; +let f (A r) = r;; (* -> escape *) +let f (A r) = r.x;; (* ok *) +let f x = A {x; y = x};; (* ok *) +let f (A r) = A {r with y = r.x + 1};; (* ok *) +let f () = A {a = 1};; (* customized error message *) +let f () = A {x = 1; y = 3};; (* ok *) + +type _ t = A: {x : 'a; y : 'b} -> 'a t;; +let f (A {x; y}) = A {x; y = ()};; (* ok *) +let f (A ({x; y} as r)) = A {x = r.x; y = r.y};; (* ok *) + +module M = struct + type 'a t = + | A of {x : 'a} + | B: {u : 'b} -> unit t;; + + exception Foo of {x : int};; +end;; + +module N : sig + type 'b t = 'b M.t = + | A of {x : 'b} + | B: {u : 'bla} -> unit t + + exception Foo of {x : int} +end = struct + type 'b t = 'b M.t = + | A of {x : 'b} + | B: {u : 'z} -> unit t + + exception Foo = M.Foo +end;; + + +module type S = sig exception A of {x:int} end;; + +module F (X : sig val x : (module S) end) = struct + module A = (val X.x) +end;; (* -> this expression creates fresh types (not really!) *) + + +module type S = sig + exception A of {x : int} + exception A of {x : string} +end;; + +module M = struct + exception A of {x : int} + exception A of {x : string} +end;; + + +module M1 = struct + exception A of {x : int} +end;; + +module M = struct + include M1 + include M1 +end;; + + +module type S1 = sig + exception A of {x : int} +end;; + +module type S = sig + include S1 + include S1 +end;; + +module M = struct + exception A = M1.A +end;; + +module X1 = struct + type t = .. +end;; +module X2 = struct + type t = .. +end;; +module Z = struct + type X1.t += A of {x: int} + type X2.t += A of {x: int} +end;; + +(* PR#6716 *) + +type _ c = C : [`A] c +type t = T : {x:[<`A] c} -> t;; +let f (T { x = C }) = ();; diff --git a/testsuite/tests/typing-recordarg/recordarg.ml.reference b/testsuite/tests/typing-recordarg/recordarg.ml.reference new file mode 100644 index 00000000..5a671d65 --- /dev/null +++ b/testsuite/tests/typing-recordarg/recordarg.ml.reference @@ -0,0 +1,67 @@ + +# type t = A of { x : int; mutable y : int; } +# Characters 14-15: + let f (A r) = r;; (* -> escape *) + ^ +Error: This form is not allowed as the type of the inlined record could escape. +# val f : t -> int = +# val f : int -> t = +# val f : t -> t = +# Characters 14-15: + let f () = A {a = 1};; (* customized error message *) + ^ +Error: The field a is not part of the record argument for the t.A constructor +# val f : unit -> t = +# type _ t = A : { x : 'a; y : 'b; } -> 'a t +# val f : 'a t -> 'a t = +# val f : 'a t -> 'a t = +# module M : + sig + type 'a t = A of { x : 'a; } | B : { u : 'b; } -> unit t + exception Foo of { x : int; } + end +# module N : + sig + type 'b t = 'b M.t = A of { x : 'b; } | B : { u : 'bla; } -> unit t + exception Foo of { x : int; } + end +# module type S = sig exception A of { x : int; } end +# Characters 65-74: + module A = (val X.x) + ^^^^^^^^^ +Error: This expression creates fresh types. + It is not allowed inside applicative functors. +# Characters 61-62: + exception A of {x : string} + ^ +Error: Multiple definition of the extension constructor name A. + Names must be unique in a given structure or signature. +# Characters 58-59: + exception A of {x : string} + ^ +Error: Multiple definition of the extension constructor name A. + Names must be unique in a given structure or signature. +# module M1 : sig exception A of { x : int; } end +# Characters 34-44: + include M1 + ^^^^^^^^^^ +Error: Multiple definition of the extension constructor name A. + Names must be unique in a given structure or signature. +# module type S1 = sig exception A of { x : int; } end +# Characters 36-46: + include S1 + ^^^^^^^^^^ +Error: Multiple definition of the extension constructor name A. + Names must be unique in a given structure or signature. +# module M : sig exception A of { x : int; } end +# module X1 : sig type t = .. end +# module X2 : sig type t = .. end +# Characters 62-63: + type X2.t += A of {x: int} + ^ +Error: Multiple definition of the extension constructor name A. + Names must be unique in a given structure or signature. +# type _ c = C : [ `A ] c +type t = T : { x : [< `A ] c; } -> t +# val f : t -> unit = +# diff --git a/testsuite/tests/typing-rectypes-bugs/Makefile b/testsuite/tests/typing-rectypes-bugs/Makefile index e0202b0a..5d8e8dbd 100644 --- a/testsuite/tests/typing-rectypes-bugs/Makefile +++ b/testsuite/tests/typing-rectypes-bugs/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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. * +#* * +#************************************************************************** include ../../makefiles/Makefile.okbad include ../../makefiles/Makefile.common diff --git a/testsuite/tests/typing-safe-linking/Makefile b/testsuite/tests/typing-safe-linking/Makefile new file mode 100644 index 00000000..a1e8aba8 --- /dev/null +++ b/testsuite/tests/typing-safe-linking/Makefile @@ -0,0 +1,15 @@ +# Check safety of linking + +SOURCES = a.ml b_bad.ml +OBJECTS = $(SOURCES:%.ml=%.cmo) + +all: a.cmo + @printf " ... testing 'b_bad.ml'" + @$(OCAMLC) -c -safe-string -warn-error +8 b_bad.ml 2> /dev/null \ + && echo " => failed" || echo " => passed" + +clean: + @rm -f *.cmo *.cmi + +BASEDIR=../.. +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-safe-linking/a.ml b/testsuite/tests/typing-safe-linking/a.ml new file mode 100644 index 00000000..6c4ca42e --- /dev/null +++ b/testsuite/tests/typing-safe-linking/a.ml @@ -0,0 +1,5 @@ + type _ t = + X of string + | Y : bytes t + +let y : string t = Y diff --git a/testsuite/tests/typing-safe-linking/b_bad.ml b/testsuite/tests/typing-safe-linking/b_bad.ml new file mode 100644 index 00000000..8730dcbd --- /dev/null +++ b/testsuite/tests/typing-safe-linking/b_bad.ml @@ -0,0 +1,4 @@ +let f : string A.t -> unit = function + A.X s -> print_endline s + +let () = f A.y diff --git a/testsuite/tests/typing-short-paths/Makefile b/testsuite/tests/typing-short-paths/Makefile index 3b7cbaa3..3e5a5df0 100644 --- a/testsuite/tests/typing-short-paths/Makefile +++ b/testsuite/tests/typing-short-paths/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-short-paths/short-paths.ml.reference b/testsuite/tests/typing-short-paths/short-paths.ml.reference index b45fdd0d..df8f2c10 100644 --- a/testsuite/tests/typing-short-paths/short-paths.ml.reference +++ b/testsuite/tests/typing-short-paths/short-paths.ml.reference @@ -25,6 +25,8 @@ val merge : (key -> 'a option -> 'b option -> 'c option) -> 'a t -> 'b t -> 'c t + val union : + (key -> 'a -> 'a -> 'a option) -> 'a t -> 'a t -> 'a t val compare : ('a -> 'a -> key) -> 'a t -> 'a t -> key val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> bool val iter : (key -> 'a -> unit) -> 'a t -> unit @@ -69,7 +71,7 @@ type u = M.u = C # module N1 : sig type u = v and v = t1 end # type t1 = B # module N2 : sig type u = v and v = N1.v end -# module type PR6566 = sig type t = bytes end +# module type PR6566 = sig type t = string end # module PR6566 : sig type t = int end # Characters 26-32: module PR6566' : PR6566 = PR6566;; @@ -79,7 +81,7 @@ Error: Signature mismatch: Type declarations do not match: type t = int is not included in - type t = bytes + type t = string # module A : sig module B : sig type t = T end end # module M2 : sig type u = A.B.t type foo = int type v = u end # diff --git a/testsuite/tests/typing-signatures/Makefile b/testsuite/tests/typing-signatures/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-signatures/Makefile +++ b/testsuite/tests/typing-signatures/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-signatures/els.ml.reference b/testsuite/tests/typing-signatures/els.ml.reference index 407ced1d..460820b7 100644 --- a/testsuite/tests/typing-signatures/els.ml.reference +++ b/testsuite/tests/typing-signatures/els.ml.reference @@ -91,5 +91,5 @@ USERCODE(TV).F end # module type X = functor (X : CORE) -> BARECODE -# module type X = functor (_ : CORE) -> BARECODE +# module type X = CORE -> BARECODE # diff --git a/testsuite/tests/typing-signatures/pr6672.ml b/testsuite/tests/typing-signatures/pr6672.ml new file mode 100644 index 00000000..5b168f05 --- /dev/null +++ b/testsuite/tests/typing-signatures/pr6672.ml @@ -0,0 +1,3 @@ +module type S = sig type 'a t end;; +module type T = S with type +'a t = 'a list;; +module type T = S with type -'a t = 'a list;; diff --git a/testsuite/tests/typing-signatures/pr6672.ml.reference b/testsuite/tests/typing-signatures/pr6672.ml.reference new file mode 100644 index 00000000..959cee7e --- /dev/null +++ b/testsuite/tests/typing-signatures/pr6672.ml.reference @@ -0,0 +1,10 @@ + +# module type S = sig type 'a t end +# module type T = sig type 'a t = 'a list end +# Characters 23-43: + module type T = S with type -'a t = 'a list;; + ^^^^^^^^^^^^^^^^^^^^ +Error: In this definition, expected parameter variances are not satisfied. + The 1st type parameter was expected to be contravariant, + but it is injective covariant. +# diff --git a/testsuite/tests/typing-sigsubst/Makefile b/testsuite/tests/typing-sigsubst/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-sigsubst/Makefile +++ b/testsuite/tests/typing-sigsubst/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-typeparam/Makefile b/testsuite/tests/typing-typeparam/Makefile index c9433b2e..7fc00661 100644 --- a/testsuite/tests/typing-typeparam/Makefile +++ b/testsuite/tests/typing-typeparam/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-typeparam/newtype.ml.reference b/testsuite/tests/typing-typeparam/newtype.ml.reference index c28cf53a..21769753 100644 --- a/testsuite/tests/typing-typeparam/newtype.ml.reference +++ b/testsuite/tests/typing-typeparam/newtype.ml.reference @@ -9,11 +9,11 @@ false # Characters 33-34: let f x (type a) (y : a) = (x = y);; (* Fails *) ^ -Error: This expression has type a but an expression was expected of type a +Error: This expression has type a but an expression was expected of type 'a The type constructor a would escape its scope # Characters 117-118: method n : 'a -> 'a = fun (type g) (x:g) -> self#m x ^ -Error: This expression has type g but an expression was expected of type g +Error: This expression has type g but an expression was expected of type 'a The type constructor g would escape its scope # diff --git a/testsuite/tests/typing-unboxed/Makefile b/testsuite/tests/typing-unboxed/Makefile new file mode 100644 index 00000000..7fc00661 --- /dev/null +++ b/testsuite/tests/typing-unboxed/Makefile @@ -0,0 +1,18 @@ +#************************************************************************** +#* * +#* 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=../.. +include $(BASEDIR)/makefiles/Makefile.toplevel +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/typing-unboxed/test.ml b/testsuite/tests/typing-unboxed/test.ml new file mode 100644 index 00000000..bb265c44 --- /dev/null +++ b/testsuite/tests/typing-unboxed/test.ml @@ -0,0 +1,126 @@ + +external a : (int [@untagged]) -> unit = "a" "a_nat" +external b : (int32 [@unboxed]) -> unit = "b" "b_nat" +external c : (int64 [@unboxed]) -> unit = "c" "c_nat" +external d : (nativeint [@unboxed]) -> unit = "d" "d_nat" +external e : (float [@unboxed]) -> unit = "e" "e_nat" + +type t = private int + +external f : (t [@untagged]) -> unit = "f" "f_nat" + +module M : sig + external a : int -> (int [@untagged]) = "a" "a_nat" + external b : (int [@untagged]) -> int = "b" "b_nat" +end = struct + external a : int -> (int [@untagged]) = "a" "a_nat" + external b : (int [@untagged]) -> int = "b" "b_nat" +end;; + +module Global_attributes = struct + [@@@ocaml.warning "-3"] + + external a : float -> float = "a" "noalloc" "a_nat" "float" + external b : float -> float = "b" "noalloc" "b_nat" + external c : float -> float = "c" "c_nat" "float" + external d : float -> float = "d" "noalloc" + external e : float -> float = "e" + + (* Should output a warning: no native implementation provided *) + external f : (int32 [@unboxed]) -> (int32 [@unboxed]) = "f" "noalloc" + external g : int32 -> int32 = "g" "g_nat" [@@unboxed] [@@noalloc] + + external h : (int [@untagged]) -> (int [@untagged]) = "h" "h_nat" "noalloc" + external i : int -> int = "i" "i_nat" [@@untagged] [@@noalloc] +end;; + +module Old_style_warning = struct + [@@@ocaml.warning "+3"] + external a : float -> float = "a" "noalloc" "a_nat" "float" + external b : float -> float = "b" "noalloc" "b_nat" + external c : float -> float = "c" "c_nat" "float" + external d : float -> float = "d" "noalloc" + external e : float -> float = "c" "float" +end + +(* Bad: attributes not reported in the interface *) + +module Bad1 : sig + external f : int -> int = "f" "f_nat" +end = struct + external f : int -> (int [@untagged]) = "f" "f_nat" +end;; + +module Bad2 : sig + external f : int -> int = "a" "a_nat" +end = struct + external f : (int [@untagged]) -> int = "f" "f_nat" +end;; + +module Bad3 : sig + external f : float -> float = "f" "f_nat" +end = struct + external f : float -> (float [@unboxed]) = "f" "f_nat" +end;; + +module Bad4 : sig + external f : float -> float = "a" "a_nat" +end = struct + external f : (float [@unboxed]) -> float = "f" "f_nat" +end;; + +(* Bad: attributes in the interface but not in the implementation *) + +module Bad5 : sig + external f : int -> (int [@untagged]) = "f" "f_nat" +end = struct + external f : int -> int = "f" "f_nat" +end;; + +module Bad6 : sig + external f : (int [@untagged]) -> int = "f" "f_nat" +end = struct + external f : int -> int = "a" "a_nat" +end;; + +module Bad7 : sig + external f : float -> (float [@unboxed]) = "f" "f_nat" +end = struct + external f : float -> float = "f" "f_nat" +end;; + +module Bad8 : sig + external f : (float [@unboxed]) -> float = "f" "f_nat" +end = struct + external f : float -> float = "a" "a_nat" +end;; + +(* Bad: unboxed or untagged with the wrong type *) + +external g : (float [@untagged]) -> float = "g" "g_nat";; +external h : (int [@unboxed]) -> float = "h" "h_nat";; + +(* Bad: unboxing the function type *) +external i : int -> float [@unboxed] = "i" "i_nat";; + +(* Bad: unboxing a "deep" sub-type. *) +external j : int -> (float [@unboxed]) * float = "j" "j_nat";; + +(* This should be rejected, but it is quite complicated to do + in the current state of things *) + +external k : int -> (float [@unboxd]) = "k" "k_nat";; + +(* Bad: old style annotations + new style attributes *) + +external l : float -> float = "l" "l_nat" "float" [@@unboxed];; +external m : (float [@unboxed]) -> float = "m" "m_nat" "float";; +external n : float -> float = "n" "noalloc" [@@noalloc];; + +(* Warnings: unboxed / untagged without any native implementation *) +external o : (float[@unboxed]) -> float = "o";; +external p : float -> (float[@unboxed]) = "p";; +external q : (int[@untagged]) -> float = "q";; +external r : int -> (int[@untagged]) = "r";; +external s : int -> int = "s" [@@untagged];; +external t : float -> float = "t" [@@unboxed];; diff --git a/testsuite/tests/typing-unboxed/test.ml.reference b/testsuite/tests/typing-unboxed/test.ml.reference new file mode 100644 index 00000000..c76b8af4 --- /dev/null +++ b/testsuite/tests/typing-unboxed/test.ml.reference @@ -0,0 +1,191 @@ + +# external a : (int [@untagged]) -> unit = "a" "a_nat" +external b : (int32 [@unboxed]) -> unit = "b" "b_nat" +external c : (int64 [@unboxed]) -> unit = "c" "c_nat" +external d : (nativeint [@unboxed]) -> unit = "d" "d_nat" +external e : (float [@unboxed]) -> unit = "e" "e_nat" +type t = private int +external f : (t [@untagged]) -> unit = "f" "f_nat" +module M : + sig + external a : int -> (int [@untagged]) = "a" "a_nat" + external b : (int [@untagged]) -> int = "b" "b_nat" + end +# Characters 382-451: + external f : (int32 [@unboxed]) -> (int32 [@unboxed]) = "f" "noalloc" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# Characters 63-122: + external a : float -> float = "a" "noalloc" "a_nat" "float" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 3: deprecated: [@@unboxed] + [@@noalloc] should be used instead of "float" +Characters 125-176: + external b : float -> float = "b" "noalloc" "b_nat" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 3: deprecated: [@@noalloc] should be used instead of "noalloc" +Characters 179-228: + external c : float -> float = "c" "c_nat" "float" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 3: deprecated: [@@unboxed] + [@@noalloc] should be used instead of "float" +Characters 231-274: + external d : float -> float = "d" "noalloc" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 3: deprecated: [@@noalloc] should be used instead of "noalloc" +Characters 441-505: + ......struct + external f : int -> (int [@untagged]) = "f" "f_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : int -> (int [@untagged]) = "f" "f_nat" end + is not included in + sig external f : int -> int = "f" "f_nat" end + Values do not match: + external f : int -> (int [@untagged]) = "f" "f_nat" + is not included in + external f : int -> int = "f" "f_nat" +# Characters 65-129: + ......struct + external f : (int [@untagged]) -> int = "f" "f_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : (int [@untagged]) -> int = "f" "f_nat" end + is not included in + sig external f : int -> int = "a" "a_nat" end + Values do not match: + external f : (int [@untagged]) -> int = "f" "f_nat" + is not included in + external f : int -> int = "a" "a_nat" +# Characters 69-136: + ......struct + external f : float -> (float [@unboxed]) = "f" "f_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : float -> (float [@unboxed]) = "f" "f_nat" end + is not included in + sig external f : float -> float = "f" "f_nat" end + Values do not match: + external f : float -> (float [@unboxed]) = "f" "f_nat" + is not included in + external f : float -> float = "f" "f_nat" +# Characters 69-136: + ......struct + external f : (float [@unboxed]) -> float = "f" "f_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : (float [@unboxed]) -> float = "f" "f_nat" end + is not included in + sig external f : float -> float = "a" "a_nat" end + Values do not match: + external f : (float [@unboxed]) -> float = "f" "f_nat" + is not included in + external f : float -> float = "a" "a_nat" +# Characters 149-199: + ......struct + external f : int -> int = "f" "f_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : int -> int = "f" "f_nat" end + is not included in + sig external f : int -> (int [@untagged]) = "f" "f_nat" end + Values do not match: + external f : int -> int = "f" "f_nat" + is not included in + external f : int -> (int [@untagged]) = "f" "f_nat" +# Characters 79-129: + ......struct + external f : int -> int = "a" "a_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : int -> int = "a" "a_nat" end + is not included in + sig external f : (int [@untagged]) -> int = "f" "f_nat" end + Values do not match: + external f : int -> int = "a" "a_nat" + is not included in + external f : (int [@untagged]) -> int = "f" "f_nat" +# Characters 82-136: + ......struct + external f : float -> float = "f" "f_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : float -> float = "f" "f_nat" end + is not included in + sig external f : float -> (float [@unboxed]) = "f" "f_nat" end + Values do not match: + external f : float -> float = "f" "f_nat" + is not included in + external f : float -> (float [@unboxed]) = "f" "f_nat" +# Characters 82-136: + ......struct + external f : float -> float = "a" "a_nat" + end.. +Error: Signature mismatch: + Modules do not match: + sig external f : float -> float = "a" "a_nat" end + is not included in + sig external f : (float [@unboxed]) -> float = "f" "f_nat" end + Values do not match: + external f : float -> float = "a" "a_nat" + is not included in + external f : (float [@unboxed]) -> float = "f" "f_nat" +# Characters 67-72: + external g : (float [@untagged]) -> float = "g" "g_nat";; + ^^^^^ +Error: Don't know how to untag this type. Only int can be untagged +# Characters 14-17: + external h : (int [@unboxed]) -> float = "h" "h_nat";; + ^^^ +Error: Don't know how to unbox this type. Only float, int32, int64 and nativeint can be unboxed +# Characters 52-64: + external i : int -> float [@unboxed] = "i" "i_nat";; + ^^^^^^^^^^^^ +Error: Don't know how to unbox this type. Only float, int32, int64 and nativeint can be unboxed +# Characters 61-66: + external j : int -> (float [@unboxed]) * float = "j" "j_nat";; + ^^^^^ +Error: The attribute '@unboxed' should be attached to a direct argument or result of the primitive, it should not occur deeply into its type +# * external k : int -> float = "k" "k_nat" +# Characters 58-119: + external l : float -> float = "l" "l_nat" "float" [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot use "float" in conjunction with [@unboxed]/[@untagged] +# Characters 0-62: + external m : (float [@unboxed]) -> float = "m" "m_nat" "float";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot use "float" in conjunction with [@unboxed]/[@untagged] +# Characters 0-55: + external n : float -> float = "n" "noalloc" [@@noalloc];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: Cannot use "noalloc" in conjunction with [@@noalloc] +# Characters 70-115: + external o : (float[@unboxed]) -> float = "o";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# Characters 0-45: + external p : float -> (float[@unboxed]) = "p";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# Characters 0-44: + external q : (int[@untagged]) -> float = "q";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# Characters 0-42: + external r : int -> (int[@untagged]) = "r";; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# Characters 0-42: + external s : int -> int = "s" [@@untagged];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# Characters 0-45: + external t : float -> float = "t" [@@unboxed];; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Error: The native code version of the primitive is mandatory when attributes [@untagged] or [@unboxed] are present +# diff --git a/testsuite/tests/typing-warnings/Makefile b/testsuite/tests/typing-warnings/Makefile index 9d79c58e..fd7f751c 100644 --- a/testsuite/tests/typing-warnings/Makefile +++ b/testsuite/tests/typing-warnings/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. include $(BASEDIR)/makefiles/Makefile.toplevel diff --git a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml new file mode 100644 index 00000000..78557072 --- /dev/null +++ b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml @@ -0,0 +1,203 @@ +let () = print_endline "\n\ + <----------------------------------------------------------------------\n\ + To check the result file for this test, it suffices to look for \"val\"\n\ + lines corresponding to toplevel answers. If they start with\n\ + \n\ + \ val ambiguous_...\n\ + \n\ + then just above there should be the warning text for Warning 57\n\ + (we try to avoid all other warnings). If they start with\n\ + \n\ + \ val not_ambiguous_...\n\ + \n\ + then just above there should be *no* warning text.\n\ + ---------------------------------------------------------------------->\n\ +";; + + +type expr = Val of int | Rest;; + +let ambiguous_typical_example = function + | ((Val x, _) | (_, Val x)) when x < 0 -> () + | (_, Rest) -> () + | (_, Val x) -> + (* the reader might expect *) + assert (x >= 0); + (* to hold here, but it is wrong! *) + () +;; + +let () = print_endline "Note that an Assert_failure is expected just below.";; +let fails = ambiguous_typical_example (Val 2, Val (-1)) +;; + +let not_ambiguous__no_orpat = function + | Some x when x > 0 -> () + | Some _ -> () + | None -> () +;; + +let not_ambiguous__no_guard = function + | `A -> () + | (`B | `C) -> () +;; + +let not_ambiguous__no_patvar_in_guard b = function + | (`B x | `C x) when b -> ignore x + | _ -> () +;; + +let not_ambiguous__disjoint_cases = function + | (`B x | `C x) when x -> () + | _ -> () +;; + +(* the curious (..., _, Some _) | (..., Some _, _) device used in + those tests serves to avoid warning 12 (this sub-pattern + is unused), by making sure that, even if the two sides of the + disjunction overlap, none is fully included in the other. *) +let not_ambiguous__prefix_variables = function + | (`B (x, _, Some y) | `B (x, Some y, _)) when x -> ignore y + | _ -> () +;; + +let ambiguous__y = function + | (`B (x, _, Some y) | `B (x, Some y, _)) when y -> ignore x + | _ -> () +;; + +(* it should be understood that the ambiguity warning only protects + (p | q) when guard -> ... + it will never warn on + (p | q) -> if guard ... + This is not a limitation. The point is that people have an + intuitive understanding of [(p | q) when guard -> ...] that differs + from the reality, while there is no such issue with + [(p | q) -> if guard ...]. +*) +let not_ambiguous__rhs_not_protected = function + | (`B (x, _, Some y) | `B (x, Some y, _)) -> if y then ignore x else () + | _ -> () +;; + +let ambiguous__x_y = function + | (`B (x, _, Some y) | `B (x, Some y, _)) when x < y -> () + | _ -> () +;; + +let ambiguous__x_y_z = function + | (`B (x, z, Some y) | `B (x, Some y, z)) when x < y || Some x = z -> () + | _ -> () +;; + +let not_ambiguous__disjoint_in_depth = function + | `A (`B x | `C x) when x -> () + | _ -> () +;; + +let not_ambiguous__prefix_variables_in_depth = function + | `A (`B (x, `C1) | `B (x, `C2)) when x -> () + | _ -> () +;; + +let ambiguous__in_depth = function + | `A (`B (Some x, _) | `B (_, Some x)) when x -> () + | _ -> () +;; + +let not_ambiguous__several_orpats = function + | `A ((`B (x, Some _, _) | `B (x, _, Some _)), + (`C (y, Some _, _) | `C (y, _, Some _)), + (`D1 (_, z, Some _, _) | `D2 (_, z, _, Some _))) when x < y && x < z -> + () + | _ -> () +;; + +let ambiguous__first_orpat = function + | `A ((`B (Some x, _) | `B (_, Some x)), + (`C (Some y, Some _, _) | `C (Some y, _, Some _))) when x < y -> () + | _ -> () +;; + +let ambiguous__second_orpat = function + | `A ((`B (Some x, Some _, _) | `B (Some x, _, Some _)), + (`C (Some y, _) | `C (_, Some y))) when x < y -> () + | _ -> () +;; + +(* check that common prefixes work as expected *) +let not_ambiguous__pairs = function + | (x, Some _, _) | (x, _, Some _) when x -> () + | _ -> () +;; + +let not_ambiguous__vars = + begin[@warning "-12"] function + | (x | x) when x -> () + | _ -> () + end +;; + +let not_ambiguous__as p = function + | (([], _) as x | ((_, []) as x)) when p x -> () + | _ -> () +;; + +let not_ambiguous__as_var p = function + | (([], _) as x | x) when p x -> () + | _ -> () +;; + +let not_ambiguous__var_as p = function + | (x, Some _, _) | (([], _) as x, _, Some _) when p x -> () + | _ -> () +;; + +let not_ambiguous__lazy = function + | (([], _), lazy x) | ((_, []), lazy x) when x -> () + | _ -> () + +;; + +type t = A of int * int option * int option | B;; + +let not_ambiguous__constructor = function + | A (x, Some _, _) | A (x, _, Some _) when x > 0 -> () + | A _ | B -> () +;; + + +type amoi = Z of int | Y of int * int | X of amoi * amoi +;; + +let ambiguous__amoi a = match a with +| X (Z x,Y (y,0)) +| X (Z y,Y (x,_)) + when x+y > 0 -> 0 +| X _|Y _|Z _ -> 1 +;; + +module type S = sig val b : bool end +;; + +let ambiguous__module_variable x b = match x with + | (module M:S),_,(1,_) + | _,(module M:S),(_,1) when M.b && b -> 1 + | _ -> 2 +;; + +let not_ambiguous__module_variable x b = match x with + | (module M:S),_,(1,_) + | _,(module M:S),(_,1) when b -> 1 + | _ -> 2 +;; + +(* Mixed case *) + +type t = A of int * int | B of int * int +;; + +let ambiguous_xy_but_not_ambiguous_z g = function + | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 + | _ -> 2 +;; diff --git a/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference new file mode 100644 index 00000000..2b9d4c2b --- /dev/null +++ b/testsuite/tests/typing-warnings/ambiguous_guarded_disjunction.ml.reference @@ -0,0 +1,139 @@ + +# +<---------------------------------------------------------------------- +To check the result file for this test, it suffices to look for "val" +lines corresponding to toplevel answers. If they start with + + val ambiguous_... + +then just above there should be the warning text for Warning 57 +(we try to avoid all other warnings). If they start with + + val not_ambiguous_... + +then just above there should be *no* warning text. +----------------------------------------------------------------------> + +# type expr = Val of int | Rest +# Characters 46-71: + | ((Val x, _) | (_, Val x)) when x < 0 -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^ +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). +# val not_ambiguous__no_orpat : int option -> unit = +# val not_ambiguous__no_guard : [< `A | `B | `C ] -> unit = +# val not_ambiguous__no_patvar_in_guard : + bool -> [> `B of 'a | `C of 'a ] -> unit = +# val not_ambiguous__disjoint_cases : [> `B of bool | `C of bool ] -> unit = + +# * * * val not_ambiguous__prefix_variables : + [> `B of bool * 'a option * 'a option ] -> unit = +# Characters 33-72: + | (`B (x, _, Some y) | `B (x, Some y, _)) when y -> ignore x + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 8.5) +val ambiguous__y : [> `B of 'a * bool option * bool option ] -> unit = +# * * * * * * * * val not_ambiguous__rhs_not_protected : + [> `B of 'a * bool option * bool option ] -> unit = +# Characters 35-74: + | (`B (x, _, Some y) | `B (x, Some y, _)) when x < y -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 8.5) +val ambiguous__x_y : [> `B of 'a * 'a option * 'a option ] -> unit = +# Characters 37-76: + | (`B (x, z, Some y) | `B (x, Some y, z)) when x < y || Some x = z -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variables y,z may match different arguments. (See manual section 8.5) +val ambiguous__x_y_z : [> `B of 'a * 'a option * 'a option ] -> unit = +# val not_ambiguous__disjoint_in_depth : + [> `A of [> `B of bool | `C of bool ] ] -> unit = +# val not_ambiguous__prefix_variables_in_depth : + [> `A of [> `B of bool * [> `C1 | `C2 ] ] ] -> unit = +# Characters 40-76: + | `A (`B (Some x, _) | `B (_, Some x)) when x -> () + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variable x may match different arguments. (See manual section 8.5) +val ambiguous__in_depth : + [> `A of [> `B of bool option * bool option ] ] -> unit = +# val not_ambiguous__several_orpats : + [> `A of + [> `B of 'a * 'b option * 'c option ] * + [> `C of 'a * 'd option * 'e option ] * + [> `D1 of 'f * 'a * 'g option * 'h | `D2 of 'i * 'a * 'j * 'k option ] ] -> + unit = +# Characters 43-140: + ....`A ((`B (Some x, _) | `B (_, Some x)), + (`C (Some y, Some _, _) | `C (Some y, _, Some _)))................. +Warning 57: Ambiguous or-pattern variables under guard; +variable x may match different arguments. (See manual section 8.5) +val ambiguous__first_orpat : + [> `A of + [> `B of 'a option * 'a option ] * + [> `C of 'a option * 'b option * 'c option ] ] -> + unit = +# Characters 44-141: + ....`A ((`B (Some x, Some _, _) | `B (Some x, _, Some _)), + (`C (Some y, _) | `C (_, Some y)))................. +Warning 57: Ambiguous or-pattern variables under guard; +variable y may match different arguments. (See manual section 8.5) +val ambiguous__second_orpat : + [> `A of + [> `B of 'a option * 'b option * 'c option ] * + [> `C of 'a option * 'a option ] ] -> + unit = +# val not_ambiguous__pairs : bool * 'a option * 'b option -> unit = +# val not_ambiguous__vars : bool -> unit = +# val not_ambiguous__as : + ('a list * 'b list -> bool) -> 'a list * 'b list -> unit = +# val not_ambiguous__as_var : ('a list * 'b -> bool) -> 'a list * 'b -> unit = + +# val not_ambiguous__var_as : + ('a list * 'b -> bool) -> ('a list * 'b) * 'c option * 'd option -> unit = + +# val not_ambiguous__lazy : ('a list * 'b list) * bool lazy_t -> unit = +# type t = A of int * int option * int option | B +# val not_ambiguous__constructor : t -> unit = +# type amoi = Z of int | Y of int * int | X of amoi * amoi +# Characters 40-73: + ..X (Z x,Y (y,0)) + | X (Z y,Y (x,_)) +Warning 57: Ambiguous or-pattern variables under guard; +variables x,y may match different arguments. (See manual section 8.5) +val ambiguous__amoi : amoi -> int = +# module type S = sig val b : bool end +# Characters 56-101: + ....(module M:S),_,(1,_) + | _,(module M:S),(_,1)................... +Warning 57: Ambiguous or-pattern variables under guard; +variable M may match different arguments. (See manual section 8.5) +val ambiguous__module_variable : + (module S) * (module S) * (int * int) -> bool -> int = +# val not_ambiguous__module_variable : + (module S) * (module S) * (int * int) -> bool -> int = +# type t = A of int * int | B of int * int +# Characters 55-56: + | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 + ^ +Warning 41: A belongs to several types: t t +The first one was selected. Please disambiguate if this is wrong. +Characters 42-138: + .........................................function + | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 + | _ -> 2 +Warning 4: this pattern-matching is fragile. +It will remain exhaustive when constructors are added to type t. +Characters 55-107: + | A (x as z,(0 as y))|A (0 as y as z,x)|B (x,(y as z)) when g x (y+z) -> 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 57: Ambiguous or-pattern variables under guard; +variables x,y may match different arguments. (See manual section 8.5) +val ambiguous_xy_but_not_ambiguous_z : (int -> int -> bool) -> t -> int = + +# diff --git a/testsuite/tests/typing-warnings/application.ml b/testsuite/tests/typing-warnings/application.ml new file mode 100644 index 00000000..a0c42061 --- /dev/null +++ b/testsuite/tests/typing-warnings/application.ml @@ -0,0 +1,2 @@ +let _ = ignore (+);; +let _ = raise Exit 3;; diff --git a/testsuite/tests/typing-warnings/application.ml.reference b/testsuite/tests/typing-warnings/application.ml.reference new file mode 100644 index 00000000..da825fd0 --- /dev/null +++ b/testsuite/tests/typing-warnings/application.ml.reference @@ -0,0 +1,13 @@ + +# Characters 15-18: + let _ = ignore (+);; + ^^^ +Warning 5: this function application is partial, +maybe some arguments are missing. +- : unit = () +# Characters 19-20: + let _ = raise Exit 3;; + ^ +Warning 20: this argument will not be used by the function. +Exception: Pervasives.Exit. +# diff --git a/testsuite/tests/typing-warnings/coercions.ml b/testsuite/tests/typing-warnings/coercions.ml index 1ca390b2..5fd77e1a 100644 --- a/testsuite/tests/typing-warnings/coercions.ml +++ b/testsuite/tests/typing-warnings/coercions.ml @@ -2,4 +2,21 @@ fun b -> if b then format_of_string "x" else "y";; fun b -> if b then "x" else format_of_string "y";; -fun b -> (if b then "x" else "y" : (_,_,_) format);; +fun b : (_,_,_) format -> if b then "x" else "y";; + +(* PR#7135 *) + +module PR7135 = struct + module M : sig type t = private int end = struct type t = int end + include M + + let lift2 (f : int -> int -> int) (x : t) (y : t) = + f (x :> int) (y :> int) +end;; + +(* exemple of non-ground coercion *) + +module Test1 = struct + type t = private int + let f x = let y = if true then x else (x:t) in (y :> int) +end;; diff --git a/testsuite/tests/typing-warnings/coercions.ml.principal.reference b/testsuite/tests/typing-warnings/coercions.ml.principal.reference index d5397bf0..c16dd9f8 100644 --- a/testsuite/tests/typing-warnings/coercions.ml.principal.reference +++ b/testsuite/tests/typing-warnings/coercions.ml.principal.reference @@ -12,4 +12,15 @@ Error: This expression has type ('a, 'b, 'c, 'd, 'd, 'a) CamlinternalFormatBasics.format6 but an expression was expected of type string # - : bool -> ('a, 'b, 'a) format = +# module PR7135 : + sig + module M : sig type t = private int end + type t = M.t + val lift2 : (int -> int -> int) -> t -> t -> int + end +# Characters 133-143: + let f x = let y = if true then x else (x:t) in (y :> int) + ^^^^^^^^^^ +Warning 18: this ground coercion is not principal. +module Test1 : sig type t = private int val f : t -> int end # diff --git a/testsuite/tests/typing-warnings/coercions.ml.reference b/testsuite/tests/typing-warnings/coercions.ml.reference index f4421305..f5ff65b7 100644 --- a/testsuite/tests/typing-warnings/coercions.ml.reference +++ b/testsuite/tests/typing-warnings/coercions.ml.reference @@ -8,4 +8,11 @@ Error: This expression has type ('a, 'b, 'c, 'd, 'd, 'a) CamlinternalFormatBasics.format6 but an expression was expected of type string # - : bool -> ('a, 'b, 'a) format = +# module PR7135 : + sig + module M : sig type t = private int end + type t = M.t + val lift2 : (int -> int -> int) -> t -> t -> int + end +# module Test1 : sig type t = private int val f : t -> int end # diff --git a/testsuite/tests/typing-warnings/exhaustiveness.ml b/testsuite/tests/typing-warnings/exhaustiveness.ml new file mode 100644 index 00000000..2ddb79d3 --- /dev/null +++ b/testsuite/tests/typing-warnings/exhaustiveness.ml @@ -0,0 +1,109 @@ +(* Warn about all relevant cases when possible *) +let f = function + None, None -> 1 + | Some _, Some _ -> 2;; + +(* Exhaustiveness check is very slow *) +type _ t = + A : int t | B : bool t | C : char t | D : float t +type (_,_,_,_) u = U : (int, int, int, int) u +type v = E | F | G +;; + +let f : type a b c d e f g. + a t * b t * c t * d t * e t * f t * g t * v + * (a,b,c,d) u * (e,f,g,g) u -> int = + function A, A, A, A, A, A, A, _, U, U -> 1 + | _, _, _, _, _, _, _, G, _, _ -> 1 + (*| _ -> _ *) +;; + +(* Unused cases *) +let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) +let f (x : unit t option) = match x with None -> 1 | _ -> 2 ;; (* warn? *) +let f (x : unit t option) = match x with None -> 1 | Some _ -> 2 ;; (* warn *) +let f (x : int t option) = match x with None -> 1 | _ -> 2;; +let f (x : int t option) = match x with None -> 1;; (* warn *) + +(* Example with record, type, single case *) + +type 'a box = Box of 'a +type 'a pair = {left: 'a; right: 'a};; + +let f : (int t box pair * bool) option -> unit = function None -> ();; +let f : (string t box pair * bool) option -> unit = function None -> ();; + + +(* Examples from ML2015 paper *) + +type _ t = + | Int : int t + | Bool : bool t +;; + +let f : type a. a t -> a = function + | Int -> 1 + | Bool -> true +;; +let g : int t -> int = function + | Int -> 1 +;; +let h : type a. a t -> a t -> bool = + fun x y -> match x, y with + | Int, Int -> true + | Bool, Bool -> true +;; +type (_, _) cmp = + | Eq : ('a, 'a) cmp + | Any: ('a, 'b) cmp +module A : sig type a type b val eq : (a, b) cmp end + = struct type a type b = a let eq = Eq end +;; +let f : (A.a, A.b) cmp -> unit = function Any -> () +;; +let deep : char t option -> char = + function None -> 'c' +;; +type zero = Zero +type _ succ = Succ +;; +type (_,_,_) plus = + | Plus0 : (zero, 'a, 'a) plus + | PlusS : ('a, 'b, 'c) plus -> + ('a succ, 'b, 'c succ) plus +;; +let trivial : (zero succ, zero, zero) plus option -> bool = + function None -> false +;; +let easy : (zero, zero succ, zero) plus option -> bool = + function None -> false +;; +let harder : (zero succ, zero succ, zero succ) plus option -> bool = + function None -> false +;; +let harder : (zero succ, zero succ, zero succ) plus option -> bool = + function None -> false | Some (PlusS _) -> . +;; +let inv_zero : type a b c d. (a,b,c) plus -> (c,d,zero) plus -> bool = + fun p1 p2 -> + match p1, p2 with + | Plus0, Plus0 -> true +;; + + +(* Empty match *) + +type _ t = Int : int t;; +let f (x : bool t) = match x with _ -> . ;; (* ok *) + + +(* trefis in PR#6437 *) + +let f () = match None with _ -> .;; (* error *) +let g () = match None with _ -> () | exception _ -> .;; (* error *) +let h () = match None with _ -> . | exception _ -> .;; (* error *) +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;; diff --git a/testsuite/tests/typing-warnings/exhaustiveness.ml.reference b/testsuite/tests/typing-warnings/exhaustiveness.ml.reference new file mode 100644 index 00000000..e19efbb0 --- /dev/null +++ b/testsuite/tests/typing-warnings/exhaustiveness.ml.reference @@ -0,0 +1,122 @@ + +# Characters 58-110: + ........function + None, None -> 1 + | Some _, Some _ -> 2.. +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +((Some _, None)|(None, Some _)) +val f : 'a option * 'b option -> int = +# type _ t = A : int t | B : bool t | C : char t | D : float t +type (_, _, _, _) u = U : (int, int, int, int) u +type v = E | F | G +# Characters 124-205: + .function A, A, A, A, A, A, A, _, U, U -> 1 + | _, _, _, _, _, _, _, G, _, _ -> 1 +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +(A, A, A, A, A, A, B, (E|F), _, _) +Characters 172-200: + | _, _, _, _, _, _, _, G, _, _ -> 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : + 'a t * 'b t * 'c t * 'd t * 'e t * 'f t * 'g t * v * ('a, 'b, 'c, 'd) u * + ('e, 'f, 'g, 'g) u -> int = +# Characters 40-68: + let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 4: this pattern-matching is fragile. +It will remain exhaustive when constructors are added to type t. +Characters 62-63: + let f (x : int t) = match x with A -> 1 | _ -> 2;; (* warn *) + ^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : int t -> int = +# Characters 53-54: + let f (x : unit t option) = match x with None -> 1 | _ -> 2 ;; (* warn? *) + ^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : unit t option -> int = +# Characters 53-59: + let f (x : unit t option) = match x with None -> 1 | Some _ -> 2 ;; (* warn *) + ^^^^^^ +Warning 56: this match case is unreachable. +Consider replacing it with a refutation case ' -> .' +val f : unit t option -> int = +# val f : int t option -> int = +# Characters 27-49: + let f (x : int t option) = match x with None -> 1;; (* warn *) + ^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Some A +val f : int t option -> int = +# type 'a box = Box of 'a +type 'a pair = { left : 'a; right : 'a; } +# Characters 50-69: + let f : (int t box pair * bool) option -> unit = function None -> ();; + ^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Some ({left=Box A; right=Box A}, _) +val f : (int t box pair * bool) option -> unit = +# val f : (string t box pair * bool) option -> unit = +# type _ t = Int : int t | Bool : bool t +# val f : 'a t -> 'a = +# val g : int t -> int = +# val h : 'a t -> 'a t -> bool = +# type (_, _) cmp = Eq : ('a, 'a) cmp | Any : ('a, 'b) cmp +module A : sig type a type b val eq : (a, b) cmp end +# Characters 33-51: + let f : (A.a, A.b) cmp -> unit = function Any -> () + ^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Eq +val f : (A.a, A.b) cmp -> unit = +# val deep : char t option -> char = +# type zero = Zero +type _ succ = Succ +# type (_, _, _) plus = + Plus0 : (zero, 'a, 'a) plus + | PlusS : ('a, 'b, 'c) plus -> ('a succ, 'b, 'c succ) plus +# val trivial : (zero succ, zero, zero) plus option -> bool = +# val easy : (zero, zero succ, zero) plus option -> bool = +# Characters 71-93: + function None -> false + ^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Some (PlusS _) +val harder : (zero succ, zero succ, zero succ) plus option -> bool = +# val harder : (zero succ, zero succ, zero succ) plus option -> bool = +# val inv_zero : ('a, 'b, 'c) plus -> ('c, 'd, zero) plus -> bool = +# type _ t = Int : int t +# val f : bool t -> 'a = +# Characters 54-55: + let f () = match None with _ -> .;; (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +# Characters 47-48: + let g () = match None with _ -> () | exception _ -> .;; (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +# Characters 27-28: + let h () = match None with _ -> . | exception _ -> .;; (* error *) + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: _ +# val f : 'a option -> unit = +# Characters 47-77: + let f x y = match 1 with 1 when x = y -> 1;; + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +All clauses in this pattern-matching are guarded. +val f : 'a -> 'a -> int = +# diff --git a/testsuite/tests/typing-warnings/pr6872.ml b/testsuite/tests/typing-warnings/pr6872.ml index 6eba3e70..283af4cc 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml +++ b/testsuite/tests/typing-warnings/pr6872.ml @@ -6,4 +6,3 @@ raise A;; fun (A : a) -> ();; function Not_found -> 1 | A -> 2 | _ -> 3;; try raise A with A -> 2;; - diff --git a/testsuite/tests/typing-warnings/pr6872.ml.principal.reference b/testsuite/tests/typing-warnings/pr6872.ml.principal.reference index 0227cfd9..097e34f9 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml.principal.reference +++ b/testsuite/tests/typing-warnings/pr6872.ml.principal.reference @@ -32,4 +32,4 @@ Characters 17-18: ^ Warning 42: this use of A required disambiguation. - : int = 2 -# +# diff --git a/testsuite/tests/typing-warnings/pr6872.ml.reference b/testsuite/tests/typing-warnings/pr6872.ml.reference index 7aeebbeb..072ccb4d 100644 --- a/testsuite/tests/typing-warnings/pr6872.ml.reference +++ b/testsuite/tests/typing-warnings/pr6872.ml.reference @@ -27,4 +27,4 @@ Characters 17-18: ^ Warning 42: this use of A required disambiguation. - : int = 2 -# +# diff --git a/testsuite/tests/typing-warnings/pr7085.ml b/testsuite/tests/typing-warnings/pr7085.ml new file mode 100644 index 00000000..21ca0d67 --- /dev/null +++ b/testsuite/tests/typing-warnings/pr7085.ml @@ -0,0 +1,23 @@ +module TypEq = struct + type (_, _) t = Eq : ('a, 'a) t +end + +module type T = sig + type _ is_t = Is : ('a, 'b) TypEq.t -> 'a is_t + val is_t : unit -> unit is_t option +end + +module Make (M : T) = + struct + let _ = + match M.is_t () with + | None -> 0 + | Some _ -> 0 + let f () = + match M.is_t () with None -> 0 +end;; + +module Make2 (M : T) = struct + type t = T of unit M.is_t + let g : t -> int = function _ -> . +end;; diff --git a/testsuite/tests/typing-warnings/pr7085.ml.reference b/testsuite/tests/typing-warnings/pr7085.ml.reference new file mode 100644 index 00000000..960ccaff --- /dev/null +++ b/testsuite/tests/typing-warnings/pr7085.ml.reference @@ -0,0 +1,20 @@ + +# Characters 292-322: + match M.is_t () with None -> 0 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a value that is not matched: +Some (Is Eq) +module TypEq : sig type (_, _) t = Eq : ('a, 'a) t end +module type T = + sig + type _ is_t = Is : ('a, 'b) TypEq.t -> 'a is_t + val is_t : unit -> unit is_t option + end +module Make : functor (M : T) -> sig val f : unit -> int end +# Characters 89-90: + let g : t -> int = function _ -> . + ^ +Error: This match case could not be refuted. + Here is an example of a value that would reach it: T (Is Eq) +# diff --git a/testsuite/tests/typing-warnings/pr7115.ml b/testsuite/tests/typing-warnings/pr7115.ml new file mode 100755 index 00000000..1a892061 --- /dev/null +++ b/testsuite/tests/typing-warnings/pr7115.ml @@ -0,0 +1,20 @@ +type t = A : t;; + +module X1 : sig end = struct + let _f ~x (* x unused argument *) = function + | A -> let x = () in x +end;; + +module X2 : sig end = struct + let x = 42 (* unused value *) + let _f = function + | A -> let x = () in x +end;; + +module X3 : sig end = struct + module O = struct let x = 42 (* unused *) end + open O (* unused open *) + + let _f = function + | A -> let x = () in x +end;; diff --git a/testsuite/tests/typing-warnings/pr7115.ml.reference b/testsuite/tests/typing-warnings/pr7115.ml.reference new file mode 100644 index 00000000..8a4fcd6a --- /dev/null +++ b/testsuite/tests/typing-warnings/pr7115.ml.reference @@ -0,0 +1,22 @@ + +# type t = A : t +# Characters 40-41: + let _f ~x (* x unused argument *) = function + ^ +Warning 27: unused variable x. +module X1 : sig end +# Characters 36-37: + let x = 42 (* unused value *) + ^ +Warning 32: unused value x. +module X2 : sig end +# Characters 54-55: + module O = struct let x = 42 (* unused *) end + ^ +Warning 32: unused value x. +Characters 80-86: + open O (* unused open *) + ^^^^^^ +Warning 33: unused open O. +module X3 : sig end +# diff --git a/testsuite/tests/typing-warnings/records.ml b/testsuite/tests/typing-warnings/records.ml index 59a45549..768bb965 100644 --- a/testsuite/tests/typing-warnings/records.ml +++ b/testsuite/tests/typing-warnings/records.ml @@ -45,7 +45,7 @@ module OK = struct open M open N let f (r:M.t) = r.x -end;; +end;; module M = struct type t = {x:int} diff --git a/testsuite/tests/unboxed-primitive-args/Makefile b/testsuite/tests/unboxed-primitive-args/Makefile new file mode 100644 index 00000000..7a5c5ef1 --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/Makefile @@ -0,0 +1,40 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Jeremie Dimino, Jane Street Europe * +#* * +#* Copyright 2015 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 +MODULES=common +MAIN_MODULE=main +C_FILES=test_common stubs +C_INCLUDES=-I $(OTOPDIR)/otherlibs/bigarray +ADD_COMPFLAGS=-I $(OTOPDIR)/otherlibs/bigarray \ + -I $(OTOPDIR)/otherlibs/$(UNIXLIB) + +include $(BASEDIR)/makefiles/Makefile.one +include $(BASEDIR)/makefiles/Makefile.common + +NATIVECODE_ONLY=true +NATIVECCCOMPOPTS+=-I $(OTOPDIR)/otherlibs/bigarray +GENERATED_SOURCES+=main.ml stubs.c + +main.ml: gen_test.ml + @$(OCAML) gen_test.ml ml > $@ + +stubs.c: gen_test.ml + @$(OCAML) gen_test.ml c > $@ + +common.cmx: common.cmi + +compile: stubs.c diff --git a/testsuite/tests/unboxed-primitive-args/README b/testsuite/tests/unboxed-primitive-args/README new file mode 100644 index 00000000..4bd7601e --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/README @@ -0,0 +1,26 @@ +This directory contains tests to check that OCaml values are correctly +passed between OCaml and C when a primitive takes some or all of its +arguments unboxed/untagged and/or return its result unboxed/untagged. + +To test one primitive we do: +- write all its argument and expected result in buffer A +- call the C external using arguments read from buffer A +- the C function write all the arguments it receive into buffer B +- the C function read the result from buffer A and returns it +- on the OCaml side we write the received result into buffer B +- the test is successful if A and B have the same contents + +Between each call, we call a function with 128 value arguments set to +0 and a function with 32 unboxed float arguments set to 0., just to +clean-up the registers and stacks in case garbage would make a test +succeed. We don't pass more floats as it doesn't build on arm32. + +We construct the set of primitives to test as follow: +- all combination of unboxed int32/int64/float arguments for functions + taking up to 6 arguments (with more than 6 ocamlopt takes a really + long time to compile the test files) +- a bunch of manual tests for the rest and specific patterns. + The list is [Gen_test.manual_tests] + +We test the set of primitives a thousand times, with different random +data each time. diff --git a/testsuite/tests/unboxed-primitive-args/common.ml b/testsuite/tests/unboxed-primitive-args/common.ml new file mode 100644 index 00000000..53ffe758 --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/common.ml @@ -0,0 +1,301 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +open StdLabels + +open Bigarray + +type 'a typ = + | Int : int typ + | Int32 : int32 typ + | Int64 : int64 typ + | Nativeint : nativeint typ + | Float : float typ + +type 'a proto = + | Ret : 'a typ -> 'a proto + | Abs : 'a typ * 'b proto -> ('a -> 'b) proto + +let ( ** ) x y = Abs (x, y) + +(* This form is easier to process programmatically. We don't expose it as + ocamlopt takes a really really long time to compile a constant list + of these. *) +type simplified_test = Test : string * 'a * 'a proto -> simplified_test + +type test = + | T1 : string * ('a -> 'b) * 'a typ * 'b typ -> test + | T2 : string * ('a -> 'b -> 'c) * 'a typ * 'b typ * 'c typ -> test + | T3 : string * ('a -> 'b -> 'c -> 'd) * + 'a typ * 'b typ * 'c typ * 'd typ -> test + | T4 : string * ('a -> 'b -> 'c -> 'd -> 'e) * + 'a typ * 'b typ * 'c typ * 'd typ * 'e typ -> test + | T5 : string * ('a -> 'b -> 'c -> 'd -> 'e -> 'f) * + 'a typ * 'b typ * 'c typ * 'd typ * 'e typ * 'f typ -> test + | T6 : string * ('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g) * + 'a typ * 'b typ * 'c typ * 'd typ * 'e typ * 'f typ * 'g typ -> test + | T : string * 'a * 'a proto -> test + +let expand_test = function + | T1 (s, fn, a, b) -> Test (s, fn, a ** Ret b) + | T2 (s, fn, a, b, c) -> Test (s, fn, a ** b ** Ret c) + | T3 (s, fn, a, b, c, d) -> Test (s, fn, a ** b ** c ** Ret d) + | T4 (s, fn, a, b, c, d, e) -> Test (s, fn, a ** b ** c ** d ** Ret e) + | T5 (s, fn, a, b, c, d, e, f) -> + Test (s, fn, a ** b ** c ** d ** e ** Ret f) + | T6 (s, fn, a, b, c, d, e, f, g) -> + Test (s, fn, a ** b ** c ** d ** e ** f ** Ret g) + | T (s, fn, p) -> Test (s, fn, p) + +let string_of : type a. a typ -> a -> string = function + | Int -> string_of_int + | Int32 -> Printf.sprintf "%ldl" + | Int64 -> Printf.sprintf "%LdL" + | Nativeint -> Printf.sprintf "%ndn" + | Float -> + fun f -> Printf.sprintf "float_of_bits 0x%LxL" (Int64.bits_of_float f) + +let rec arity : type a. a proto -> int = function + | Ret _ -> 0 + | Abs (_, p) -> 1 + arity p + +module Buffer = struct + type t = (char, int8_unsigned_elt, c_layout) Array1.t + + let arg_size = 8 + + let create ~arity : t = + Array1.create char c_layout ((arity + 1) * arg_size) + + let clear (t : t) = Array1.fill t '\000' + + let length : t -> int = Array1.dim + + external init_c_side : ocaml_buffer:t -> c_buffer:t -> unit + = "test_set_buffers" + + external get_int32 : t -> int -> int32 = "%caml_bigstring_get32" + external get_int64 : t -> int -> int64 = "%caml_bigstring_get64" + external set_int32 : t -> int -> int32 -> unit = "%caml_bigstring_set32" + external set_int64 : t -> int -> int64 -> unit = "%caml_bigstring_set64" + + let get_int32 t ~arg = get_int32 t (arg * arg_size) + let get_int64 t ~arg = get_int64 t (arg * arg_size) + let set_int32 t ~arg x = set_int32 t (arg * arg_size) x + let set_int64 t ~arg x = set_int64 t (arg * arg_size) x + + let get_nativeint, set_nativeint = + match Sys.word_size with + | 32 -> ((fun t ~arg -> get_int32 t ~arg |> Nativeint.of_int32), + (fun t ~arg x -> set_int32 t ~arg (Nativeint.to_int32 x))) + | 64 -> ((fun t ~arg -> get_int64 t ~arg |> Int64.to_nativeint), + (fun t ~arg x -> set_int64 t ~arg (Int64.of_nativeint x))) + | n -> Printf.ksprintf failwith "unknown word size (%d)" n + + let get_int = + if Sys.word_size = 32 then + fun buf ~arg -> get_int32 buf ~arg |> Int32.to_int + else + fun buf ~arg -> get_int64 buf ~arg |> Int64.to_int + + let set_int = + if Sys.word_size = 32 then + fun buf ~arg x -> set_int32 buf ~arg (Int32.of_int x) + else + fun buf ~arg x -> set_int64 buf ~arg (Int64.of_int x) + + let get_float buf ~arg = get_int64 buf ~arg |> Int64.float_of_bits + let set_float buf ~arg x = set_int64 buf ~arg (Int64.bits_of_float x) + + let get : type a. a typ -> t -> arg:int -> a = function + | Int -> get_int + | Int32 -> get_int32 + | Int64 -> get_int64 + | Nativeint -> get_nativeint + | Float -> get_float + + let set : type a. a typ -> t -> arg:int -> a -> unit = function + | Int -> set_int + | Int32 -> set_int32 + | Int64 -> set_int64 + | Nativeint -> set_nativeint + | Float -> set_float + + (* This is almost a memcpy except that we use get/set which should + ensure that the values in [dst] don't overflow. *) + let copy_args ~src ~dst proto = + let rec loop : type a. a proto -> int -> unit = fun proto arg -> + match proto with + | Ret typ -> + set typ dst ~arg (get typ src ~arg) + | Abs (typ, rest) -> + set typ dst ~arg (get typ src ~arg); + loop rest (arg + 1) + in + loop proto 0 +end + +let exec proto f ~ocaml_buffer ~c_buffer = + let rec loop : type a. a proto -> a -> int -> unit = fun proto f arg -> + match proto with + | Ret typ -> + Buffer.set typ c_buffer ~arg f + | Abs (typ, rest) -> + let x = Buffer.get typ ocaml_buffer ~arg in + loop rest (f x) (arg + 1) + in + loop proto f 0 + +let strings_of_test_instance name proto buffer = + let rec loop : type a. a proto -> int -> string list -> string list * string = + fun proto arg acc -> + match proto with + | Ret typ -> + (List.rev acc, string_of typ (Buffer.get typ buffer ~arg)) + | Abs (typ, rest) -> + let s = string_of typ (Buffer.get typ buffer ~arg) in + loop rest (arg + 1) (s :: acc) + in + loop proto 0 [] + +let typ_size : type a. a typ -> int = function + | Int -> Sys.word_size / 8 + | Int32 -> 4 + | Int64 -> 8 + | Nativeint -> Sys.word_size / 8 + | Float -> 8 + +let rec sizes : type a. a proto -> int list = function + | Ret typ -> [typ_size typ] + | Abs (typ, rest) -> typ_size typ :: sizes rest + +let print_hex ~sizes ~arity buffer = + let printf = Printf.printf in + printf "("; + for i = 0 to arity do + if i = arity then + printf ") -> " + else if i > 0 then + printf ", "; + for ofs = i * Buffer.arg_size to i * Buffer.arg_size + sizes.(i) - 1 do + printf "%02x" (Char.code buffer.{ofs}); + done; + done + +let printed_mismatches = ref 0 + +let print_mismatch name proto ~ocaml_buffer ~c_buffer = + let printf = Printf.printf in + printf "Mismatch for %s\n" name; + let o_args, o_res = strings_of_test_instance name proto ocaml_buffer in + let c_args, c_res = strings_of_test_instance name proto c_buffer in + let o_args, c_args = + (* Align arguments *) + List.map2 o_args c_args ~f:(fun a b -> + let len_a = String.length a and len_b = String.length b in + let len = max len_a len_b in + (Printf.sprintf "%*s" len a, + Printf.sprintf "%*s" len b)) + |> List.split + in + printf "ocaml side : (%s) -> %s\n" (String.concat ~sep:", " o_args) o_res; + printf "c side : (%s) -> %s\n" (String.concat ~sep:", " c_args) c_res; + let sizes = sizes proto |> Array.of_list in + let arity = arity proto in + printf "ocaml side : "; print_hex ~sizes ~arity ocaml_buffer; printf "\n"; + printf "c side : "; print_hex ~sizes ~arity c_buffer; printf "\n"; + incr printed_mismatches; + if !printed_mismatches >= 1000 then begin + printf "Output truncated at 1000 failures."; + exit 0 + end + +external cleanup_normal + : int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int -> int -> int -> int -> int -> int -> int -> int + -> int = "" "test_cleanup_normal" [@@noalloc] + +external cleanup_float + : float -> float -> float -> float -> float -> float -> float -> float + -> float -> float -> float -> float -> float -> float -> float -> float + -> float -> float -> float -> float -> float -> float -> float -> float + -> float -> float -> float -> float -> float -> float -> float -> float + -> float = "" "test_cleanup_float" [@@noalloc] [@@unboxed] + +let cleanup_args_and_stack () = + let _ : int = + cleanup_normal + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + in + let _ : float = + cleanup_float + 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. + in + () + +let run_test ~random_data ~ocaml_buffer ~c_buffer (Test (name, f, proto)) = + Buffer.clear ocaml_buffer; + Buffer.clear c_buffer; + Buffer.copy_args ~src:random_data ~dst:ocaml_buffer proto; + cleanup_args_and_stack (); + exec proto f ~ocaml_buffer ~c_buffer; + let success = ocaml_buffer = c_buffer in + if not success then print_mismatch name proto ~ocaml_buffer ~c_buffer; + success + +let run_tests tests = + let tests = List.map tests ~f:expand_test in + let max_args = + List.fold_left tests ~init:0 ~f:(fun acc (Test (_, _, p)) -> + max acc (arity p)) + in + + let ocaml_buffer = Buffer.create ~arity:max_args + and c_buffer = Buffer.create ~arity:max_args in + Buffer.init_c_side ~ocaml_buffer ~c_buffer; + + let random_data = Buffer.create ~arity:max_args in + let new_random_data () = + for i = 0 to Buffer.length random_data - 1 do + random_data.{i} <- char_of_int (Random.int 256) + done + in + + let failure = ref false in + for i = 1 to 1000 do + new_random_data (); + List.iter tests ~f:(fun test -> + if not (run_test ~random_data ~ocaml_buffer ~c_buffer test) then + failure := true) + done; + exit (if !failure then 1 else 0) diff --git a/testsuite/tests/unboxed-primitive-args/common.mli b/testsuite/tests/unboxed-primitive-args/common.mli new file mode 100644 index 00000000..4f31d84d --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/common.mli @@ -0,0 +1,44 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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 of arguments/result *) +type 'a typ = + | Int : int typ + | Int32 : int32 typ + | Int64 : int64 typ + | Nativeint : nativeint typ + | Float : float typ + +type 'a proto = + | Ret : 'a typ -> 'a proto + | Abs : 'a typ * 'b proto -> ('a -> 'b) proto + +(** Same as [Abs]. We choose this operator for its associativity. *) +val ( ** ) : 'a typ -> 'b proto -> ('a -> 'b) proto + +type test = + | T1 : string * ('a -> 'b) * 'a typ * 'b typ -> test + | T2 : string * ('a -> 'b -> 'c) * 'a typ * 'b typ * 'c typ -> test + | T3 : string * ('a -> 'b -> 'c -> 'd) * + 'a typ * 'b typ * 'c typ * 'd typ -> test + | T4 : string * ('a -> 'b -> 'c -> 'd -> 'e) * + 'a typ * 'b typ * 'c typ * 'd typ * 'e typ -> test + | T5 : string * ('a -> 'b -> 'c -> 'd -> 'e -> 'f) * + 'a typ * 'b typ * 'c typ * 'd typ * 'e typ * 'f typ -> test + | T6 : string * ('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g) * + 'a typ * 'b typ * 'c typ * 'd typ * 'e typ * 'f typ * 'g typ -> test + | T : string * 'a * 'a proto -> test + +val run_tests : test list -> unit diff --git a/testsuite/tests/unboxed-primitive-args/gen_test.ml b/testsuite/tests/unboxed-primitive-args/gen_test.ml new file mode 100644 index 00000000..65de0e7b --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/gen_test.ml @@ -0,0 +1,243 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jeremie Dimino, Jane Street Europe *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +(* This programs generate stubs with various prototype combinations *) + +open StdLabels + +type boxed_integer = Pnativeint | Pint32 | Pint64 + +type native_repr = + | Same_as_ocaml_repr + | Unboxed_float + | Unboxed_integer of boxed_integer + | Untagged_int + +(* Generate primitives with up to this number of arguments *) +let test_all_combination_up_to_n_args = 6 + +(* Generate primitives using all combination of these argument + representations. No need to test all combination of other + representations: regarding the calling convention + [Same_as_ocaml_repr], [Untagged_int] and + [Unboxed_integer Pnativeint] are all the same, and are the + same as [Unboxed_integer Pint]. + + We have specific tests for the other representations and for the + result representation in [manual_tests]. +*) +let test_all_args_combination_of = + [ Unboxed_float + ; Unboxed_integer Pint32 + ; Unboxed_integer Pint64 + ] + +let code_of_repr = function + | Same_as_ocaml_repr -> "v" (* for "value" *) + | Unboxed_float -> "f" + | Unboxed_integer Pint32 -> "l" + | Unboxed_integer Pint64 -> "L" + | Unboxed_integer Pnativeint -> "n" + | Untagged_int -> "i" + +let repr_of_code = function + | 'v' -> Same_as_ocaml_repr + | 'f' -> Unboxed_float + | 'l' -> Unboxed_integer Pint32 + | 'L' -> Unboxed_integer Pint64 + | 'n' -> Unboxed_integer Pnativeint + | 'i' -> Untagged_int + | _ -> assert false + +let manual_tests = + [ "v_v" + ; "f_f" + ; "l_l" + ; "L_L" + ; "n_n" + ; "i_i" + ; "f_fffff" + ; "f_ffffff" + ; "f_fffffff" + ; "f_fffffffffffffffff" + ; "v_iiiiiiiiiiiiiiiii" + ; "v_lllllllllllllllll" + ; "v_LLLLLLLLLLLLLLLLL" + ; "v_iLiLiLiLiLiLiLiLi" + ; "v_LiLiLiLiLiLiLiLiL" + ; "v_flflflflflflflflflflflflflflflflflfl" + ; "v_fLfLfLfLfLfLfLfLfLfLfLfLfLfLfLfLfLfL" + ] + +let ocaml_type_of_repr = function + (* Doesn't really matters what we choose for this case *) + | Same_as_ocaml_repr -> "int" + | Unboxed_float -> "(float [@unboxed])" + | Unboxed_integer Pint32 -> "(int32 [@unboxed])" + | Unboxed_integer Pint64 -> "(int64 [@unboxed])" + | Unboxed_integer Pnativeint -> "(nativeint [@unboxed])" + | Untagged_int -> "(int [@untagged])" + +let ocaml_type_gadt_of_repr = function + (* Doesn't really matters what we choose for this case *) + | Same_as_ocaml_repr -> "Int" + | Unboxed_float -> "Float" + | Unboxed_integer Pint32 -> "Int32" + | Unboxed_integer Pint64 -> "Int64" + | Unboxed_integer Pnativeint -> "Nativeint" + | Untagged_int -> "Int" + +let c_type_of_repr = function + | Same_as_ocaml_repr -> "value" + | Unboxed_float -> "double" + | Unboxed_integer Pint32 -> "int32_t" + | Unboxed_integer Pint64 -> "int64_t" + | Unboxed_integer Pnativeint -> "intnat" + | Untagged_int -> "intnat" + +type proto = + { params : native_repr list + ; return : native_repr + } + +let rec explode s = + let rec loop i acc = + if i < 0 then + acc + else + loop (i - 1) (s.[i] :: acc) + in + loop (String.length s - 1) [] + +let proto_of_str s = + Scanf.sscanf s "%c_%s" (fun return params -> + { params = List.map (explode params) ~f:repr_of_code + ; return = repr_of_code return + }) + +let function_name_of_proto proto = + Printf.sprintf "test_%s_%s" (code_of_repr proto.return) + (String.concat ~sep:"" (List.map proto.params ~f:code_of_repr)) + +let ocaml_type_gadt_of_proto proto = + Printf.sprintf "%s ** Ret %s" + (String.concat ~sep:" ** " + (List.map proto.params ~f:ocaml_type_gadt_of_repr)) + (ocaml_type_gadt_of_repr proto.return) + +let ocaml_type_of_proto proto = + String.concat ~sep:" -> " + (List.map proto.params ~f:ocaml_type_of_repr + @ [ocaml_type_of_repr proto.return]) + +let c_args_of_proto proto = + String.concat ~sep:", " + (List.mapi proto.params ~f:(fun i p -> + Printf.sprintf "%s x%d" (c_type_of_repr p) i)) + +let manual_protos = List.map manual_tests ~f:proto_of_str + +let iter_protos ~f = + let iter_for_arity arity = + let rec loop params to_gen = + List.iter test_all_args_combination_of ~f:(fun repr -> + let params = repr :: params in + let to_gen = to_gen - 1 in + if to_gen = 0 then + f { params = List.rev params + ; return = Same_as_ocaml_repr + } + else + loop params to_gen) + in + loop [] arity + in + let rec iter_arities arity = + if arity <= test_all_combination_up_to_n_args then begin + iter_for_arity arity; + iter_arities (arity + 1) + end + in + List.iter manual_protos ~f; + iter_arities 1 + +let pr fmt = Printf.ksprintf (fun s -> print_string s; print_char '\n') fmt + +let generate_ml () = + pr "open Common"; + pr ""; + iter_protos ~f:(fun proto -> + let name = function_name_of_proto proto in + pr "external %s : %s = \"\" %S [@@noalloc]" + name (ocaml_type_of_proto proto) name; + ); + pr ""; + pr "let tests = []"; + iter_protos ~f:(fun proto -> + let name = function_name_of_proto proto in + let arity = List.length proto.params in + if arity <= 6 then + pr "let tests = T%d (%S, %s, %s, %s) :: tests" + arity name name + (List.map proto.params ~f:ocaml_type_gadt_of_repr + |> String.concat ~sep:", ") + (ocaml_type_gadt_of_repr proto.return) + else + pr "let tests = T (%S, %s, %s) :: tests" + name name (ocaml_type_gadt_of_proto proto)); + pr ""; + pr "let () = run_tests (List.rev tests)" + +let generate_stubs () = + pr "#include "; + pr "#include "; + pr "#include \"test_common.h\""; + iter_protos ~f:(fun proto -> + let name = function_name_of_proto proto in + pr ""; + pr "%s %s(%s)" + (c_type_of_repr proto.return) + name + (c_args_of_proto proto); + pr "{"; + List.iteri proto.params ~f:(fun i p -> + pr " %(%d%d%);" + (match p with + | Same_as_ocaml_repr -> "set_intnat(%d, Long_val(x%d))" + | Unboxed_float -> "set_double(%d, x%d)" + | Unboxed_integer Pint32 -> "set_int32(%d, x%d)" + | Unboxed_integer Pint64 -> "set_int64(%d, x%d)" + | Unboxed_integer Pnativeint -> "set_intnat(%d, x%d)" + | Untagged_int -> "set_intnat(%d, x%d)") + i i); + pr " return %(%d%);" + (match proto.return with + | Same_as_ocaml_repr -> "Val_long(get_intnat(%d))" + | Unboxed_float -> "get_double(%d)" + | Unboxed_integer Pint32 -> "get_int32(%d)" + | Unboxed_integer Pint64 -> "get_int64(%d)" + | Unboxed_integer Pnativeint -> "get_intnat(%d)" + | Untagged_int -> "get_intnat(%d)") + (List.length proto.params); + pr "}" + ) + +let () = + match Sys.argv with + | [|_; "ml"|] -> generate_ml () + | [|_; "c" |] -> generate_stubs () + | _ -> + prerr_endline "Usage: ocaml gen_test.ml {ml|c}"; + exit 2 diff --git a/testsuite/tests/unboxed-primitive-args/main.reference b/testsuite/tests/unboxed-primitive-args/main.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/unboxed-primitive-args/test_common.c b/testsuite/tests/unboxed-primitive-args/test_common.c new file mode 100644 index 00000000..8fe2765f --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/test_common.c @@ -0,0 +1,37 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jeremie Dimino, Jane Street Europe */ +/* */ +/* Copyright 2015 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 +#include + +char *ocaml_buffer; +char *c_buffer; + +value test_set_buffers(value v_ocaml_buffer, value v_c_buffer) +{ + ocaml_buffer = Caml_ba_data_val(v_ocaml_buffer); + c_buffer = Caml_ba_data_val(v_c_buffer); + return Val_unit; +} + +value test_cleanup_normal(void) +{ + return Val_int(0); +} + +double test_cleanup_float(void) +{ + return 0.; +} diff --git a/testsuite/tests/unboxed-primitive-args/test_common.h b/testsuite/tests/unboxed-primitive-args/test_common.h new file mode 100644 index 00000000..2a1019ca --- /dev/null +++ b/testsuite/tests/unboxed-primitive-args/test_common.h @@ -0,0 +1,44 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jeremie Dimino, Jane Street Europe */ +/* */ +/* Copyright 2015 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. */ +/* */ +/**************************************************************************/ + +#ifndef __TEST_COMMON_H +#define __TEST_COMMON_H + +/* Where the OCaml side stores the arguments and result for a test + case. The C function will read the result it is supposed to return + from this buffer. + + Argument [n] is stored at [n * 8] and the result is stored at + [arity * 8]. +*/ +extern char *ocaml_buffer; + +/* Where the C function stores the arguments it receive for a test + case. The OCaml side will store the result from the C function in + this buffer. At the of a test case, both these buffers must be + equal. */ +extern char *c_buffer; + +#define get_intnat(n) *(intnat*)(ocaml_buffer+((n)*8)) +#define get_int32(n) *(int32_t*)(ocaml_buffer+((n)*8)) +#define get_int64(n) *(int64_t*)(ocaml_buffer+((n)*8)) +#define get_double(n) *(double*)(ocaml_buffer+((n)*8)) + +#define set_intnat(n, x) *(intnat*)(c_buffer+((n)*8)) = (x) +#define set_int32(n, x) *(int32_t*)(c_buffer+((n)*8)) = (x) +#define set_int64(n, x) *(int64_t*)(c_buffer+((n)*8)) = (x) +#define set_double(n, x) *(double*)(c_buffer+((n)*8)) = (x) + +#endif /* __TEST_COMMON_H */ diff --git a/testsuite/tests/unwind/Makefile b/testsuite/tests/unwind/Makefile new file mode 100644 index 00000000..bd26bc65 --- /dev/null +++ b/testsuite/tests/unwind/Makefile @@ -0,0 +1,39 @@ +BASEDIR=../.. + +# The -keep_dwarf_unwind option of ld was introduced in ld version 224.1. +# (The last released version where it is not supported is version 136.) +default: + @printf " ... testing 'unwind_test':" + @if [ ! $(SYSTEM) = macosx ]; then \ + echo " => skipped (not on Mac OSX)"; \ + elif $(BYTECODE_ONLY); then \ + echo " => skipped (bytecode only)"; \ + else \ + LDFULL="`ld -v 2>&1`"; \ + LD="`echo $$LDFULL | grep -o \"ld64-[0-9]*\"`"; \ + LDVER="`echo $$LD | sed \"s/ld64-//\"`"; \ + if [[ -z "$$LD" ]]; then \ + echo " => skipped (ld64-[0-9]* not found in 'ld -v' output)"; \ + elif [[ $$LDVER -lt 224 ]]; then \ + echo " => skipped (ld version is $$LDVER < 224)"; \ + else \ + $(MAKE) native_macosx_tests; \ + fi; \ + fi + +native_macosx_tests: + @$(MAKE) clean ; $(MAKE) unwind_test && \ + ./unwind_test >/dev/null 2>&1 && echo " => passed" || echo " => failed" + +unwind_test: + @$(OCAMLOPT) -c -opaque mylib.mli + @$(OCAMLOPT) -c driver.ml + @$(OCAMLOPT) -c mylib.ml + @$(OCAMLOPT) -c stack_walker.c + @$(OCAMLOPT) -cclib -Wl,-keep_dwarf_unwind -o unwind_test mylib.cmx \ + driver.cmx stack_walker.o + +clean: + @rm -f *.cm* *.o unwind_test + +include $(BASEDIR)/makefiles/Makefile.common diff --git a/testsuite/tests/unwind/README b/testsuite/tests/unwind/README new file mode 100644 index 00000000..ff467e25 --- /dev/null +++ b/testsuite/tests/unwind/README @@ -0,0 +1,9 @@ +This test case is motivated by the fact that on OS X, external functions may +cause stack walks into the OCaml-generated stack frames. In particular, the +Objective-C runtime does so in function objc_addExceptionHandler. This function +is invoked from Cocoa. Errors in the stack unwinding info generated by OCaml +can cause random crashes. This test case checks that, for at least one OCaml +program, correct unwind info is generated such that the platform's unwinder +(called libunwind) correctly walks the stack up to the main function. OCaml +used to generate incorrect stack unwinding information for this program. See +PR#7118, PR#7120. diff --git a/testsuite/tests/unwind/driver.ml b/testsuite/tests/unwind/driver.ml new file mode 100644 index 00000000..cd289b6b --- /dev/null +++ b/testsuite/tests/unwind/driver.ml @@ -0,0 +1,3 @@ +let () = + Mylib.foo1 Mylib.bar 1 2 3 4 5 6 7 8 9 10; + Mylib.foo2 Mylib.baz 1 2 3 4 5 6 7 8 9 10 diff --git a/testsuite/tests/unwind/mylib.ml b/testsuite/tests/unwind/mylib.ml new file mode 100644 index 00000000..318b537a --- /dev/null +++ b/testsuite/tests/unwind/mylib.ml @@ -0,0 +1,20 @@ +let foo1 f x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 = + f x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 + +let foo2 f x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 = + f x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 + +external func_with_10_params: + int -> int -> int -> int -> int -> int -> int -> int -> int -> int -> unit + = "ml_func_with_10_params_bytecode" "ml_func_with_10_params_native" + +let bar x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 = + func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10; + func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 + +external perform_stack_walk: unit -> unit = "ml_perform_stack_walk" + +let baz x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 = + func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10; + func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10; + perform_stack_walk () diff --git a/testsuite/tests/unwind/mylib.mli b/testsuite/tests/unwind/mylib.mli new file mode 100644 index 00000000..c1655228 --- /dev/null +++ b/testsuite/tests/unwind/mylib.mli @@ -0,0 +1,10 @@ +val foo1: ('a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> unit) + -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> unit + +val foo2: ('a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> unit) + -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> 'a -> unit + +val bar: + int -> int -> int -> int -> int -> int -> int -> int -> int -> int -> unit +val baz: + int -> int -> int -> int -> int -> int -> int -> int -> int -> int -> unit diff --git a/testsuite/tests/unwind/stack_walker.c b/testsuite/tests/unwind/stack_walker.c new file mode 100644 index 00000000..09afcadd --- /dev/null +++ b/testsuite/tests/unwind/stack_walker.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include + +value ml_func_with_10_params_native(value x1, value x2, value x3, value x4, + value x5, value x6, value x7, value x8, + value x9, value x10) { + return Val_unit; +} + +void error() { + exit(1); +} + +void perform_stack_walk() { + unw_context_t ctxt; + unw_getcontext(&ctxt); + + unw_cursor_t cursor; + { + int result = unw_init_local(&cursor, &ctxt); + if (result != 0) error(); + } + + int reached_main = 0; + + for (;;) { + { + char procname[256]; + unw_word_t ip_offset; // IP - start_of_proc + int result = unw_get_proc_name(&cursor, procname, sizeof(procname), + &ip_offset); + if (result != 0) error(); + if (strcmp(procname, "main") == 0) + reached_main = 1; + //printf("%s + %lld\n", procname, (long long int)ip_offset); + } + + { + int result = unw_step(&cursor); + if (result == 0) break; + if (result < 0) error(); + } + } + + //printf("Reached end of stack.\n"); + if (!reached_main) { + //printf("Failure: Did not reach main.\n"); + error(); + } +} + +value ml_perform_stack_walk() { + perform_stack_walk(); + return Val_unit; +} diff --git a/testsuite/tests/utils/Makefile b/testsuite/tests/utils/Makefile index 1d508680..f2d74860 100644 --- a/testsuite/tests/utils/Makefile +++ b/testsuite/tests/utils/Makefile @@ -1,17 +1,20 @@ -######################################################################### -# # -# OCaml # -# # -# Alain Frisch, LexiFi # -# # -# Copyright 2012 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Alain Frisch, LexiFi * +#* * +#* Copyright 2012 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 misc +MODULES=testing misc identifiable numbers strongly_connected_components INCLUDES= -I $(OTOPDIR)/utils ADD_COMPFLAGS=$(INCLUDES) CMO_FILES+="misc.cmo" diff --git a/testsuite/tests/utils/edit_distance.ml b/testsuite/tests/utils/edit_distance.ml index 76eec0ba..294b02ce 100644 --- a/testsuite/tests/utils/edit_distance.ml +++ b/testsuite/tests/utils/edit_distance.ml @@ -44,6 +44,5 @@ let () = test "" "" 3 (Some 0); test "" "abc" 3 (Some 3); test "abcd" "" 3 None; - - () + () diff --git a/testsuite/tests/utils/test_strongly_connected_components.ml b/testsuite/tests/utils/test_strongly_connected_components.ml new file mode 100644 index 00000000..8f3392e4 --- /dev/null +++ b/testsuite/tests/utils/test_strongly_connected_components.ml @@ -0,0 +1,29 @@ +module Int = Numbers.Int +module SCC = Strongly_connected_components.Make (Int) + +let graph_1 = + [1, [2;3;4]; + 2, [3;5]; + 3, [5]; + 4, [1]; + 5, [5]] + +let empty = [] + +let print_scc scc = + Printf.printf "begin\n"; + Array.iter (function + | SCC.No_loop e -> Printf.printf "%i\n" e + | SCC.Has_loop l -> + Printf.printf "[%s]\n" + (String.concat "; " (List.map string_of_int l))) scc; + Printf.printf "end\n" + +let scc graph = + SCC.connected_components_sorted_from_roots_to_leaf + (Int.Map.map Int.Set.of_list (Int.Map.of_list graph)) + +let run () = + print_scc (scc empty); + print_scc (scc graph_1); + Format.printf "done@." diff --git a/testsuite/tests/utils/test_strongly_connected_components.reference b/testsuite/tests/utils/test_strongly_connected_components.reference new file mode 100644 index 00000000..197c9280 --- /dev/null +++ b/testsuite/tests/utils/test_strongly_connected_components.reference @@ -0,0 +1,2 @@ + +All tests succeeded. diff --git a/testsuite/tests/warnings/Makefile b/testsuite/tests/warnings/Makefile index 06f574f1..58a8eae9 100644 --- a/testsuite/tests/warnings/Makefile +++ b/testsuite/tests/warnings/Makefile @@ -1,31 +1,60 @@ -######################################################################### -# # -# 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* 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=../.. FLAGS=-w A -EXECNAME=./program run-all: + @$(OCAMLC) $(FLAGS) -c deprecated_module.mli + @$(OCAMLC) $(FLAGS) -c module_without_cmx.mli @for file in *.ml; do \ printf " ... testing '$$file':"; \ F="`basename $$file .ml`"; \ - $(OCAMLC) $(FLAGS) -o $(EXECNAME) $$file 2>$$F.result; \ + $(OCAMLC) $(FLAGS) -c $$file 2>$$F.result; \ $(DIFF) $$F.reference $$F.result >/dev/null \ && echo " => passed" || echo " => failed"; \ done; + @for file in *.opt.ml; do \ + printf " ... testing '$$file' with ocamlopt:"; \ + if $(BYTECODE_ONLY); then echo " => skipped"; else \ + F="`basename $$file .ml`"; \ + $(OCAMLOPT) $(FLAGS) -c $$file 2>$$F.opt_result; \ + $(DIFF) $$F.opt_reference $$F.opt_result >/dev/null \ + && echo " => passed" || echo " => failed"; \ + fi \ + done; + @for file in *.opt_backend.ml; do \ + printf " ... testing '$$file' with ocamlopt:"; \ + if $(BYTECODE_ONLY); then echo " => skipped"; else \ + F="`basename $$file .ml`"; \ + $(OCAMLOPT) $(FLAGS) -c $$file 2>$$F.$(BACKEND).opt_result; \ + $(DIFF) $$F.$(BACKEND).opt_reference $$F.$(BACKEND).opt_result \ + >/dev/null \ + && echo " => passed" || echo " => failed"; \ + fi \ + done; promote: defaultpromote clean: defaultclean - @rm -f *.result $(EXECNAME) + @rm -f *.result *.opt_result include $(BASEDIR)/makefiles/Makefile.common + +ifeq "$(FLAMBDA)" "true" +BACKEND=flambda +else +BACKEND=clambda +endif diff --git a/testsuite/tests/warnings/deprecated_module.ml b/testsuite/tests/warnings/deprecated_module.ml new file mode 100755 index 00000000..092e9d09 --- /dev/null +++ b/testsuite/tests/warnings/deprecated_module.ml @@ -0,0 +1,9 @@ +module M = struct + type t = int + + let x = 10 +end +[@@ocaml.deprecated] + +let _ = M.x +include M diff --git a/testsuite/tests/warnings/deprecated_module.mli b/testsuite/tests/warnings/deprecated_module.mli new file mode 100755 index 00000000..dbcb19b6 --- /dev/null +++ b/testsuite/tests/warnings/deprecated_module.mli @@ -0,0 +1,13 @@ +[@@@ocaml.deprecated {| + As you could guess, Deprecated_module is deprecated. + Please use something else! +|} ] + +module M: sig + val x: int + [@@ocaml.deprecated] + + type t + [@@ocaml.deprecated] +end +[@@ocaml.deprecated] diff --git a/testsuite/tests/warnings/deprecated_module.reference b/testsuite/tests/warnings/deprecated_module.reference new file mode 100644 index 00000000..9dcde99a --- /dev/null +++ b/testsuite/tests/warnings/deprecated_module.reference @@ -0,0 +1,4 @@ +File "deprecated_module.ml", line 8, characters 8-11: +Warning 3: deprecated: module M +File "deprecated_module.ml", line 9, characters 8-9: +Warning 3: deprecated: module M diff --git a/testsuite/tests/warnings/deprecated_module_use.ml b/testsuite/tests/warnings/deprecated_module_use.ml new file mode 100755 index 00000000..f04e6f52 --- /dev/null +++ b/testsuite/tests/warnings/deprecated_module_use.ml @@ -0,0 +1,6 @@ +open Deprecated_module + +type s = M.t + +open M +let _ = x diff --git a/testsuite/tests/warnings/deprecated_module_use.reference b/testsuite/tests/warnings/deprecated_module_use.reference new file mode 100644 index 00000000..a7615cd6 --- /dev/null +++ b/testsuite/tests/warnings/deprecated_module_use.reference @@ -0,0 +1,14 @@ +File "deprecated_module_use.ml", line 1, characters 5-22: +Warning 3: deprecated: module Deprecated_module + + As you could guess, Deprecated_module is deprecated. + Please use something else! + +File "deprecated_module_use.ml", line 3, characters 9-12: +Warning 3: deprecated: module Deprecated_module.M +File "deprecated_module_use.ml", line 3, characters 9-12: +Warning 3: deprecated: Deprecated_module.M.t +File "deprecated_module_use.ml", line 5, characters 5-6: +Warning 3: deprecated: module Deprecated_module.M +File "deprecated_module_use.ml", line 6, characters 8-9: +Warning 3: deprecated: Deprecated_module.M.x diff --git a/testsuite/tests/warnings/module_without_cmx.mli b/testsuite/tests/warnings/module_without_cmx.mli new file mode 100644 index 00000000..36ca7dba --- /dev/null +++ b/testsuite/tests/warnings/module_without_cmx.mli @@ -0,0 +1,2 @@ + +val id : 'a -> 'a diff --git a/testsuite/tests/warnings/w01.ml b/testsuite/tests/warnings/w01.ml index 24a6accc..08e2f291 100644 --- a/testsuite/tests/warnings/w01.ml +++ b/testsuite/tests/warnings/w01.ml @@ -1,14 +1,3 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Moscova, INRIA Rocquencourt *) -(* *) -(* Copyright 2000 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. *) -(* *) -(***********************************************************************) (* C *) diff --git a/testsuite/tests/warnings/w01.reference b/testsuite/tests/warnings/w01.reference index 730da03c..492ec7dc 100644 --- a/testsuite/tests/warnings/w01.reference +++ b/testsuite/tests/warnings/w01.reference @@ -1,15 +1,15 @@ -File "w01.ml", line 15, characters 12-14: +File "w01.ml", line 4, characters 12-14: Warning 2: this is not the end of a comment. -File "w01.ml", line 21, characters 0-3: +File "w01.ml", line 10, characters 0-3: Warning 5: this function application is partial, maybe some arguments are missing. -File "w01.ml", line 31, characters 4-5: +File "w01.ml", line 20, characters 4-5: Warning 8: this pattern-matching is not exhaustive. Here is an example of a value that is not matched: 0 -File "w01.ml", line 36, characters 0-1: +File "w01.ml", line 25, characters 0-1: Warning 10: this expression should have type unit. -File "w01.ml", line 20, characters 8-9: +File "w01.ml", line 9, characters 8-9: Warning 27: unused variable y. -File "w01.ml", line 43, characters 2-3: +File "w01.ml", line 32, characters 2-3: Warning 11: this match case is unused. diff --git a/testsuite/tests/warnings/w06.ml b/testsuite/tests/warnings/w06.ml new file mode 100644 index 00000000..6e8a1bca --- /dev/null +++ b/testsuite/tests/warnings/w06.ml @@ -0,0 +1,6 @@ +let foo ~bar = ignore bar (* one label *) + +let bar ~foo ~baz = ignore (foo, baz) (* two labels *) + +let () = foo 2 +let () = bar 4 2 diff --git a/testsuite/tests/warnings/w06.reference b/testsuite/tests/warnings/w06.reference new file mode 100644 index 00000000..b3019f4d --- /dev/null +++ b/testsuite/tests/warnings/w06.reference @@ -0,0 +1,4 @@ +File "w06.ml", line 5, characters 9-12: +Warning 6: label bar was omitted in the application of this function. +File "w06.ml", line 6, characters 9-12: +Warning 6: labels foo, baz were omitted in the application of this function. diff --git a/testsuite/tests/warnings/w45.ml b/testsuite/tests/warnings/w45.ml new file mode 100755 index 00000000..efe89ffe --- /dev/null +++ b/testsuite/tests/warnings/w45.ml @@ -0,0 +1,16 @@ +module T1 = struct + type t = A + type s = X +end + +module T2 = struct + type t = T1.t = A + type s = X +end + +module T3 = struct + open T1 (* unused open *) + open T2 (* shadow X, which is later used; but not A, see #6762 *) + + let _ = (A, X) (* X belongs to several types *) +end diff --git a/testsuite/tests/warnings/w45.reference b/testsuite/tests/warnings/w45.reference new file mode 100644 index 00000000..8c77ab05 --- /dev/null +++ b/testsuite/tests/warnings/w45.reference @@ -0,0 +1,7 @@ +File "w45.ml", line 13, characters 2-9: +Warning 45: this open statement shadows the constructor X (which is later used) +File "w45.ml", line 15, characters 14-15: +Warning 41: X belongs to several types: T2.s T1.s +The first one was selected. Please disambiguate if this is wrong. +File "w45.ml", line 12, characters 2-9: +Warning 33: unused open T1. diff --git a/testsuite/tests/warnings/w47_inline.ml b/testsuite/tests/warnings/w47_inline.ml new file mode 100644 index 00000000..26794510 --- /dev/null +++ b/testsuite/tests/warnings/w47_inline.ml @@ -0,0 +1,15 @@ + +let a = (fun x -> x) [@inline] (* accepted *) +let b = (fun x -> x) [@inline never] (* accepted *) +let c = (fun x -> x) [@inline always] (* accepted *) +let d = (fun x -> x) [@inline malformed attribute] (* rejected *) +let e = (fun x -> x) [@inline malformed_attribute] (* rejected *) +let f = (fun x -> x) [@inline : malformed_attribute] (* rejected *) +let g = (fun x -> x) [@inline ? malformed_attribute] (* rejected *) + +let h x = (a [@inlined]) x (* accepted *) +let i x = (a [@inlined never]) x (* accepted *) +let j x = (a [@inlined always]) x (* accepted *) +let k x = (a [@inlined malformed]) x (* rejected *) + +let l x = x [@@inline] (* accepted *) diff --git a/testsuite/tests/warnings/w47_inline.reference b/testsuite/tests/warnings/w47_inline.reference new file mode 100644 index 00000000..edc2d48b --- /dev/null +++ b/testsuite/tests/warnings/w47_inline.reference @@ -0,0 +1,15 @@ +File "w47_inline.ml", line 13, characters 15-22: +Warning 47: illegal payload for attribute 'inlined'. +It must be either empty, 'always' or 'never' +File "w47_inline.ml", line 8, characters 23-29: +Warning 47: illegal payload for attribute 'inline'. +It must be either empty, 'always' or 'never' +File "w47_inline.ml", line 7, characters 23-29: +Warning 47: illegal payload for attribute 'inline'. +It must be either empty, 'always' or 'never' +File "w47_inline.ml", line 6, characters 23-29: +Warning 47: illegal payload for attribute 'inline'. +It must be either empty, 'always' or 'never' +File "w47_inline.ml", line 5, characters 23-29: +Warning 47: illegal payload for attribute 'inline'. +It must be either empty, 'always' or 'never' diff --git a/testsuite/tests/warnings/w51.ml b/testsuite/tests/warnings/w51.ml new file mode 100644 index 00000000..25e08706 --- /dev/null +++ b/testsuite/tests/warnings/w51.ml @@ -0,0 +1,5 @@ + +let rec fact = function + | 1 -> 1 + | n -> n * (fact [@tailcall]) (n-1) +;; diff --git a/testsuite/tests/warnings/w51.reference b/testsuite/tests/warnings/w51.reference new file mode 100644 index 00000000..5e3cf374 --- /dev/null +++ b/testsuite/tests/warnings/w51.reference @@ -0,0 +1,2 @@ +File "w51.ml", line 4, characters 13-37: +Warning 51: expected tailcall diff --git a/testsuite/tests/warnings/w51_bis.ml b/testsuite/tests/warnings/w51_bis.ml new file mode 100644 index 00000000..810fcdd4 --- /dev/null +++ b/testsuite/tests/warnings/w51_bis.ml @@ -0,0 +1,5 @@ +let rec foldl op acc = function + [] -> acc + | x :: xs -> + try (foldl [@tailcall]) op (op x acc) xs + with Not_found -> assert false diff --git a/testsuite/tests/warnings/w51_bis.reference b/testsuite/tests/warnings/w51_bis.reference new file mode 100644 index 00000000..ee5cab5a --- /dev/null +++ b/testsuite/tests/warnings/w51_bis.reference @@ -0,0 +1,2 @@ +File "w51_bis.ml", line 4, characters 12-48: +Warning 51: expected tailcall diff --git a/testsuite/tests/warnings/w53.ml b/testsuite/tests/warnings/w53.ml new file mode 100644 index 00000000..9d77c3cc --- /dev/null +++ b/testsuite/tests/warnings/w53.ml @@ -0,0 +1,31 @@ + +let h x = x [@inline] (* rejected *) +let h x = x [@ocaml.inline] (* rejected *) + +let i x = x [@inlined] (* rejected *) +let j x = x [@ocaml.inlined] (* rejected *) +let k x = (h [@inlined]) x (* accepted *) +let k' x = (h [@ocaml.inlined]) x (* accepted *) +let l x = h x [@inlined] (* rejected *) + +let m x = x [@tailcall] (* rejected *) +let n x = x [@ocaml.tailcall] (* rejected *) +let o x = (h [@tailcall]) x (* accepted *) +let p x = (h [@ocaml.tailcall]) x (* accepted *) +let q x = h x [@tailcall] (* rejected *) + +module type E = sig end + +module A(E:E) = struct end [@@inline] (* accepted *) +module A'(E:E) = struct end [@@ocaml.inline] (* accepted *) +module B = ((functor (E:E) -> struct end) [@inline]) (* accepted *) +module B' = ((functor (E:E) -> struct end) [@ocaml.inline]) (* accepted *) +module C = struct end [@@inline] (* rejected *) +module C' = struct end [@@ocaml.inline] (* rejected *) +module D = struct end [@@inlined] (* rejected *) +module D' = struct end [@@ocaml.inlined] (* rejected *) + +module F = (A [@inlined])(struct end) (* accepted *) +module F' = (A [@ocaml.inlined])(struct end) (* accepted *) +module G = (A [@inline])(struct end) (* rejected *) +module G' = (A [@ocaml.inline])(struct end) (* rejected *) diff --git a/testsuite/tests/warnings/w53.reference b/testsuite/tests/warnings/w53.reference new file mode 100644 index 00000000..0f70e504 --- /dev/null +++ b/testsuite/tests/warnings/w53.reference @@ -0,0 +1,26 @@ +File "w53.ml", line 2, characters 4-5: +Warning 32: unused value h. +File "w53.ml", line 31, characters 17-29: +Warning 53: the "ocaml.inline" attribute cannot appear in this context +File "w53.ml", line 30, characters 16-22: +Warning 53: the "inline" attribute cannot appear in this context +File "w53.ml", line 24, characters 0-39: +Warning 53: the "inline" attribute cannot appear in this context +File "w53.ml", line 23, characters 0-32: +Warning 53: the "inline" attribute cannot appear in this context +File "w53.ml", line 15, characters 16-24: +Warning 53: the "tailcall" attribute cannot appear in this context +File "w53.ml", line 12, characters 14-28: +Warning 53: the "ocaml.tailcall" attribute cannot appear in this context +File "w53.ml", line 11, characters 14-22: +Warning 53: the "tailcall" attribute cannot appear in this context +File "w53.ml", line 9, characters 16-23: +Warning 53: the "inlined" attribute cannot appear in this context +File "w53.ml", line 6, characters 14-27: +Warning 53: the "ocaml.inlined" attribute cannot appear in this context +File "w53.ml", line 5, characters 14-21: +Warning 53: the "inlined" attribute cannot appear in this context +File "w53.ml", line 3, characters 14-26: +Warning 53: the "ocaml.inline" attribute cannot appear in this context +File "w53.ml", line 2, characters 14-20: +Warning 53: the "inline" attribute cannot appear in this context diff --git a/testsuite/tests/warnings/w54.ml b/testsuite/tests/warnings/w54.ml new file mode 100644 index 00000000..6ea66238 --- /dev/null +++ b/testsuite/tests/warnings/w54.ml @@ -0,0 +1,9 @@ + +let f = (fun x -> x) [@inline] [@inline never] +let g = (fun x -> x) [@inline] [@something_else] [@ocaml.inline] + +let h x = (g [@inlined] [@ocaml.inlined never]) x + +let v = ((fun x -> x) [@inline] [@inlined]) 1 (* accepted *) + +let i = ((fun x -> x) [@inline]) [@@inline] diff --git a/testsuite/tests/warnings/w54.reference b/testsuite/tests/warnings/w54.reference new file mode 100644 index 00000000..39c5d75d --- /dev/null +++ b/testsuite/tests/warnings/w54.reference @@ -0,0 +1,8 @@ +File "w54.ml", line 9, characters 0-43: +Warning 54: the "inline" attribute is used more than once on this expression +File "w54.ml", line 5, characters 26-39: +Warning 54: the "ocaml.inlined" attribute is used more than once on this expression +File "w54.ml", line 3, characters 51-63: +Warning 54: the "ocaml.inline" attribute is used more than once on this expression +File "w54.ml", line 2, characters 33-39: +Warning 54: the "inline" attribute is used more than once on this expression diff --git a/testsuite/tests/warnings/w55.opt_backend.clambda.opt_reference b/testsuite/tests/warnings/w55.opt_backend.clambda.opt_reference new file mode 100644 index 00000000..933e5d2a --- /dev/null +++ b/testsuite/tests/warnings/w55.opt_backend.clambda.opt_reference @@ -0,0 +1,12 @@ +File "w55.opt_backend.ml", line 4, characters 10-26: +Warning 55: Cannot inline: Function information unavailable +File "w55.opt_backend.ml", line 8, characters 10-27: +Warning 55: Cannot inline: Unknown function +File "w55.opt_backend.ml", line 12, characters 10-26: +Warning 55: Cannot inline: Partial application +File "w55.opt_backend.ml", line 18, characters 12-30: +Warning 55: Cannot inline: Over-application +File "w55.opt_backend.ml", line 18, characters 12-30: +Warning 55: Cannot inline: Function information unavailable +File "w55.opt_backend.ml", line 21, characters 10-26: +Warning 55: Cannot inline: Function information unavailable diff --git a/testsuite/tests/warnings/w55.opt_backend.flambda.opt_reference b/testsuite/tests/warnings/w55.opt_backend.flambda.opt_reference new file mode 100644 index 00000000..b1b51205 --- /dev/null +++ b/testsuite/tests/warnings/w55.opt_backend.flambda.opt_reference @@ -0,0 +1,6 @@ +File "w55.opt_backend.ml", line 12, characters 10-26: +Warning 55: Cannot inline: [@inlined] attributes may not be used on partial applications +File "w55.opt_backend.ml", line 8, characters 10-27: +Warning 55: Cannot inline: [@inlined] attribute was not used on this function application (the optimizer did not know what function was being applied) +File "w55.opt_backend.ml", line 18, characters 12-30: +Warning 55: Cannot inline: [@inlined] attribute was not used on this function application (the optimizer did not know what function was being applied) diff --git a/testsuite/tests/warnings/w55.opt_backend.ml b/testsuite/tests/warnings/w55.opt_backend.ml new file mode 100644 index 00000000..aef2af50 --- /dev/null +++ b/testsuite/tests/warnings/w55.opt_backend.ml @@ -0,0 +1,21 @@ + +let f = (fun x -> x + 1) [@inline never] + +let g x = (f [@inlined]) x + +let h = ref f + +let i x = (!h [@inlined]) x + +let j x y = x + y + +let h x = (j [@inlined]) x + +let a x = + let b = x + 1 in + fun y -> y + b + +let b x y = (a [@inlined]) x y + +let c x = x + 1 [@@inline never] +let d x = (c [@inlined]) x diff --git a/testsuite/tests/warnings/w55.opt_backend.reference b/testsuite/tests/warnings/w55.opt_backend.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/tests/warnings/w58.opt.ml b/testsuite/tests/warnings/w58.opt.ml new file mode 100644 index 00000000..8f7bfd27 --- /dev/null +++ b/testsuite/tests/warnings/w58.opt.ml @@ -0,0 +1,2 @@ + +let () = print_endline (Module_without_cmx.id "Hello World") diff --git a/testsuite/tests/warnings/w58.opt.opt_reference b/testsuite/tests/warnings/w58.opt.opt_reference new file mode 100644 index 00000000..f913ef94 --- /dev/null +++ b/testsuite/tests/warnings/w58.opt.opt_reference @@ -0,0 +1,2 @@ +File "_none_", line 1: +Warning 58: no cmx file was found in path for module Module_without_cmx, and its interface was not compiled with -opaque diff --git a/testsuite/tests/warnings/w58.opt.reference b/testsuite/tests/warnings/w58.opt.reference new file mode 100644 index 00000000..e69de29b diff --git a/testsuite/typing b/testsuite/typing index cb953d6a..3fbfcec1 100644 --- a/testsuite/typing +++ b/testsuite/typing @@ -1,10 +1,22 @@ +tests/basic +tests/basic-float +tests/basic-io +tests/basic-io-2 +tests/basic-manyargs +tests/basic-modules +tests/basic-more +tests/basic-multdef +tests/basic-private +tests/typing-extension-constructor tests/typing-extensions tests/typing-fstclassmod tests/typing-gadts +tests/typing-immediate tests/typing-implicit_unpack tests/typing-labels tests/typing-misc tests/typing-misc-bugs +tests/typing-missing-cmi tests/typing-modules tests/typing-modules-bugs tests/typing-objects @@ -16,9 +28,13 @@ tests/typing-polyvariants-bugs-2 tests/typing-private tests/typing-private-bugs tests/typing-recmod +tests/typing-recordarg tests/typing-rectypes-bugs +tests/typing-safe-linking tests/typing-short-paths tests/typing-signatures tests/typing-sigsubst tests/typing-typeparam +tests/typing-unboxed tests/typing-warnings +tests/warnings diff --git a/tools/.depend b/tools/.depend index c33f5c6f..7ef2e505 100644 --- a/tools/.depend +++ b/tools/.depend @@ -1,32 +1,31 @@ depend.cmi : ../parsing/parsetree.cmi ../parsing/longident.cmi profiling.cmi : -tast_iter.cmi : ../typing/typedtree.cmi ../parsing/asttypes.cmi -untypeast.cmi : ../typing/typedtree.cmi ../typing/path.cmi \ - ../parsing/parsetree.cmi ../parsing/longident.cmi addlabels.cmo : ../parsing/parsetree.cmi ../parsing/parse.cmi \ ../parsing/longident.cmi ../parsing/location.cmi ../parsing/asttypes.cmi addlabels.cmx : ../parsing/parsetree.cmi ../parsing/parse.cmx \ ../parsing/longident.cmx ../parsing/location.cmx ../parsing/asttypes.cmi -cmt2annot.cmo : untypeast.cmi ../typing/types.cmi ../typing/typedtree.cmi \ - tast_iter.cmi ../typing/stypes.cmi ../parsing/pprintast.cmi \ - ../typing/path.cmi ../typing/oprint.cmi ../parsing/location.cmi \ - ../typing/ident.cmi ../typing/envaux.cmi ../typing/env.cmi \ - ../utils/config.cmi ../typing/cmt_format.cmi ../parsing/asttypes.cmi \ - ../typing/annot.cmi -cmt2annot.cmx : untypeast.cmx ../typing/types.cmx ../typing/typedtree.cmx \ - tast_iter.cmx ../typing/stypes.cmx ../parsing/pprintast.cmx \ - ../typing/path.cmx ../typing/oprint.cmx ../parsing/location.cmx \ - ../typing/ident.cmx ../typing/envaux.cmx ../typing/env.cmx \ - ../utils/config.cmx ../typing/cmt_format.cmx ../parsing/asttypes.cmi \ - ../typing/annot.cmi +cmpbyt.cmo : ../bytecomp/bytesections.cmi +cmpbyt.cmx : ../bytecomp/bytesections.cmx +cmt2annot.cmo : ../typing/untypeast.cmi ../typing/types.cmi \ + ../typing/typedtree.cmi ../typing/tast_mapper.cmi ../typing/stypes.cmi \ + ../parsing/pprintast.cmi ../typing/path.cmi ../typing/oprint.cmi \ + ../parsing/location.cmi ../typing/ident.cmi ../typing/envaux.cmi \ + ../typing/env.cmi ../utils/config.cmi ../typing/cmt_format.cmi \ + ../parsing/asttypes.cmi ../typing/annot.cmi +cmt2annot.cmx : ../typing/untypeast.cmx ../typing/types.cmx \ + ../typing/typedtree.cmx ../typing/tast_mapper.cmx ../typing/stypes.cmx \ + ../parsing/pprintast.cmx ../typing/path.cmx ../typing/oprint.cmx \ + ../parsing/location.cmx ../typing/ident.cmx ../typing/envaux.cmx \ + ../typing/env.cmx ../utils/config.cmx ../typing/cmt_format.cmx \ + ../parsing/asttypes.cmi ../typing/annot.cmi cvt_emit.cmo : cvt_emit.cmx : depend.cmo : ../parsing/parsetree.cmi ../utils/misc.cmi \ - ../parsing/longident.cmi ../parsing/location.cmi ../parsing/asttypes.cmi \ - depend.cmi + ../parsing/longident.cmi ../parsing/location.cmi ../utils/clflags.cmi \ + ../parsing/builtin_attributes.cmi ../parsing/asttypes.cmi depend.cmi depend.cmx : ../parsing/parsetree.cmi ../utils/misc.cmx \ - ../parsing/longident.cmx ../parsing/location.cmx ../parsing/asttypes.cmi \ - depend.cmi + ../parsing/longident.cmx ../parsing/location.cmx ../utils/clflags.cmx \ + ../parsing/builtin_attributes.cmx ../parsing/asttypes.cmi depend.cmi dumpobj.cmo : ../utils/tbl.cmi opnames.cmo ../bytecomp/opcodes.cmo \ ../parsing/location.cmi ../bytecomp/lambda.cmi ../bytecomp/instruct.cmi \ ../typing/ident.cmi ../utils/config.cmi ../bytecomp/cmo_format.cmi \ @@ -40,27 +39,31 @@ eqparsetree.cmo : ../parsing/parsetree.cmi ../parsing/longident.cmi \ eqparsetree.cmx : ../parsing/parsetree.cmi ../parsing/longident.cmx \ ../parsing/location.cmx ../parsing/asttypes.cmi objinfo.cmo : ../asmcomp/printclambda.cmi ../utils/misc.cmi \ - ../utils/config.cmi ../asmcomp/cmx_format.cmi ../typing/cmt_format.cmi \ - ../bytecomp/cmo_format.cmi ../typing/cmi_format.cmi \ - ../bytecomp/bytesections.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 \ - ../utils/config.cmx ../asmcomp/cmx_format.cmi ../typing/cmt_format.cmx \ - ../bytecomp/cmo_format.cmi ../typing/cmi_format.cmx \ - ../bytecomp/bytesections.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 \ + ../typing/cmt_format.cmx ../bytecomp/cmo_format.cmi \ + ../typing/cmi_format.cmx ../bytecomp/bytesections.cmx ocaml299to3.cmo : ocaml299to3.cmx : ocamlcp.cmo : ../driver/main_args.cmi ocamlcp.cmx : ../driver/main_args.cmx ocamldep.cmo : ../driver/pparse.cmi ../parsing/parsetree.cmi \ - ../parsing/parse.cmi ../utils/misc.cmi ../parsing/longident.cmi \ - ../parsing/location.cmi depend.cmi ../utils/config.cmi \ - ../driver/compenv.cmi ../utils/clflags.cmi + ../parsing/parser.cmi ../parsing/parse.cmi ../utils/misc.cmi \ + ../parsing/longident.cmi ../parsing/location.cmi ../parsing/lexer.cmi \ + depend.cmi ../utils/config.cmi ../driver/compenv.cmi ../utils/clflags.cmi ocamldep.cmx : ../driver/pparse.cmx ../parsing/parsetree.cmi \ - ../parsing/parse.cmx ../utils/misc.cmx ../parsing/longident.cmx \ - ../parsing/location.cmx depend.cmx ../utils/config.cmx \ - ../driver/compenv.cmx ../utils/clflags.cmx -ocamlmklib.cmo : ocamlmklibconfig.cmo -ocamlmklib.cmx : ocamlmklibconfig.cmx + ../parsing/parser.cmx ../parsing/parse.cmx ../utils/misc.cmx \ + ../parsing/longident.cmx ../parsing/location.cmx ../parsing/lexer.cmx \ + 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 ocamlmklibconfig.cmo : ocamlmklibconfig.cmx : ocamlmktop.cmo : ../utils/ccomp.cmi @@ -81,13 +84,5 @@ read_cmt.cmo : ../typing/cmt_format.cmi cmt2annot.cmo ../utils/clflags.cmi read_cmt.cmx : ../typing/cmt_format.cmx cmt2annot.cmx ../utils/clflags.cmx scrapelabels.cmo : scrapelabels.cmx : -tast_iter.cmo : ../typing/typedtree.cmi ../utils/misc.cmi tast_iter.cmi -tast_iter.cmx : ../typing/typedtree.cmx ../utils/misc.cmx tast_iter.cmi -untypeast.cmo : ../typing/typedtree.cmi ../typing/path.cmi \ - ../parsing/parsetree.cmi ../utils/misc.cmi ../parsing/longident.cmi \ - ../typing/ident.cmi ../parsing/asttypes.cmi ../parsing/ast_helper.cmi \ - untypeast.cmi -untypeast.cmx : ../typing/typedtree.cmx ../typing/path.cmx \ - ../parsing/parsetree.cmi ../utils/misc.cmx ../parsing/longident.cmx \ - ../typing/ident.cmx ../parsing/asttypes.cmi ../parsing/ast_helper.cmx \ - untypeast.cmi +stripdebug.cmo : ../utils/misc.cmi ../bytecomp/bytesections.cmi +stripdebug.cmx : ../utils/misc.cmx ../bytecomp/bytesections.cmx diff --git a/tools/.ignore b/tools/.ignore deleted file mode 100644 index 94fac02f..00000000 --- a/tools/.ignore +++ /dev/null @@ -1,27 +0,0 @@ -ocamldep -ocamldep.opt -ocamldep.bak -ocamlprof -opnames.ml -dumpobj -dumpapprox -objinfo -cvt_emit -cvt_emit.bak -cvt_emit.ml -ocamlcp -ocamloptp -ocamlmktop -primreq -ocamldumpobj -keywords -lexer299.ml -ocaml299to3 -ocamlmklib -ocamlmklibconfig.ml -lexer301.ml -scrapelabels -addlabels -objinfo_helper -read_cmt -read_cmt.opt diff --git a/tools/Makefile b/tools/Makefile index b5cc1010..0e91277c 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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 Makefile.shared @@ -19,7 +22,7 @@ ocamlmktop: ocamlmktop.tpl ../config/Makefile chmod +x ocamlmktop install:: - cp ocamlmktop $(INSTALL_BINDIR) + cp ocamlmktop "$(INSTALL_BINDIR)" clean:: rm -f ocamlmktop diff --git a/tools/Makefile.nt b/tools/Makefile.nt index ed9b3594..3a16f967 100644 --- a/tools/Makefile.nt +++ b/tools/Makefile.nt @@ -1,27 +1,35 @@ -######################################################################### -# # -# 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 Q Public License version 1.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 Makefile.shared +ifneq "$(wildcard ../flexdll/Makefile)" "" + CAMLOPT:=OCAML_FLEXLINK="../boot/ocamlrun ../flexdll/flexlink.exe" $(CAMLOPT) +endif + # To make custom toplevels OCAMLMKTOP=ocamlmktop.cmo -OCAMLMKTOP_IMPORTS=misc.cmo config.cmo clflags.cmo ccomp.cmo +OCAMLMKTOP_IMPORTS=misc.cmo identifiable.cmo numbers.cmo config.cmo \ + arg_helper.cmo clflags.cmo ccomp.cmo ocamlmktop: $(OCAMLMKTOP) $(CAMLC) $(LINKFLAGS) -o ocamlmktop $(OCAMLMKTOP_IMPORTS) $(OCAMLMKTOP) install:: - cp ocamlmktop $(INSTALL_BINDIR)/ocamlmktop$(EXE) + cp ocamlmktop "$(INSTALL_BINDIR)/ocamlmktop$(EXE)" clean:: - rm -f ocamlmktop$(EXE) + rm -f ocamlmktop objinfo_helper$(EXE).manifest diff --git a/tools/Makefile.shared b/tools/Makefile.shared index 0b90cd32..1a24391f 100644 --- a/tools/Makefile.shared +++ b/tools/Makefile.shared @@ -1,14 +1,17 @@ -######################################################################### -# # -# 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 Q Public License version 1.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 @@ -18,14 +21,13 @@ CAMLC=$(CAMLRUN) ../boot/ocamlc -nostdlib -I ../boot CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib CAMLLEX=$(CAMLRUN) ../boot/ocamllex INCLUDES=-I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp \ - -I ../driver -I ../toplevel + -I ../middle_end -I ../middle_end/base_types -I ../driver \ + -I ../toplevel COMPFLAGS= -strict-sequence -w +27+32..39 -warn-error A -safe-string $(INCLUDES) LINKFLAGS=$(INCLUDES) all: ocamldep ocamlprof ocamlcp ocamloptp ocamlmktop ocamlmklib dumpobj \ - objinfo read_cmt - -all: tast_iter.cmo + objinfo read_cmt stripdebug cmpbyt # scrapelabels addlabels @@ -37,13 +39,17 @@ opt.opt: ocamldep.opt read_cmt.opt # The dependency generator CAMLDEP_OBJ=depend.cmo ocamldep.cmo -CAMLDEP_IMPORTS=misc.cmo config.cmo clflags.cmo terminfo.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 pparse.cmo compenv.cmo + ccomp.cmo ast_mapper.cmo ast_iterator.cmo \ + builtin_attributes.cmo ast_invariants.cmo \ + pparse.cmo compenv.cmo ocamldep: depend.cmi $(CAMLDEP_OBJ) - $(CAMLC) $(LINKFLAGS) -compat-32 -o ocamldep $(CAMLDEP_IMPORTS) $(CAMLDEP_OBJ) + $(CAMLC) $(LINKFLAGS) -compat-32 -o ocamldep $(CAMLDEP_IMPORTS) \ + $(CAMLDEP_OBJ) ocamldep.opt: depend.cmi $(CAMLDEP_OBJ:.cmo=.cmx) $(CAMLOPT) $(LINKFLAGS) -o ocamldep.opt $(CAMLDEP_IMPORTS:.cmo=.cmx) \ @@ -60,14 +66,15 @@ INSTALL_BINDIR=$(DESTDIR)$(BINDIR) INSTALL_LIBDIR=$(DESTDIR)$(LIBDIR) install:: - cp ocamldep $(INSTALL_BINDIR)/ocamldep$(EXE) - if test -f ocamldep.opt; \ - then cp ocamldep.opt $(INSTALL_BINDIR)/ocamldep.opt$(EXE); else :; fi + cp ocamldep "$(INSTALL_BINDIR)/ocamldep$(EXE)" + if test -f ocamldep.opt; then \ + cp ocamldep.opt "$(INSTALL_BINDIR)/ocamldep.opt$(EXE)"; else :; fi # The profiler CSLPROF=ocamlprof.cmo -CSLPROF_IMPORTS=misc.cmo config.cmo clflags.cmo terminfo.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 @@ -75,22 +82,26 @@ ocamlprof: $(CSLPROF) profiling.cmo $(CAMLC) $(LINKFLAGS) -o ocamlprof $(CSLPROF_IMPORTS) $(CSLPROF) ocamlcp: ocamlcp.cmo - $(CAMLC) $(LINKFLAGS) -o ocamlcp warnings.cmo main_args.cmo ocamlcp.cmo + $(CAMLC) $(LINKFLAGS) -o ocamlcp misc.cmo warnings.cmo config.cmo \ + identifiable.cmo numbers.cmo arg_helper.cmo clflags.cmo \ + main_args.cmo ocamlcp.cmo ocamloptp: ocamloptp.cmo - $(CAMLC) $(LINKFLAGS) -o ocamloptp warnings.cmo main_args.cmo \ + $(CAMLC) $(LINKFLAGS) -o ocamloptp misc.cmo warnings.cmo config.cmo \ + identifiable.cmo numbers.cmo arg_helper.cmo clflags.cmo \ + main_args.cmo \ ocamloptp.cmo opt:: profiling.cmx install:: - cp ocamlprof $(INSTALL_BINDIR)/ocamlprof$(EXE) - cp ocamlcp $(INSTALL_BINDIR)/ocamlcp$(EXE) - cp ocamloptp $(INSTALL_BINDIR)/ocamloptp$(EXE) - cp profiling.cmi profiling.cmo $(INSTALL_LIBDIR) + cp ocamlprof "$(INSTALL_BINDIR)/ocamlprof$(EXE)" + cp ocamlcp "$(INSTALL_BINDIR)/ocamlcp$(EXE)" + cp ocamloptp "$(INSTALL_BINDIR)/ocamloptp$(EXE)" + cp profiling.cmi profiling.cmo "$(INSTALL_LIBDIR)" installopt:: - cp profiling.cmx profiling.$(O) $(INSTALL_LIBDIR) + cp profiling.cmx profiling.$(O) "$(INSTALL_LIBDIR)" clean:: rm -f ocamlprof ocamlcp ocamloptp @@ -99,20 +110,18 @@ clean:: # To help building mixed-mode libraries (OCaml + C) ocamlmklib: ocamlmklibconfig.cmo ocamlmklib.cmo - $(CAMLC) $(LINKFLAGS) -o ocamlmklib ocamlmklibconfig.cmo ocamlmklib.cmo + $(CAMLC) $(LINKFLAGS) -o ocamlmklib ocamlmklibconfig.cmo config.cmo \ + ocamlmklib.cmo install:: - cp ocamlmklib $(INSTALL_BINDIR)/ocamlmklib$(EXE) + cp ocamlmklib "$(INSTALL_BINDIR)/ocamlmklib$(EXE)" clean:: rm -f ocamlmklib -ocamlmklibconfig.ml: ../config/Makefile +ocamlmklibconfig.ml: ../config/Makefile Makefile (echo 'let bindir = "$(BINDIR)"'; \ - echo 'let ext_lib = "$(EXT_LIB)"'; \ - echo 'let ext_dll = "$(EXT_DLL)"'; \ echo 'let supports_shared_libraries = $(SUPPORTS_SHARED_LIBRARIES)';\ - echo 'let mkdll = "$(MKDLL)"'; \ echo 'let byteccrpath = "$(BYTECCRPATH)"'; \ echo 'let nativeccrpath = "$(NATIVECCRPATH)"'; \ echo 'let mksharedlibrpath = "$(MKSHAREDLIBRPATH)"'; \ @@ -137,7 +146,7 @@ lexer299.ml: lexer299.mll $(CAMLLEX) lexer299.mll #install:: -# cp ocaml299to3 $(INSTALL_BINDIR)/ocaml299to3$(EXE) +# cp ocaml299to3 "$(INSTALL_BINDIR)/ocaml299to3$(EXE)" clean:: rm -f ocaml299to3 lexer299.ml @@ -153,14 +162,15 @@ lexer301.ml: lexer301.mll $(CAMLLEX) lexer301.mll #install:: -# cp scrapelabels $(INSTALL_LIBDIR) +# 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 clflags.cmo terminfo.cmo \ +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 @@ -169,7 +179,7 @@ addlabels: addlabels.cmo $(ADDLABELS_IMPORTS) addlabels.cmo #install:: -# cp addlabels $(INSTALL_LIBDIR) +# cp addlabels "$(INSTALL_LIBDIR)" clean:: rm -f addlabels @@ -198,49 +208,19 @@ beforedepend:: cvt_emit.ml # Reading cmt files READ_CMT= \ - ../utils/misc.cmo \ - ../utils/warnings.cmo \ - ../utils/tbl.cmo \ - ../utils/consistbl.cmo \ - ../utils/config.cmo \ - ../utils/clflags.cmo \ - ../parsing/location.cmo \ - ../parsing/longident.cmo \ - ../parsing/docstrings.cmo \ - ../parsing/lexer.cmo \ - ../parsing/pprintast.cmo \ - ../parsing/ast_helper.cmo \ - ../parsing/ast_mapper.cmo \ - ../typing/ident.cmo \ - ../typing/path.cmo \ - ../typing/types.cmo \ - ../typing/typedtree.cmo \ - ../typing/btype.cmo \ - ../typing/subst.cmo \ - ../typing/predef.cmo \ - ../typing/datarepr.cmo \ - ../typing/cmi_format.cmo \ - ../typing/env.cmo \ - ../typing/ctype.cmo \ - ../typing/oprint.cmo \ - ../typing/primitive.cmo \ - ../typing/printtyp.cmo \ - ../typing/mtype.cmo \ - ../typing/envaux.cmo \ - ../typing/typedtreeMap.cmo \ - ../typing/typedtreeIter.cmo \ - ../typing/cmt_format.cmo \ - ../typing/stypes.cmo \ + ../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ \ - untypeast.cmo \ - tast_iter.cmo \ cmt2annot.cmo read_cmt.cmo +READ_CMT_OPT1 = $(READ_CMT:.cmo=.cmx) +READ_CMT_OPT = $(READ_CMT_OPT1:.cma=.cmxa) + read_cmt: $(READ_CMT) $(CAMLC) $(LINKFLAGS) -o read_cmt $(READ_CMT) -read_cmt.opt: $(READ_CMT:.cmo=.cmx) - $(CAMLOPT) $(LINKFLAGS) -o read_cmt.opt $(READ_CMT:.cmo=.cmx) +read_cmt.opt: $(READ_CMT_OPT) + $(CAMLOPT) $(LINKFLAGS) -o read_cmt.opt $(READ_CMT_OPT) clean:: rm -f read_cmt read_cmt.opt @@ -253,7 +233,8 @@ DUMPOBJ=opnames.cmo dumpobj.cmo dumpobj: $(DUMPOBJ) $(CAMLC) $(LINKFLAGS) -o dumpobj \ - misc.cmo tbl.cmo config.cmo ident.cmo \ + misc.cmo identifiable.cmo numbers.cmo \ + tbl.cmo config.cmo ident.cmo \ opcodes.cmo bytesections.cmo $(DUMPOBJ) clean:: @@ -263,7 +244,7 @@ opnames.ml: ../byterun/caml/instruct.h unset LC_ALL || : ; \ unset LC_CTYPE || : ; \ unset LC_COLLATE LANG || : ; \ - sed -e '/\/\*/d' \ + sed -e '/[/][*]/d' \ -e '/^#/d' \ -e 's/enum \(.*\) {/let names_of_\1 = [|/' \ -e 's/.*};$$/ |]/' \ @@ -278,6 +259,12 @@ 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 @@ -287,19 +274,21 @@ endif objinfo_helper$(EXE): objinfo_helper.c ../config/s.h $(BYTECC) $(CCOUT)objinfo_helper$(EXE) $(BYTECCCOMPOPTS) \ - objinfo_helper.c $(LIBBFD_LINK) + $(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 objinfo: objinfo_helper$(EXE) $(OBJINFO) $(CAMLC) -o objinfo $(OBJINFO) install:: - cp objinfo $(INSTALL_BINDIR)/ocamlobjinfo$(EXE) - cp objinfo_helper$(EXE) $(INSTALL_LIBDIR)/objinfo_helper$(EXE) + cp objinfo "$(INSTALL_BINDIR)/ocamlobjinfo$(EXE)" + cp objinfo_helper$(EXE) "$(INSTALL_LIBDIR)/objinfo_helper$(EXE)" clean:: rm -f objinfo objinfo_helper$(EXE) @@ -314,6 +303,35 @@ primreq: $(PRIMREQ) clean:: rm -f primreq +# Copy a bytecode executable, stripping debug info + +STRIPDEBUG=../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ + stripdebug.cmo + +stripdebug: $(STRIPDEBUG) + $(CAMLC) $(LINKFLAGS) -o stripdebug $(STRIPDEBUG) + +clean:: + rm -f stripdebug + +# Compare two bytecode executables + +CMPBYT=../compilerlibs/ocamlcommon.cma \ + ../compilerlibs/ocamlbytecomp.cma \ + cmpbyt.cmo + +cmpbyt: $(CMPBYT) + $(CAMLC) $(LINKFLAGS) -o cmpbyt $(CMPBYT) + +clean:: + rm -f cmpbyt + +ifeq "$(RUNTIMEI)" "true" +install:: + cp ocaml-instr-graph ocaml-instr-report $(INSTALL_BINDIR)/ +endif + # Common stuff .SUFFIXES: diff --git a/tools/addlabels.ml b/tools/addlabels.ml index 1579be19..2153b37c 100644 --- a/tools/addlabels.ml +++ b/tools/addlabels.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jacques Garrigue, Kyoto University RIMS *) -(* *) -(* Copyright 2001 Institut National de Recherche en Informatique et *) -(* en Automatique and Kyoto University. All rights reserved. *) -(* This file is distributed under the terms of the Q Public License *) -(* version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jacques Garrigue, Kyoto University RIMS *) +(* *) +(* Copyright 2001 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2001 Kyoto University *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open StdLabels open Asttypes diff --git a/tools/check-typo b/tools/check-typo index c4673da0..9b6c7c6f 100755 --- a/tools/check-typo +++ b/tools/check-typo @@ -1,16 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2012 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2012 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. * +#* * +#************************************************************************** # check-typo - Check typographic conventions on OCaml sources. @@ -23,32 +26,36 @@ # - absence of empty lines at end of file (white-at-eof) # - presence of a LF character at the end of the file (missing-lf) # - maximum line length of 80 characters (long-line) +# - maximum line length of 132 characters (very-long-line) # - presence of a copyright header (missing-header) # - absence of a leftover "$Id" string (svn-keyword) -# Exceptions are handled with a SVN property: "ocaml:typo". +# Exceptions are handled with a git attribute: "ocaml-typo". # Its value for a given file is a comma-separated list of rule names, # which lists the rules that should be disabled for this file. # The rule names are the ones shown above in parentheses. # Built-in exceptions: -# - Any binary file (i.e. with svn:mime-type = application/octet-stream) +# - Any file git identifies as binary # is automatically exempt from all the rules. # - Any file whose name matches one of the following patterns is # automatically exempt from all rules # *.reference +# *.opt_reference # */reference # */.depend* # - Any file whose name begins with "Makefile" is automatically exempt # from the "tabs" rule. # - Any file whose name matches one of the following patterns is # automatically exempt from the "missing-header" rule. -# */.ignore # *.mlpack # *.mllib # *.mltop # *.odocl # *.clib +# - Any file whose name matches the following pattern is automatically +# exempt from the "long-line" rule (but not from "very-long-line"). +# */ocamldoc/* # ASCII characters are bytes from 0 to 127. Any other byte is # flagged as a non-ASCII character. @@ -64,21 +71,24 @@ # on the command line (or by default the current directory), and check # every file therein for compliance to the rules. -# Directories named .svn and _build (and their contents) are always ignored. -# This program ignores any file that is not under svn control, unless +# Directories named .git (and their contents) are always ignored. +# This program ignores any file that is not under git control, unless # explicitly given on the command line. -# If a directory has the SVN property "ocaml:typo" set to "prune", +# If a directory has the git attribute "ocaml-typo" set to "prune", # then it and its contents are ignored. # You can ignore a rule by giving the option - on the command # line (before any file names). +# First prevent i18n from messing up everything. +export LC_ALL=C + # Special case for recursive call from the find command (see IGNORE_DIRS). case "$1" in --check-prune) - case `svn propget ocaml:typo "$2" 2>/dev/null` in - prune) echo "INFO: pruned directory $2 (ocaml:typo=prune)" >&2; exit 0;; + case `git check-attr ocaml-typo "$2" 2>/dev/null` in + *prune*) echo "INFO: pruned directory $2 (ocaml-typo=prune)" >&2; exit 0;; *) exit 3;; esac;; esac @@ -100,8 +110,7 @@ while : ; do done IGNORE_DIRS=" - -name .svn -prune -o - -name _build -prune -o + -name .git -prune -o -type d -exec $0 --check-prune {} ; -prune -o " @@ -111,10 +120,8 @@ IGNORE_DIRS=" esac ) | ( while read f; do - case `svn status "$f" 2>&1` in - '?'*) is_svn=false;; - I*) is_svn=false;; - svn:*"is not a working copy") is_svn=false;; + case `git ls-files "$f" 2>&1` in + "") is_svn=false;; *) is_svn=true;; esac case "$*" in @@ -124,20 +131,32 @@ IGNORE_DIRS=" if $is_svn || $is_cmd_line; then :; else continue; fi svnrules='' if $is_svn; then - case `svn propget svn:mime-type "$f"` in - application/octet-stream) continue;; - esac - svnrules=`svn propget ocaml:typo "$f"` + # Below is a git plumbing command to detect whether git regards a + # particular file as binary. This takes into account .gitattributes, but + # also works if the file has been automatically detected as binary by git. + # EMPTY is the hash of the empty tree (which is specially known to git - + # it is automatically included in every repository) as a way to get + # `diff-tree` to print the whole tree state; its `--numstat` output then + # prints a summary where two dashes in the first two columns indicates a + # binary file. + # (See https://git-scm.com/docs/git-diff-tree#_other_diff_formats and + # the documentation for the --numstat option. Commands designated as + # "plumbing" commands in git have stable output intended for parsing) + EMPTY=`git hash-object -t tree /dev/null` + git diff-tree --numstat $EMPTY HEAD -- "$f" | grep -q "^-[[:blank:]]-" \ + && continue + svnrules=`git check-attr ocaml-typo "$f" | sed -e 's/.*: //'` + case $svnrules in unspecified) svnrules= ;; esac fi rules="$userrules" + add_hd(){ rules="missing-header,$rules"; } case "$f" in Makefile*|*/Makefile*) rules="tab,$rules";; + *.mlpack|*.mllib|*.mltop|*.odocl|*.itarget|*.clib) add_hd;; + *.reference|*.opt_reference|*/reference|*/.depend*) continue;; esac - h(){ rules="missing-header,$rules"; } case "$f" in - */.ignore) h;; - *.mlpack|*.mllib|*.mltop|*.odocl|*.itarget|*.clib) h;; - *.reference|*/reference|*/.depend*) continue;; + ocamldoc/*|*/ocamldoc/*) rules="long-line,$rules";; esac (cat "$f"; echo) \ @@ -149,6 +168,7 @@ IGNORE_DIRS=" && counts[name] <= 10){ printf ("%s:%d.%d:", file, NR, RSTART + RLENGTH); printf (" [%s] %s\n", name, msg); + got_errors = 1; if (counts[name] == 10){ printf ("WARNING: too many [%s] in this file.", name); printf (" Others will not be reported.\n"); @@ -156,8 +176,32 @@ IGNORE_DIRS=" } } + function more_columns(str, limit, c){ + c = 0; + for (i = 1; i <= length(str); i++){ + if (substr(str, i, 1) == "\t"){ + c = int((c + 8) / 8) * 8; + }else{ + ++ c; + } + } + return c > limit; + } + + BEGIN { state = "(first line)"; } + match($0, /\t/) { err("tab", "TAB character(s)"); + if (more_columns($0, 80)){ + RSTART=81; + RLENGTH = 0; + err("long-line", "line is over 80 columns"); + } + if (more_columns($0, 132)){ + RSTART=133; + RLENGTH = 0; + err("very-long-line", "line is over 132 columns"); + } } match($0, /[\200-\377]/) { @@ -176,21 +220,39 @@ IGNORE_DIRS=" err("svn-keyword", "SVN keyword marker"); } - length($0) > 80 { + $0 !~ /\t/ && length($0) > 80 { RSTART = 81; RLENGTH = 0; - err("long-line", "line is over 80 characters"); + err("long-line", "line is over 80 columns"); } - 3 <= NR && NR <= 5 \ - && (/ OCaml / || / ocamlbuild / || / OCamldoc /) { - header_ocaml = NR; + $0 !~ /\t/ && length($0) > 132 { + RSTART = 133; + RLENGTH = 0; + err("very-long-line", "line is over 132 columns"); } - header_ocaml && header_ocaml + 4 <= NR && NR <= header_ocaml + 6 \ - && / Copyright / { - header_copyright = 1; - } + # Header-recognition automaton. Read this from bottom to top. + + state == "close" && $0 ~ /\*{74}/ { state = "OK"; } + state == "close" { state = "(last line)"; } + state == "blurb" && $0 ~ /\* {72}\*/ { state = "close"; } + state == "blurb1" && $0 ~ /\* All rights reserved. .{47} \*/ \ + { state = "blurb"; } + state == "blurb1" { state = "(blurb line 1)"; } + state == "copyright" && $0 ~ /\* {72}\*/ { state = "blurb1"; } + state == "copyright" && $0 !~ /\* Copyright [0-9]{4}.{54} \*/ \ + && $0 !~ /\* .{66} \*/ \ + { state = "(copyright lines)"; } + state == "authors" && $0 ~ /\* {72}\*/ { state = "copyright"; } + state == "authors" && $0 !~ /\* .{70} \*/ { state = "(authors)"; } + state == "blank2" && $0 ~ /\* {72}\*/ { state = "authors"; } + state == "blank2" { state = "(blank line 2)"; } + state == "title" && $0 ~ /\* {33}OCaml {34}\*/ { state = "blank2"; } + state == "title" { state = "(title line)"; } + state == "blank1" && $0 ~ /\* {72}\*/ { state = "title"; } + state == "blank1" { state = "(blank line 1)"; } + state == "(first line)" && NR < 4 && $0 ~ /\*{74}/ { state = "blank1"; } { prev_line = last_line; @@ -209,19 +271,27 @@ IGNORE_DIRS=" if (!empty_file && match(prev_line, /^$/)){ err("white-at-eof", "empty line(s) at EOF"); } - NR = 1; - RSTART = 1; - RLENGTH = 0; - if (!(header_ocaml && header_copyright)){ - err("missing-header", "missing copyright header"); + if (state != "OK"){ + if (NR >= 10){ + NR = 1; + RSTART = 1; + RLENGTH = 0; + err("missing-header", sprintf("bad copyright header %s", state)); + }else{ + counts["missing-header"] = 1; + } } split(svnrules, r, "[, ]"); for (i in r){ name = r[i]; if (name != "" && !counts[name]){ - err("unused-prop", sprintf("unused [%s] in ocaml:typo", name)); + NR = 1; + RSTART = 1; + RLENGTH = 0; + err("unused-prop", sprintf("unused [%s] in ocaml-typo", name)); } } + exit got_errors; } ' done diff --git a/tools/checkstack.c b/tools/checkstack.c index dea6a0a6..c6c213f0 100644 --- a/tools/checkstack.c +++ b/tools/checkstack.c @@ -1,14 +1,17 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2002 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. */ -/* */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2002 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 #include diff --git a/tools/ci-build b/tools/ci-build index de96090e..6d9439e3 100755 --- a/tools/ci-build +++ b/tools/ci-build @@ -1,22 +1,27 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2014 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Gallium, INRIA Rocquencourt * +#* * +#* Copyright 2014 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. * +#* * +#************************************************************************** # This script is run on our continuous-integration servers to recompile # from scratch and run the test suite. # arguments: # 1. architecture: bsd, macos, linux, cygwin, mingw, mingw64, msvc, msvc64 -# 2. for windows, directory in which to build (trunk, 4.02, etc) +# 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 # -patch1 file-name apply patch with -p1 @@ -26,11 +31,26 @@ error () { exit 3 } +quote1 () { + printf "'%s'" "`printf %s "$1" | sed -e "s/'/'\\\\\\\\''/g"`"; +} + +######################################################################### +# be verbose +set -x + +######################################################################### +# "Parse" mandatory command-line arguments. + +arch="$1" +branch="$2" +shift 2 + ######################################################################### # If we are called from a Windows batch script, we must set up the # Unix environment variables (e.g. PATH). -case "$1" in +case "$arch" in bsd|macos|linux) ;; cygwin|mingw|mingw64) . /etc/profile @@ -46,7 +66,7 @@ case "$1" in . "$HOME/.profile" . "$HOME/.msenv64" ;; - *) error "unknown architecture: $1";; + *) error "unknown architecture: $arch";; esac ######################################################################### @@ -54,37 +74,26 @@ esac # be verbose and stop on error set -ex -# parse command line -# Configure options are not allowed to have spaces or special characters -# for the moment. We'll fix that when needed. -arch="$1" -branch="$2" -confoptions="" -shift 2 -while [ $# -gt 0 ]; do - case $1 in - -conf) confoptions="$confoptions $2"; shift 2;; - -patch1) patch -f -p1 <"$2"; shift 2;; - *) error "unknown option $1";; - esac -done - ######################################################################### # set up variables # default values make=make instdir="$HOME/ocaml-tmp-install" -workdir=. docheckout=false nt= case "$arch" in bsd) make=gmake + workdir=. + ;; + macos) + workdir=. + ;; + linux) + workdir=. ;; - macos) ;; # FIXME to be checked - linux) ;; cygwin) workdir="$HOME/jenkins-workspace/$branch" docheckout=true @@ -117,17 +126,38 @@ case "$arch" in esac ######################################################################### +# Go to the right directory +pwd cd "$workdir" +######################################################################### +# 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 2;; + -patch1) patch -f -p1 <"$2"; shift 2;; + *) error "unknown option $1";; + esac +done + +######################################################################### +# Do the work + +# Tell gcc to use only ASCII in its diagnostic outputs. +export LC_ALL=C + $make -f Makefile$nt distclean || : if $docheckout; then - svn update --accept theirs-full + git pull fi case $nt in - "") ./configure -prefix "$instdir" $confoptions;; + "") eval "./configure -prefix '$instdir' $confoptions";; .nt) cp config/m-nt.h config/m.h cp config/s-nt.h config/s.h diff --git a/tools/cleanup-header b/tools/cleanup-header index bc64f2e9..5945597b 100644 --- a/tools/cleanup-header +++ b/tools/cleanup-header @@ -1,16 +1,19 @@ #!/bin/sed -f -####################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2002 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. # -# # -####################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 2002 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. * +#* * +#************************************************************************** # Remove private parts from runtime include files, before installation # in /usr/local/lib/ocaml/caml diff --git a/tools/cmpbyt.ml b/tools/cmpbyt.ml new file mode 100644 index 00000000..e6b42434 --- /dev/null +++ b/tools/cmpbyt.ml @@ -0,0 +1,87 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Gallium, INRIA Paris *) +(* *) +(* Copyright 2015 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. *) +(* *) +(**************************************************************************) + +(* Compare two bytecode executables for equality. + Ignore loader prefix and debug infos. *) + +open Printf + +let readtoc ic = + Bytesections.read_toc ic; + (Bytesections.toc(), Bytesections.pos_first_section ic) + +type cmpresult = Same | Differ of int + +let rec cmpbytes ic1 ic2 len ofs = + if len <= 0 then Same else begin + let c1 = input_char ic1 and c2 = input_char ic2 in + if c1 = c2 then cmpbytes ic1 ic2 (len - 1) (ofs + 1) else Differ ofs + end + +let skip_section name = + name = "DBUG" + +let cmpbyt file1 file2 = + let ic1 = open_in_bin file1 in + let (toc1, pos1) = readtoc ic1 in + let ic2 = open_in_bin file2 in + let (toc2, pos2) = readtoc ic2 in + seek_in ic1 pos1; + seek_in ic2 pos2; + let rec cmpsections t1 t2 = + match t1, t2 with + | [], [] -> + true + | (name1, len1) :: t1, t2 when skip_section name1 -> + seek_in ic1 (pos_in ic1 + len1); + cmpsections t1 t2 + | t1, (name2, len2) :: t2 when skip_section name2 -> + seek_in ic2 (pos_in ic2 + len2); + cmpsections t1 t2 + | [], _ -> + eprintf "%s has more sections than %s\n" file2 file1; + false + | _, [] -> + eprintf "%s has more sections than %s\n" file1 file2; + false + | (name1, len1) :: t1, (name2, len2) :: t2 -> + if name1 <> name2 then begin + eprintf "Section mismatch: %s (in %s) / %s (in %s)\n" + name1 file1 name2 file2; + false + end else if len1 <> len2 then begin + eprintf "Length of section %s differ: %d (in %s) / %d (in %s)\n" + name1 len1 file1 len2 file2; + false + end else begin + match cmpbytes ic1 ic2 len1 0 with + | Differ ofs -> + eprintf "Files %s and %s differ: section %s, offset %d\n" + file1 file2 name1 ofs; + false + | Same -> + cmpsections t1 t2 + end + in + let res = cmpsections toc1 toc2 in + close_in ic1; close_in ic2; + res + +let _ = + if Array.length Sys.argv <> 3 then begin + eprintf "Usage: cmpbyt \n"; + exit 2 + end; + if cmpbyt Sys.argv.(1) Sys.argv.(2) then exit 0 else exit 2 diff --git a/tools/cmt2annot.ml b/tools/cmt2annot.ml index 36ca187c..69dcca78 100644 --- a/tools/cmt2annot.ml +++ b/tools/cmt2annot.ml @@ -1,37 +1,45 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) (* Generate an .annot file from a .cmt file. *) open Asttypes open Typedtree +open Tast_mapper let bind_variables scope = - object - inherit Tast_iter.iter as super - - method! pattern pat = - super # pattern pat; - match pat.pat_desc with - | Tpat_var (id, _) | Tpat_alias (_, id, _) -> - Stypes.record (Stypes.An_ident (pat.pat_loc, - Ident.name id, - Annot.Idef scope)) - | _ -> () - end + let super = Tast_mapper.default in + let pat sub p = + begin match p.pat_desc with + | Tpat_var (id, _) | Tpat_alias (_, id, _) -> + Stypes.record (Stypes.An_ident (p.pat_loc, + Ident.name id, + Annot.Idef scope)) + | _ -> () + end; + super.pat sub p; + in + {super with pat} + +let bind_variables scope = + let o = bind_variables scope in + fun p -> ignore (o.pat o p) let bind_bindings scope bindings = let o = bind_variables scope in - List.iter (fun x -> o # pattern x.vb_pat) bindings + List.iter (fun x -> o x.vb_pat) bindings let bind_cases l = List.iter @@ -42,110 +50,108 @@ let bind_cases l = | None -> c_rhs.exp_loc | Some g -> {c_rhs.exp_loc with loc_start=g.exp_loc.loc_start} in - (bind_variables loc) # pattern c_lhs) l - -let iterator rebuild_env = - object(this) - val scope = Location.none (* scope of the surrounding structure *) - - inherit Tast_iter.iter as super - - method! class_expr node = - Stypes.record (Stypes.Ti_class node); - super # class_expr node - - method! module_expr node = - Stypes.record (Stypes.Ti_mod node); - Tast_iter.module_expr {< scope = node.mod_loc >} node - - method! expression exp = - begin match exp.exp_desc with - | Texp_ident (path, _, _) -> - let full_name = Path.name ~paren:Oprint.parenthesized_ident path in - let env = - if rebuild_env then - try - Env.env_of_only_summary Envaux.env_from_summary exp.exp_env - with Envaux.Error err -> - Format.eprintf "%a@." Envaux.report_error err; - exit 2 - else - exp.exp_env - in - let annot = + bind_variables loc c_lhs + ) + l + +let rec iterator ~scope rebuild_env = + let super = Tast_mapper.default in + let class_expr sub node = + Stypes.record (Stypes.Ti_class node); + super.class_expr sub node + + and module_expr _sub node = + Stypes.record (Stypes.Ti_mod node); + super.module_expr (iterator ~scope:node.mod_loc rebuild_env) node + + and expr sub exp = + begin match exp.exp_desc with + | Texp_ident (path, _, _) -> + let full_name = Path.name ~paren:Oprint.parenthesized_ident path in + let env = + if rebuild_env then try - let desc = Env.find_value path env in - let dloc = desc.Types.val_loc in - if dloc.Location.loc_ghost then Annot.Iref_external - else Annot.Iref_internal dloc - with Not_found -> - Annot.Iref_external - in - Stypes.record - (Stypes.An_ident (exp.exp_loc, full_name , annot)) - | Texp_let (Recursive, bindings, _) -> - bind_bindings exp.exp_loc bindings - | Texp_let (Nonrecursive, bindings, body) -> - bind_bindings body.exp_loc bindings - | Texp_match (_, f1, f2, _) -> + Env.env_of_only_summary Envaux.env_from_summary exp.exp_env + with Envaux.Error err -> + Format.eprintf "%a@." Envaux.report_error err; + exit 2 + else + exp.exp_env + in + let annot = + try + let desc = Env.find_value path env in + let dloc = desc.Types.val_loc in + if dloc.Location.loc_ghost then Annot.Iref_external + else Annot.Iref_internal dloc + with Not_found -> + Annot.Iref_external + in + Stypes.record + (Stypes.An_ident (exp.exp_loc, full_name , annot)) + | Texp_let (Recursive, bindings, _) -> + bind_bindings exp.exp_loc bindings + | Texp_let (Nonrecursive, bindings, body) -> + bind_bindings body.exp_loc bindings + | Texp_match (_, f1, f2, _) -> bind_cases f1; bind_cases f2 - | Texp_function (_, f, _) - | Texp_try (_, f) -> - bind_cases f - | _ -> () - end; - Stypes.record (Stypes.Ti_expr exp); - super # expression exp - - method! pattern pat = - super # pattern pat; - Stypes.record (Stypes.Ti_pat pat) - - method private structure_item_rem s rem = - begin match s with - | {str_desc = Tstr_value (rec_flag, bindings); str_loc = loc} -> - let open Location in - let doit loc_start = bind_bindings {scope with loc_start} bindings in - begin match rec_flag, rem with - | Recursive, _ -> doit loc.loc_start - | Nonrecursive, [] -> doit loc.loc_end - | Nonrecursive, {str_loc = loc2} :: _ -> doit loc2.loc_start - end - | _ -> - () - end; - Stypes.record_phrase s.str_loc; - super # structure_item s - - method! structure_item s = - (* This will be used for Partial_structure_item. - We don't have here the location of the "next" item, - this will give a slightly different scope for the non-recursive - binding case. *) - this # structure_item_rem s [] - - method! structure l = - let rec loop = function - | str :: rem -> this # structure_item_rem str rem; loop rem - | [] -> () - in - loop l.str_items + | Texp_function (_, f, _) + | Texp_try (_, f) -> + bind_cases f + | _ -> () + end; + Stypes.record (Stypes.Ti_expr exp); + super.expr sub exp + + and pat sub p = + Stypes.record (Stypes.Ti_pat p); + super.pat sub p + in -(* TODO: support binding for Tcl_fun, Tcl_let, etc *) - end + let structure_item_rem sub s rem = + begin match s with + | {str_desc = Tstr_value (rec_flag, bindings); str_loc = loc} -> + let open Location in + let doit loc_start = bind_bindings {scope with loc_start} bindings in + begin match rec_flag, rem with + | Recursive, _ -> doit loc.loc_start + | Nonrecursive, [] -> doit loc.loc_end + | Nonrecursive, {str_loc = loc2} :: _ -> doit loc2.loc_start + end + | _ -> + () + end; + Stypes.record_phrase s.str_loc; + super.structure_item sub s + in + let structure_item sub s = + (* This will be used for Partial_structure_item. + We don't have here the location of the "next" item, + this will give a slightly different scope for the non-recursive + binding case. *) + structure_item_rem sub s [] + and structure sub l = + let rec loop = function + | str :: rem -> structure_item_rem sub str rem :: loop rem + | [] -> [] + in + {l with str_items = loop l.str_items} + in + {super with class_expr; module_expr; expr; pat; structure_item; structure} let binary_part iter x = + let app f x = ignore (f iter x) in let open Cmt_format in match x with - | Partial_structure x -> iter # structure x - | Partial_structure_item x -> iter # structure_item x - | Partial_expression x -> iter # expression x - | Partial_pattern x -> iter # pattern x - | Partial_class_expr x -> iter # class_expr x - | Partial_signature x -> iter # signature x - | Partial_signature_item x -> iter # signature_item x - | Partial_module_type x -> iter # module_type x + | Partial_structure x -> app iter.structure x + | Partial_structure_item x -> app iter.structure_item x + | Partial_expression x -> app iter.expr x + | Partial_pattern x -> app iter.pat x + | Partial_class_expr x -> app iter.class_expr x + | Partial_signature x -> app iter.signature x + | Partial_signature_item x -> app iter.signature_item x + | Partial_module_type x -> app iter.module_type x let gen_annot target_filename filename {Cmt_format.cmt_loadpath; cmt_annots; cmt_use_summaries; _} = @@ -158,10 +164,10 @@ let gen_annot target_filename filename | Some "-" -> None | Some _ -> target_filename in - let iterator = iterator cmt_use_summaries in + let iterator = iterator ~scope:Location.none cmt_use_summaries in match cmt_annots with | Implementation typedtree -> - iterator # structure typedtree; + ignore (iterator.structure iterator typedtree); Stypes.dump target_filename | Interface _ -> Printf.eprintf "Cannot generate annotations for interface file\n%!"; diff --git a/tools/cvt_emit.mll b/tools/cvt_emit.mll index d54243e2..396f644b 100644 --- a/tools/cvt_emit.mll +++ b/tools/cvt_emit.mll @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) { let first_item = ref false diff --git a/tools/depend.ml b/tools/depend.ml index aeb121cb..a29f8435 100644 --- a/tools/depend.ml +++ b/tools/depend.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* 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 Q Public License version 1.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. *) +(* *) +(**************************************************************************) open Asttypes open Location @@ -16,27 +19,82 @@ open Longident open Parsetree module StringSet = Set.Make(struct type t = string let compare = compare end) +module StringMap = Map.Make(String) + +(* Module resolution map *) +(* Node (set of imports for this path, map for submodules) *) +type map_tree = Node of StringSet.t * bound_map +and bound_map = map_tree StringMap.t +let bound = Node (StringSet.empty, StringMap.empty) + +(*let get_free (Node (s, _m)) = s*) +let get_map (Node (_s, m)) = m +let make_leaf s = Node (StringSet.singleton s, StringMap.empty) +let make_node m = Node (StringSet.empty, m) +let rec weaken_map s (Node(s0,m0)) = + Node (StringSet.union s s0, StringMap.map (weaken_map s) m0) +let rec collect_free (Node (s, m)) = + StringMap.fold (fun _ n -> StringSet.union (collect_free n)) m s + +(* Returns the imports required to access the structure at path p *) +(* Only raises Not_found if the head of p is not in the toplevel map *) +let rec lookup_free p m = + match p with + [] -> raise Not_found + | s::p -> + let Node (f, m') = StringMap.find s m in + try lookup_free p m' with Not_found -> f + +(* Returns the node corresponding to the structure at path p *) +let rec lookup_map lid m = + match lid with + Lident s -> StringMap.find s m + | Ldot (l, s) -> StringMap.find s (get_map (lookup_map l m)) + | Lapply _ -> raise Not_found (* Collect free module identifiers in the a.s.t. *) let free_structure_names = ref StringSet.empty -let rec add_path bv = function +let add_names s = + free_structure_names := StringSet.union s !free_structure_names + +let rec add_path bv ?(p=[]) = function | Lident s -> - if not (StringSet.mem s bv) - then free_structure_names := StringSet.add s !free_structure_names - | Ldot(l, _s) -> add_path bv l + let free = + try lookup_free (s::p) bv with Not_found -> StringSet.singleton s + in + (*StringSet.iter (fun s -> Printf.eprintf "%s " s) free; + prerr_endline "";*) + add_names free + | Ldot(l, s) -> add_path bv ~p:(s::p) l | Lapply(l1, l2) -> add_path bv l1; add_path bv l2 -let open_module bv lid = add_path bv lid +let open_module bv lid = + match lookup_map lid bv with + | Node (s, m) -> + add_names s; + StringMap.fold StringMap.add m bv + | exception Not_found -> + add_path bv lid; bv -let add bv lid = +let add_parent bv lid = match lid.txt with Ldot(l, _s) -> add_path bv l | _ -> () +let add = add_parent + let addmodule bv lid = add_path bv lid.txt +let handle_extension ext = + match (fst ext).txt with + | "error" | "ocaml.error" -> + raise (Location.Error + (Builtin_attributes.error_of_extension ext)) + | _ -> + () + let rec add_type bv ty = match ty.ptyp_desc with Ptyp_any -> () @@ -54,7 +112,7 @@ let rec add_type bv ty = fl | Ptyp_poly(_, t) -> add_type bv t | Ptyp_package pt -> add_package_type bv pt - | Ptyp_extension _ -> () + | Ptyp_extension e -> handle_extension e and add_package_type bv (lid, l) = add bv lid; @@ -64,8 +122,13 @@ let add_opt add_fn bv = function None -> () | Some x -> add_fn bv x +let add_constructor_arguments bv = function + | Pcstr_tuple l -> List.iter (add_type bv) l + | Pcstr_record l -> List.iter (fun l -> add_type bv l.pld_type) l + let add_constructor_decl bv pcd = - List.iter (add_type bv) pcd.pcd_args; Misc.may (add_type bv) pcd.pcd_res + add_constructor_arguments bv pcd.pcd_args; + Misc.may (add_type bv) pcd.pcd_res let add_type_declaration bv td = List.iter @@ -83,9 +146,10 @@ let add_type_declaration bv td = let add_extension_constructor bv ext = match ext.pext_kind with - Pext_decl(args, rty) -> - List.iter (add_type bv) args; Misc.may (add_type bv) rty - | Pext_rebind lid -> add bv lid + Pext_decl(args, rty) -> + add_constructor_arguments bv args; + Misc.may (add_type bv) rty + | Pext_rebind lid -> add bv lid let add_type_extension bv te = add bv te.ptyext_path; @@ -100,7 +164,7 @@ let rec add_class_type bv cty = List.iter (add_class_type_field bv) fieldl | Pcty_arrow(_, ty1, cty2) -> add_type bv ty1; add_class_type bv cty2 - | Pcty_extension _ -> () + | Pcty_extension e -> handle_extension e and add_class_type_field bv pctf = match pctf.pctf_desc with @@ -109,14 +173,14 @@ and add_class_type_field bv pctf = | Pctf_method(_, _, _, ty) -> add_type bv ty | Pctf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2 | Pctf_attribute _ -> () - | Pctf_extension _ -> () + | Pctf_extension e -> handle_extension e let add_class_description bv infos = add_class_type bv infos.pci_expr let add_class_type_declaration = add_class_description -let pattern_bv = ref StringSet.empty +let pattern_bv = ref StringMap.empty let rec add_pattern bv pat = match pat.ppat_desc with @@ -135,9 +199,9 @@ let rec add_pattern bv pat = | Ppat_variant(_, op) -> add_opt add_pattern bv op | Ppat_type li -> add bv li | Ppat_lazy p -> add_pattern bv p - | Ppat_unpack id -> pattern_bv := StringSet.add id.txt !pattern_bv + | Ppat_unpack id -> pattern_bv := StringMap.add id.txt bound !pattern_bv | Ppat_exception p -> add_pattern bv p - | Ppat_extension _ -> () + | Ppat_extension e -> handle_extension e let add_pattern bv pat = pattern_bv := bv; @@ -185,7 +249,8 @@ let rec add_expr bv exp = | Pexp_setinstvar(_v, e) -> add_expr bv e | Pexp_override sel -> List.iter (fun (_s, e) -> add_expr bv e) sel | Pexp_letmodule(id, m, e) -> - add_module bv m; add_expr (StringSet.add id.txt bv) e + let b = add_module_binding bv m in + add_expr (StringMap.add id.txt b bv) e | Pexp_assert (e) -> add_expr bv e | Pexp_lazy (e) -> add_expr bv e | Pexp_poly (e, t) -> add_expr bv e; add_opt add_type bv t @@ -193,8 +258,17 @@ let rec add_expr bv exp = let bv = add_pattern bv pat in List.iter (add_class_field bv) fieldl | Pexp_newtype (_, e) -> add_expr bv e | Pexp_pack m -> add_module bv m - | Pexp_open (_ovf, m, e) -> open_module bv m.txt; add_expr bv e - | Pexp_extension _ -> () + | Pexp_open (_ovf, m, e) -> + let bv = open_module bv m.txt in add_expr bv e + | Pexp_extension (({ txt = ("ocaml.extension_constructor"| + "extension_constructor"); _ }, + PStr [item]) as e) -> + begin match item.pstr_desc with + | Pstr_eval ({ pexp_desc = Pexp_construct (c, None) }, _) -> add bv c + | _ -> handle_extension e + end + | Pexp_extension e -> handle_extension e + | Pexp_unreachable -> () and add_cases bv cases = List.iter (add_case bv) cases @@ -217,7 +291,7 @@ and add_modtype bv mty = | Pmty_signature s -> add_signature bv s | Pmty_functor(id, mty1, mty2) -> Misc.may (add_modtype bv) mty1; - add_modtype (StringSet.add id.txt bv) mty2 + add_modtype (StringMap.add id.txt bound bv) mty2 | Pmty_with(mty, cstrl) -> add_modtype bv mty; List.iter @@ -229,47 +303,95 @@ and add_modtype bv mty = ) cstrl | Pmty_typeof m -> add_module bv m - | Pmty_extension _ -> () - -and add_signature bv = function - [] -> () - | item :: rem -> add_signature (add_sig_item bv item) rem - -and add_sig_item bv item = + | Pmty_extension e -> handle_extension e + +and add_module_alias bv l = + try + add_parent bv l; + lookup_map l.txt bv + with Not_found -> + match l.txt with + Lident s -> make_leaf s + | _ -> addmodule bv l; bound (* cannot delay *) + +and add_modtype_binding bv mty = + if not !Clflags.transparent_modules then add_modtype bv mty; + match mty.pmty_desc with + Pmty_alias l -> + add_module_alias bv l + | Pmty_signature s -> + make_node (add_signature_binding bv s) + | Pmty_typeof modl -> + add_module_binding bv modl + | _ -> + if !Clflags.transparent_modules then add_modtype bv mty; bound + +and add_signature bv sg = + ignore (add_signature_binding bv sg) + +and add_signature_binding bv sg = + snd (List.fold_left add_sig_item (bv, StringMap.empty) sg) + +and add_sig_item (bv, m) item = match item.psig_desc with Psig_value vd -> - add_type bv vd.pval_type; bv - | Psig_type dcls -> - List.iter (add_type_declaration bv) dcls; bv + add_type bv vd.pval_type; (bv, m) + | Psig_type (_, dcls) -> + List.iter (add_type_declaration bv) dcls; (bv, m) | Psig_typext te -> - add_type_extension bv te; bv + add_type_extension bv te; (bv, m) | Psig_exception pext -> - add_extension_constructor bv pext; bv + add_extension_constructor bv pext; (bv, m) | Psig_module pmd -> - add_modtype bv pmd.pmd_type; StringSet.add pmd.pmd_name.txt bv + let m' = add_modtype_binding bv pmd.pmd_type in + let add = StringMap.add pmd.pmd_name.txt m' in + (add bv, add m) | Psig_recmodule decls -> - let bv' = - List.fold_right StringSet.add - (List.map (fun pmd -> pmd.pmd_name.txt) decls) bv + let add = + List.fold_right (fun pmd -> StringMap.add pmd.pmd_name.txt bound) + decls in + let bv' = add bv and m' = add m in List.iter (fun pmd -> add_modtype bv' pmd.pmd_type) decls; - bv' + (bv', m') | Psig_modtype x -> begin match x.pmtd_type with None -> () | Some mty -> add_modtype bv mty end; - bv + (bv, m) | Psig_open od -> - open_module bv od.popen_lid.txt; bv + (open_module bv od.popen_lid.txt, m) | Psig_include incl -> - add_modtype bv incl.pincl_mod; bv + let Node (s, m') = add_modtype_binding bv incl.pincl_mod in + add_names s; + let add = StringMap.fold StringMap.add m' in + (add bv, add m) | Psig_class cdl -> - List.iter (add_class_description bv) cdl; bv + List.iter (add_class_description bv) cdl; (bv, m) | Psig_class_type cdtl -> - List.iter (add_class_type_declaration bv) cdtl; bv - | Psig_attribute _ | Psig_extension _ -> - bv + List.iter (add_class_type_declaration bv) cdtl; (bv, m) + | Psig_attribute _ -> (bv, m) + | Psig_extension (e, _) -> + handle_extension e; + (bv, m) + +and add_module_binding bv modl = + if not !Clflags.transparent_modules then add_module bv modl; + match modl.pmod_desc with + Pmod_ident l -> + begin try + add_parent bv l; + lookup_map l.txt bv + with Not_found -> + match l.txt with + Lident s -> make_leaf s + | _ -> addmodule bv l; bound + end + | Pmod_structure s -> + make_node (snd (add_structure_binding bv s)) + | _ -> + if !Clflags.transparent_modules then add_module bv modl; bound and add_module bv modl = match modl.pmod_desc with @@ -277,66 +399,84 @@ and add_module bv modl = | Pmod_structure s -> ignore (add_structure bv s) | Pmod_functor(id, mty, modl) -> Misc.may (add_modtype bv) mty; - add_module (StringSet.add id.txt bv) modl + add_module (StringMap.add id.txt bound bv) modl | Pmod_apply(mod1, mod2) -> add_module bv mod1; add_module bv mod2 | Pmod_constraint(modl, mty) -> add_module bv modl; add_modtype bv mty | Pmod_unpack(e) -> add_expr bv e - | Pmod_extension _ -> - () + | Pmod_extension e -> + handle_extension e and add_structure bv item_list = - List.fold_left add_struct_item bv item_list + let (bv, m) = add_structure_binding bv item_list in + add_names (collect_free (make_node m)); + bv -and add_struct_item bv item = +and add_structure_binding bv item_list = + List.fold_left add_struct_item (bv, StringMap.empty) item_list + +and add_struct_item (bv, m) item : _ StringMap.t * _ StringMap.t = match item.pstr_desc with Pstr_eval (e, _attrs) -> - add_expr bv e; bv + add_expr bv e; (bv, m) | Pstr_value(rf, pel) -> - let bv = add_bindings rf bv pel in bv + let bv = add_bindings rf bv pel in (bv, m) | Pstr_primitive vd -> - add_type bv vd.pval_type; bv - | Pstr_type dcls -> - List.iter (add_type_declaration bv) dcls; bv + add_type bv vd.pval_type; (bv, m) + | Pstr_type (_, dcls) -> + List.iter (add_type_declaration bv) dcls; (bv, m) | Pstr_typext te -> add_type_extension bv te; - bv + (bv, m) | Pstr_exception pext -> - add_extension_constructor bv pext; bv + add_extension_constructor bv pext; (bv, m) | Pstr_module x -> - add_module bv x.pmb_expr; StringSet.add x.pmb_name.txt bv + let b = add_module_binding bv x.pmb_expr in + let add = StringMap.add x.pmb_name.txt b in + (add bv, add m) | Pstr_recmodule bindings -> - let bv' = - List.fold_right StringSet.add - (List.map (fun x -> x.pmb_name.txt) bindings) bv in + let add = + List.fold_right (fun x -> StringMap.add x.pmb_name.txt bound) bindings + in + let bv' = add bv and m = add m in List.iter (fun x -> add_module bv' x.pmb_expr) bindings; - bv' + (bv', m) | Pstr_modtype x -> begin match x.pmtd_type with None -> () | Some mty -> add_modtype bv mty end; - bv + (bv, m) | Pstr_open od -> - open_module bv od.popen_lid.txt; bv + (open_module bv od.popen_lid.txt, m) | Pstr_class cdl -> - List.iter (add_class_declaration bv) cdl; bv + List.iter (add_class_declaration bv) cdl; (bv, m) | Pstr_class_type cdtl -> - List.iter (add_class_type_declaration bv) cdtl; bv + List.iter (add_class_type_declaration bv) cdtl; (bv, m) | Pstr_include incl -> - add_module bv incl.pincl_mod; bv - | Pstr_attribute _ | Pstr_extension _ -> - bv + let Node (s, m') = add_module_binding bv incl.pincl_mod in + add_names s; + let add = StringMap.fold StringMap.add m' in + (add bv, add m) + | Pstr_attribute _ -> (bv, m) + | Pstr_extension (e, _) -> + handle_extension e; + (bv, m) and add_use_file bv top_phrs = ignore (List.fold_left add_top_phrase bv top_phrs) and add_implementation bv l = - ignore (add_structure bv l) + if !Clflags.transparent_modules then + ignore (add_structure_binding bv l) + else ignore (add_structure bv l) + +and add_implementation_binding bv l = + snd (add_structure_binding bv l) and add_top_phrase bv = function | Ptop_def str -> add_structure bv str @@ -357,7 +497,7 @@ and add_class_expr bv ce = let bv = add_bindings rf bv pel in add_class_expr bv ce | Pcl_constraint(ce, ct) -> add_class_expr bv ce; add_class_type bv ct - | Pcl_extension _ -> () + | Pcl_extension e -> handle_extension e and add_class_field bv pcf = match pcf.pcf_desc with @@ -368,7 +508,8 @@ and add_class_field bv pcf = | Pcf_method(_, _, Cfk_virtual ty) -> add_type bv ty | Pcf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2 | Pcf_initializer e -> add_expr bv e - | Pcf_attribute _ | Pcf_extension _ -> () + | Pcf_attribute _ -> () + | Pcf_extension e -> handle_extension e and add_class_declaration bv decl = add_class_expr bv decl.pci_expr diff --git a/tools/depend.mli b/tools/depend.mli index 93fc084f..e34abbe7 100644 --- a/tools/depend.mli +++ b/tools/depend.mli @@ -1,25 +1,38 @@ -(***********************************************************************) -(* *) -(* 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 Q Public License version 1.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. *) +(* *) +(**************************************************************************) (** Module dependencies. *) module StringSet : Set.S with type elt = string +module StringMap : Map.S with type key = string + +type map_tree = Node of StringSet.t * bound_map +and bound_map = map_tree StringMap.t +val make_leaf : string -> map_tree +val make_node : bound_map -> map_tree +val weaken_map : StringSet.t -> map_tree -> map_tree val free_structure_names : StringSet.t ref -val open_module : StringSet.t -> Longident.t -> unit +val open_module : bound_map -> Longident.t -> bound_map + +val add_use_file : bound_map -> Parsetree.toplevel_phrase list -> unit -val add_use_file : StringSet.t -> Parsetree.toplevel_phrase list -> unit +val add_signature : bound_map -> Parsetree.signature -> unit -val add_signature : StringSet.t -> Parsetree.signature -> unit +val add_implementation : bound_map -> Parsetree.structure -> unit -val add_implementation : StringSet.t -> Parsetree.structure -> unit +val add_implementation_binding : bound_map -> Parsetree.structure -> bound_map +val add_signature_binding : bound_map -> Parsetree.signature -> bound_map diff --git a/tools/dumpobj.ml b/tools/dumpobj.ml index f1e28973..3c462e67 100644 --- a/tools/dumpobj.ml +++ b/tools/dumpobj.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Disassembler for executable and .cmo object files *) @@ -394,6 +397,8 @@ let op_shapes = [ opSTOP, Nothing; opEVENT, Nothing; opBREAK, Nothing; + opRERAISE, Nothing; + opRAISE_NOTRACE, Nothing; ];; let print_event ev = @@ -412,52 +417,54 @@ let print_instr ic = if op >= Array.length names_of_instructions || op < 0 then (print_string "*** unknown opcode : "; print_int op) else print_string names_of_instructions.(op); - print_string " "; - begin try match List.assoc op op_shapes with - | Uint -> print_int (inputu ic) - | Sint -> print_int (inputs ic) - | Uint_Uint - -> print_int (inputu ic); print_string ", "; print_int (inputu ic) - | Disp -> let p = currpc ic in print_int (p + inputs ic) - | Uint_Disp - -> print_int (inputu ic); print_string ", "; - let p = currpc ic in print_int (p + inputs ic) - | Sint_Disp - -> print_int (inputs ic); print_string ", "; - let p = currpc ic in print_int (p + inputs ic) - | Getglobal -> print_getglobal_name ic - | Getglobal_Uint - -> print_getglobal_name ic; print_string ", "; print_int (inputu ic) - | Setglobal -> print_setglobal_name ic - | Primitive -> print_primitive ic - | Uint_Primitive - -> print_int(inputu ic); print_string ", "; print_primitive ic - | Switch - -> let n = inputu ic in - let orig = currpc ic in - for i = 0 to (n land 0xFFFF) - 1 do - print_string "\n int "; print_int i; print_string " -> "; - print_int(orig + inputs ic); - done; - for i = 0 to (n lsr 16) - 1 do - print_string "\n tag "; print_int i; print_string " -> "; - print_int(orig + inputs ic); - done; - | Closurerec - -> let nfuncs = inputu ic in - let nvars = inputu ic in - let orig = currpc ic in - print_int nvars; - for _i = 0 to nfuncs - 1 do - print_string ", "; - print_int (orig + inputs ic); - done; - | Pubmet - -> let tag = inputs ic in - let _cache = inputu ic in - print_int tag - | Nothing -> () - with Not_found -> print_string "(unknown arguments)" + begin try + let shape = List.assoc op op_shapes in + if shape <> Nothing then print_string " "; + match shape with + | Uint -> print_int (inputu ic) + | Sint -> print_int (inputs ic) + | Uint_Uint + -> print_int (inputu ic); print_string ", "; print_int (inputu ic) + | Disp -> let p = currpc ic in print_int (p + inputs ic) + | Uint_Disp + -> print_int (inputu ic); print_string ", "; + let p = currpc ic in print_int (p + inputs ic) + | Sint_Disp + -> print_int (inputs ic); print_string ", "; + let p = currpc ic in print_int (p + inputs ic) + | Getglobal -> print_getglobal_name ic + | Getglobal_Uint + -> print_getglobal_name ic; print_string ", "; print_int (inputu ic) + | Setglobal -> print_setglobal_name ic + | Primitive -> print_primitive ic + | Uint_Primitive + -> print_int(inputu ic); print_string ", "; print_primitive ic + | Switch + -> let n = inputu ic in + let orig = currpc ic in + for i = 0 to (n land 0xFFFF) - 1 do + print_string "\n int "; print_int i; print_string " -> "; + print_int(orig + inputs ic); + done; + for i = 0 to (n lsr 16) - 1 do + print_string "\n tag "; print_int i; print_string " -> "; + print_int(orig + inputs ic); + done; + | Closurerec + -> let nfuncs = inputu ic in + let nvars = inputu ic in + let orig = currpc ic in + print_int nvars; + for _i = 0 to nfuncs - 1 do + print_string ", "; + print_int (orig + inputs ic); + done; + | Pubmet + -> let tag = inputs ic in + let _cache = inputu ic in + print_int tag + | Nothing -> () + with Not_found -> print_string " (unknown arguments)" end; print_string "\n"; ;; diff --git a/tools/eqparsetree.ml b/tools/eqparsetree.ml index 4c699e99..ae204bfb 100644 --- a/tools/eqparsetree.ml +++ b/tools/eqparsetree.ml @@ -1,12 +1,15 @@ (**************************************************************************) (* *) -(* OCaml *) +(* OCaml *) (* *) (* Hongbo Zhang (University of Pennsylvania) *) (* *) (* Copyright 2007 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. *) +(* 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. *) (* *) (**************************************************************************) diff --git a/tools/gdb-macros b/tools/gdb-macros new file mode 100644 index 00000000..3c8c33a6 --- /dev/null +++ b/tools/gdb-macros @@ -0,0 +1,321 @@ +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, Jane Street Group, LLC * +#* * +#* Copyright 2015 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. * +#* * +#************************************************************************** + +# A set of macros for low-level debugging of OCaml programs and of the +# OCaml runtime itself (both native and byte-code). + +# This file should be loaded in gdb with [ source gdb-macros ]. +# It defines one command: [caml] +# Usage: +# [caml ] +# If is an OCaml value, this will display it in a low-level +# but legible format, including the header information. + +# To do: a [camlsearch] command to find all (gc-traceable) pointers to +# a given heap block. + +set $camlwordsize = sizeof(char *) + +if $camlwordsize == 8 + set $caml_unalloc_mask = 0xFF00FFFFFF00FFFF + set $caml_unalloc_value = 0xD700D7D7D700D6D7 +else + set $caml_unalloc_mask = 0xFF00FFFF + set $caml_unalloc_value = 0xD700D6D7 +end + +define camlcheckheader + if $arg0 >> 10 <= 0 || $arg0 >> 10 >= 0x1000000000000 + if ($arg0 & $caml_unalloc_mask) == $caml_unalloc_value + set $camlcheckheader_result = 2 + else + if $arg0 == (unsigned long) 0 + set $camlcheckheader_result = 3 + else + set $camlcheckheader_result = 1 + end + end + else + set $camlcheckheader_result = 0 + end +end + +define camlheader + set $hd = * (unsigned long *) ($arg0 - $camlwordsize) + set $tag = $hd & 0xFF + set $color = ($hd >> 8) & 3 + set $size = $hd >> 10 + + camlcheckheader $hd + if $camlcheckheader_result != 0 + if $camlcheckheader_result == 2 + printf "[UNALLOCATED MEMORY]" + else + if $camlcheckheader_result == 3 + printf "[** fragment **] 0x%016lu", $hd + else + printf "[**invalid header**] 0x%016lu", $hd + end + end + set $size = 0 + else + printf "[" + if $color == 0 + printf "white " + end + if $color == 1 + printf "gray " + end + if $color == 2 + printf "blue " + end + if $color == 3 + printf "black " + end + + if $tag < 246 + printf "tag%d ", $tag + end + if $tag == 246 + printf "Lazy " + end + if $tag == 247 + printf "Closure " + end + if $tag == 248 + printf "Object " + end + if $tag == 249 + printf "Infix " + end + if $tag == 250 + printf "Forward " + end + if $tag == 251 + printf "Abstract " + end + if $tag == 252 + printf "String " + end + if $tag == 253 + printf "Double " + end + if $tag == 254 + printf "Double_array " + end + if $tag == 255 + printf "Custom " + end + + printf "%lu]", $size + end +end + +define camlheap + if $arg0 >= caml_young_start && $arg0 < caml_young_end + printf "YOUNG" + set $camlheap_result = 1 + else + set $chunk = caml_heap_start + set $found = 0 + while $chunk != 0 && ! $found + set $chunk_size = * (unsigned long *) ($chunk - 2 * $camlwordsize) + if $arg0 > $chunk && $arg0 <= $chunk + $chunk_size + printf "OLD" + set $found = 1 + end + set $chunk = * (unsigned long *) ($chunk - $camlwordsize) + end + if $found + set $camlheap_result = 1 + else + printf "OUT-OF-HEAP" + set $camlheap_result = 0 + end + end +end + +define camlint + if ($arg0 & $caml_unalloc_mask) == $caml_unalloc_value + printf "UNALLOCATED MEMORY" + else + printf "INT %ld", ($arg0 >> 1) + end + if ($arg0 & 0xFF) == 0xF9 && ($arg0 >> 10) < 0x1000000000000 + printf " [possible infix header]" + end +end + +define camlblock + printf "%#lx: ", $arg0 - $camlwordsize + camlheap $arg0 + printf " " + camlheader $arg0 + set $mysize = $size + set $camlnext = $arg0 + $camlwordsize * ($size + 1) + printf "\n" + + if $tag == 252 + x/s $arg0 + end + if $tag == 253 + x/f $arg0 + end + if $tag == 254 + while $count < $mysize && $count < 10 + if $count + 1 < $size + x/2f $arg0 + $camlwordsize * $count + else + x/f $arg0 + $camlwordsize * $count + end + set $count = $count + 2 + end + if $count < $mysize + printf "... truncated ...\n" + end + end + + if $tag == 249 + printf "... infix header, displaying enclosing block:\n" + set $mybaseaddr = $arg0 - $camlwordsize * $mysize + camlblock $mybaseaddr + # reset $tag, which was clobbered by the recursive call (yuck) + set $tag = 249 + end + + if $tag != 249 && $tag != 252 && $tag != 253 && $tag != 254 + set $isvalues = $tag < 251 + set $count = 0 + while $count < $mysize && $count < 10 + set $adr = $arg0 + $camlwordsize * $count + set $field = * (unsigned long *) $adr + printf "%#lx: [%d] 0x%016lx ", $adr, $count, $field + if ($field & 7) == 0 && $isvalues + camlheap $field + if $camlheap_result + printf " " + camlheader $field + end + end + if ($field & 1) == 1 + camlint $field + end + printf "\n" + set $count = $count + 1 + end + if $count < $mysize + printf "... truncated ...\n" + end + end + printf "next block head: %#lx value: %#lx\n", \ + $arg0 + $camlwordsize * $mysize, $arg0 + $camlwordsize * ($mysize+1) +end + +# displays an OCaml value +define caml + set $camllast = (long) $arg0 + if ($camllast & 1) == 1 + set $camlnext = 0 + camlint $camllast + printf "\n" + end + if ($camllast & 7) == 0 + camlblock $camllast + end + if ($camllast & 7) != 0 && ($camllast & 1) != 1 + set $camlnext = 0 + printf "invalid pointer: %#016lx\n", $camllast + end +end + +# displays the next OCaml value in memory +define camlnext + caml $camlnext +end + +# displays the n-th field of the previously displayed value +define camlfield + set $camlfield_addr = ((long *) $camllast)[$arg0] + caml $camlfield_addr +end + +# displays the list of heap chunks +define camlchunks + set $chunk = * (unsigned long *) &caml_heap_start + while $chunk != 0 + set $chunk_size = * (unsigned long *) ($chunk - 2 * $camlwordsize) + set $chunk_alloc = * (unsigned long *) ($chunk - 3 * $camlwordsize) + printf "chunk: addr = %#lx .. %#lx", $chunk, $chunk + $chunk_size + printf " (size = %#lx; alloc = %#lx)\n", $chunk_size, $chunk_alloc + set $chunk = * (unsigned long *) ($chunk - $camlwordsize) + end +end + +# walk the heap and launch command `camlvisitfun` on each block +# the variables `$hp` `$val` `$hd` `$tag` `$color` and `$size` +# are set before calling `camlvisitfun` +# `camlvisitfun` can set `$camlvisitstop` to stop the iteration + +define camlvisit + set $cvchunk = * (unsigned long *) &caml_heap_start + set $camlvisitstop = 0 + while $cvchunk != 0 && ! $camlvisitstop + set $cvchunk_size = * (unsigned long *) ($cvchunk - 2 * $camlwordsize) + set $cvhp = $cvchunk + while $cvhp < $cvchunk + $cvchunk_size && !$camlvisitstop + set $hp = $cvhp + set $val = $hp + $camlwordsize + set $hd = * (unsigned long *) $hp + set $tag = $hd & 0xFF + set $color = ($hd >> 8) & 3 + set $cvsize = $hd >> 10 + set $size = $cvsize + camlvisitfun + set $cvhp = $cvhp + (($cvsize + 1) * $camlwordsize) + end + set $cvchunk = * (unsigned long *) ($cvchunk - $camlwordsize) + end +end + +define caml_cv_check_fl0 + if $hp == * (unsigned long *) &caml_heap_start + set $flcheck_prev = ((unsigned long) &sentinels + 16) + end + if $color == 2 && $size > 5 + if $val != * (unsigned long *) $flcheck_prev + printf "free-list: missing link %#x -> %#x\n", $flcheck_prev, $val + set $camlvisitstop = 1 + end + set $flcheck_prev = $val + end +end + +define caml_check_fl + set $listsize = $arg0 + set $blueseen = $listsize == 0 + set $val = * (unsigned long *) ((long) &sentinels + 16 + 32 * $listsize) + while $val != 0 + printf "%#x\n", $val + set $hd = * (unsigned long *) ($val - 8) + set $color = ($hd >> 8) & 3 + if $blueseen && $color != 2 + printf "non-blue block at address %#x\n", $val + loop_break + else + set $blueseen = 1 + end + set $val = * (unsigned long *) $val + end +end diff --git a/tools/lexer299.mll b/tools/lexer299.mll index e7709602..6ff82a89 100644 --- a/tools/lexer299.mll +++ b/tools/lexer299.mll @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexer definition *) diff --git a/tools/lexer301.mll b/tools/lexer301.mll index 24bd807f..3823952e 100644 --- a/tools/lexer301.mll +++ b/tools/lexer301.mll @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The lexer definition *) diff --git a/tools/make-opcodes b/tools/make-opcodes index 7cc7c5aa..6dba377a 100644 --- a/tools/make-opcodes +++ b/tools/make-opcodes @@ -1,14 +1,17 @@ -######################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 1995 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 1995 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. * +#* * +#************************************************************************** $1=="enum" {n=0; next; } {for (i = 1; i <= NF; i++) {printf("let op%s = %d\n", $i, n++);}} diff --git a/tools/make-package-macosx b/tools/make-package-macosx index e823156b..1ac36a01 100755 --- a/tools/make-package-macosx +++ b/tools/make-package-macosx @@ -1,16 +1,19 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Moscova, INRIA Rocquencourt # -# # -# Copyright 2003 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Moscova, INRIA Rocquencourt * +#* * +#* Copyright 2003 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. * +#* * +#************************************************************************** cd package-macosx rm -rf ocaml.pkg ocaml-rw.dmg @@ -84,8 +87,9 @@ mkdir -p resources # stop here -> | cat >resources/ReadMe.txt <&2 + exit 0 +fi + +IFS=: +T= +FOUND=0 +FIRST=1 +for i in $PATH +do + if [ $FIRST -eq 1 ] ; then + T="$i" + FIRST=0 + else + if [ $FOUND -eq 0 -a -x $i/link ] && [ "`$i/link --version | head -1 | \ + fgrep "Microsoft (R) Incremental Linker"`" != "" ] ; then + FOUND=1 + T="$i:$T" + PROM=$i + else + T="$T:$i" + fi + fi +done +unset IFS + +if [ $FOUND -eq 0 ] ; then + echo The Microsoft Linker was not found in any of the PATH entries!>&2 + exit 1 +else + echo "$PROM moved to the front of \$PATH">&2 + echo export PATH=\"$T\" +fi diff --git a/tools/objinfo.ml b/tools/objinfo.ml index 37a03b34..30bc353d 100644 --- a/tools/objinfo.ml +++ b/tools/objinfo.ml @@ -1,17 +1,19 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* Mehdi Dogguy, PPS laboratory, University Paris Diderot *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. Modifications Copyright 2010 Mehdi Dogguy, *) -(* used and distributed as part of OCaml by permission from *) -(* the author. This file is distributed under the terms of the *) -(* Q Public License version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* Mehdi Dogguy, PPS laboratory, University Paris Diderot *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* Copyright 2010 Mehdi Dogguy *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (* Dump info on .cmi, .cmo, .cmx, .cma, .cmxa, .cmxs files and on bytecode executables. *) @@ -113,8 +115,19 @@ open Cmx_format let print_cmx_infos (ui, crc) = print_general_infos ui.ui_name crc ui.ui_defines ui.ui_imports_cmi ui.ui_imports_cmx; - printf "Approximation:\n"; - Format.fprintf Format.std_formatter " %a@." Printclambda.approx ui.ui_approx; + begin match ui.ui_export_info with + | Clambda approx -> + printf "Approximation:\n"; + Format.fprintf Format.std_formatter " %a@." Printclambda.approx approx + | 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 + end; let pr_funs _ fns = List.iter (fun arity -> printf " %d" arity) fns in printf "Currying functions:%a\n" pr_funs ui.ui_curry_fun; @@ -199,13 +212,13 @@ let read_dyn_header filename ic = (Filename.quote filename) tempfile) in if rc <> 0 then failwith "cannot read"; - let tc = open_in tempfile in + let tc = Scanf.Scanning.from_file tempfile in try_finally (fun () -> - let ofs = Scanf.fscanf tc "%Ld" (fun x -> x) in + let ofs = Scanf.bscanf tc "%Ld" (fun x -> x) in LargeFile.seek_in ic ofs; Some(input_value ic : dynheader)) - (fun () -> close_in tc)) + (fun () -> Scanf.Scanning.close_in tc)) (fun () -> remove_file tempfile) with Failure _ | Sys_error _ -> None diff --git a/tools/objinfo_helper.c b/tools/objinfo_helper.c index 4a76cff1..125c2c1d 100644 --- a/tools/objinfo_helper.c +++ b/tools/objinfo_helper.c @@ -1,13 +1,16 @@ -/***********************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Mehdi Dogguy, PPS laboratory, University Paris Diderot */ -/* */ -/* Copyright 2010 Mehdi Dogguy. Used and distributed as part of */ -/* OCaml by permission from the author. This file is */ -/* distributed under the terms of the Q Public License version 1.0. */ -/***********************************************************************/ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Mehdi Dogguy, PPS laboratory, University Paris Diderot */ +/* */ +/* Copyright 2010 Mehdi Dogguy */ +/* */ +/* 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/s.h" #include "../byterun/caml/mlvalues.h" @@ -24,11 +27,7 @@ #include #undef PACKAGE -#ifdef __APPLE__ -#define plugin_header_sym "_caml_plugin_header" -#else -#define plugin_header_sym "caml_plugin_header" -#endif +#define plugin_header_sym (symbol_prefix "caml_plugin_header") int main(int argc, char ** argv) { diff --git a/tools/ocaml-instr-graph b/tools/ocaml-instr-graph new file mode 100755 index 00000000..5792da11 --- /dev/null +++ b/tools/ocaml-instr-graph @@ -0,0 +1,116 @@ +#!/bin/bash + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, Jane Street Group, LLC * +#* * +#* Copyright 2015 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. * +#* * +#************************************************************************** + +# Use this script on OCAML_INSTR_FILE files + +default_curves=major,minor,coll,dispatch + +usage () { + echo 'usage: ocaml-instr-graph file [options]' + echo ' options:' + echo " -d names plot the data for names (default: $default_curves)" + echo ' -t title set the graph title' + echo ' -m n clip the values to n (default 1G)' + echo ' -rt n set the range for times to 0..n' + echo ' -rn n set the range for counts to 0..n' + echo ' -from t start at time t' + echo ' -to t stop at time t' + echo ' -help display this help message and exit' +} + +datafile= +curves=, +title= +titleset=false +max=1000000000 +ranget= +rangen= +from=0 +to=1e19 + +while [[ $# > 0 ]]; do + case $1 in + -d) curves=$curves$2,; shift 2;; + -t) title=$2; titleset=true; shift 2;; + -m) max=$2; shift 2;; + -rt) ranget="set yrange [0:$2]"; shift 2;; + -rn) rangen="set y2range [0:$2]"; shift 2;; + -from) from=$2; shift 2;; + -to) to=$2; shift 2;; + -help) usage; exit 0;; + *) datafile=$1; shift 1;; + esac +done + +if [[ "$curves" = , ]]; then + curves=,$default_curves, +fi + +if ! $titleset; then + title=$datafile +fi + +tmpfile=/tmp/ocaml-instr-graph.$$ + +rm -f $tmpfile-* + +awk -v curves="$curves" -v clip=$max -v tmpfile="$tmpfile" -v from=$from \ + -v to=$to ' + function output (filename){ + time = ($2 - starttime) / 1e9; + if (time < from || time >= to) return; + if (index(curves, "," filename ",") != 0){ + gsub (/\//,":",filename); + if (filename ~ /#/){ + point = $3; + }else{ + point = ($3 - $2) / 1000; + } + if (point > clip) point = clip; + printf ("%.6f %.3f\n", time, point) >> tmpfile "-" filename; + } + } + BEGIN {starttime = 9e18;} + $1 != "@@" { next; } + $2 < starttime { starttime = $2 } + { output($4); } +' $datafile + +( echo set title \"$title\" + echo set key left top + echo set ytics nomirror + echo 'set format y "%gus"' + echo "$ranget" + echo "$rangen" + echo set y2tics nomirror + echo 'set format x "%gs"' + printf "plot " + for curve in ${curves//,/ }; do + f=$tmpfile-${curve//\//:} + if [ -f $f ]; then + case $f in + *#) printf "\"%s\" using 1:2 axes x1y2 title '%s', " "$f" \ + "$curve" + ;; + *) printf "\"%s\" using 1:2 title '%s', " "$f" "$curve";; + esac + fi + done + printf "\n" +) | gnuplot -p + +rm -f $tmpfile-* diff --git a/tools/ocaml-instr-report b/tools/ocaml-instr-report new file mode 100755 index 00000000..bac4f6ba --- /dev/null +++ b/tools/ocaml-instr-report @@ -0,0 +1,162 @@ +#!/bin/awk -f + +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, Jane Street Group, LLC * +#* * +#* Copyright 2014 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. * +#* * +#************************************************************************** + +# usage: +# ocaml-instr-report { file ... } +# generate a report from the data files (or stdin if no file is given) + +function short(n, kind, i, r){ + for (i = 0; i < 5; i++){ + if (n < 1000) break; + n /= 1000; + } + r = sprintf ("%f", n); + if (index(r, ".") == 3){ + r = substr(r, 1, 2); + }else{ + r = substr(r, 1, 3); + } + return sprintf("%s%s", r, units[kind,i]); +} + +function add(limit){ + lim[nscales] = limit; + scale["t",nscales] = short(limit, "t"); + scale["n",nscales] = short(limit, "n"); + ++ nscales; +} + +# kind is "t" (for timer) or "n" (for number) +# events are simply a special kind of timer + +BEGIN { + units["t",0] = "ns"; + units["t",1] = "us"; + units["t",2] = "ms"; + units["t",3] = "s"; + units["t",4] = "ks"; + units["t",5] = "Ms"; + + units["n",0] = ""; + units["n",1] = "k"; + units["n",2] = "M"; + units["n",3] = "G"; + units["n",4] = "T"; + units["n",5] = "P"; + + nscales=0; + add(0); + for (mul = 100; mul < 10000000000; mul *= 10){ + add(mul); + add(2.2 * mul); + add(4.7 * mul); + } +} + +function store(value, tag) { + ++ total[tag]; + for (i = 0; i < nscales; i++){ + if (value <= lim[i]){ + ++ bin[tag, lim[i]]; + val[tag, lim[i]] = value; + return; + } + } + ++ bin[tag, "off-scale"]; + val[tag, "off-scale"] = value; +} + +$1 == "@@" && $4 ~ /@/ { total[$4] += $3; } + +$1 == "@@" && $4 ~ /#/ { store($3, $4); } + +$1 == "@@" { store($3 - $2, $4); } + +function display(n, val, kind, i) { + graph_width = 35; + + if (n > 0){ + for (i = 0; i < log (n) / log (2); i++){ + printf("#"); + } + if (n == 1){ + printf(" %-6d", n); + printf ("%-*s", graph_width - 7 - i, + sprintf("(%s)", short(val, kind))); + }else{ + printf(" %-*d", graph_width - 1 - i, n); + } + }else{ + printf("%*s", graph_width, ""); + } +} + +END { + n = asorti(total,tags); + total_alloc = 0; + for (i = 1; i <= n; i++){ + t = tags[i]; + if (t ~ /^alloc/) total_alloc += total[t]; + } + for (i = 1; i <= n; i++){ + t = tags[i]; + if (t ~ /#/){ + kind = "n"; # number + }else if (t ~ /@/){ + kind = "e"; # event + }else{ + kind = "t"; # timer + } + if (kind == "e"){ + printf ("==== %-12s:%9d", t, total[t]); + if (t ~ /^alloc/){ + cumul += total[t] / total_alloc; + printf(" (%6.2f%%)", cumul * 100); + } + printf ("\n"); + continue; + }else{ + printf ("==== %s: %d\n", t, total[t]); + } + num = bin[t,0]; + found = num; + if (num == total[t] && kind == "t"){ + /* nothing */ + }else if (num > 0){ + printf (" 0: "); + display(bin[t,0], val[t, 0], kind); + printf ("%6.2f%%\n", found * 100 / total[t]); + } + for (j = 1; j < nscales; j++){ + if (found == total[t]) break; + num = bin [t, lim[j]]; + found += num; + if (found > 0){ + printf ("%5s..%-5s: ", scale[kind,j-1], scale[kind,j]); + display(num, val[t, lim[j]], kind); + printf ("%6.2f%%\n", found * 100 / total[t]); + } + } + num = bin[t, "off-scale"]; + if (num != 0){ + printf (" off scale : "); + display(bin[t, "off-scale"], val[t, "off-scale"]); + printf ("\n"); + } + printf ("====\n"); + } +} diff --git a/tools/ocaml-objcopy-macosx b/tools/ocaml-objcopy-macosx index e3fb6cbc..3b8dcc2a 100755 --- a/tools/ocaml-objcopy-macosx +++ b/tools/ocaml-objcopy-macosx @@ -1,16 +1,19 @@ #!/bin/bash -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2005 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. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 2005 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. * +#* * +#************************************************************************** TMP="${TMPDIR=/tmp}" TEMP="${TMP}"/ocaml-objcopy-$$.o diff --git a/tools/ocaml299to3.ml b/tools/ocaml299to3.ml index a8eab92a..f0352c19 100644 --- a/tools/ocaml299to3.ml +++ b/tools/ocaml299to3.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jacques Garrigue, Kyoto University RIMS *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jacques Garrigue, Kyoto University RIMS *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Lexer299 diff --git a/tools/ocamlcp.ml b/tools/ocamlcp.ml index 26ced6c5..5508b179 100644 --- a/tools/ocamlcp.ml +++ b/tools/ocamlcp.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1998 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1998 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. *) +(* *) +(**************************************************************************) open Printf @@ -62,11 +65,15 @@ module Options = Main_args.Make_bytecomp_options (struct let _intf s = with_intf := true; option_with_arg "-intf" s let _intf_suffix s = option_with_arg "-intf-suffix" s let _keep_docs = option "-keep-docs" + let _no_keep_docs = option "-no-keep-docs" let _keep_locs = option "-keep-locs" + let _no_keep_locs = option "-no-keep-locs" let _labels = option "-labels" let _linkall = option "-linkall" let _make_runtime = option "-make-runtime" + let _alias_deps = option "-alias-deps" let _no_alias_deps = option "-no-alias-deps" + let _app_funct = option "-app-funct" let _no_app_funct = option "-no-app-funct" let _no_check_prims = option "-no-check-prims" let _noassert = option "-noassert" @@ -74,6 +81,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _noautolink = option "-noautolink" let _nostdlib = option "-nostdlib" let _o s = option_with_arg "-o" s + let _opaque = option "-opaque" let _open s = option_with_arg "-open" s let _output_obj = option "-output-obj" let _output_complete_obj = option "-output-complete-obj" @@ -81,12 +89,16 @@ module Options = Main_args.Make_bytecomp_options (struct let _pp _s = incompatible "-pp" let _ppx _s = incompatible "-ppx" let _principal = option "-principal" + let _no_principal = option "-no-principal" let _rectypes = option "-rectypes" + let _no_rectypes = option "-no-rectypes" let _runtime_variant s = option_with_arg "-runtime-variant" s let _safe_string = option "-safe-string" let _short_paths = option "-short-paths" let _strict_sequence = option "-strict-sequence" + let _no_strict_sequence = option "-no-strict-sequence" let _strict_formats = option "-strict-formats" + let _no_strict_formats = option "-no-strict-formats" let _thread () = option "-thread" () let _vmthread () = option "-vmthread" () let _unsafe = option "-unsafe" @@ -100,6 +112,7 @@ module Options = Main_args.Make_bytecomp_options (struct let _w = option_with_arg "-w" let _warn_error = option_with_arg "-warn-error" let _warn_help = option "-warn-help" + let _color s = option_with_arg "-color" s let _where = option "-where" let _nopervasives = option "-nopervasives" let _dsource = option "-dsource" @@ -107,7 +120,9 @@ module Options = Main_args.Make_bytecomp_options (struct let _dtypedtree = option "-dtypedtree" let _drawlambda = option "-drawlambda" let _dlambda = option "-dlambda" + let _dflambda = option "-dflambda" let _dinstr = option "-dinstr" + let _dtimings = option "-dtimings" let anonymous = process_file end);; diff --git a/tools/ocamldep.ml b/tools/ocamldep.ml index db0695c9..6e102e9b 100644 --- a/tools/ocamldep.ml +++ b/tools/ocamldep.ml @@ -1,17 +1,21 @@ -(***********************************************************************) -(* *) -(* 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 Q Public License version 1.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. *) +(* *) +(**************************************************************************) open Compenv open Parsetree +module StringMap = Depend.StringMap let ppf = Format.err_formatter (* Print the dependencies *) @@ -28,6 +32,10 @@ let sort_files = ref false let all_dependencies = ref false let one_line = ref false let files = ref [] +let allow_approximation = ref false +let map_files = ref [] +let module_map = ref StringMap.empty +let debug = ref false (* Fix path to use '/' as directory separator instead of '\'. Only under Windows. *) @@ -39,7 +47,6 @@ let fix_slash s = (* Since we reinitialize load_path after reading OCAMLCOMP, we must use a cache instead of calling Sys.readdir too often. *) -module StringMap = Map.Make(String) let dirs = ref StringMap.empty let readdir dir = try @@ -78,7 +85,7 @@ let add_to_synonym_list synonyms suffix = (* Find file 'name' (capitalized) in search path *) let find_file name = - let uname = String.uncapitalize name in + let uname = String.uncapitalize_ascii name in let rec find_in_array a pos = if pos >= Array.length a then None else begin let s = a.(pos) in @@ -104,6 +111,7 @@ let find_dependency target_kind modname (byt_deps, opt_deps) = let filename = find_file_in_list candidates in let basename = Filename.chop_extension filename in let cmi_file = basename ^ ".cmi" in + let cmx_file = basename ^ ".cmx" in let ml_exists = List.exists (fun ext -> Sys.file_exists (basename ^ ext)) !ml_synonyms in let new_opt_dep = @@ -111,12 +119,12 @@ let find_dependency target_kind modname (byt_deps, opt_deps) = match target_kind with | MLI -> [ cmi_file ] | ML -> - cmi_file :: (if ml_exists then [ basename ^ ".cmx"] else []) + cmi_file :: (if ml_exists then [ cmx_file ] else []) else (* this is a make-specific hack that makes .cmx to be a 'proxy' target that would force the dependency on .cmi via transitivity *) if ml_exists - then [ basename ^ ".cmx" ] + then [ cmx_file ] else [ cmi_file ] in ( cmi_file :: byt_deps, new_opt_dep @ opt_deps) @@ -126,20 +134,22 @@ let find_dependency target_kind modname (byt_deps, opt_deps) = let candidates = List.map ((^) modname) !ml_synonyms in let filename = find_file_in_list candidates in let basename = Filename.chop_extension filename in + let cmi_file = basename ^ ".cmi" in + let cmx_file = basename ^ ".cmx" in let bytenames = if !all_dependencies then match target_kind with - | MLI -> [basename ^ ".cmi"] - | ML -> [basename ^ ".cmi";] + | MLI -> [ cmi_file ] + | ML -> [ cmi_file ] else (* again, make-specific hack *) [basename ^ (if !native_only then ".cmx" else ".cmo")] in let optnames = if !all_dependencies then match target_kind with - | MLI -> [basename ^ ".cmi"] - | ML -> [basename ^ ".cmi"; basename ^ ".cmx"] - else [ basename ^ ".cmx" ] + | MLI -> [ cmi_file ] + | ML -> [ cmi_file; cmx_file ] + else [ cmx_file ] in (bytenames @ byt_deps, optnames @ opt_deps) with Not_found -> @@ -192,11 +202,15 @@ let print_raw_dependencies source_file deps = print_filename source_file; print_string depends_on; Depend.StringSet.iter (fun dep -> + (* filter out "*predef*" *) if (String.length dep > 0) - && (match dep.[0] with 'A'..'Z' -> true | _ -> false) then begin - print_char ' '; - print_string dep - end) + && (match dep.[0] with + | 'A'..'Z' | '\128'..'\255' -> true + | _ -> false) then + begin + print_char ' '; + print_string dep + end) deps; print_char '\n' @@ -217,29 +231,83 @@ let report_err exn = let tool_name = "ocamldep" -let read_parse_and_extract parse_function extract_function magic source_file = +let rec lexical_approximation lexbuf = + (* Approximation when a file can't be parsed. + Heuristic: + - first component of any path starting with an uppercase character is a + dependency. + - always skip the token after a dot, unless dot is preceded by a + lower-case identifier + - always skip the token after a backquote + *) + try + let rec process after_lident lexbuf = + match Lexer.token lexbuf with + | Parser.UIDENT name -> + Depend.free_structure_names := + Depend.StringSet.add name !Depend.free_structure_names; + process false lexbuf + | Parser.LIDENT _ -> process true lexbuf + | Parser.DOT when after_lident -> process false lexbuf + | Parser.DOT | Parser.BACKQUOTE -> skip_one lexbuf + | Parser.EOF -> () + | _ -> process false lexbuf + and skip_one lexbuf = + match Lexer.token lexbuf with + | Parser.DOT | Parser.BACKQUOTE -> skip_one lexbuf + | Parser.EOF -> () + | _ -> process false lexbuf + + in + process false lexbuf + with Lexer.Error _ -> lexical_approximation lexbuf + +let read_and_approximate inputfile = + error_occurred := false; + Depend.free_structure_names := Depend.StringSet.empty; + let ic = open_in_bin inputfile in + try + seek_in ic 0; + Location.input_name := inputfile; + let lexbuf = Lexing.from_channel ic in + Location.init lexbuf inputfile; + lexical_approximation lexbuf; + close_in ic; + !Depend.free_structure_names + with exn -> + close_in ic; + report_err exn; + !Depend.free_structure_names + +let read_parse_and_extract parse_function extract_function def magic + source_file = Depend.free_structure_names := Depend.StringSet.empty; try let input_file = Pparse.preprocess source_file in begin try let ast = Pparse.file ~tool_name Format.err_formatter - input_file parse_function magic + input_file parse_function magic in - let bound_vars = Depend.StringSet.empty in - List.iter (fun modname -> - Depend.open_module bound_vars (Longident.Lident modname) - ) !Clflags.open_modules; - extract_function bound_vars ast; + let bound_vars = + List.fold_left + (fun bv modname -> + Depend.open_module bv (Longident.Lident modname)) + !module_map !Clflags.open_modules + in + let r = extract_function bound_vars ast in Pparse.remove_preprocessed input_file; - !Depend.free_structure_names + (!Depend.free_structure_names, r) with x -> Pparse.remove_preprocessed input_file; raise x end - with x -> + with x -> begin report_err x; - Depend.StringSet.empty + if not !allow_approximation + then (Depend.StringSet.empty, def) + else (read_and_approximate source_file, def) + end let ml_file_dependencies source_file = let parse_use_file_as_impl lexbuf = @@ -250,8 +318,8 @@ let ml_file_dependencies source_file = in List.flatten (List.map f (Parse.use_file lexbuf)) in - let extracted_deps = - read_parse_and_extract parse_use_file_as_impl Depend.add_implementation + let (extracted_deps, ()) = + read_parse_and_extract parse_use_file_as_impl Depend.add_implementation () Config.ast_impl_magic_number source_file in if !sort_files then @@ -278,13 +346,14 @@ let ml_file_dependencies source_file = let (byt_deps, native_deps) = Depend.StringSet.fold (find_dependency ML) extracted_deps init_deps in - print_dependencies (byte_targets @ extra_targets) byt_deps; + if not !native_only then + print_dependencies (byte_targets @ extra_targets) byt_deps; print_dependencies (native_targets @ extra_targets) native_deps; end let mli_file_dependencies source_file = - let extracted_deps = - read_parse_and_extract Parse.interface Depend.add_signature + let (extracted_deps, ()) = + read_parse_and_extract Parse.interface Depend.add_signature () Config.ast_intf_magic_number source_file in if !sort_files then @@ -300,8 +369,8 @@ let mli_file_dependencies source_file = print_dependencies [basename ^ ".cmi"] byt_deps end -let file_dependencies_as kind source_file = - Compenv.readenv ppf Before_compile; +let process_file_as process_fun def source_file = + Compenv.readenv ppf (Before_compile source_file); load_path := []; List.iter add_to_load_path ( (!Compenv.last_include_dirs @ @@ -310,19 +379,25 @@ let file_dependencies_as kind source_file = )); Location.input_name := source_file; try - if Sys.file_exists source_file then begin - match kind with - | ML -> ml_file_dependencies source_file - | MLI -> mli_file_dependencies source_file - end - with x -> report_err x + if Sys.file_exists source_file then process_fun source_file else def + with x -> report_err x; def -let file_dependencies source_file = +let process_file source_file ~ml_file ~mli_file ~def = if List.exists (Filename.check_suffix source_file) !ml_synonyms then - file_dependencies_as ML source_file + process_file_as ml_file def source_file else if List.exists (Filename.check_suffix source_file) !mli_synonyms then - file_dependencies_as MLI source_file - else () + process_file_as mli_file def source_file + else def + +let file_dependencies source_file = + process_file source_file ~def:() + ~ml_file:ml_file_dependencies + ~mli_file:mli_file_dependencies + +let file_dependencies_as kind = + match kind with + | ML -> process_file_as ml_file_dependencies () + | MLI -> process_file_as mli_file_dependencies () let sort_files_by_dependencies files = let h = Hashtbl.create 31 in @@ -331,7 +406,7 @@ let sort_files_by_dependencies files = (* Init Hashtbl with all defined modules *) let files = List.map (fun (file, file_kind, deps) -> let modname = - String.capitalize (Filename.chop_extension (Filename.basename file)) + String.capitalize_ascii (Filename.chop_extension (Filename.basename file)) in let key = (modname, file_kind) in let new_deps = ref [] in @@ -385,18 +460,70 @@ let sort_files_by_dependencies files = if !worklist <> [] then begin Format.fprintf Format.err_formatter "@[Warning: cycle in dependencies. End of list is not sorted.@]@."; - Hashtbl.iter (fun _ (file, deps) -> + let sorted_deps = + let li = ref [] in + Hashtbl.iter (fun _ file_deps -> li := file_deps :: !li) h; + List.sort (fun (file1, _) (file2, _) -> String.compare file1 file2) !li + in + List.iter (fun (file, deps) -> Format.fprintf Format.err_formatter "\t@[%s: " file; List.iter (fun (modname, kind) -> Format.fprintf Format.err_formatter "%s.%s " modname (if kind=ML then "ml" else "mli"); ) !deps; Format.fprintf Format.err_formatter "@]@."; - Printf.printf "%s " file) h; + Printf.printf "%s " file) sorted_deps; end; Printf.printf "\n%!"; () +(* Map *) + +let rec dump_map s0 ppf m = + let open Depend in + StringMap.iter + (fun key (Node(s1,m')) -> + let s = StringSet.diff s1 s0 in + if StringSet.is_empty s then + Format.fprintf ppf "@ @[module %s : sig%a@;<1 -2>end@]" + key (dump_map (StringSet.union s1 s0)) m' + else + Format.fprintf ppf "@ module %s = %s" key (StringSet.choose s)) + m + +let process_ml_map = + read_parse_and_extract Parse.implementation Depend.add_implementation_binding + StringMap.empty Config.ast_impl_magic_number + +let process_mli_map = + read_parse_and_extract Parse.interface Depend.add_signature_binding + StringMap.empty Config.ast_intf_magic_number + +let parse_map fname = + map_files := fname :: !map_files ; + let old_transp = !Clflags.transparent_modules in + Clflags.transparent_modules := true; + let (deps, m) = + process_file fname ~def:(Depend.StringSet.empty, StringMap.empty) + ~ml_file:process_ml_map + ~mli_file:process_mli_map + in + Clflags.transparent_modules := old_transp; + let modname = + String.capitalize_ascii + (Filename.basename (Filename.chop_extension fname)) in + if StringMap.is_empty m then + report_err (Failure (fname ^ " : empty map file or parse error")); + let mm = Depend.make_node m in + if !debug then begin + Format.printf "@[%s:%t%a@]@." fname + (fun ppf -> Depend.StringSet.iter (Format.fprintf ppf " %s") deps) + (dump_map deps) (StringMap.add modname mm StringMap.empty) + end; + let mm = Depend.(weaken_map (StringSet.singleton modname) mm) in + module_map := StringMap.add modname mm !module_map +;; + (* Entry point *) @@ -421,12 +548,21 @@ let _ = " Show absolute filenames in error messages"; "-all", Arg.Set all_dependencies, " Generate dependencies on all files"; + "-allow-approx", Arg.Set allow_approximation, + " Fallback to a lexer-based approximation on unparseable files"; + "-as-map", Arg.Set Clflags.transparent_modules, + " Omit delayed dependencies for module aliases (-no-alias-deps -w -49)"; + (* "compiler uses -no-alias-deps, and no module is coerced"; *) + "-debug-map", Arg.Set debug, + " Dump the delayed dependency map for each map file"; "-I", Arg.String (add_to_list Clflags.include_dirs), " Add to the list of include directories"; "-impl", Arg.String (file_dependencies_as ML), " Process as a .ml file"; "-intf", Arg.String (file_dependencies_as MLI), " Process as a .mli file"; + "-map", Arg.String parse_map, + " Read and propagate delayed dependencies to following files"; "-ml-synonym", Arg.String(add_to_synonym_list ml_synonyms), " Consider as a synonym of the .ml extension"; "-mli-synonym", Arg.String(add_to_synonym_list mli_synonyms), diff --git a/tools/ocamlmklib.ml b/tools/ocamlmklib.ml index 23a273ec..391bad54 100644 --- a/tools/ocamlmklib.ml +++ b/tools/ocamlmklib.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open Printf open Ocamlmklibconfig @@ -20,15 +23,15 @@ let compiler_path name = let bytecode_objs = ref [] (* .cmo,.cma,.ml,.mli files to pass to ocamlc *) and native_objs = ref [] (* .cmx,.cmxa,.ml,.mli files to pass to ocamlopt *) -and c_objs = ref [] (* .o, .a, .obj, .lib, .dll files to pass - to mksharedlib and ar *) +and c_objs = ref [] (* .o, .a, .obj, .lib, .dll, .dylib, .so files to + pass to mksharedlib and ar *) and caml_libs = ref [] (* -cclib to pass to ocamlc, ocamlopt *) and caml_opts = ref [] (* -ccopt to pass to ocamlc, ocamlopt *) and dynlink = ref supports_shared_libraries and failsafe = ref false (* whether to fall back on static build only *) and c_libs = ref [] (* libs to pass to mksharedlib and ocamlc -cclib *) -and c_Lopts = ref [] (* options to pass to mksharedlib and ocamlc -cclib *) -and c_opts = ref [] (* options to pass to mksharedlib and ocamlc -ccopt *) +and c_Lopts = ref [] (* options to pass to mksharedlib and ocamlc -cclib *) +and c_opts = ref [] (* options to pass to mksharedlib and ocamlc -ccopt *) and ld_opts = ref [] (* options to pass only to the linker *) and ocamlc = ref (compiler_path "ocamlc") and ocamlc_opts = ref [] (* options to pass only to ocamlc *) @@ -75,7 +78,9 @@ let parse_arguments argv = else if ends_with s ".ml" || ends_with s ".mli" then (bytecode_objs := s :: !bytecode_objs; native_objs := s :: !native_objs) - else if List.exists (ends_with s) [".o"; ".a"; ".obj"; ".lib"; ".dll"] then + else if List.exists (ends_with s) + [".o"; ".a"; ".obj"; ".lib"; ".dll"; ".dylib"; ".so"] + then c_objs := s :: !c_objs else if s = "-cclib" then caml_libs := next_arg () :: "-cclib" :: !caml_libs @@ -153,7 +158,7 @@ let parse_arguments argv = let usage = "\ Usage: ocamlmklib [options] <.cmo|.cma|.cmx|.cmxa|.ml|.mli|.o|.a|.obj|.lib|\ - .dll files>\ + .dll|.dylib files>\ \nOptions are:\ \n -cclib C library passed to ocamlc -a or ocamlopt -a only\ \n -ccopt C option passed to ocamlc -a or ocamlopt -a only\ @@ -242,9 +247,9 @@ let build_libs () = if !dynlink then begin let retcode = command (Printf.sprintf "%s %s -o %s %s %s %s %s %s" - mkdll + Config.mkdll (if !debug then "-g" else "") - (prepostfix "dll" !output_c ext_dll) + (prepostfix "dll" !output_c Config.ext_dll) (String.concat " " !c_objs) (String.concat " " !c_opts) (String.concat " " !ld_opts) @@ -254,14 +259,15 @@ let build_libs () = in if retcode <> 0 then if !failsafe then dynlink := false else exit 2 end; - safe_remove (prepostfix "lib" !output_c ext_lib); + safe_remove (prepostfix "lib" !output_c Config.ext_lib); scommand - (mklib (prepostfix "lib" !output_c ext_lib) + (mklib (prepostfix "lib" !output_c Config.ext_lib) (String.concat " " !c_objs) ""); end; if !bytecode_objs <> [] then scommand - (sprintf "%s -a %s %s %s -o %s.cma %s %s -dllib -l%s -cclib -l%s %s %s %s %s" + (sprintf "%s -a %s %s %s -o %s.cma %s %s -dllib -l%s -cclib -l%s \ + %s %s %s %s" (transl_path !ocamlc) (if !debug then "-g" else "") (if !dynlink then "" else "-custom") diff --git a/tools/ocamlmktop.ml b/tools/ocamlmktop.ml index 06288d74..30b9d50b 100644 --- a/tools/ocamlmktop.ml +++ b/tools/ocamlmktop.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) let _ = let args = Ccomp.quote_files (List.tl (Array.to_list Sys.argv)) in diff --git a/tools/ocamlmktop.tpl b/tools/ocamlmktop.tpl index 6d7d68b4..f9d9fae1 100644 --- a/tools/ocamlmktop.tpl +++ b/tools/ocamlmktop.tpl @@ -1,15 +1,18 @@ #!/bin/sh -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Para, 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 Q Public License version 1.0. # -# # -######################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Damien Doligez, projet Para, 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. * +#* * +#************************************************************************** exec %%BINDIR%%/ocamlc -I +compiler-libs -linkall ocamlcommon.cma \ ocamlbytecomp.cma ocamltoplevel.cma "$@" topstart.cmo diff --git a/tools/ocamloptp.ml b/tools/ocamloptp.ml index fd15fe59..b96d2834 100644 --- a/tools/ocamloptp.ml +++ b/tools/ocamloptp.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) open Printf @@ -23,6 +26,9 @@ let option_with_arg opt arg = let option_with_int opt arg = compargs := (string_of_int arg) :: opt :: !compargs ;; +let option_with_float opt arg = + compargs := (string_of_float arg) :: opt :: !compargs +;; let make_archive = ref false;; let with_impl = ref false;; @@ -51,6 +57,7 @@ module Options = Main_args.Make_optcomp_options (struct let _cc s = option_with_arg "-cc" s let _cclib s = option_with_arg "-cclib" s let _ccopt s = option_with_arg "-ccopt" s + let _clambda_checks = option "-clambda-checks" let _compact = option "-compact" let _config = option "-config" let _for_pack s = option_with_arg "-for-pack" s @@ -58,14 +65,32 @@ module Options = Main_args.Make_optcomp_options (struct let _i = option "-i" let _I s = option_with_arg "-I" s let _impl s = with_impl := true; option_with_arg "-impl" s - let _inline n = option_with_int "-inline" n + let _inline s = option_with_arg "-inline" s + let _inline_toplevel n = option_with_arg "-inline-toplevel" n + let _inlining_report = option "-inlining-report" + let _dump_pass = option_with_arg "-dump-pass" + let _inline_max_depth n = option_with_arg "-inline-max-depth" n + let _rounds n = option_with_int "-rounds" n + let _inline_max_unroll n = option_with_arg "-unroll" n + let _inline_call_cost n = option_with_arg "-inline-call-cost" n + let _inline_alloc_cost n = option_with_arg "-inline-alloc-cost" n + let _inline_prim_cost n = option_with_arg "-inline-prim-cost" n + let _inline_branch_cost n = option_with_arg "-inline-branch-cost" n + let _inline_indirect_cost n = option_with_arg "-inline-indirect-cost" n + let _inline_lifting_benefit n = option_with_arg "-inline-lifting-benefit" n + let _inline_branch_factor n = option_with_arg "-inline-branch-factor" n + let _classic_inlining = option "-Oclassic" let _intf s = with_intf := true; option_with_arg "-intf" s let _intf_suffix s = option_with_arg "-intf-suffix" s let _keep_docs = option "-keep-docs" + let _no_keep_docs = option "-no-keep-docs" let _keep_locs = option "-keep-locs" + let _no_keep_locs = option "-no-keep-locs" let _labels = option "-labels" let _linkall = option "-linkall" + let _alias_deps = option "-alias-deps" let _no_alias_deps = option "-no-alias-deps" + let _app_funct = option "-app-funct" let _no_app_funct = option "-no-app-funct" let _no_float_const_prop = option "-no-float-const-prop" let _noassert = option "-noassert" @@ -73,7 +98,11 @@ module Options = Main_args.Make_optcomp_options (struct let _nodynlink = option "-nodynlink" let _nolabels = option "-nolabels" let _nostdlib = option "-nostdlib" + let _no_unbox_free_vars_of_closures = option "-no-unbox-free-vars-of-closures" + let _no_unbox_specialised_args = option "-no-unbox-specialised-args" let _o s = option_with_arg "-o" s + let _o2 = option "-O2" + let _o3 = option "-O3" let _open s = option_with_arg "-open" s let _output_obj = option "-output-obj" let _output_complete_obj = option "-output-complete-obj" @@ -82,15 +111,22 @@ module Options = Main_args.Make_optcomp_options (struct let _pp _s = incompatible "-pp" let _ppx _s = incompatible "-ppx" let _principal = option "-principal" + let _no_principal = option "-no-principal" let _rectypes = option "-rectypes" + let _no_rectypes = option "-no-rectypes" + let _remove_unused_arguments = option "-remove-unused-arguments" let _runtime_variant s = option_with_arg "-runtime-variant" s let _S = option "-S" let _safe_string = option "-safe-string" let _short_paths = option "-short-paths" let _strict_sequence = option "-strict-sequence" + let _no_strict_sequence = option "-no-strict-sequence" let _strict_formats = option "-strict-formats" + let _no_strict_formats = option "-no-strict-formats" let _shared = option "-shared" let _thread = option "-thread" + let _unbox_closures = option "-unbox-closures" + let _unbox_closures_factor = option_with_int "-unbox-closures" let _unsafe = option "-unsafe" let _unsafe_string = option "-unsafe-string" let _v = option "-v" @@ -100,6 +136,7 @@ module Options = Main_args.Make_optcomp_options (struct let _w = option_with_arg "-w" let _warn_error = option_with_arg "-warn-error" let _warn_help = option "-warn-help" + let _color s = option_with_arg "-color" s let _where = option "-where" let _nopervasives = option "-nopervasives" @@ -108,7 +145,13 @@ module Options = Main_args.Make_optcomp_options (struct let _dtypedtree = option "-dtypedtree" let _drawlambda = option "-drawlambda" let _dlambda = option "-dlambda" + let _drawclambda = option "-drawclambda" let _dclambda = option "-dclambda" + let _drawflambda = option "-drawflambda" + let _dflambda = option "-dflambda" + let _dflambda_no_invariants = option "-dflambda-no-invariants" + let _dflambda_let stamp = option_with_int "-dflambda-let" stamp + let _dflambda_verbose = option "-dflambda-verbose" let _dcmm = option "-dcmm" let _dsel = option "-dsel" let _dcombine = option "-dcombine" @@ -123,6 +166,7 @@ module Options = Main_args.Make_optcomp_options (struct let _dscheduling = option "-dscheduling" let _dlinear = option "-dlinear" let _dstartup = option "-dstartup" + let _dtimings = option "-dtimings" let _opaque = option "-opaque" let anonymous = process_file diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml index dde248cd..68e7d9b0 100644 --- a/tools/ocamlprof.ml +++ b/tools/ocamlprof.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *) -(* Ported to Caml Special Light by John Malecki *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *) +(* Ported to Caml Special Light by John Malecki *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Printf @@ -294,6 +297,7 @@ and rw_exp iflag sexp = | Pexp_open (_ovf, _, e) -> rewrite_exp iflag e | Pexp_pack (smod) -> rewrite_mod iflag smod | Pexp_extension _ -> () + | Pexp_unreachable -> () and rewrite_ifbody iflag ghost sifbody = if !instr_if && not ghost then diff --git a/tools/ocamlsize b/tools/ocamlsize index 7b419ceb..84798ce1 100755 --- a/tools/ocamlsize +++ b/tools/ocamlsize @@ -1,21 +1,24 @@ #!/usr/bin/perl -####################################################################### -# # -# OCaml # -# # -# Xavier Leroy, projet Cristal, INRIA Rocquencourt # -# # -# Copyright 2002 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. # -# # -####################################################################### +#************************************************************************** +#* * +#* OCaml * +#* * +#* Xavier Leroy, projet Cristal, INRIA Rocquencourt * +#* * +#* Copyright 2002 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. * +#* * +#************************************************************************** foreach $f (@ARGV) { open(FILE, $f) || die("Cannot open $f"); seek(FILE, -16, 2); - $num_sections = do read_int(); + $num_sections = &read_int(); read(FILE, $magic, 12); seek(FILE, -16 - 8 * $num_sections, 2); @secname = (); @@ -24,13 +27,13 @@ foreach $f (@ARGV) { for ($i = 0; $i < $num_sections; $i++) { read(FILE, $sec, 4); $secname[$i] = $sec; - $seclength[$i] = do read_int(); + $seclength[$i] = &read_int(); $length{$sec} = $seclength[$i]; } print $f, ":\n" if ($#ARGV > 0); $path = $length{'RNTM'} > 0 ? - do read_section('RNTM') : + &read_section('RNTM') : "(default runtime)\n"; printf ("\tcode: %-7d data: %-7d symbols: %-7d debug: %-7d\n", $length{'CODE'}, $length{'DATA'}, diff --git a/tools/primreq.ml b/tools/primreq.ml index aea932f8..fc7dcf22 100644 --- a/tools/primreq.ml +++ b/tools/primreq.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* 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 Q Public License version 1.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. *) +(* *) +(**************************************************************************) (* Determine the set of C primitives required by the given .cmo and .cma files *) diff --git a/tools/profiling.ml b/tools/profiling.ml index 49a84108..d2eee4df 100644 --- a/tools/profiling.ml +++ b/tools/profiling.ml @@ -1,16 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *) -(* Ported to Caml Special Light by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *) +(* Ported to Caml Special Light by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Run-time library for profiled programs *) diff --git a/tools/profiling.mli b/tools/profiling.mli index baedc241..9d97a4a5 100644 --- a/tools/profiling.mli +++ b/tools/profiling.mli @@ -1,16 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *) -(* Ported to OCaml by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the GNU Library General Public License, with *) -(* the special exception on linking described in file ../LICENSE. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez and Francois Rouaix, INRIA Rocquencourt *) +(* Ported to OCaml by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Run-time library for profiled programs *) diff --git a/tools/read_cmt.ml b/tools/read_cmt.ml index eacba02a..ad3c50ad 100644 --- a/tools/read_cmt.ml +++ b/tools/read_cmt.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) let gen_annot = ref false let gen_ml = ref false diff --git a/tools/scrapelabels.ml b/tools/scrapelabels.ml index 39279320..018bc398 100644 --- a/tools/scrapelabels.ml +++ b/tools/scrapelabels.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jacques Garrigue, Kyoto University RIMS *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jacques Garrigue, Kyoto University RIMS *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open StdLabels open Lexer301 diff --git a/tools/setignore b/tools/setignore deleted file mode 100755 index 43d37a97..00000000 --- a/tools/setignore +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh - -######################################################################### -# # -# OCaml # -# # -# Damien Doligez, projet Gallium, INRIA Rocquencourt # -# # -# Copyright 2011 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. # -# # -######################################################################### - -( - cat < +*) + +open Printf +open Misc + +let stripdebug infile outfile = + let ic = open_in_bin infile in + Bytesections.read_toc ic; + let toc = Bytesections.toc() in + let pos_first_section = Bytesections.pos_first_section ic in + let oc = + open_out_gen [Open_wronly; Open_creat; Open_trunc; Open_binary] 0o777 + outfile in + (* Skip the #! header, going straight to the first section. *) + seek_in ic pos_first_section; + (* Copy each section except DBUG *) + Bytesections.init_record oc; + List.iter + (fun (name, len) -> + if name = "DBUG" then begin + seek_in ic (in_channel_length ic + len) + end else begin + copy_file_chunk ic oc len; + Bytesections.record oc name + end) + toc; + (* Rewrite the toc and trailer *) + Bytesections.write_toc_and_trailer oc; + (* Done *) + close_in ic; + close_out oc + +let _ = + if Array.length Sys.argv = 3 + then stripdebug Sys.argv.(1) Sys.argv.(2) + else begin + eprintf "Usage: stripdebug \n"; + exit 2 + end diff --git a/tools/tast_iter.ml b/tools/tast_iter.ml deleted file mode 100644 index 791fb6a5..00000000 --- a/tools/tast_iter.ml +++ /dev/null @@ -1,390 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Alain Frisch, LexiFi *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) - -open Typedtree - -let opt f = function None -> () | Some x -> f x - -let structure sub str = - List.iter (sub # structure_item) str.str_items - -let structure_item sub x = - match x.str_desc with - | Tstr_eval (exp, _attrs) -> sub # expression exp - | Tstr_value (rec_flag, list) -> sub # bindings (rec_flag, list) - | Tstr_primitive v -> sub # value_description v - | Tstr_type list -> List.iter (sub # type_declaration) list - | Tstr_typext te -> sub # type_extension te - | Tstr_exception ext -> sub # extension_constructor ext - | Tstr_module mb -> sub # module_binding mb - | Tstr_recmodule list -> List.iter (sub # module_binding) list - | Tstr_modtype mtd -> opt (sub # module_type) mtd.mtd_type - | Tstr_open _ -> () - | Tstr_class list -> - List.iter (fun (ci, _, _) -> sub # class_expr ci.ci_expr) list - | Tstr_class_type list -> - List.iter (fun (_id, _, ct) -> sub # class_type ct.ci_expr) list - | Tstr_include incl -> sub # module_expr incl.incl_mod - | Tstr_attribute _ -> () - -let value_description sub x = - sub # core_type x.val_desc - -let constructor_decl sub cd = - List.iter (sub # core_type) cd.cd_args; - opt (sub # core_type) cd.cd_res - -let label_decl sub ld = - sub # core_type ld.ld_type - -let type_declaration sub decl = - List.iter - (fun (ct1, ct2, _loc) -> sub # core_type ct1; sub # core_type ct2) - decl.typ_cstrs; - begin match decl.typ_kind with - | Ttype_abstract -> () - | Ttype_variant list -> - List.iter (constructor_decl sub) list - | Ttype_record list -> - List.iter (label_decl sub) list - | Ttype_open -> () - end; - opt (sub # core_type) decl.typ_manifest - -let type_extension sub te = - List.iter (sub # extension_constructor) te.tyext_constructors - -let extension_constructor sub ext = - match ext.ext_kind with - Text_decl(ctl, cto) -> - List.iter (sub # core_type) ctl; - opt (sub # core_type) cto - | Text_rebind _ -> () - -let pattern sub pat = - let extra = function - | Tpat_type _ - | Tpat_unpack -> () - | Tpat_constraint ct -> sub # core_type ct - in - List.iter (fun (c, _, _) -> extra c) pat.pat_extra; - match pat.pat_desc with - | Tpat_any - | Tpat_var _ - | Tpat_constant _ -> () - | Tpat_tuple l - | Tpat_construct (_, _, l) -> List.iter (sub # pattern) l - | Tpat_variant (_, po, _) -> opt (sub # pattern) po - | Tpat_record (l, _) -> List.iter (fun (_, _, pat) -> sub # pattern pat) l - | Tpat_array l -> List.iter (sub # pattern) l - | Tpat_or (p1, p2, _) -> sub # pattern p1; sub # pattern p2 - | Tpat_alias (p, _, _) - | Tpat_lazy p -> sub # pattern p - -let expression sub exp = - let extra = function - | Texp_constraint cty -> - sub # core_type cty - | Texp_coerce (cty1, cty2) -> - opt (sub # core_type) cty1; sub # core_type cty2 - | Texp_open _ - | Texp_newtype _ -> () - | Texp_poly cto -> opt (sub # core_type) cto - in - List.iter (fun (c, _, _) -> extra c) exp.exp_extra; - match exp.exp_desc with - | Texp_ident _ - | Texp_constant _ -> () - | Texp_let (rec_flag, list, exp) -> - sub # bindings (rec_flag, list); - sub # expression exp - | Texp_function (_, cases, _) -> - sub # cases cases - | Texp_apply (exp, list) -> - sub # expression exp; - List.iter (fun (_, expo, _) -> opt (sub # expression) expo) list - | Texp_match (exp, cases, exn_cases, _) -> - sub # expression exp; - sub # cases cases; - sub # cases exn_cases - | Texp_try (exp, cases) -> - sub # expression exp; - sub # cases cases - | Texp_tuple list -> - List.iter (sub # expression) list - | Texp_construct (_, _, args) -> - List.iter (sub # expression) args - | Texp_variant (_, expo) -> - opt (sub # expression) expo - | Texp_record (list, expo) -> - List.iter (fun (_, _, exp) -> sub # expression exp) list; - opt (sub # expression) expo - | Texp_field (exp, _, _label) -> - sub # expression exp - | Texp_setfield (exp1, _, _label, exp2) -> - sub # expression exp1; - sub # expression exp2 - | Texp_array list -> - List.iter (sub # expression) list - | Texp_ifthenelse (exp1, exp2, expo) -> - sub # expression exp1; - sub # expression exp2; - opt (sub # expression) expo - | Texp_sequence (exp1, exp2) -> - sub # expression exp1; - sub # expression exp2 - | Texp_while (exp1, exp2) -> - sub # expression exp1; - sub # expression exp2 - | Texp_for (_id, _, exp1, exp2, _dir, exp3) -> - sub # expression exp1; - sub # expression exp2; - sub # expression exp3 - | Texp_send (exp, _meth, expo) -> - sub # expression exp; - opt (sub # expression) expo - | Texp_new (_path, _, _) -> () - | Texp_instvar (_, _path, _) -> () - | Texp_setinstvar (_, _, _, exp) -> - sub # expression exp - | Texp_override (_, list) -> - List.iter (fun (_path, _, exp) -> sub # expression exp) list - | Texp_letmodule (_id, _, mexpr, exp) -> - sub # module_expr mexpr; - sub # expression exp - | Texp_assert exp -> sub # expression exp - | Texp_lazy exp -> sub # expression exp - | Texp_object (cl, _) -> - sub # class_structure cl - | Texp_pack (mexpr) -> - sub # module_expr mexpr - - -let package_type sub pack = - List.iter (fun (_s, ct) -> sub # core_type ct) pack.pack_fields - -let signature sub sg = - List.iter (sub # signature_item) sg.sig_items - -let signature_item sub item = - match item.sig_desc with - | Tsig_value v -> - sub # value_description v - | Tsig_type list -> - List.iter (sub # type_declaration) list - | Tsig_typext te -> - sub # type_extension te - | Tsig_exception ext -> - sub # extension_constructor ext - | Tsig_module md -> - sub # module_type md.md_type - | Tsig_recmodule list -> - List.iter (fun md -> sub # module_type md.md_type) list - | Tsig_modtype mtd -> - opt (sub # module_type) mtd.mtd_type - | Tsig_open _ -> () - | Tsig_include incl -> sub # module_type incl.incl_mod - | Tsig_class list -> - List.iter (sub # class_description) list - | Tsig_class_type list -> - List.iter (sub # class_type_declaration) list - | Tsig_attribute _ -> () - -let class_description sub cd = - sub # class_type cd.ci_expr - -let class_type_declaration sub cd = - sub # class_type cd.ci_expr - -let module_type sub mty = - match mty.mty_desc with - | Tmty_ident (_path, _) -> () - | Tmty_alias (_path, _) -> () - | Tmty_signature sg -> sub # signature sg - | Tmty_functor (_id, _, mtype1, mtype2) -> - Misc.may (sub # module_type) mtype1; sub # module_type mtype2 - | Tmty_with (mtype, list) -> - sub # module_type mtype; - List.iter (fun (_, _, withc) -> sub # with_constraint withc) list - | Tmty_typeof mexpr -> - sub # module_expr mexpr - -let with_constraint sub cstr = - match cstr with - | Twith_type decl -> sub # type_declaration decl - | Twith_module _ -> () - | Twith_typesubst decl -> sub # type_declaration decl - | Twith_modsubst _ -> () - -let module_expr sub mexpr = - match mexpr.mod_desc with - | Tmod_ident (_p, _) -> () - | Tmod_structure st -> sub # structure st - | Tmod_functor (_id, _, mtype, mexpr) -> - Misc.may (sub # module_type) mtype; - sub # module_expr mexpr - | Tmod_apply (mexp1, mexp2, _) -> - sub # module_expr mexp1; - sub # module_expr mexp2 - | Tmod_constraint (mexpr, _, Tmodtype_implicit, _ ) -> - sub # module_expr mexpr - | Tmod_constraint (mexpr, _, Tmodtype_explicit mtype, _) -> - sub # module_expr mexpr; - sub # module_type mtype - | Tmod_unpack (exp, _mty) -> - sub # expression exp -(* sub # module_type mty *) - -let module_binding sub mb = - module_expr sub mb.mb_expr - -let class_expr sub cexpr = - match cexpr.cl_desc with - | Tcl_constraint (cl, None, _, _, _ ) -> - sub # class_expr cl; - | Tcl_structure clstr -> sub # class_structure clstr - | Tcl_fun (_label, pat, priv, cl, _partial) -> - sub # pattern pat; - List.iter (fun (_id, _, exp) -> sub # expression exp) priv; - sub # class_expr cl - | Tcl_apply (cl, args) -> - sub # class_expr cl; - List.iter (fun (_label, expo, _) -> opt (sub # expression) expo) args - | Tcl_let (rec_flat, bindings, ivars, cl) -> - sub # bindings (rec_flat, bindings); - List.iter (fun (_id, _, exp) -> sub # expression exp) ivars; - sub # class_expr cl - | Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) -> - sub # class_expr cl; - sub # class_type clty - | Tcl_ident (_, _, tyl) -> - List.iter (sub # core_type) tyl - -let class_type sub ct = - match ct.cltyp_desc with - | Tcty_signature csg -> sub # class_signature csg - | Tcty_constr (_path, _, list) -> List.iter (sub # core_type) list - | Tcty_arrow (_label, ct, cl) -> - sub # core_type ct; - sub # class_type cl - -let class_signature sub cs = - sub # core_type cs.csig_self; - List.iter (sub # class_type_field) cs.csig_fields - -let class_type_field sub ctf = - match ctf.ctf_desc with - | Tctf_inherit ct -> sub # class_type ct - | Tctf_val (_s, _mut, _virt, ct) -> - sub # core_type ct - | Tctf_method (_s, _priv, _virt, ct) -> - sub # core_type ct - | Tctf_constraint (ct1, ct2) -> - sub # core_type ct1; - sub # core_type ct2 - | Tctf_attribute _ -> () - -let core_type sub ct = - match ct.ctyp_desc with - | Ttyp_any -> () - | Ttyp_var _s -> () - | Ttyp_arrow (_label, ct1, ct2) -> - sub # core_type ct1; - sub # core_type ct2 - | Ttyp_tuple list -> List.iter (sub # core_type) list - | Ttyp_constr (_path, _, list) -> - List.iter (sub # core_type) list - | Ttyp_object (list, _o) -> - List.iter (fun (_, _, t) -> sub # core_type t) list - | Ttyp_class (_path, _, list) -> - List.iter (sub # core_type) list - | Ttyp_alias (ct, _s) -> - sub # core_type ct - | Ttyp_variant (list, _bool, _labels) -> - List.iter (sub # row_field) list - | Ttyp_poly (_list, ct) -> sub # core_type ct - | Ttyp_package pack -> sub # package_type pack - -let class_structure sub cs = - sub # pattern cs.cstr_self; - List.iter (sub # class_field) cs.cstr_fields - -let row_field sub rf = - match rf with - | Ttag (_label, _attrs, _bool, list) -> List.iter (sub # core_type) list - | Tinherit ct -> sub # core_type ct - -let class_field sub cf = - match cf.cf_desc with - | Tcf_inherit (_ovf, cl, _super, _vals, _meths) -> - sub # class_expr cl - | Tcf_constraint (cty, cty') -> - sub # core_type cty; - sub # core_type cty' - | Tcf_val (_, _, _mut, Tcfk_virtual cty, _override) -> - sub # core_type cty - | Tcf_val (_, _, _mut, Tcfk_concrete (_, exp), _override) -> - sub # expression exp - | Tcf_method (_, _priv, Tcfk_virtual cty) -> - sub # core_type cty - | Tcf_method (_, _priv, Tcfk_concrete (_, exp)) -> - sub # expression exp - | Tcf_initializer exp -> - sub # expression exp - | Tcf_attribute _ -> () - -let bindings sub (_rec_flag, list) = - List.iter (sub # binding) list - -let cases sub l = - List.iter (sub # case) l - -let case sub {c_lhs; c_guard; c_rhs} = - sub # pattern c_lhs; - opt (sub # expression) c_guard; - sub # expression c_rhs - -let binding sub vb = - sub # pattern vb.vb_pat; - sub # expression vb.vb_expr - -class iter = object(this) - method binding = binding this - method bindings = bindings this - method case = case this - method cases = cases this - method class_description = class_description this - method class_expr = class_expr this - method class_field = class_field this - method class_signature = class_signature this - method class_structure = class_structure this - method class_type = class_type this - method class_type_declaration = class_type_declaration this - method class_type_field = class_type_field this - method core_type = core_type this - method expression = expression this - method extension_constructor = extension_constructor this - method module_binding = module_binding this - method module_expr = module_expr this - method module_type = module_type this - method package_type = package_type this - method pattern = pattern this - method row_field = row_field this - method signature = signature this - method signature_item = signature_item this - method structure = structure this - method structure_item = structure_item this - method type_declaration = type_declaration this - method type_extension = type_extension this - method value_description = value_description this - method with_constraint = with_constraint this -end diff --git a/tools/tast_iter.mli b/tools/tast_iter.mli deleted file mode 100644 index 1d81afa5..00000000 --- a/tools/tast_iter.mli +++ /dev/null @@ -1,82 +0,0 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Alain Frisch, LexiFi *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) - -open Asttypes -open Typedtree - -class iter: object - method binding: value_binding -> unit - method bindings: (rec_flag * value_binding list) -> unit - method case: case -> unit - method cases: case list -> unit - method class_description: class_description -> unit - method class_expr: class_expr -> unit - method class_field: class_field -> unit - method class_signature: class_signature -> unit - method class_structure: class_structure -> unit - method class_type: class_type -> unit - method class_type_declaration: class_type_declaration -> unit - method class_type_field: class_type_field -> unit - method core_type: core_type -> unit - method expression: expression -> unit - method extension_constructor: extension_constructor -> unit - method module_binding: module_binding -> unit - method module_expr: module_expr -> unit - method module_type: module_type -> unit - method package_type: package_type -> unit - method pattern: pattern -> unit - method row_field: row_field -> unit - method signature: signature -> unit - method signature_item: signature_item -> unit - method structure: structure -> unit - method structure_item: structure_item -> unit - method type_declaration: type_declaration -> unit - method type_extension: type_extension -> unit - method value_description: value_description -> unit - method with_constraint: with_constraint -> unit -end -(** Recursive iterator class. By inheriting from it and - overriding selected methods, it is possible to implement - custom behavior for specific kinds of nodes. *) - -(** {2 One-level iterators} *) - -(** The following functions apply the provided iterator to each - sub-component of the argument. *) - -val binding: iter -> value_binding -> unit -val bindings: iter -> (rec_flag * value_binding list) -> unit -val class_description: iter -> class_description -> unit -val class_expr: iter -> class_expr -> unit -val class_field: iter -> class_field -> unit -val class_signature: iter -> class_signature -> unit -val class_structure: iter -> class_structure -> unit -val class_type: iter -> class_type -> unit -val class_type_declaration: iter -> class_type_declaration -> unit -val class_type_field: iter -> class_type_field -> unit -val core_type: iter -> core_type -> unit -val expression: iter -> expression -> unit -val extension_constructor: iter -> extension_constructor -> unit -val module_binding: iter -> module_binding -> unit -val module_expr: iter -> module_expr -> unit -val module_type: iter -> module_type -> unit -val package_type: iter -> package_type -> unit -val pattern: iter -> pattern -> unit -val row_field: iter -> row_field -> unit -val signature: iter -> signature -> unit -val signature_item: iter -> signature_item -> unit -val structure: iter -> structure -> unit -val structure_item: iter -> structure_item -> unit -val type_declaration: iter -> type_declaration -> unit -val type_extension: iter -> type_extension -> unit -val value_description: iter -> value_description -> unit -val with_constraint: iter -> with_constraint -> unit diff --git a/tools/untypeast.ml b/tools/untypeast.ml deleted file mode 100644 index a8b992ef..00000000 --- a/tools/untypeast.ml +++ /dev/null @@ -1,636 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Thomas Gazagnaire (OCamlPro), Fabrice Le Fessant (INRIA Saclay) *) -(* *) -(* Copyright 2007 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. *) -(* *) -(**************************************************************************) - -open Asttypes -open Typedtree -open Parsetree -open Ast_helper - -(* -Some notes: - - * For Pexp_function, we cannot go back to the exact original version - when there is a default argument, because the default argument is - translated in the typer. The code, if printed, will not be parsable because - new generated identifiers are not correct. - - * For Pexp_apply, it is unclear whether arguments are reordered, especially - when there are optional arguments. - - * TODO: check Ttype_variant -> Ptype_variant (stub None) - -*) - -let string_is_prefix sub str = - let sublen = String.length sub in - String.length str >= sublen && String.sub str 0 sublen = sub - -let option f = function None -> None | Some e -> Some (f e) - -let rec lident_of_path path = - match path with - Path.Pident id -> Longident.Lident (Ident.name id) - | Path.Pdot (p, s, _) -> Longident.Ldot (lident_of_path p, s) - | Path.Papply (p1, p2) -> - Longident.Lapply (lident_of_path p1, lident_of_path p2) - -let rec untype_structure str = - List.map untype_structure_item str.str_items - -and untype_structure_item item = - let desc = - match item.str_desc with - Tstr_eval (exp, attrs) -> Pstr_eval (untype_expression exp, attrs) - | Tstr_value (rec_flag, list) -> - Pstr_value (rec_flag, List.map untype_binding list) - | Tstr_primitive vd -> - Pstr_primitive (untype_value_description vd) - | Tstr_type list -> - Pstr_type (List.map untype_type_declaration list) - | Tstr_typext tyext -> - Pstr_typext (untype_type_extension tyext) - | Tstr_exception ext -> - Pstr_exception (untype_extension_constructor ext) - | Tstr_module mb -> - Pstr_module (untype_module_binding mb) - | Tstr_recmodule list -> - Pstr_recmodule (List.map untype_module_binding list) - | Tstr_modtype mtd -> - Pstr_modtype {pmtd_name=mtd.mtd_name; - pmtd_type=option untype_module_type mtd.mtd_type; - pmtd_loc=mtd.mtd_loc;pmtd_attributes=mtd.mtd_attributes;} - | Tstr_open od -> - Pstr_open {popen_lid = od.open_txt; popen_override = od.open_override; - popen_attributes = od.open_attributes; - popen_loc = od.open_loc; - } - | Tstr_class list -> - Pstr_class - (List.map - (fun (ci, _, _) -> untype_class_declaration ci) - list) - | Tstr_class_type list -> - Pstr_class_type - (List.map - (fun (_id, _name, ct) -> untype_class_type_declaration ct) - list) - | Tstr_include incl -> - Pstr_include {pincl_mod = untype_module_expr incl.incl_mod; - pincl_attributes = incl.incl_attributes; - pincl_loc = incl.incl_loc; - } - | Tstr_attribute x -> - Pstr_attribute x - in - { pstr_desc = desc; pstr_loc = item.str_loc; } - -and untype_value_description v = - { - pval_name = v.val_name; - pval_prim = v.val_prim; - pval_type = untype_core_type v.val_desc; - pval_loc = v.val_loc; - pval_attributes = v.val_attributes; - } - -and untype_module_binding mb = - { - pmb_name = mb.mb_name; - pmb_expr = untype_module_expr mb.mb_expr; - pmb_attributes = mb.mb_attributes; - pmb_loc = mb.mb_loc; - } - -and untype_type_declaration decl = - { - ptype_name = decl.typ_name; - ptype_params = List.map untype_type_parameter decl.typ_params; - ptype_cstrs = List.map (fun (ct1, ct2, loc) -> - (untype_core_type ct1, - untype_core_type ct2, loc) - ) decl.typ_cstrs; - ptype_kind = (match decl.typ_kind with - Ttype_abstract -> Ptype_abstract - | Ttype_variant list -> - Ptype_variant (List.map untype_constructor_declaration list) - | Ttype_record list -> - Ptype_record (List.map untype_label_declaration list) - | Ttype_open -> Ptype_open - ); - ptype_private = decl.typ_private; - ptype_manifest = option untype_core_type decl.typ_manifest; - ptype_attributes = decl.typ_attributes; - ptype_loc = decl.typ_loc; - } - -and untype_type_parameter (ct, v) = (untype_core_type ct, v) - -and untype_constructor_declaration cd = - { - pcd_name = cd.cd_name; - pcd_args = List.map untype_core_type cd.cd_args; - pcd_res = option untype_core_type cd.cd_res; - pcd_loc = cd.cd_loc; - pcd_attributes = cd.cd_attributes; - } - -and untype_label_declaration ld = - { - pld_name=ld.ld_name; - pld_mutable=ld.ld_mutable; - pld_type=untype_core_type ld.ld_type; - pld_loc=ld.ld_loc; - pld_attributes=ld.ld_attributes - } - -and untype_type_extension tyext = - { - ptyext_path = tyext.tyext_txt; - ptyext_params = List.map untype_type_parameter tyext.tyext_params; - ptyext_constructors = - List.map untype_extension_constructor tyext.tyext_constructors; - ptyext_private = tyext.tyext_private; - ptyext_attributes = tyext.tyext_attributes; - } - -and untype_extension_constructor ext = - { - pext_name = ext.ext_name; - pext_kind = (match ext.ext_kind with - Text_decl (args, ret) -> - Pext_decl (List.map untype_core_type args, - option untype_core_type ret) - | Text_rebind (_p, lid) -> Pext_rebind lid - ); - pext_loc = ext.ext_loc; - pext_attributes = ext.ext_attributes; - } - -and untype_pattern pat = - let desc = - match pat with - { pat_extra=[Tpat_unpack, _, _attrs]; pat_desc = Tpat_var (_,name); _ } -> - Ppat_unpack name - | { pat_extra=[Tpat_type (_path, lid), _, _attrs]; _ } -> Ppat_type lid - | { pat_extra= (Tpat_constraint ct, _, _attrs) :: rem; _ } -> - Ppat_constraint (untype_pattern { pat with pat_extra=rem }, - untype_core_type ct) - | _ -> - match pat.pat_desc with - Tpat_any -> Ppat_any - | Tpat_var (id, name) -> - begin - match (Ident.name id).[0] with - 'A'..'Z' -> - Ppat_unpack name - | _ -> - Ppat_var name - end - | Tpat_alias (pat, _id, name) -> - Ppat_alias (untype_pattern pat, name) - | Tpat_constant cst -> Ppat_constant cst - | Tpat_tuple list -> - Ppat_tuple (List.map untype_pattern list) - | Tpat_construct (lid, _, args) -> - Ppat_construct (lid, - (match args with - [] -> None - | [arg] -> Some (untype_pattern arg) - | args -> - Some - (Pat.tuple ~loc:pat.pat_loc - (List.map untype_pattern args) - ) - )) - | Tpat_variant (label, pato, _) -> - Ppat_variant (label, option untype_pattern pato) - | Tpat_record (list, closed) -> - Ppat_record (List.map (fun (lid, _, pat) -> - lid, untype_pattern pat) list, closed) - | Tpat_array list -> Ppat_array (List.map untype_pattern list) - | Tpat_or (p1, p2, _) -> Ppat_or (untype_pattern p1, untype_pattern p2) - | Tpat_lazy p -> Ppat_lazy (untype_pattern p) - in - Pat.mk ~loc:pat.pat_loc ~attrs:pat.pat_attributes desc - (* todo: fix attributes on extras *) - -and untype_extra (extra, loc, attrs) sexp = - let desc = - match extra with - Texp_coerce (cty1, cty2) -> - Pexp_coerce (sexp, - option untype_core_type cty1, - untype_core_type cty2) - | Texp_constraint cty -> - Pexp_constraint (sexp, untype_core_type cty) - | Texp_open (ovf, _path, lid, _) -> Pexp_open (ovf, lid, sexp) - | Texp_poly cto -> Pexp_poly (sexp, option untype_core_type cto) - | Texp_newtype s -> Pexp_newtype (s, sexp) - in - Exp.mk ~loc ~attrs desc - -and untype_cases l = List.map untype_case l - -and untype_case {c_lhs; c_guard; c_rhs} = - { - pc_lhs = untype_pattern c_lhs; - pc_guard = option untype_expression c_guard; - pc_rhs = untype_expression c_rhs; - } - -and untype_binding {vb_pat; vb_expr; vb_attributes; vb_loc} = - { - pvb_pat = untype_pattern vb_pat; - pvb_expr = untype_expression vb_expr; - pvb_attributes = vb_attributes; - pvb_loc = vb_loc; - } - -and untype_expression exp = - let desc = - match exp.exp_desc with - Texp_ident (_path, lid, _) -> Pexp_ident (lid) - | Texp_constant cst -> Pexp_constant cst - | Texp_let (rec_flag, list, exp) -> - Pexp_let (rec_flag, - List.map untype_binding list, - untype_expression exp) - | Texp_function (label, [{c_lhs=p; c_guard=None; c_rhs=e}], _) -> - Pexp_fun (label, None, untype_pattern p, untype_expression e) - | Texp_function ("", cases, _) -> - Pexp_function (untype_cases cases) - | Texp_function _ -> - assert false - | Texp_apply (exp, list) -> - Pexp_apply (untype_expression exp, - List.fold_right (fun (label, expo, _) list -> - match expo with - None -> list - | Some exp -> (label, untype_expression exp) :: list - ) list []) - | Texp_match (exp, cases, exn_cases, _) -> - let merged_cases = untype_cases cases - @ List.map - (fun c -> - let uc = untype_case c in - let pat = { uc.pc_lhs - with ppat_desc = Ppat_exception uc.pc_lhs } - in - { uc with pc_lhs = pat }) - exn_cases - in - Pexp_match (untype_expression exp, merged_cases) - | Texp_try (exp, cases) -> - Pexp_try (untype_expression exp, untype_cases cases) - | Texp_tuple list -> - Pexp_tuple (List.map untype_expression list) - | Texp_construct (lid, _, args) -> - Pexp_construct (lid, - (match args with - [] -> None - | [ arg ] -> Some (untype_expression arg) - | args -> - Some - (Exp.tuple ~loc:exp.exp_loc (List.map untype_expression args)) - )) - | Texp_variant (label, expo) -> - Pexp_variant (label, option untype_expression expo) - | Texp_record (list, expo) -> - Pexp_record (List.map (fun (lid, _, exp) -> - lid, untype_expression exp - ) list, - option untype_expression expo) - | Texp_field (exp, lid, _label) -> - Pexp_field (untype_expression exp, lid) - | Texp_setfield (exp1, lid, _label, exp2) -> - Pexp_setfield (untype_expression exp1, lid, - untype_expression exp2) - | Texp_array list -> - Pexp_array (List.map untype_expression list) - | Texp_ifthenelse (exp1, exp2, expo) -> - Pexp_ifthenelse (untype_expression exp1, - untype_expression exp2, - option untype_expression expo) - | Texp_sequence (exp1, exp2) -> - Pexp_sequence (untype_expression exp1, untype_expression exp2) - | Texp_while (exp1, exp2) -> - Pexp_while (untype_expression exp1, untype_expression exp2) - | Texp_for (_id, name, exp1, exp2, dir, exp3) -> - Pexp_for (name, - untype_expression exp1, untype_expression exp2, - dir, untype_expression exp3) - | Texp_send (exp, meth, _) -> - Pexp_send (untype_expression exp, match meth with - Tmeth_name name -> name - | Tmeth_val id -> Ident.name id) - | Texp_new (_path, lid, _) -> Pexp_new (lid) - | Texp_instvar (_, path, name) -> - Pexp_ident ({name with txt = lident_of_path path}) - | Texp_setinstvar (_, _path, lid, exp) -> - Pexp_setinstvar (lid, untype_expression exp) - | Texp_override (_, list) -> - Pexp_override (List.map (fun (_path, lid, exp) -> - lid, untype_expression exp - ) list) - | Texp_letmodule (_id, name, mexpr, exp) -> - Pexp_letmodule (name, untype_module_expr mexpr, - untype_expression exp) - | Texp_assert exp -> Pexp_assert (untype_expression exp) - | Texp_lazy exp -> Pexp_lazy (untype_expression exp) - | Texp_object (cl, _) -> - Pexp_object (untype_class_structure cl) - | Texp_pack (mexpr) -> - Pexp_pack (untype_module_expr mexpr) - in - List.fold_right untype_extra exp.exp_extra - (Exp.mk ~loc:exp.exp_loc ~attrs:exp.exp_attributes desc) - -and untype_package_type pack = - (pack.pack_txt, - List.map (fun (s, ct) -> - (s, untype_core_type ct)) pack.pack_fields) - -and untype_signature sg = - List.map untype_signature_item sg.sig_items - -and untype_signature_item item = - let desc = - match item.sig_desc with - Tsig_value v -> - Psig_value (untype_value_description v) - | Tsig_type list -> - Psig_type (List.map untype_type_declaration list) - | Tsig_typext tyext -> - Psig_typext (untype_type_extension tyext) - | Tsig_exception ext -> - Psig_exception (untype_extension_constructor ext) - | Tsig_module md -> - Psig_module {pmd_name = md.md_name; - pmd_type = untype_module_type md.md_type; - pmd_attributes = md.md_attributes; pmd_loc = md.md_loc; - } - | Tsig_recmodule list -> - Psig_recmodule (List.map (fun md -> - {pmd_name = md.md_name; pmd_type = untype_module_type md.md_type; - pmd_attributes = md.md_attributes; pmd_loc = md.md_loc}) list) - | Tsig_modtype mtd -> - Psig_modtype {pmtd_name=mtd.mtd_name; - pmtd_type=option untype_module_type mtd.mtd_type; - pmtd_attributes=mtd.mtd_attributes; pmtd_loc=mtd.mtd_loc} - | Tsig_open od -> - Psig_open {popen_lid = od.open_txt; - popen_override = od.open_override; - popen_attributes = od.open_attributes; - popen_loc = od.open_loc; - } - | Tsig_include incl -> - Psig_include {pincl_mod = untype_module_type incl.incl_mod; - pincl_attributes = incl.incl_attributes; - pincl_loc = incl.incl_loc; - } - | Tsig_class list -> - Psig_class (List.map untype_class_description list) - | Tsig_class_type list -> - Psig_class_type (List.map untype_class_type_declaration list) - | Tsig_attribute x -> - Psig_attribute x - in - { psig_desc = desc; - psig_loc = item.sig_loc; - } - -and untype_class_declaration cd = - { - pci_virt = cd.ci_virt; - pci_params = List.map untype_type_parameter cd.ci_params; - pci_name = cd.ci_id_name; - pci_expr = untype_class_expr cd.ci_expr; - pci_loc = cd.ci_loc; - pci_attributes = cd.ci_attributes; - } - -and untype_class_description cd = - { - pci_virt = cd.ci_virt; - pci_params = List.map untype_type_parameter cd.ci_params; - pci_name = cd.ci_id_name; - pci_expr = untype_class_type cd.ci_expr; - pci_loc = cd.ci_loc; - pci_attributes = cd.ci_attributes; - } - -and untype_class_type_declaration cd = - { - pci_virt = cd.ci_virt; - pci_params = List.map untype_type_parameter cd.ci_params; - pci_name = cd.ci_id_name; - pci_expr = untype_class_type cd.ci_expr; - pci_loc = cd.ci_loc; - pci_attributes = cd.ci_attributes; - } - -and untype_module_type mty = - let desc = match mty.mty_desc with - Tmty_ident (_path, lid) -> Pmty_ident (lid) - | Tmty_alias (_path, lid) -> Pmty_alias (lid) - | Tmty_signature sg -> Pmty_signature (untype_signature sg) - | Tmty_functor (_id, name, mtype1, mtype2) -> - Pmty_functor (name, Misc.may_map untype_module_type mtype1, - untype_module_type mtype2) - | Tmty_with (mtype, list) -> - Pmty_with (untype_module_type mtype, - List.map (fun (_path, lid, withc) -> - untype_with_constraint lid withc - ) list) - | Tmty_typeof mexpr -> - Pmty_typeof (untype_module_expr mexpr) - in - Mty.mk ~loc:mty.mty_loc desc - -and untype_with_constraint lid cstr = - match cstr with - Twith_type decl -> Pwith_type (lid, untype_type_declaration decl) - | Twith_module (_path, lid2) -> Pwith_module (lid, lid2) - | Twith_typesubst decl -> Pwith_typesubst (untype_type_declaration decl) - | Twith_modsubst (_path, lid2) -> - Pwith_modsubst ({loc = lid.loc; txt=Longident.last lid.txt}, lid2) - -and untype_module_expr mexpr = - match mexpr.mod_desc with - Tmod_constraint (m, _, Tmodtype_implicit, _ ) -> - untype_module_expr m - | _ -> - let desc = match mexpr.mod_desc with - Tmod_ident (_p, lid) -> Pmod_ident (lid) - | Tmod_structure st -> Pmod_structure (untype_structure st) - | Tmod_functor (_id, name, mtype, mexpr) -> - Pmod_functor (name, Misc.may_map untype_module_type mtype, - untype_module_expr mexpr) - | Tmod_apply (mexp1, mexp2, _) -> - Pmod_apply (untype_module_expr mexp1, untype_module_expr mexp2) - | Tmod_constraint (mexpr, _, Tmodtype_explicit mtype, _) -> - Pmod_constraint (untype_module_expr mexpr, - untype_module_type mtype) - | Tmod_constraint (_mexpr, _, Tmodtype_implicit, _) -> - assert false - | Tmod_unpack (exp, _pack) -> - Pmod_unpack (untype_expression exp) - (* TODO , untype_package_type pack) *) - - in - Mod.mk ~loc:mexpr.mod_loc desc - -and untype_class_expr cexpr = - let desc = match cexpr.cl_desc with - | Tcl_constraint ( { cl_desc = Tcl_ident (_path, lid, tyl); _ }, - None, _, _, _ ) -> - Pcl_constr (lid, - List.map untype_core_type tyl) - | Tcl_structure clstr -> Pcl_structure (untype_class_structure clstr) - - | Tcl_fun (label, pat, _pv, cl, _partial) -> - Pcl_fun (label, None, untype_pattern pat, untype_class_expr cl) - - | Tcl_apply (cl, args) -> - Pcl_apply (untype_class_expr cl, - List.fold_right (fun (label, expo, _) list -> - match expo with - None -> list - | Some exp -> (label, untype_expression exp) :: list - ) args []) - - | Tcl_let (rec_flat, bindings, _ivars, cl) -> - Pcl_let (rec_flat, - List.map untype_binding bindings, - untype_class_expr cl) - - | Tcl_constraint (cl, Some clty, _vals, _meths, _concrs) -> - Pcl_constraint (untype_class_expr cl, untype_class_type clty) - - | Tcl_ident _ -> assert false - | Tcl_constraint (_, None, _, _, _) -> assert false - in - { pcl_desc = desc; - pcl_loc = cexpr.cl_loc; - pcl_attributes = cexpr.cl_attributes; - } - -and untype_class_type ct = - let desc = match ct.cltyp_desc with - Tcty_signature csg -> Pcty_signature (untype_class_signature csg) - | Tcty_constr (_path, lid, list) -> - Pcty_constr (lid, List.map untype_core_type list) - | Tcty_arrow (label, ct, cl) -> - Pcty_arrow (label, untype_core_type ct, untype_class_type cl) - in - { pcty_desc = desc; - pcty_loc = ct.cltyp_loc; - pcty_attributes = ct.cltyp_attributes; - } - -and untype_class_signature cs = - { - pcsig_self = untype_core_type cs.csig_self; - pcsig_fields = List.map untype_class_type_field cs.csig_fields; - } - -and untype_class_type_field ctf = - let desc = match ctf.ctf_desc with - Tctf_inherit ct -> Pctf_inherit (untype_class_type ct) - | Tctf_val (s, mut, virt, ct) -> - Pctf_val (s, mut, virt, untype_core_type ct) - | Tctf_method (s, priv, virt, ct) -> - Pctf_method (s, priv, virt, untype_core_type ct) - | Tctf_constraint (ct1, ct2) -> - Pctf_constraint (untype_core_type ct1, untype_core_type ct2) - | Tctf_attribute x -> Pctf_attribute x - in - { - pctf_desc = desc; - pctf_loc = ctf.ctf_loc; - pctf_attributes = ctf.ctf_attributes; - } - -and untype_core_type ct = - let desc = match ct.ctyp_desc with - Ttyp_any -> Ptyp_any - | Ttyp_var s -> Ptyp_var s - | Ttyp_arrow (label, ct1, ct2) -> - Ptyp_arrow (label, untype_core_type ct1, untype_core_type ct2) - | Ttyp_tuple list -> Ptyp_tuple (List.map untype_core_type list) - | Ttyp_constr (_path, lid, list) -> - Ptyp_constr (lid, - List.map untype_core_type list) - | Ttyp_object (list, o) -> - Ptyp_object - (List.map (fun (s, a, t) -> (s, a, untype_core_type t)) list, o) - | Ttyp_class (_path, lid, list) -> - Ptyp_class (lid, List.map untype_core_type list) - | Ttyp_alias (ct, s) -> - Ptyp_alias (untype_core_type ct, s) - | Ttyp_variant (list, bool, labels) -> - Ptyp_variant (List.map untype_row_field list, bool, labels) - | Ttyp_poly (list, ct) -> Ptyp_poly (list, untype_core_type ct) - | Ttyp_package pack -> Ptyp_package (untype_package_type pack) - in - Typ.mk ~loc:ct.ctyp_loc desc - -and untype_class_structure cs = - let rec remove_self = function - | { pat_desc = Tpat_alias (p, id, _s) } when string_is_prefix "selfpat-" id.Ident.name -> - remove_self p - | p -> p - in - { pcstr_self = untype_pattern (remove_self cs.cstr_self); - pcstr_fields = List.map untype_class_field cs.cstr_fields; - } - -and untype_row_field rf = - match rf with - Ttag (label, attrs, bool, list) -> - Rtag (label, attrs, bool, List.map untype_core_type list) - | Tinherit ct -> Rinherit (untype_core_type ct) - -and is_self_pat = function - | { pat_desc = Tpat_alias(_pat, id, _) } -> - string_is_prefix "self-" (Ident.name id) - | _ -> false - -and untype_class_field cf = - let desc = match cf.cf_desc with - Tcf_inherit (ovf, cl, super, _vals, _meths) -> - Pcf_inherit (ovf, untype_class_expr cl, super) - | Tcf_constraint (cty, cty') -> - Pcf_constraint (untype_core_type cty, untype_core_type cty') - | Tcf_val (lab, mut, _, Tcfk_virtual cty, _) -> - Pcf_val (lab, mut, Cfk_virtual (untype_core_type cty)) - | Tcf_val (lab, mut, _, Tcfk_concrete (o, exp), _) -> - Pcf_val (lab, mut, Cfk_concrete (o, untype_expression exp)) - | Tcf_method (lab, priv, Tcfk_virtual cty) -> - Pcf_method (lab, priv, Cfk_virtual (untype_core_type cty)) - | Tcf_method (lab, priv, Tcfk_concrete (o, exp)) -> - let remove_fun_self = function - | { exp_desc = Texp_function("", [case], _) } when is_self_pat case.c_lhs && case.c_guard = None -> case.c_rhs - | e -> e - in - let exp = remove_fun_self exp in - Pcf_method (lab, priv, Cfk_concrete (o, untype_expression exp)) - | Tcf_initializer exp -> - let remove_fun_self = function - | { exp_desc = Texp_function("", [case], _) } when is_self_pat case.c_lhs && case.c_guard = None -> case.c_rhs - | e -> e - in - let exp = remove_fun_self exp in - Pcf_initializer (untype_expression exp) - | Tcf_attribute x -> Pcf_attribute x - in - { pcf_desc = desc; pcf_loc = cf.cf_loc; pcf_attributes = cf.cf_attributes } diff --git a/tools/untypeast.mli b/tools/untypeast.mli deleted file mode 100644 index efd0a031..00000000 --- a/tools/untypeast.mli +++ /dev/null @@ -1,20 +0,0 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Thomas Gazagnaire (OCamlPro), Fabrice Le Fessant (INRIA Saclay) *) -(* *) -(* Copyright 2007 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. *) -(* *) -(**************************************************************************) - -val untype_structure : Typedtree.structure -> Parsetree.structure -val untype_signature : Typedtree.signature -> Parsetree.signature -val untype_expression : Typedtree.expression -> Parsetree.expression -val untype_type_declaration : - Typedtree.type_declaration -> Parsetree.type_declaration -val untype_module_type : Typedtree.module_type -> Parsetree.module_type - -val lident_of_path : Path.t -> Longident.t diff --git a/toplevel/expunge.ml b/toplevel/expunge.ml index a893c60d..47c370d8 100644 --- a/toplevel/expunge.ml +++ b/toplevel/expunge.ml @@ -1,16 +1,19 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) -(* "Expunge" a toplevel by removing compiler modules from the global List.map. +(* "Expunge" a toplevel by removing compiler modules from the global map. Usage: expunge *) open Misc @@ -44,7 +47,7 @@ let main () = let input_name = Sys.argv.(1) in let output_name = Sys.argv.(2) in for i = (if negate then 4 else 3) to Array.length Sys.argv - 1 do - to_keep := StringSet.add (String.capitalize Sys.argv.(i)) !to_keep + to_keep := StringSet.add (String.capitalize_ascii Sys.argv.(i)) !to_keep done; let ic = open_in_bin input_name in Bytesections.read_toc ic; diff --git a/toplevel/genprintval.ml b/toplevel/genprintval.ml index 3144594f..dc7c8d88 100644 --- a/toplevel/genprintval.ml +++ b/toplevel/genprintval.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* To print values *) @@ -378,40 +381,41 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct | _ -> assert false end | None -> decl.type_params in - let ty_args = - List.map - (function ty -> - try Ctype.apply env type_params ty ty_list with - Ctype.Cannot_apply -> abstract_type) - cd_args in - tree_of_constr_with_args (tree_of_constr env path) - (Ident.name cd_id) 0 depth obj ty_args + begin + match cd_args with + | Cstr_tuple l -> + let ty_args = + List.map + (function ty -> + try Ctype.apply env type_params ty ty_list with + Ctype.Cannot_apply -> abstract_type) + l + in + tree_of_constr_with_args (tree_of_constr env path) + (Ident.name cd_id) false 0 depth obj + ty_args + | Cstr_record lbls -> + let r = + tree_of_record_fields depth + env path type_params ty_list + lbls 0 obj + in + Oval_constr(tree_of_constr env path + (Ident.name cd_id), + [ r ]) + end | {type_kind = Type_record(lbl_list, rep)} -> begin match check_depth depth obj ty with Some x -> x | None -> - let rec tree_of_fields pos = function - | [] -> [] - | {ld_id; ld_type} :: remainder -> - let ty_arg = - try - Ctype.apply env decl.type_params ld_type - ty_list - with - Ctype.Cannot_apply -> abstract_type in - let name = Ident.name ld_id in - (* PR#5722: print full module path only - for first record field *) - let lid = - if pos = 0 then tree_of_label env path name - else Oide_ident name - and v = - nest tree_of_val (depth - 1) (O.field obj pos) - ty_arg - in - (lid, v) :: tree_of_fields (pos + 1) remainder + let pos = + match rep with + | Record_extension -> 1 + | _ -> 0 in - Oval_record (tree_of_fields 0 lbl_list) + tree_of_record_fields depth + env path decl.type_params ty_list + lbl_list pos obj end | {type_kind = Type_open} -> tree_of_extension path depth obj @@ -459,6 +463,31 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct Oval_stuff "" end + and tree_of_record_fields depth env path type_params ty_list + lbl_list pos obj = + let rec tree_of_fields pos = function + | [] -> [] + | {ld_id; ld_type} :: remainder -> + let ty_arg = + try + Ctype.apply env type_params ld_type + ty_list + with + Ctype.Cannot_apply -> abstract_type in + let name = Ident.name ld_id in + (* PR#5722: print full module path only + for first record field *) + let lid = + if pos = 0 then tree_of_label env path name + else Oide_ident name + and v = + nest tree_of_val (depth - 1) (O.field obj pos) + ty_arg + in + (lid, v) :: tree_of_fields (pos + 1) remainder + in + Oval_record (tree_of_fields pos lbl_list) + and tree_of_val_list start depth obj ty_list = let rec tree_list i = function | [] -> [] @@ -468,9 +497,16 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct tree_list start ty_list and tree_of_constr_with_args - tree_of_cstr cstr_name start depth obj ty_args = + tree_of_cstr cstr_name inlined start depth obj ty_args = let lid = tree_of_cstr cstr_name in - let args = tree_of_val_list start depth obj ty_args in + let args = + if inlined then + match ty_args with + | [ty] -> [ tree_of_val (depth - 1) obj ty ] + | _ -> assert false + else + tree_of_val_list start depth obj ty_args + in Oval_constr (lid, args) and tree_of_extension type_path depth bucket = @@ -495,7 +531,9 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct if not (EVP.same_value slot (EVP.eval_path env path)) then raise Not_found; tree_of_constr_with_args - (fun x -> Oide_ident x) name 1 depth bucket cstr.cstr_args + (fun x -> Oide_ident x) name (cstr.cstr_inlined <> None) + 1 depth bucket + cstr.cstr_args with Not_found | EVP.Error -> match check_depth depth bucket ty with Some x -> x diff --git a/toplevel/genprintval.mli b/toplevel/genprintval.mli index 1c2ec471..744aaaea 100644 --- a/toplevel/genprintval.mli +++ b/toplevel/genprintval.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Printing of values *) diff --git a/toplevel/opttopdirs.ml b/toplevel/opttopdirs.ml index 9741d17b..cb155ff0 100644 --- a/toplevel/opttopdirs.ml +++ b/toplevel/opttopdirs.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Toplevel directives *) @@ -34,6 +37,15 @@ let dir_directory s = Config.load_path := d :: !Config.load_path let _ = Hashtbl.add directive_table "directory" (Directive_string dir_directory) +(* To remove a directory from the load path *) +let dir_remove_directory s = + let d = expand_directory Config.standard_library s in + Config.load_path := List.filter (fun d' -> d' <> d) !Config.load_path + +let _ = + Hashtbl.add directive_table "remove_directory" + (Directive_string dir_remove_directory) + let _ = Hashtbl.add directive_table "show_dirs" (Directive_none (fun () -> @@ -51,35 +63,36 @@ let _ = Hashtbl.add directive_table "cd" (Directive_string dir_cd) let load_file ppf name0 = let name = try Some (find_in_path !Config.load_path name0) - with Not_found -> None in + with Not_found -> None + in match name with - | None -> fprintf ppf "File not found: %s@." name0; false - | Some name -> - let fn,tmp = - if Filename.check_suffix name ".cmx" || Filename.check_suffix name ".cmxa" - then - let cmxs = Filename.temp_file "caml" ".cmxs" in - Asmlink.link_shared ppf [name] cmxs; - cmxs,true - else - name,false in - - let success = - (* The Dynlink interface does not allow us to distinguish between - a Dynlink.Error exceptions raised in the loaded modules - or a genuine error during dynlink... *) - try Dynlink.loadfile fn; true - with + | None -> fprintf ppf "File not found: %s@." name0; false + | Some name -> + let fn,tmp = + if Filename.check_suffix name ".cmx" || Filename.check_suffix name ".cmxa" + then + let cmxs = Filename.temp_file "caml" ".cmxs" in + Asmlink.link_shared ppf [name] cmxs; + cmxs,true + else + name,false + in + let success = + (* The Dynlink interface does not allow us to distinguish between + a Dynlink.Error exceptions raised in the loaded modules + or a genuine error during dynlink... *) + try Dynlink.loadfile fn; true + with | Dynlink.Error err -> - fprintf ppf "Error while loading %s: %s.@." - name (Dynlink.error_message err); - false + fprintf ppf "Error while loading %s: %s.@." + name (Dynlink.error_message err); + false | exn -> - print_exception_outcome ppf exn; - false - in - if tmp then (try Sys.remove fn with Sys_error _ -> ()); - success + print_exception_outcome ppf exn; + false + in + if tmp then (try Sys.remove fn with Sys_error _ -> ()); + success let dir_load ppf name = ignore (load_file ppf name) @@ -135,7 +148,7 @@ let find_printer_type ppf lid = let dir_install_printer ppf lid = try let (ty_arg, path, is_old_style) = find_printer_type ppf lid in - let v = eval_path path in + let v = eval_path !toplevel_env path in let print_function = if is_old_style then (fun formatter repr -> Obj.obj v (Obj.obj repr)) diff --git a/toplevel/opttopdirs.mli b/toplevel/opttopdirs.mli index 8caf71d4..01d13569 100644 --- a/toplevel/opttopdirs.mli +++ b/toplevel/opttopdirs.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The toplevel directives. *) @@ -16,6 +19,7 @@ open Format val dir_quit : unit -> unit val dir_directory : string -> unit +val dir_remove_directory : string -> unit val dir_cd : string -> unit val dir_load : formatter -> string -> unit val dir_use : formatter -> string -> unit diff --git a/toplevel/opttoploop.ml b/toplevel/opttoploop.ml index d21860a8..628aee7c 100644 --- a/toplevel/opttoploop.ml +++ b/toplevel/opttoploop.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The interactive toplevel loop *) @@ -20,6 +23,7 @@ open Parsetree open Types open Typedtree open Outcometree +open Ast_helper type res = Ok of Obj.t | Err of string type evaluation_outcome = Result of Obj.t | Exception of exn @@ -60,9 +64,35 @@ type directive_fun = (* Return the value referred to by a path *) +let remembered = ref Ident.empty + +let rec remember phrase_name i = function + | [] -> () + | Sig_value (id, _) :: rest + | Sig_module (id, _, _) :: rest + | Sig_typext (id, _, _) :: rest + | Sig_class (id, _, _) :: rest -> + remembered := Ident.add id (phrase_name, i) !remembered; + remember phrase_name (succ i) rest + | _ :: rest -> remember phrase_name i rest + let toplevel_value id = - let (glb,pos) = Translmod.nat_toplevel_name id in - (Obj.magic (global_symbol glb)).(pos) + try Ident.find_same id !remembered + with _ -> Misc.fatal_error @@ "Unknown ident: " ^ Ident.unique_name id + +let close_phrase lam = + let open Lambda in + IdentSet.fold (fun id l -> + let glb, pos = toplevel_value id in + let glob = Lprim (Pfield pos, [Lprim (Pgetglobal glb, [])]) in + Llet(Strict, id, glob, l) + ) (free_variables lam) lam + +let toplevel_value id = + let glob, pos = + if Config.flambda then toplevel_value id else Translmod.nat_toplevel_name id + in + (Obj.magic (global_symbol glob)).(pos) let rec eval_path = function | Pident id -> @@ -74,12 +104,15 @@ let rec eval_path = function | Papply(p1, p2) -> fatal_error "Toploop.eval_path" +let eval_path env path = + eval_path (Env.normalize_path (Some Location.none) env path) + (* To print values *) module EvalPath = struct type valu = Obj.t exception Error - let eval_path p = try eval_path p with _ -> raise Error + let eval_path env p = try eval_path env p with _ -> raise Error let same_value v1 v2 = (v1 == v2) end @@ -105,7 +138,13 @@ let outval_of_value env obj ty = let print_value env obj ppf ty = !print_out_value ppf (outval_of_value env obj ty) +type ('a, 'b) gen_printer = ('a, 'b) Genprintval.gen_printer = + | Zero of 'b + | Succ of ('a -> ('a, 'b) gen_printer) + let install_printer = Printer.install_printer +let install_generic_printer = Printer.install_generic_printer +let install_generic_printer' = Printer.install_generic_printer' let remove_printer = Printer.remove_printer (* Hooks for parsing functions *) @@ -117,6 +156,25 @@ let print_error = Location.print_error let print_warning = Location.print_warning let input_name = Location.input_name +let parse_mod_use_file name lb = + let modname = + String.capitalize_ascii (Filename.chop_extension (Filename.basename name)) + in + let items = + List.concat + (List.map + (function Ptop_def s -> s | Ptop_dir _ -> []) + (!parse_use_file lb)) + in + [ Ptop_def + [ Str.module_ + (Mb.mk + (Location.mknoloc modname) + (Mod.structure items) + ) + ] + ] + (* Hooks for initialization *) let toplevel_startup_hook = ref (fun () -> ()) @@ -126,7 +184,28 @@ let toplevel_startup_hook = ref (fun () -> ()) let phrase_seqid = ref 0 let phrase_name = ref "TOP" -let load_lambda ppf (size, lam) = +(* CR-soon trefis for mshinwell: copy/pasted from Optmain. Should it be shared + or? + mshinwell: It should be shared, but after 4.03. *) +module Backend = struct + (* See backend_intf.mli. *) + + let symbol_for_global' = Compilenv.symbol_for_global' + let closure_symbol = Compilenv.closure_symbol + + let really_import_approx = Import_approx.really_import_approx + let import_symbol = Import_approx.import_symbol + + let size_int = Arch.size_int + let big_endian = Arch.big_endian + + let max_sensible_number_of_arguments = + (* The "-1" is to allow for a potential closure environment parameter. *) + Proc.max_arguments_for_tailcalls - 1 +end +let backend = (module Backend : Backend_intf.S) + +let load_lambda ppf ~module_ident lam size = if !Clflags.dump_rawlambda then fprintf ppf "%a@." Printlambda.lambda lam; let slam = Simplif.simplify_lambda lam in if !Clflags.dump_lambda then fprintf ppf "%a@." Printlambda.lambda slam; @@ -136,7 +215,16 @@ let load_lambda ppf (size, lam) = else Filename.temp_file ("caml" ^ !phrase_name) ext_dll in let fn = Filename.chop_extension dll in - Asmgen.compile_implementation ~toplevel:need_symbol fn ppf (size, slam); + 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 } + else + Asmgen.compile_implementation_flambda ~source_provenance:Timings.Toplevel + ~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"); Asmlink.call_linker_shared [fn ^ ext_obj] dll; Sys.remove (fn ^ ext_obj); @@ -153,48 +241,13 @@ let load_lambda ppf (size, lam) = (* Print the outcome of an evaluation *) -let rec pr_item env = function - | Sig_value(id, decl) :: rem -> - let tree = Printtyp.tree_of_value_description id decl in - let valopt = - match decl.val_kind with - | Val_prim _ -> None - | _ -> - let v = - outval_of_value env (toplevel_value id) - decl.val_type - in - Some v - in - Some (tree, valopt, rem) - | Sig_type(id, _, _) :: rem when Btype.is_row_name (Ident.name id) -> - pr_item env rem - | Sig_type(id, decl, rs) :: rem -> - let tree = Printtyp.tree_of_type_declaration id decl rs in - Some (tree, None, rem) - | Sig_typext(id, ext, es) :: rem -> - let tree = Printtyp.tree_of_extension_constructor id ext es in - Some (tree, None, rem) - | Sig_module(id, mty, rs) :: rem -> - let tree = Printtyp.tree_of_module id mty rs in - Some (tree, None, rem) - | Sig_modtype(id, decl) :: rem -> - let tree = Printtyp.tree_of_modtype_declaration id decl in - Some (tree, None, rem) - | Sig_class(id, decl, rs) :: cltydecl :: tydecl1 :: tydecl2 :: rem -> - let tree = Printtyp.tree_of_class_declaration id decl rs in - Some (tree, None, rem) - | Sig_class_type(id, decl, rs) :: tydecl1 :: tydecl2 :: rem -> - let tree = Printtyp.tree_of_cltype_declaration id decl rs in - Some (tree, None, rem) - | _ -> None - -let rec item_list env = function - | [] -> [] - | items -> - match pr_item env items with - | None -> [] - | Some (tree, valopt, items) -> (tree, valopt) :: item_list env items +let pr_item = + Printtyp.print_items + (fun env -> function + | Sig_value(id, {val_kind = Val_reg; val_type}) -> + Some (outval_of_value env (toplevel_value id) val_type) + | _ -> None + ) (* The current typing environment for the toplevel *) @@ -223,32 +276,71 @@ let execute_phrase print_outcome ppf phr = let oldenv = !toplevel_env in incr phrase_seqid; phrase_name := Printf.sprintf "TOP%i" !phrase_seqid; - Compilenv.reset ?packname:None !phrase_name; + Compilenv.reset ~source_provenance:Timings.Toplevel + ?packname:None !phrase_name; Typecore.reset_delayed_checks (); - let (str, sg, newenv) = Typemod.type_structure oldenv sstr Location.none + let sstr, rewritten = + match sstr with + | [ { pstr_desc = Pstr_eval (e, attrs) ; pstr_loc = loc } ] + | [ { pstr_desc = Pstr_value (Asttypes.Nonrecursive, + [{ pvb_expr = e + ; pvb_pat = { ppat_desc = Ppat_any ; _ } + ; pvb_attributes = attrs + ; _ }]) + ; pstr_loc = loc } + ] -> + let pat = Ast_helper.Pat.var (Location.mknoloc "_$") in + let vb = Ast_helper.Vb.mk ~loc ~attrs pat e in + [ Ast_helper.Str.value ~loc Asttypes.Nonrecursive [vb] ], true + | _ -> sstr, false in + let (str, sg, newenv) = Typemod.type_toplevel_phrase oldenv sstr in if !Clflags.dump_typedtree then Printtyped.implementation ppf str; + let sg' = Typemod.simplify_signature sg in + (* Why is this done? *) + ignore (Includemod.signatures oldenv sg sg'); Typecore.force_delayed_checks (); - let res = Translmod.transl_store_phrases !phrase_name str in + let module_ident, res, size = + if Config.flambda then + let ((module_ident, size), res) = + Translmod.transl_implementation_flambda !phrase_name + (str, Tcoerce_none) + in + remember module_ident 0 sg'; + module_ident, close_phrase res, size + else + let size, res = Translmod.transl_store_phrases !phrase_name str in + Ident.create_persistent !phrase_name, res, size + in Warnings.check_fatal (); begin try toplevel_env := newenv; - let res = load_lambda ppf res in + let res = load_lambda ppf ~module_ident res size in let out_phr = match res with | Result v -> - Compilenv.record_global_approx_toplevel (); + if Config.flambda then + (* CR-someday trefis: *) + () + else + Compilenv.record_global_approx_toplevel (); if print_outcome then + Printtyp.wrap_printing_env oldenv (fun () -> match str.str_items with - | [ {str_desc = Tstr_eval exp} ] -> - let outv = outval_of_value newenv v exp.exp_type in - let ty = Printtyp.tree_of_type_scheme exp.exp_type in - Ophr_eval (outv, ty) | [] -> Ophr_signature [] | _ -> - Ophr_signature (item_list newenv - (Typemod.simplify_signature sg)) - + if rewritten then + match sg' with + | [ Sig_value (id, vd) ] -> + let outv = + outval_of_value newenv (toplevel_value id) + vd.val_type + in + let ty = Printtyp.tree_of_type_scheme vd.val_type in + Ophr_eval (outv, ty) + | _ -> assert false + else + Ophr_signature (pr_item newenv sg')) else Ophr_signature [] | Exception exn -> toplevel_env := oldenv; @@ -267,19 +359,38 @@ let execute_phrase print_outcome ppf phr = toplevel_env := oldenv; raise x end | Ptop_dir(dir_name, dir_arg) -> - try - match (Hashtbl.find directive_table dir_name, dir_arg) with - | (Directive_none f, Pdir_none) -> f (); true - | (Directive_string f, Pdir_string s) -> f s; true - | (Directive_int f, Pdir_int n) -> f n; true - | (Directive_ident f, Pdir_ident lid) -> f lid; true - | (Directive_bool f, Pdir_bool b) -> f b; true - | (_, _) -> - fprintf ppf "Wrong type of argument for directive `%s'.@." dir_name; - false - with Not_found -> - fprintf ppf "Unknown directive `%s'.@." dir_name; - false + let d = + try Some (Hashtbl.find directive_table dir_name) + with Not_found -> None + in + begin match d with + | None -> + fprintf ppf "Unknown directive `%s'.@." dir_name; + false + | Some d -> + match d, dir_arg with + | Directive_none f, Pdir_none -> f (); true + | Directive_string f, Pdir_string s -> f s; true + | Directive_int f, Pdir_int (n,None) -> + begin match Int_literal_converter.int n with + | n -> f n; true + | exception _ -> + fprintf ppf "Integer literal exceeds the range of \ + representable integers for directive `%s'.@." + dir_name; + false + end + | Directive_int f, Pdir_int (n, Some _) -> + fprintf ppf "Wrong integer literal for directive `%s'.@." + dir_name; + false + | Directive_ident f, Pdir_ident lid -> f lid; true + | Directive_bool f, Pdir_bool b -> f b; true + | _ -> + fprintf ppf "Wrong type of argument for directive `%s'.@." + dir_name; + false + end (* Temporary assignment to a reference *) @@ -294,11 +405,25 @@ let protect r newval body = r := oldval; raise x -(* Read and execute commands from a file *) +(* Read and execute commands from a file, or from stdin if [name] is "". *) let use_print_results = ref true -let use_file ppf name = +let preprocess_phrase ppf phr = + let phr = + match phr with + | Ptop_def str -> + let str = + Pparse.apply_rewriters_str ~restore:true ~tool_name:"ocaml" str + in + Ptop_def str + | phr -> phr + in + if !Clflags.dump_parsetree then Printast.top_phrase ppf phr; + if !Clflags.dump_source then Pprintast.top_phrase ppf phr; + phr + +let use_file ppf wrap_mod name = try let (filename, ic, must_close) = if name = "" then @@ -318,10 +443,12 @@ let use_file ppf name = try List.iter (fun ph -> - if !Clflags.dump_parsetree then Printast.top_phrase ppf ph; - if !Clflags.dump_source then Pprintast.top_phrase ppf ph; + let ph = preprocess_phrase ppf ph in if not (execute_phrase !use_print_results ppf ph) then raise Exit) - (!parse_use_file lb); + (if wrap_mod then + parse_mod_use_file name lb + else + !parse_use_file lb); true with | Exit -> false @@ -331,6 +458,9 @@ let use_file ppf name = success with Not_found -> fprintf ppf "Cannot find file %s.@." name; false +let mod_use_file ppf name = use_file ppf true name +let use_file ppf name = use_file ppf false name + let use_silently ppf name = protect use_print_results false (fun () -> use_file ppf name) @@ -345,8 +475,8 @@ let read_input_default prompt buffer len = try while true do if !i >= len then raise Exit; - let c = input_char stdin in - buffer.[!i] <- c; + let c = input_char Pervasives.stdin in + Bytes.set buffer !i c; incr i; if c = '\n' then raise Exit; done; @@ -418,6 +548,7 @@ let initialize_toplevel_env () = exception PPerror let loop ppf = + Location.formatter_for_warnings := ppf; fprintf ppf " OCaml version %s - native toplevel@.@." Config.version; initialize_toplevel_env (); let lb = Lexing.from_function refill_lexbuf in @@ -433,6 +564,8 @@ let loop ppf = Location.reset(); first_line := true; let phr = try !parse_toplevel_phrase lb with Exit -> raise PPerror in + let phr = preprocess_phrase ppf phr in + Env.reset_cache_toplevel (); if !Clflags.dump_parsetree then Printast.top_phrase ppf phr; if !Clflags.dump_source then Pprintast.top_phrase ppf phr; ignore(execute_phrase true ppf phr) @@ -443,7 +576,7 @@ let loop ppf = | x -> Location.report_exception ppf x; Btype.backtrack snap done -(* Execute a script *) +(* Execute a script. If [name] is "", read the script from stdin. *) let run_script ppf name args = let len = Array.length args in @@ -451,7 +584,14 @@ let run_script ppf name args = Array.blit args 0 Sys.argv 0 len; Obj.truncate (Obj.repr Sys.argv) len; Arg.current := 0; - Compmisc.init_path true; + Compmisc.init_path ~dir:(Filename.dirname name) true; + (* Note: would use [Filename.abspath] here, if we had it. *) toplevel_env := Compmisc.initial_env(); Sys.interactive := false; - use_silently ppf name + let explicit_name = + (* Prevent use_silently from searching in the path. *) + if Filename.is_implicit name + then Filename.concat Filename.current_dir_name name + else name + in + use_silently ppf explicit_name diff --git a/toplevel/opttoploop.mli b/toplevel/opttoploop.mli index 22362558..3ce4d191 100644 --- a/toplevel/opttoploop.mli +++ b/toplevel/opttoploop.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format @@ -47,12 +50,18 @@ val execute_phrase : bool -> formatter -> Parsetree.toplevel_phrase -> bool phrase executed with no errors and [false] otherwise. First bool says whether the values and types of the results should be printed. Uncaught exceptions are always printed. *) +val preprocess_phrase : + formatter -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase + (* Preprocess the given toplevel phrase using regular and ppx + preprocessors. Return the updated phrase. *) val use_file : formatter -> string -> bool val use_silently : formatter -> string -> bool +val mod_use_file : formatter -> string -> bool (* Read and execute commands from a file. [use_file] prints the types and values of the results. - [use_silently] does not print them. *) -val eval_path: Path.t -> Obj.t + [use_silently] does not print them. + [mod_use_file] wrap the file contents into a module. *) +val eval_path: Env.t -> Path.t -> Obj.t (* Return the toplevel object referred to by the given path *) (* Printing of values *) @@ -60,8 +69,19 @@ val eval_path: Path.t -> Obj.t val print_value: Env.t -> Obj.t -> formatter -> Types.type_expr -> unit val print_untyped_exception: formatter -> Obj.t -> unit +type ('a, 'b) gen_printer = + | Zero of 'b + | Succ of ('a -> ('a, 'b) gen_printer) + val install_printer : Path.t -> Types.type_expr -> (formatter -> Obj.t -> unit) -> unit +val install_generic_printer : + Path.t -> Path.t -> + (int -> (int -> Obj.t -> Outcometree.out_value, + Obj.t -> Outcometree.out_value) gen_printer) -> unit +val install_generic_printer' : + Path.t -> Path.t -> (formatter -> Obj.t -> unit, + formatter -> Obj.t -> unit) gen_printer -> unit val remove_printer : Path.t -> unit val max_printer_depth: int ref @@ -95,7 +115,7 @@ val print_out_phrase : (* Hooks for external line editor *) -val read_interactive_input : (string -> string -> int -> int * bool) ref +val read_interactive_input : (string -> bytes -> int -> int * bool) ref (* Hooks for initialization *) diff --git a/toplevel/opttopmain.ml b/toplevel/opttopmain.ml index 51d1daac..2f1795e1 100644 --- a/toplevel/opttopmain.ml +++ b/toplevel/opttopmain.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Clflags @@ -67,9 +70,73 @@ module Options = Main_args.Make_opttop_options (struct let dir = Misc.expand_directory Config.standard_library dir in include_dirs := dir :: !include_dirs let _init s = init_file := Some s - let _inline n = inline_threshold := n * 8 + let _noinit = set noinit + let _clambda_checks () = clambda_checks := true + let _inline spec = + Float_arg_helper.parse spec ~update:inline_threshold + ~help_text:"Syntax: -inline | =[,...]" + let _inline_indirect_cost spec = + Int_arg_helper.parse spec ~update:inline_indirect_cost + ~help_text:"Syntax: -inline-indirect-cost | =[,...]" + let _inline_toplevel spec = + Int_arg_helper.parse spec ~update:inline_toplevel_threshold + ~help_text:"Syntax: -inline-toplevel | =[,...]" + let _inlining_report () = inlining_report := true + let _dump_pass pass = set_dumped_pass pass true + let _rounds n = simplify_rounds := Some n + let _inline_max_unroll spec = + Int_arg_helper.parse spec ~update:inline_max_unroll + ~help_text:"Syntax: -inline-max-unroll | =[,...]" + let _classic_inlining () = classic_inlining := true + let _inline_call_cost spec = + Int_arg_helper.parse spec ~update:inline_call_cost + ~help_text:"Syntax: -inline-call-cost | =[,...]" + let _inline_alloc_cost spec = + Int_arg_helper.parse spec ~update:inline_alloc_cost + ~help_text:"Syntax: -inline-alloc-cost | =[,...]" + let _inline_prim_cost spec = + Int_arg_helper.parse spec ~update:inline_prim_cost + ~help_text:"Syntax: -inline-prim-cost | =[,...]" + let _inline_branch_cost spec = + Int_arg_helper.parse spec ~update:inline_branch_cost + ~help_text:"Syntax: -inline-branch-cost | =[,...]" + let _inline_lifting_benefit spec = + Int_arg_helper.parse spec ~update:inline_lifting_benefit + ~help_text:"Syntax: -inline-lifting-benefit | =[,...]" + let _inline_branch_factor spec = + Float_arg_helper.parse spec ~update:inline_branch_factor + ~help_text:"Syntax: -inline-branch-factor | =[,...]" + let _inline_max_depth spec = + Int_arg_helper.parse spec ~update:inline_max_depth + ~help_text:"Syntax: -inline-max-depth | =[,...]" + let _no_unbox_free_vars_of_closures = clear unbox_free_vars_of_closures + let _no_unbox_specialised_args = clear unbox_specialised_args + let _o s = output_name := Some s + let _o2 () = + default_simplify_rounds := 2; + use_inlining_arguments_set o2_arguments; + use_inlining_arguments_set ~round:0 o1_arguments + let _o3 () = + default_simplify_rounds := 3; + use_inlining_arguments_set o3_arguments; + use_inlining_arguments_set ~round:1 o2_arguments; + use_inlining_arguments_set ~round:0 o1_arguments + let _remove_unused_arguments = set remove_unused_arguments + let _unbox_closures = set unbox_closures + let _unbox_closures_factor f = unbox_closures_factor := f + let _drawclambda = set dump_rawclambda + let _dclambda = set dump_clambda + let _drawflambda = set dump_rawflambda + let _dflambda = set dump_flambda + let _dflambda_let stamp = dump_flambda_let := Some stamp + let _dflambda_verbose () = + set dump_flambda (); + set dump_flambda_verbose () + let _dflambda_no_invariants = clear flambda_invariant_checks let _labels = clear classic + let _alias_deps = clear transparent_modules let _no_alias_deps = set transparent_modules + let _app_funct = set applicative_functors let _no_app_funct = clear applicative_functors let _noassert = set noassert let _nolabels = set classic @@ -78,10 +145,14 @@ module Options = Main_args.Make_opttop_options (struct let _nostdlib = set no_std_include let _ppx s = Compenv.first_ppx := s :: !Compenv.first_ppx let _principal = set principal + let _no_principal = clear principal let _real_paths = set real_paths let _rectypes = set recursive_types + let _no_rectypes = clear recursive_types let _strict_sequence = set strict_sequence + let _no_strict_sequence = clear strict_sequence let _strict_formats = set strict_formats + let _no_strict_formats = clear strict_formats let _S = set keep_asm_file let _short_paths = clear real_paths let _stdin () = file_argument "" @@ -97,10 +168,12 @@ module Options = Main_args.Make_opttop_options (struct let _dtypedtree = set dump_typedtree let _drawlambda = set dump_rawlambda let _dlambda = set dump_lambda + let _drawclambda = set dump_rawclambda let _dclambda = set dump_clambda let _dcmm = set dump_cmm let _dsel = set dump_selection let _dcombine = set dump_combine + let _dcse = set dump_cse let _dlive () = dump_live := true; Printmach.print_live := true let _dspill = set dump_spill let _dsplit = set dump_split @@ -111,11 +184,15 @@ module Options = Main_args.Make_opttop_options (struct let _dscheduling = set dump_scheduling let _dlinear = set dump_linear let _dstartup = set keep_startup_file + let _safe_string = clear unsafe_string + let _unsafe_string = set unsafe_string + let _open s = open_modules := s :: !open_modules let anonymous = file_argument end);; let main () = + native_code := true; Arg.parse Options.list file_argument usage; if not (prepare Format.err_formatter) then exit 2; Opttoploop.loop Format.std_formatter diff --git a/toplevel/opttopmain.mli b/toplevel/opttopmain.mli index 74044e51..93fea4c7 100644 --- a/toplevel/opttopmain.mli +++ b/toplevel/opttopmain.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Start the [ocaml] toplevel loop *) diff --git a/toplevel/opttopstart.ml b/toplevel/opttopstart.ml index 9fa9b47f..a8127208 100644 --- a/toplevel/opttopstart.ml +++ b/toplevel/opttopstart.ml @@ -1,13 +1,16 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) let _ = Opttopmain.main() diff --git a/toplevel/topdirs.ml b/toplevel/topdirs.ml index 7ba572b2..7cce1987 100644 --- a/toplevel/topdirs.ml +++ b/toplevel/topdirs.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Toplevel directives *) @@ -23,11 +26,45 @@ open Toploop (* The standard output formatter *) let std_out = std_formatter +(* Directive sections (used in #help) *) +let section_general = "General" +let section_run = "Loading code" +let section_env = "Environment queries" + +let section_print = "Pretty-printing" +let section_trace = "Tracing" +let section_options = "Compiler options" + +let section_undocumented = "Undocumented" + +(* we will print the sections in the first list, + then all user-defined sections, + then the sections in the second list, + then all undocumented directives *) +let order_of_sections = + ([ + section_general; + section_run; + section_env; + ], [ + section_print; + section_trace; + section_options; + + section_undocumented; + ]) +(* Do not forget to keep the directives synchronized with the manual in + manual/manual/cmds/top.etex *) + (* To quit *) let dir_quit () = exit 0 -let _ = Hashtbl.add directive_table "quit" (Directive_none dir_quit) +let _ = add_directive "quit" (Directive_none dir_quit) + { + section = section_general; + doc = "Exit the toplevel."; + } (* To add a directory to the load path *) @@ -36,7 +73,12 @@ let dir_directory s = Config.load_path := d :: !Config.load_path; Dll.add_path [d] -let _ = Hashtbl.add directive_table "directory" (Directive_string dir_directory) +let _ = add_directive "directory" (Directive_string dir_directory) + { + section = section_run; + doc = "Add the given directory to search path for source and compiled \ + files."; + } (* To remove a directory from the load path *) let dir_remove_directory s = @@ -44,16 +86,20 @@ let dir_remove_directory s = Config.load_path := List.filter (fun d' -> d' <> d) !Config.load_path; Dll.remove_path [d] -let _ = - Hashtbl.add directive_table "remove_directory" - (Directive_string dir_remove_directory) - +let _ = add_directive "remove_directory" (Directive_string dir_remove_directory) + { + section = section_run; + doc = "Remove the given directory from the search path."; + } (* To change the current directory *) let dir_cd s = Sys.chdir s -let _ = Hashtbl.add directive_table "cd" (Directive_string dir_cd) - +let _ = add_directive "cd" (Directive_string dir_cd) + { + section = section_run; + doc = "Change the current working directory."; + } (* Load in-core a .cmo file *) exception Load_failed @@ -86,11 +132,19 @@ let load_compunit ic filename ppf compunit = let initial_symtable = Symtable.current_state() in Symtable.patch_object code compunit.cu_reloc; Symtable.update_global_table(); + let events = + if compunit.cu_debug = 0 then [| |] + else begin + seek_in ic compunit.cu_debug; + [| input_value ic |] + end in + Meta.add_debug_info code code_size events; begin try may_trace := true; ignore((Meta.reify_bytecode code code_size) ()); may_trace := false; with exn -> + record_backtrace (); may_trace := false; Symtable.restore_state initial_symtable; print_exception_outcome ppf exn; @@ -114,7 +168,6 @@ let rec load_file recursive ppf name = raise exn and really_load_file recursive ppf name filename ic = - let ic = open_in_bin filename in let buffer = really_input_string ic (String.length Config.cmo_magic_number) in try if buffer = Config.cmo_magic_number then begin @@ -165,12 +218,20 @@ and really_load_file recursive ppf name filename ic = let dir_load ppf name = ignore (load_file false ppf name) -let _ = Hashtbl.add directive_table "load" (Directive_string (dir_load std_out)) +let _ = add_directive "load" (Directive_string (dir_load std_out)) + { + section = section_run; + doc = "Load in memory a bytecode object, produced by ocamlc."; + } let dir_load_rec ppf name = ignore (load_file true ppf name) -let _ = Hashtbl.add directive_table "load_rec" - (Directive_string (dir_load_rec std_out)) +let _ = add_directive "load_rec" + (Directive_string (dir_load_rec std_out)) + { + section = section_run; + doc = "As #load, but loads dependencies recursively."; + } let load_file = load_file false @@ -179,9 +240,19 @@ let load_file = load_file false let dir_use ppf name = ignore(Toploop.use_file ppf name) let dir_mod_use ppf name = ignore(Toploop.mod_use_file ppf name) -let _ = Hashtbl.add directive_table "use" (Directive_string (dir_use std_out)) -let _ = Hashtbl.add directive_table "mod_use" - (Directive_string (dir_mod_use std_out)) +let _ = add_directive "use" (Directive_string (dir_use std_out)) + { + section = section_run; + doc = "Read, compile and execute source phrases from the given file."; + } + +let _ = add_directive "mod_use" (Directive_string (dir_mod_use std_out)) + { + section = section_run; + doc = "Usage is identical to #use but #mod_use \ + wraps the contents in a module."; + } + (* Install, remove a printer *) @@ -236,7 +307,8 @@ let match_generic_printer_type ppf desc path args printer_type = List.map (fun ty_var -> Ctype.newconstr printer_type [ty_var]) args in let ty_expected = List.fold_right - (fun ty_arg ty -> Ctype.newty (Tarrow ("", ty_arg, ty, Cunknown))) + (fun ty_arg ty -> Ctype.newty (Tarrow (Asttypes.Nolabel, ty_arg, ty, + Cunknown))) ty_args (Ctype.newconstr printer_type [ty_target]) in Ctype.unify !toplevel_env ty_expected @@ -315,10 +387,19 @@ let dir_remove_printer ppf lid = end with Exit -> () -let _ = Hashtbl.add directive_table "install_printer" - (Directive_ident (dir_install_printer std_out)) -let _ = Hashtbl.add directive_table "remove_printer" - (Directive_ident (dir_remove_printer std_out)) +let _ = add_directive "install_printer" + (Directive_ident (dir_install_printer std_out)) + { + section = section_print; + doc = "Registers a printer for values of a certain type."; + } + +let _ = add_directive "remove_printer" + (Directive_ident (dir_remove_printer std_out)) + { + section = section_print; + doc = "Remove the named function from the table of toplevel printers."; + } (* The trace *) @@ -397,19 +478,15 @@ let parse_warnings ppf iserr s = (* Typing information *) -let rec trim_modtype = function - Mty_signature _ -> Mty_signature [] - | Mty_functor (id, mty, mty') -> - Mty_functor (id, mty, trim_modtype mty') - | Mty_ident _ | Mty_alias _ as mty -> mty - let trim_signature = function Mty_signature sg -> Mty_signature (List.map (function Sig_module (id, md, rs) -> - Sig_module (id, {md with md_type = trim_modtype md.md_type}, + Sig_module (id, {md with md_attributes = + (Location.mknoloc "...", Parsetree.PStr []) + :: md.md_attributes}, rs) (*| Sig_modtype (id, Modtype_manifest mty) -> Sig_modtype (id, Modtype_manifest (trim_modtype mty))*) @@ -440,9 +517,15 @@ let show_prim to_sig ppf lid = let all_show_funs = ref [] -let reg_show_prim name to_sig = +let reg_show_prim name to_sig doc = all_show_funs := to_sig :: !all_show_funs; - Hashtbl.add directive_table name (Directive_ident (show_prim to_sig std_out)) + add_directive + name + (Directive_ident (show_prim to_sig std_out)) + { + section = section_env; + doc; + } let () = reg_show_prim "show_val" @@ -450,6 +533,7 @@ let () = let path, desc = Typetexp.find_value env loc lid in [ Sig_value (id, desc) ] ) + "Print the signature of the corresponding value." let () = reg_show_prim "show_type" @@ -457,6 +541,7 @@ let () = let path, desc = Typetexp.find_type env loc lid in [ Sig_type (id, desc, Trec_not) ] ) + "Print the signature of the corresponding type constructor." let () = reg_show_prim "show_exception" @@ -471,7 +556,7 @@ let () = let ext = { ext_type_path = Predef.path_exn; ext_type_params = []; - ext_args = desc.cstr_args; + ext_args = Cstr_tuple desc.cstr_args; ext_ret_type = ret_type; ext_private = Asttypes.Public; Types.ext_loc = desc.cstr_loc; @@ -479,6 +564,7 @@ let () = in [Sig_typext (id, ext, Text_exception)] ) + "Print the signature of the corresponding exception." let () = reg_show_prim "show_module" @@ -487,6 +573,7 @@ let () = [ Sig_module (id, {md with md_type = trim_signature md.md_type}, Trec_not) ] ) + "Print the signature of the corresponding module." let () = reg_show_prim "show_module_type" @@ -494,6 +581,7 @@ let () = let path, desc = Typetexp.find_modtype env loc lid in [ Sig_modtype (id, desc) ] ) + "Print the signature of the corresponding module type." let () = reg_show_prim "show_class" @@ -501,6 +589,7 @@ let () = let path, desc = Typetexp.find_class env loc lid in [ Sig_class (id, desc, Trec_not) ] ) + "Print the signature of the corresponding class." let () = reg_show_prim "show_class_type" @@ -508,7 +597,7 @@ let () = let path, desc = Typetexp.find_class_type env loc lid in [ Sig_class_type (id, desc, Trec_not) ] ) - + "Print the signature of the corresponding class type." let show env loc id lid = let sg = @@ -519,39 +608,158 @@ let show env loc id lid = if sg = [] then raise Not_found else sg let () = - Hashtbl.add directive_table "show" (Directive_ident (show_prim show std_out)) - -let _ = - Hashtbl.add directive_table "trace" (Directive_ident (dir_trace std_out)); - Hashtbl.add directive_table "untrace" (Directive_ident (dir_untrace std_out)); - Hashtbl.add directive_table - "untrace_all" (Directive_none (dir_untrace_all std_out)); + add_directive "show" (Directive_ident (show_prim show std_out)) + { + section = section_env; + doc = "Print the signatures of components \ + from any of the above categories."; + } + +let _ = add_directive "trace" + (Directive_ident (dir_trace std_out)) + { + section = section_trace; + doc = "All calls to the function \ + named function-name will be traced."; + } + +let _ = add_directive "untrace" + (Directive_ident (dir_untrace std_out)) + { + section = section_trace; + doc = "Stop tracing the given function."; + } + +let _ = add_directive "untrace_all" + (Directive_none (dir_untrace_all std_out)) + { + section = section_trace; + doc = "Stop tracing all functions traced so far."; + } (* Control the printing of values *) - Hashtbl.add directive_table "print_depth" - (Directive_int(fun n -> max_printer_depth := n)); - Hashtbl.add directive_table "print_length" - (Directive_int(fun n -> max_printer_steps := n)); +let _ = add_directive "print_depth" + (Directive_int(fun n -> max_printer_depth := n)) + { + section = section_print; + doc = "Limit the printing of values to a maximal depth of n."; + } -(* Set various compiler flags *) +let _ = add_directive "print_length" + (Directive_int(fun n -> max_printer_steps := n)) + { + section = section_print; + doc = "Limit the number of value nodes printed to at most n."; + } - Hashtbl.add directive_table "labels" - (Directive_bool(fun b -> Clflags.classic := not b)); - - Hashtbl.add directive_table "principal" - (Directive_bool(fun b -> Clflags.principal := b)); - - Hashtbl.add directive_table "rectypes" - (Directive_none(fun () -> Clflags.recursive_types := true)); - - Hashtbl.add directive_table "ppx" - (Directive_string(fun s -> Clflags.all_ppx := s :: !Clflags.all_ppx)); +(* Set various compiler flags *) - Hashtbl.add directive_table "warnings" - (Directive_string (parse_warnings std_out false)); +let _ = add_directive "labels" + (Directive_bool(fun b -> Clflags.classic := not b)) + { + section = section_options; + doc = "Choose whether to ignore labels in function types."; + } + +let _ = add_directive "principal" + (Directive_bool(fun b -> Clflags.principal := b)) + { + section = section_options; + doc = "Make sure that all types are derived in a principal way."; + } + +let _ = add_directive "rectypes" + (Directive_none(fun () -> Clflags.recursive_types := true)) + { + section = section_options; + doc = "Allow arbitrary recursive types during type-checking."; + } + +let _ = add_directive "ppx" + (Directive_string(fun s -> Clflags.all_ppx := s :: !Clflags.all_ppx)) + { + section = section_options; + doc = "After parsing, pipe the abstract \ + syntax tree through the preprocessor command."; + } + +let _ = add_directive "warnings" + (Directive_string (parse_warnings std_out false)) + { + section = section_options; + doc = "Enable or disable warnings according to the argument."; + } + +let _ = add_directive "warn_error" + (Directive_string (parse_warnings std_out true)) + { + section = section_options; + doc = "Treat as errors the warnings enabled by the argument."; + } + +(* #help directive *) + +let directive_sections () = + let sections = Hashtbl.create 10 in + let add_dir name dir = + let section, doc = + match Hashtbl.find directive_info_table name with + | { section; doc } -> section, Some doc + | exception Not_found -> "Undocumented", None + in + Hashtbl.replace sections section + ((name, dir, doc) + :: (try Hashtbl.find sections section with Not_found -> [])) + in + Hashtbl.iter add_dir directive_table; + let take_section section = + if not (Hashtbl.mem sections section) then (section, []) + else begin + let section_dirs = + Hashtbl.find sections section + |> List.sort (fun (n1, _, _) (n2, _, _) -> String.compare n1 n2) in + Hashtbl.remove sections section; + (section, section_dirs) + end + in + let before, after = order_of_sections in + let sections_before = List.map take_section before in + let sections_after = List.map take_section after in + let sections_user = + Hashtbl.fold (fun section _ acc -> section::acc) sections [] + |> List.sort String.compare + |> List.map take_section in + sections_before @ sections_user @ sections_after + +let print_directive ppf (name, directive, doc) = + let param = match directive with + | Directive_none _ -> "" + | Directive_string _ -> " " + | Directive_int _ -> " " + | Directive_bool _ -> " " + | Directive_ident _ -> " " in + match doc with + | None -> printf "#%s%s@." name param + | Some doc -> + printf "@[#%s%s@\n%a@]@." + name param + Format.pp_print_text doc + +let print_section ppf (section, directives) = + if directives <> [] then begin + fprintf ppf "%30s%s@." "" section; + List.iter (print_directive ppf) directives; + fprintf ppf "@."; + end - Hashtbl.add directive_table "warn_error" - (Directive_string (parse_warnings std_out true)); +let print_directives ppf () = + List.iter (print_section ppf) (directive_sections ()) - () +let _ = add_directive "help" + (Directive_none (print_directives std_out)) + { + section = section_general; + doc = "Prints a list of all available directives, with \ + corresponding argument type if appropriate."; + } diff --git a/toplevel/topdirs.mli b/toplevel/topdirs.mli index 42ea4ddb..1cdc2fa2 100644 --- a/toplevel/topdirs.mli +++ b/toplevel/topdirs.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The toplevel directives. *) diff --git a/toplevel/toplevellib.mllib b/toplevel/toplevellib.mllib deleted file mode 100644 index 886d1d2c..00000000 --- a/toplevel/toplevellib.mllib +++ /dev/null @@ -1,21 +0,0 @@ -Myocamlbuild_config -Misc Tbl Config Clflags Terminfo Ccomp Warnings Consistbl - -Location Longident Syntaxerr Parser -Lexer Parse Printast - -Ident Path Primitive Types -Btype Oprint Subst Predef Datarepr -Cmi_format Env -Typedtree -Cmt_format Ctype Printtyp Includeclass Mtype Includecore -Includemod Parmatch Typetexp Stypes Typecore -Typedecl Typeclass Typemod - -Lambda Printlambda Typeopt Switch Matching Translobj Translcore -Translclass Translmod Simplif Runtimedef - -Meta Instruct Bytegen Printinstr Opcodes Emitcode -Bytesections Dll Symtable Bytelink Bytelibrarian Bytepackager - -Pparse Errors Compile Main_args Genprintval Toploop Trace Topdirs Topmain diff --git a/toplevel/toploop.ml b/toplevel/toploop.ml index a3cb06b0..1e54ed7d 100644 --- a/toplevel/toploop.ml +++ b/toplevel/toploop.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The interactive toplevel loop *) @@ -29,6 +32,11 @@ type directive_fun = | Directive_ident of (Longident.t -> unit) | Directive_bool of (bool -> unit) +type directive_info = { + section: string; + doc: string; +} + (* The table of toplevel value bindings and its accessors *) module StringMap = Map.Make(String) @@ -116,7 +124,7 @@ let input_name = Location.input_name let parse_mod_use_file name lb = let modname = - String.capitalize (Filename.chop_extension (Filename.basename name)) + String.capitalize_ascii (Filename.chop_extension (Filename.basename name)) in let items = List.concat @@ -142,6 +150,12 @@ let toplevel_startup_hook = ref (fun () -> ()) let may_trace = ref false (* Global lock on tracing *) type evaluation_outcome = Result of Obj.t | Exception of exn +let backtrace = ref None + +let record_backtrace () = + if Printexc.backtrace_status () + then backtrace := Some (Printexc.get_backtrace ()) + let load_lambda ppf lam = if !Clflags.dump_rawlambda then fprintf ppf "%a@." Printlambda.lambda lam; let slam = Simplif.simplify_lambda lam in @@ -151,7 +165,10 @@ let load_lambda ppf lam = fprintf ppf "%a%a@." Printinstr.instrlist init_code Printinstr.instrlist fun_code; - let (code, code_size, reloc) = Emitcode.to_memory init_code fun_code in + let (code, code_size, reloc, events) = + Emitcode.to_memory init_code fun_code + in + Meta.add_debug_info code code_size [| events |]; let can_free = (fun_code = []) in let initial_symtable = Symtable.current_state() in Symtable.patch_object code reloc; @@ -163,13 +180,16 @@ let load_lambda ppf lam = let retval = (Meta.reify_bytecode code code_size) () in may_trace := false; if can_free then begin + Meta.remove_debug_info code; Meta.static_release_bytecode code code_size; Meta.static_free code; end; Result retval with x -> may_trace := false; + record_backtrace (); if can_free then begin + Meta.remove_debug_info code; Meta.static_release_bytecode code code_size; Meta.static_free code; end; @@ -179,50 +199,14 @@ let load_lambda ppf lam = (* Print the outcome of an evaluation *) -let rec pr_item env items = - Printtyp.hide_rec_items items; - match items with - | Sig_value(id, decl) :: rem -> - let tree = Printtyp.tree_of_value_description id decl in - let valopt = - match decl.val_kind with - | Val_prim _ -> None - | _ -> - let v = - outval_of_value env (getvalue (Translmod.toplevel_name id)) - decl.val_type - in - Some v - in - Some (tree, valopt, rem) - | Sig_type(id, _, _) :: rem when Btype.is_row_name (Ident.name id) -> - pr_item env rem - | Sig_type(id, decl, rs) :: rem -> - let tree = Printtyp.tree_of_type_declaration id decl rs in - Some (tree, None, rem) - | Sig_typext(id, ext, es) :: rem -> - let tree = Printtyp.tree_of_extension_constructor id ext es in - Some (tree, None, rem) - | Sig_module(id, md, rs) :: rem -> - let tree = Printtyp.tree_of_module id md.md_type rs in - Some (tree, None, rem) - | Sig_modtype(id, decl) :: rem -> - let tree = Printtyp.tree_of_modtype_declaration id decl in - Some (tree, None, rem) - | Sig_class(id, decl, rs) :: cltydecl :: tydecl1 :: tydecl2 :: rem -> - let tree = Printtyp.tree_of_class_declaration id decl rs in - Some (tree, None, rem) - | Sig_class_type(id, decl, rs) :: tydecl1 :: tydecl2 :: rem -> - let tree = Printtyp.tree_of_cltype_declaration id decl rs in - Some (tree, None, rem) - | _ -> None - -let rec item_list env = function - | [] -> [] - | items -> - match pr_item env items with - | None -> [] - | Some (tree, valopt, items) -> (tree, valopt) :: item_list env items +let pr_item = + Printtyp.print_items + (fun env -> function + | Sig_value(id, {val_kind = Val_reg; val_type}) -> + Some (outval_of_value env (getvalue (Translmod.toplevel_name id)) + val_type) + | _ -> None + ) (* The current typing environment for the toplevel *) @@ -236,12 +220,26 @@ let print_out_exception ppf exn outv = let print_exception_outcome ppf exn = if exn = Out_of_memory then Gc.full_major (); let outv = outval_of_value !toplevel_env (Obj.repr exn) Predef.type_exn in - print_out_exception ppf exn outv + print_out_exception ppf exn outv; + if Printexc.backtrace_status () + then + match !backtrace with + | None -> () + | Some b -> + print_string b; + backtrace := None + + +(* Inserting new toplevel directives *) -(* The table of toplevel directives. - Filled by functions from module topdirs. *) +let directive_table = (Hashtbl.create 23 : (string, directive_fun) Hashtbl.t) -let directive_table = (Hashtbl.create 13 : (string, directive_fun) Hashtbl.t) +let directive_info_table = + (Hashtbl.create 23 : (string, directive_info) Hashtbl.t) + +let add_directive name dir_fun dir_info = + Hashtbl.add directive_table name dir_fun; + Hashtbl.add directive_info_table name dir_info (* Execute a toplevel phrase *) @@ -266,12 +264,23 @@ let execute_phrase print_outcome ppf phr = if print_outcome then Printtyp.wrap_printing_env oldenv (fun () -> match str.str_items with - | [ { str_desc = Tstr_eval (exp, _attrs) }] -> + | [ { str_desc = + (Tstr_eval (exp, _) + |Tstr_value + (Asttypes.Nonrecursive, + [{vb_pat = {pat_desc=Tpat_any}; + vb_expr = exp} + ] + ) + ) + } + ] -> let outv = outval_of_value newenv v exp.exp_type in let ty = Printtyp.tree_of_type_scheme exp.exp_type in Ophr_eval (outv, ty) + | [] -> Ophr_signature [] - | _ -> Ophr_signature (item_list newenv sg')) + | _ -> Ophr_signature (pr_item newenv sg')) else Ophr_signature [] | Exception exn -> toplevel_env := oldenv; @@ -282,6 +291,15 @@ let execute_phrase print_outcome ppf phr = Ophr_exception (exn, outv) in !print_out_phrase ppf out_phr; + if Printexc.backtrace_status () + then begin + match !backtrace with + | None -> () + | Some b -> + pp_print_string ppf b; + pp_print_flush ppf (); + backtrace := None; + end; begin match out_phr with | Ophr_eval (_, _) | Ophr_signature _ -> true | Ophr_exception _ -> false @@ -296,13 +314,30 @@ let execute_phrase print_outcome ppf phr = in begin match d with | None -> - fprintf ppf "Unknown directive `%s'.@." dir_name; + fprintf ppf "Unknown directive `%s'." dir_name; + let directives = + Hashtbl.fold (fun dir _ acc -> dir::acc) directive_table [] in + Misc.did_you_mean ppf + (fun () -> Misc.spellcheck directives dir_name); + fprintf ppf "@."; false | Some d -> match d, dir_arg with | Directive_none f, Pdir_none -> f (); true | Directive_string f, Pdir_string s -> f s; true - | Directive_int f, Pdir_int n -> f n; true + | Directive_int f, Pdir_int (n,None) -> + begin match Int_literal_converter.int n with + | n -> f n; true + | exception _ -> + fprintf ppf "Integer literal exceeds the range of \ + representable integers for directive `%s'.@." + dir_name; + false + end + | Directive_int f, Pdir_int (n, Some _) -> + fprintf ppf "Wrong integer literal for directive `%s'.@." + dir_name; + false | Directive_ident f, Pdir_ident lid -> f lid; true | Directive_bool f, Pdir_bool b -> f b; true | _ -> @@ -311,6 +346,11 @@ let execute_phrase print_outcome ppf phr = false end +let execute_phrase print_outcome ppf phr = + try execute_phrase print_outcome ppf phr + with exn -> + Warnings.reset_fatal (); + raise exn (* Temporary assignment to a reference *) @@ -355,6 +395,7 @@ let use_file ppf wrap_mod name = end in let lb = Lexing.from_channel ic in + Warnings.reset_fatal (); Location.init lb filename; (* Skip initial #! line if any *) Lexer.skip_sharp_bang lb; @@ -433,6 +474,10 @@ let refill_lexbuf buffer len = can call directives from Topdirs. *) let _ = + if !Sys.interactive then (* PR#6108 *) + invalid_arg "The ocamltoplevel.cma library from compiler-libs \ + cannot be loaded inside the OCaml toplevel"; + Clflags.debug := true; Sys.interactive := true; let crc_intfs = Symtable.init_toplevel() in Compmisc.init_path false; @@ -476,7 +521,11 @@ exception PPerror let loop ppf = Location.formatter_for_warnings := ppf; fprintf ppf " OCaml version %s@.@." Config.version; - initialize_toplevel_env (); + begin + try initialize_toplevel_env () + with Env.Error _ | Typetexp.Error _ as exn -> + Location.report_exception ppf exn; exit 2 + end; let lb = Lexing.from_function refill_lexbuf in Location.init lb "//toplevel//"; Location.input_name := "//toplevel//"; @@ -488,6 +537,7 @@ let loop ppf = try Lexing.flush_input lb; Location.reset(); + Warnings.reset_fatal (); first_line := true; let phr = try !parse_toplevel_phrase lb with Exit -> raise PPerror in let phr = preprocess_phrase ppf phr in @@ -508,7 +558,18 @@ let run_script ppf name args = Array.blit args 0 Sys.argv 0 len; Obj.truncate (Obj.repr Sys.argv) len; Arg.current := 0; - Compmisc.init_path false; - toplevel_env := Compmisc.initial_env(); + Compmisc.init_path ~dir:(Filename.dirname name) true; + (* Note: would use [Filename.abspath] here, if we had it. *) + begin + try toplevel_env := Compmisc.initial_env() + with Env.Error _ | Typetexp.Error _ as exn -> + Location.report_exception ppf exn; exit 2 + end; Sys.interactive := false; - use_silently ppf name + let explicit_name = + (* Prevent use_silently from searching in the path. *) + if name <> "" && Filename.is_implicit name + then Filename.concat Filename.current_dir_name name + else name + in + use_silently ppf explicit_name diff --git a/toplevel/toploop.mli b/toplevel/toploop.mli index 6638d769..ba2f0c6d 100644 --- a/toplevel/toploop.mli +++ b/toplevel/toploop.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format @@ -40,8 +43,22 @@ type directive_fun = | Directive_ident of (Longident.t -> unit) | Directive_bool of (bool -> unit) +type directive_info = { + section: string; + doc: string; +} + +val add_directive : string -> directive_fun -> directive_info -> unit + (* Add toplevel directive and its documentation. + + @since 4.03 *) + val directive_table : (string, directive_fun) Hashtbl.t - (* Table of known directives, with their execution function *) + (* Deprecated: please use [add_directive] instead of inserting + in this table directly. *) + +val directive_info_table : (string, directive_info) Hashtbl.t + val toplevel_env : Env.t ref (* Typing environment for the toplevel *) val initialize_toplevel_env : unit -> unit @@ -53,7 +70,8 @@ val execute_phrase : bool -> formatter -> Parsetree.toplevel_phrase -> bool phrase executed with no errors and [false] otherwise. First bool says whether the values and types of the results should be printed. Uncaught exceptions are always printed. *) -val preprocess_phrase : formatter -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase +val preprocess_phrase : + formatter -> Parsetree.toplevel_phrase -> Parsetree.toplevel_phrase (* Preprocess the given toplevel phrase using regular and ppx preprocessors. Return the updated phrase. *) val use_file : formatter -> string -> bool @@ -65,6 +83,7 @@ val mod_use_file : formatter -> string -> bool [mod_use_file] wrap the file contents into a module. *) val eval_path: Env.t -> Path.t -> Obj.t (* Return the toplevel object referred to by the given path *) +val record_backtrace : unit -> unit (* Printing of values *) diff --git a/toplevel/topmain.ml b/toplevel/topmain.ml index 0d8f2d4c..581abd43 100644 --- a/toplevel/topmain.ml +++ b/toplevel/topmain.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Clflags open Compenv @@ -68,7 +71,9 @@ module Options = Main_args.Make_bytetop_options (struct let _init s = init_file := Some s let _noinit = set noinit let _labels = clear classic + let _alias_deps = clear transparent_modules let _no_alias_deps = set transparent_modules + let _app_funct = set applicative_functors let _no_app_funct = clear applicative_functors let _noassert = set noassert let _nolabels = set classic @@ -78,12 +83,16 @@ module Options = Main_args.Make_bytetop_options (struct let _open s = open_modules := s :: !open_modules let _ppx s = first_ppx := s :: !first_ppx let _principal = set principal + let _no_principal = clear principal let _rectypes = set recursive_types + let _no_rectypes = clear recursive_types let _safe_string = clear unsafe_string let _short_paths = clear real_paths let _stdin () = file_argument "" let _strict_sequence = set strict_sequence + let _no_strict_sequence = clear strict_sequence let _strict_formats = set strict_formats + let _no_strict_formats = clear strict_formats let _unsafe = set fast let _unsafe_string = set unsafe_string let _version () = print_version () @@ -96,6 +105,8 @@ module Options = Main_args.Make_bytetop_options (struct let _dsource = set dump_source let _drawlambda = set dump_rawlambda let _dlambda = set dump_lambda + let _dflambda = set dump_flambda + let _dtimings = set print_timings let _dinstr = set dump_instr let anonymous s = file_argument s diff --git a/toplevel/topmain.mli b/toplevel/topmain.mli index 74044e51..93fea4c7 100644 --- a/toplevel/topmain.mli +++ b/toplevel/topmain.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Start the [ocaml] toplevel loop *) diff --git a/toplevel/topstart.ml b/toplevel/topstart.ml index f03e2aa6..e3dd62c9 100644 --- a/toplevel/topstart.ml +++ b/toplevel/topstart.ml @@ -1,13 +1,16 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) let _ = Topmain.main() diff --git a/toplevel/trace.ml b/toplevel/trace.ml index 66904483..fbc03427 100644 --- a/toplevel/trace.ml +++ b/toplevel/trace.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The "trace" facility *) @@ -52,7 +55,8 @@ let set_code_pointer cls ptr = Obj.set_field cls 0 ptr let invoke_traced_function codeptr env arg = Meta.invoke_traced_function codeptr env arg -let print_label ppf l = if l <> "" then fprintf ppf "%s:" l +let print_label ppf l = + if l <> Asttypes.Nolabel then fprintf ppf "%s:" (Printtyp.string_of_label l) (* If a function returns a functional value, wrap it into a trace code *) diff --git a/toplevel/trace.mli b/toplevel/trace.mli index 41c119e6..ab9d217e 100644 --- a/toplevel/trace.mli +++ b/toplevel/trace.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* The "trace" facility *) diff --git a/typing/annot.mli b/typing/annot.mli index f75d4c19..3cae8f27 100644 --- a/typing/annot.mli +++ b/typing/annot.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) -(* *) -(* Copyright 2007 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Damien Doligez, projet Gallium, INRIA Rocquencourt *) +(* *) +(* Copyright 2007 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. *) +(* *) +(**************************************************************************) (* Data types for annotations (Stypes.ml) *) diff --git a/typing/btype.ml b/typing/btype.ml index c1228f62..69c93647 100644 --- a/typing/btype.ml +++ b/typing/btype.ml @@ -1,18 +1,22 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Basic operations on core types *) open Misc +open Asttypes open Types (**** Sets, maps and hashtables of types ****) @@ -61,6 +65,34 @@ let default_mty = function Some mty -> mty | None -> Mty_signature [] +(**** Definitions for backtracking ****) + +type change = + Ctype of type_expr * type_desc + | Ccompress of type_expr * type_desc * type_desc + | Clevel of type_expr * int + | Cname of + (Path.t * type_expr list) option ref * (Path.t * type_expr list) option + | Crow of row_field option ref * row_field option + | Ckind of field_kind option ref * field_kind option + | Ccommu of commutable ref * commutable + | Cuniv of type_expr option ref * type_expr option + | Ctypeset of TypeSet.t ref * TypeSet.t + +type changes = + Change of change * changes ref + | Unchanged + | Invalid + +let trail = Weak.create 1 + +let log_change ch = + match Weak.get trail 0 with None -> () + | Some r -> + let r' = ref Unchanged in + r := Change (ch, r'); + Weak.set trail 0 (Some r') + (**** Representative of a type ****) let rec field_kind_repr = @@ -68,19 +100,25 @@ let rec field_kind_repr = Fvar {contents = Some kind} -> field_kind_repr kind | kind -> kind -let rec repr = - function - {desc = Tlink t'} -> - (* - We do no path compression. Path compression does not seem to - improve notably efficiency, and it prevents from changing a - [Tlink] into another type (for instance, for undoing a - unification). - *) - repr t' - | {desc = Tfield (_, k, _, t')} when field_kind_repr k = Fabsent -> - repr t' - | t -> t +let rec repr_link compress t d = + function + {desc = Tlink t' as d'} -> + repr_link true t d' t' + | {desc = Tfield (_, k, _, t') as d'} when field_kind_repr k = Fabsent -> + repr_link true t d' t' + | t' -> + if compress then begin + log_change (Ccompress (t, t.desc, d)); t.desc <- d + end; + t' + +let repr t = + match t.desc with + Tlink t' as d -> + repr_link false t d t' + | Tfield (_, k, _, t') as d when field_kind_repr k = Fabsent -> + repr_link false t d t' + | _ -> t let rec commu_repr = function Clink r when !r <> Cunknown -> commu_repr !r @@ -253,6 +291,30 @@ type type_iterators = it_type_expr: type_iterators -> type_expr -> unit; it_path: Path.t -> unit; } +let iter_type_expr_cstr_args f = function + | Cstr_tuple tl -> List.iter f tl + | Cstr_record lbls -> List.iter (fun d -> f d.ld_type) lbls + +let map_type_expr_cstr_args f = function + | Cstr_tuple tl -> Cstr_tuple (List.map f tl) + | Cstr_record lbls -> + Cstr_record (List.map (fun d -> {d with ld_type=f d.ld_type}) lbls) + +let iter_type_expr_kind f = function + | Type_abstract -> () + | Type_variant cstrs -> + List.iter + (fun cd -> + iter_type_expr_cstr_args f cd.cd_args; + Misc.may f cd.cd_res + ) + cstrs + | Type_record(lbls, _) -> + List.iter (fun d -> f d.ld_type) lbls + | Type_open -> + () + + let type_iterators = let it_signature it = List.iter (it.it_signature_item it) @@ -273,7 +335,7 @@ let type_iterators = and it_extension_constructor it td = it.it_path td.ext_type_path; List.iter (it.it_type_expr it) td.ext_type_params; - List.iter (it.it_type_expr it) td.ext_args; + iter_type_expr_cstr_args (it.it_type_expr it) td.ext_args; may (it.it_type_expr it) td.ext_ret_type and it_module_declaration it md = it.it_module_type it md.md_type @@ -309,16 +371,8 @@ let type_iterators = | Cty_arrow (_, ty, cty) -> it.it_type_expr it ty; it.it_class_type it cty - and it_type_kind it = function - Type_abstract -> () - | Type_record (ll, _) -> - List.iter (fun ld -> it.it_type_expr it ld.ld_type) ll - | Type_variant cl -> - List.iter (fun cd -> - List.iter (it.it_type_expr it) cd.cd_args; - may (it.it_type_expr it) cd.cd_res) - cl - | Type_open -> () + and it_type_kind it kind = + iter_type_expr_kind (it.it_type_expr it) kind and it_do_type_expr it ty = iter_type_expr (it.it_type_expr it) ty; match ty.desc with @@ -464,7 +518,7 @@ let unmark_type_decl decl = let unmark_extension_constructor ext = List.iter unmark_type ext.ext_type_params; - List.iter unmark_type ext.ext_args; + iter_type_expr_cstr_args unmark_type ext.ext_args; Misc.may unmark_type ext.ext_ret_type let unmark_class_signature sign = @@ -480,10 +534,16 @@ let unmark_class_type cty = (*******************************************) (* Search whether the expansion has been memorized. *) + +let lte_public p1 p2 = (* Private <= Public *) + match p1, p2 with + | Private, _ | _, Public -> true + | Public, Private -> false + let rec find_expans priv p1 = function Mnil -> None | Mcons (priv', p2, ty0, ty, _) - when priv' >= priv && Path.same p1 p2 -> Some ty + when lte_public priv priv' && Path.same p1 p2 -> Some ty | Mcons (_, _, _, _, rem) -> find_expans priv p1 rem | Mlink {contents = rem} -> find_expans priv p1 rem @@ -545,15 +605,17 @@ let check_memorized_abbrevs () = (* Utilities for labels *) (**********************************) -let is_optional l = - String.length l > 0 && l.[0] = '?' +let is_optional = function Optional _ -> true | _ -> false -let label_name l = - if is_optional l then String.sub l 1 (String.length l - 1) - else l +let label_name = function + Nolabel -> "" + | Labelled s + | Optional s -> s -let prefixed_label_name l = - if is_optional l then l else "~" ^ l +let prefixed_label_name = function + Nolabel -> "" + | Labelled s -> "~" ^ s + | Optional s -> "?" ^ s let rec extract_label_aux hd l = function [] -> raise Not_found @@ -568,19 +630,9 @@ let extract_label l ls = extract_label_aux [] l ls (* Utilities for backtracking *) (**********************************) -type change = - Ctype of type_expr * type_desc - | Clevel of type_expr * int - | Cname of - (Path.t * type_expr list) option ref * (Path.t * type_expr list) option - | Crow of row_field option ref * row_field option - | Ckind of field_kind option ref * field_kind option - | Ccommu of commutable ref * commutable - | Cuniv of type_expr option ref * type_expr option - | Ctypeset of TypeSet.t ref * TypeSet.t - let undo_change = function Ctype (ty, desc) -> ty.desc <- desc + | Ccompress (ty, desc, _) -> ty.desc <- desc | Clevel (ty, level) -> ty.level <- level | Cname (r, v) -> r := v | Crow (r, v) -> r := v @@ -589,23 +641,9 @@ let undo_change = function | Cuniv (r, v) -> r := v | Ctypeset (r, v) -> r := v -type changes = - Change of change * changes ref - | Unchanged - | Invalid - type snapshot = changes ref * int - -let trail = Weak.create 1 let last_snapshot = ref 0 -let log_change ch = - match Weak.get trail 0 with None -> () - | Some r -> - let r' = ref Unchanged in - r := Change (ch, r'); - Weak.set trail 0 (Some r') - let log_type ty = if ty.id <= !last_snapshot then log_change (Ctype (ty, ty.desc)) let link_type ty ty' = @@ -670,3 +708,25 @@ let backtrack (changes, old) = changes := Unchanged; last_snapshot := old; Weak.set trail 0 (Some changes) + +let rec rev_compress_log log r = + match !r with + Unchanged | Invalid -> + log + | Change (Ccompress _, next) -> + rev_compress_log (r::log) next + | Change (_, next) -> + rev_compress_log log next + +let undo_compress (changes, old) = + match !changes with + Unchanged + | Invalid -> () + | Change _ -> + let log = rev_compress_log [] changes in + List.iter + (fun r -> match !r with + Change (Ccompress (ty, desc, d), next) when ty.desc == d -> + ty.desc <- desc; r := !next + | _ -> ()) + log diff --git a/typing/btype.mli b/typing/btype.mli index e770fa61..08d8d047 100644 --- a/typing/btype.mli +++ b/typing/btype.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Basic operations on core types *) @@ -162,15 +165,15 @@ val forget_abbrev: (**** Utilities for labels ****) -val is_optional : label -> bool -val label_name : label -> label +val is_optional : arg_label -> bool +val label_name : arg_label -> label (* Returns the label name with first character '?' or '~' as appropriate. *) -val prefixed_label_name : label -> label +val prefixed_label_name : arg_label -> label val extract_label : - label -> (label * 'a) list -> - label * 'a * (label * 'a) list * (label * 'a) list + label -> (arg_label * 'a) list -> + arg_label * 'a * (arg_label * 'a) list * (arg_label * 'a) list (* actual label, value, before list, after list *) (**** Utilities for backtracking ****) @@ -183,6 +186,10 @@ val backtrack: snapshot -> unit (* Backtrack to a given snapshot. Only possible if you have not already backtracked to a previous snapshot. Calls [cleanup_abbrev] internally *) +val undo_compress: snapshot -> unit + (* Backtrack only path compression. Only meaningful if you have + not already backtracked to a previous snapshot. + Does not call [cleanup_abbrev] *) (* Functions to use when modifying a type (only Ctype?) *) val link_type: type_expr -> type_expr -> unit @@ -203,3 +210,10 @@ val log_type: type_expr -> unit (**** Forward declarations ****) val print_raw: (Format.formatter -> type_expr -> unit) ref + +val iter_type_expr_kind: (type_expr -> unit) -> (type_kind -> unit) + +val iter_type_expr_cstr_args: (type_expr -> unit) -> + (constructor_arguments -> unit) +val map_type_expr_cstr_args: (type_expr -> type_expr) -> + (constructor_arguments -> constructor_arguments) diff --git a/typing/cmi_format.ml b/typing/cmi_format.ml index 6f421fdc..c37bb20e 100644 --- a/typing/cmi_format.ml +++ b/typing/cmi_format.ml @@ -1,16 +1,22 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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 pers_flags = Rectypes +type pers_flags = + | Rectypes + | Deprecated of string + | Opaque type error = Not_an_interface of string diff --git a/typing/cmi_format.mli b/typing/cmi_format.mli index 32cec451..252f2f64 100644 --- a/typing/cmi_format.mli +++ b/typing/cmi_format.mli @@ -1,16 +1,22 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) - -type pers_flags = Rectypes +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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 pers_flags = + | Rectypes + | Deprecated of string + | Opaque type cmi_infos = { cmi_name : string; diff --git a/typing/cmt_format.ml b/typing/cmt_format.ml index 6cecb1b6..e552ca39 100644 --- a/typing/cmt_format.ml +++ b/typing/cmt_format.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) open Cmi_format open Typedtree @@ -68,68 +71,36 @@ let need_to_clear_env = let keep_only_summary = Env.keep_only_summary -module ClearEnv = TypedtreeMap.MakeMap (struct - open TypedtreeMap - include DefaultMapArgument - - let leave_pattern p = { p with pat_env = keep_only_summary p.pat_env } - let leave_expression e = - let exp_extra = List.map (function - (Texp_open (ovf, path, lloc, env), loc, attrs) -> - (Texp_open (ovf, path, lloc, keep_only_summary env), loc, attrs) - | exp_extra -> exp_extra) e.exp_extra in - { e with - exp_env = keep_only_summary e.exp_env; - exp_extra = exp_extra } - let leave_class_expr c = - { c with cl_env = keep_only_summary c.cl_env } - let leave_module_expr m = - { m with mod_env = keep_only_summary m.mod_env } - let leave_structure s = - { s with str_final_env = keep_only_summary s.str_final_env } - let leave_structure_item str = - { str with str_env = keep_only_summary str.str_env } - let leave_module_type m = - { m with mty_env = keep_only_summary m.mty_env } - let leave_signature s = - { s with sig_final_env = keep_only_summary s.sig_final_env } - let leave_signature_item s = - { s with sig_env = keep_only_summary s.sig_env } - let leave_core_type c = - { c with ctyp_env = keep_only_summary c.ctyp_env } - let leave_class_type c = - { c with cltyp_env = keep_only_summary c.cltyp_env } - -end) - -let clear_part p = match p with - | Partial_structure s -> Partial_structure (ClearEnv.map_structure s) +open Tast_mapper + +let cenv = + {Tast_mapper.default with env = fun _sub env -> keep_only_summary env} + +let clear_part = function + | Partial_structure s -> Partial_structure (cenv.structure cenv s) | Partial_structure_item s -> - Partial_structure_item (ClearEnv.map_structure_item s) - | Partial_expression e -> Partial_expression (ClearEnv.map_expression e) - | Partial_pattern p -> Partial_pattern (ClearEnv.map_pattern p) - | Partial_class_expr ce -> Partial_class_expr (ClearEnv.map_class_expr ce) - | Partial_signature s -> Partial_signature (ClearEnv.map_signature s) + Partial_structure_item (cenv.structure_item cenv s) + | Partial_expression e -> Partial_expression (cenv.expr cenv e) + | Partial_pattern p -> Partial_pattern (cenv.pat cenv p) + | Partial_class_expr ce -> Partial_class_expr (cenv.class_expr cenv ce) + | Partial_signature s -> Partial_signature (cenv.signature cenv s) | Partial_signature_item s -> - Partial_signature_item (ClearEnv.map_signature_item s) - | Partial_module_type s -> Partial_module_type (ClearEnv.map_module_type s) + Partial_signature_item (cenv.signature_item cenv s) + | Partial_module_type s -> Partial_module_type (cenv.module_type cenv s) let clear_env binary_annots = if need_to_clear_env then match binary_annots with - | Implementation s -> Implementation (ClearEnv.map_structure s) - | Interface s -> Interface (ClearEnv.map_signature s) - | Packed _ -> binary_annots - | Partial_implementation array -> + | Implementation s -> Implementation (cenv.structure cenv s) + | Interface s -> Interface (cenv.signature cenv s) + | Packed _ -> binary_annots + | Partial_implementation array -> Partial_implementation (Array.map clear_part array) - | Partial_interface array -> + | Partial_interface array -> Partial_interface (Array.map clear_part array) else binary_annots - - - exception Error of error let input_cmt ic = (input_value ic : cmt_infos) @@ -167,12 +138,6 @@ let read filename = close_in ic; raise e -let string_of_file filename = - let ic = open_in filename in - let s = Misc.string_of_file ic in - close_in ic; - s - let read_cmt filename = match read filename with _, None -> raise (Error (Not_a_typedtree filename)) @@ -202,6 +167,12 @@ let record_value_dependency vd1 vd2 = let save_cmt filename modname binary_annots sourcefile initial_env sg = 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 @@ -210,8 +181,7 @@ let save_cmt filename modname binary_annots sourcefile initial_env sg = let cmi = { cmi_name = modname; cmi_sign = sg; - cmi_flags = - if !Clflags.recursive_types then [Cmi_format.Rectypes] else []; + cmi_flags = flags; cmi_crcs = imports; } in Some (output_cmi filename oc cmi) diff --git a/typing/cmt_format.mli b/typing/cmt_format.mli index 48fbc639..b1514433 100644 --- a/typing/cmt_format.mli +++ b/typing/cmt_format.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 2012 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* Copyright 2012 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. *) +(* *) +(**************************************************************************) (** cmt and cmti files format. *) diff --git a/typing/ctype.ml b/typing/ctype.ml index d1ff9da5..75211e14 100644 --- a/typing/ctype.ml +++ b/typing/ctype.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Operations on core types *) @@ -49,35 +52,6 @@ open Btype policy can then be easily changed. *) -(* - A faire - ======= - - Revoir affichage des types. - - Etendre la portee d'un alias [... as 'a] a tout le type englobant. - - #-type implementes comme de vraies abreviations. - - Niveaux plus fins pour les identificateurs : - Champ [global] renomme en [level]; - Niveau -1 : global - 0 : module toplevel - 1 : module contenu dans module toplevel - ... - En fait, incrementer le niveau a chaque fois que l'on rentre dans - un module. - - 3 4 6 - \ / / - 1 2 5 - \|/ - 0 - - [Subst] doit ecreter les niveaux (pour qu'un variable non - generalisable dans un module de niveau 2 ne se retrouve pas - generalisable lorsque l'on l'utilise au niveau 0). - - - Traitement de la trace de l'unification separe de la fonction - [unify]. -*) - (**** Errors ****) exception Unify of (type_expr * type_expr) list @@ -116,6 +90,20 @@ let nongen_level = ref 0 let global_level = ref 1 let saved_level = ref [] +type levels = + { current_level: int; nongen_level: int; global_level: int; + saved_level: (int * int) list; } +let save_levels () = + { current_level = !current_level; + nongen_level = !nongen_level; + global_level = !global_level; + saved_level = !saved_level } +let set_levels l = + current_level := l.current_level; + nongen_level := l.nongen_level; + global_level := l.global_level; + saved_level := l.saved_level + let get_current_level () = !current_level let init_def level = current_level := level; nongen_level := level let begin_def () = @@ -182,7 +170,6 @@ let proper_abbrevs path tl abbrev = let newty2 = Btype.newty2 let newty desc = newty2 !current_level desc -let new_global_ty desc = newty2 !global_level desc let newvar ?name () = newty2 !current_level (Tvar name) let newvar2 ?name level = newty2 level (Tvar name) @@ -219,17 +206,6 @@ let umode = ref Expression let generate_equations = ref false let assume_injective = ref false -let set_mode_expression f = - let old_unification_mode = !umode in - try - umode := Expression; - let ret = f () in - umode := old_unification_mode; - ret - with e -> - umode := old_unification_mode; - raise e - let set_mode_pattern ~generate ~injective f = let old_unification_mode = !umode and old_gen = !generate_equations @@ -317,7 +293,7 @@ let associate_fields fields1 fields2 = (**** Check whether an object is open ****) -(* +++ Il faudra penser a eventuellement expanser l'abreviation *) +(* +++ The abbreviation should eventually be expanded *) let rec object_row ty = let ty = repr ty in match ty.desc with @@ -454,38 +430,6 @@ let rec filter_row_fields erase = function (**************************************) -exception Non_closed - -let rec closed_schema_rec ty = - let ty = repr ty in - if ty.level >= lowest_level then begin - let level = ty.level in - ty.level <- pivot_level - level; - match ty.desc with - Tvar _ when level <> generic_level -> - raise Non_closed - | Tfield(_, kind, t1, t2) -> - if field_kind_repr kind = Fpresent then - closed_schema_rec t1; - closed_schema_rec t2 - | Tvariant row -> - let row = row_repr row in - iter_row closed_schema_rec row; - if not (static_row row) then closed_schema_rec row.row_more - | _ -> - iter_type_expr closed_schema_rec ty - end - -(* Return whether all variables of type [ty] are generic. *) -let closed_schema ty = - try - closed_schema_rec ty; - unmark_type ty; - true - with Non_closed -> - unmark_type ty; - false - exception Non_closed of type_expr * bool let free_variables = ref [] @@ -561,7 +505,11 @@ let closed_type_decl decl = (fun {cd_args; cd_res; _} -> match cd_res with | Some _ -> () - | None -> List.iter closed_type cd_args) + | None -> + match cd_args with + | Cstr_tuple l -> List.iter closed_type l + | Cstr_record l -> List.iter (fun l -> closed_type l.ld_type) l + ) v | Type_record(r, rep) -> List.iter (fun l -> closed_type l.ld_type) r @@ -582,7 +530,7 @@ let closed_extension_constructor ext = List.iter mark_type ext.ext_type_params; begin match ext.ext_ret_type with | Some _ -> () - | None -> List.iter closed_type ext.ext_args + | None -> iter_type_expr_cstr_args closed_type ext.ext_args end; unmark_extension_constructor ext; None @@ -594,7 +542,7 @@ type closed_class_failure = CC_Method of type_expr * bool * string * type_expr | CC_Value of type_expr * bool * string * type_expr -exception Failure of closed_class_failure +exception CCFailure of closed_class_failure let closed_class params sign = let ty = object_fields (repr sign.csig_self) in @@ -610,13 +558,13 @@ let closed_class params sign = (fun (lab, kind, ty) -> if field_kind_repr kind = Fpresent then try closed_type ty with Non_closed (ty0, real) -> - raise (Failure (CC_Method (ty0, real, lab, ty)))) + raise (CCFailure (CC_Method (ty0, real, lab, ty)))) fields; mark_type_params (repr sign.csig_self); List.iter unmark_type params; unmark_class_signature sign; None - with Failure reason -> + with CCFailure reason -> mark_type_params (repr sign.csig_self); List.iter unmark_type params; unmark_class_signature sign; @@ -648,32 +596,21 @@ let duplicate_class_type ty = [expand_abbrev] (via [subst]) requires these expansions to be preserved. Does it worth duplicating this code ? *) -let rec iter_generalize tyl ty = +let rec generalize ty = let ty = repr ty in if (ty.level > !current_level) && (ty.level <> generic_level) then begin set_level ty generic_level; begin match ty.desc with Tconstr (_, _, abbrev) -> - iter_abbrev (iter_generalize tyl) !abbrev + iter_abbrev generalize !abbrev | _ -> () end; - iter_type_expr (iter_generalize tyl) ty - end else - tyl := ty :: !tyl - -let iter_generalize tyl ty = - simple_abbrevs := Mnil; - iter_generalize tyl ty + iter_type_expr generalize ty + end let generalize ty = - iter_generalize (ref []) ty - -(* Efficient repeated generalisation of the same type *) -let iterative_generalization min_level tyl = - let tyl' = ref [] in - List.iter (iter_generalize tyl') tyl; - List.fold_right (fun ty l -> if ty.level <= min_level then l else ty::l) - !tyl' [] + simple_abbrevs := Mnil; + generalize ty (* Generalize the structure and lower the variables *) @@ -753,7 +690,14 @@ let rec normalize_package_path env p = in match t with | Some (Mty_ident p) -> normalize_package_path env p - | Some (Mty_signature _ | Mty_functor _ | Mty_alias _) | None -> p + | Some (Mty_signature _ | Mty_functor _ | Mty_alias _) | None -> + match p with + Path.Pdot (p1, s, n) -> + (* For module aliases *) + let p1' = Env.normalize_path None env p1 in + if Path.same p1 p1' then p else + normalize_package_path env (Path.Pdot (p1', s, n)) + | _ -> p let rec update_level env level ty = let ty = repr ty in @@ -775,7 +719,7 @@ let rec update_level env level ty = if level < get_level env p then raise (Unify [(ty, newvar2 level)]); iter_type_expr (update_level env level) ty end - | Tpackage (p, nl, tl) when level < get_level env p -> + | Tpackage (p, nl, tl) when level < Path.binding_time p -> let p' = normalize_package_path env p in if Path.same p p' then raise (Unify [(ty, newvar2 level)]); log_type ty; ty.desc <- Tpackage (p', nl, tl); @@ -1005,7 +949,7 @@ let rec copy ?env ?partial ?keep_names ty = | Tconstr (p, tl, _) -> let abbrevs = proper_abbrevs p tl !abbreviations in begin match find_repr p !abbrevs with - Some ty when repr ty != t -> (* XXX Commentaire... *) + Some ty when repr ty != t -> Tlink ty | _ -> (* @@ -1120,6 +1064,13 @@ let instance_def sch = cleanup_types (); ty +let generic_instance ?partial env sch = + let old = !current_level in + current_level := generic_level; + let ty = instance env sch in + current_level := old; + ty + let instance_list env schl = let env = gadt_env env in let tyl = List.map (fun t -> copy ?env t) schl in @@ -1127,6 +1078,8 @@ let instance_list env schl = tyl let reified_var_counter = ref Vars.empty +let reset_reified_var_counter () = + reified_var_counter := Vars.empty (* names given to new type constructors. Used for existential types and @@ -1136,7 +1089,8 @@ let get_new_abstract_name s = try Vars.find s !reified_var_counter + 1 with Not_found -> 0 in reified_var_counter := Vars.add s index !reified_var_counter; - Printf.sprintf "%s#%d" s index + if index = 0 && s <> "" && s.[String.length s - 1] <> '$' then s else + Printf.sprintf "%s%d" s index let new_declaration newtype manifest = { @@ -1149,6 +1103,7 @@ let new_declaration newtype manifest = type_newtype_level = newtype; type_loc = Location.none; type_attributes = []; + type_immediate = false; } let instance_constructor ?in_pattern cstr = @@ -1159,8 +1114,8 @@ let instance_constructor ?in_pattern cstr = let decl = new_declaration (Some (newtype_lev, newtype_lev)) None in let name = match repr existential with - {desc = Tvar (Some name)} -> name - | _ -> "ex" + {desc = Tvar (Some name)} -> "$" ^ cstr.cstr_name ^ "_'" ^ name + | _ -> "$" ^ cstr.cstr_name in let (id, new_env) = Env.enter_type (get_new_abstract_name name) decl !env in @@ -1190,26 +1145,31 @@ let instance_parameterized_type_2 sch_args sch_lst sch = cleanup_types (); (ty_args, ty_lst, ty) +let map_kind f = function + | Type_abstract -> Type_abstract + | Type_open -> Type_open + | Type_variant cl -> + Type_variant ( + List.map + (fun c -> + {c with + cd_args = map_type_expr_cstr_args f c.cd_args; + cd_res = may_map f c.cd_res + }) + cl) + | Type_record (fl, rr) -> + Type_record ( + List.map + (fun l -> + {l with ld_type = f l.ld_type} + ) fl, rr) + + let instance_declaration decl = let decl = {decl with type_params = List.map simple_copy decl.type_params; type_manifest = may_map simple_copy decl.type_manifest; - type_kind = match decl.type_kind with - | Type_abstract -> Type_abstract - | Type_variant cl -> - Type_variant ( - List.map - (fun c -> - {c with cd_args=List.map simple_copy c.cd_args; - cd_res=may_map simple_copy c.cd_res}) - cl) - | Type_record (fl, rr) -> - Type_record ( - List.map - (fun l -> - {l with ld_type = copy l.ld_type} - ) fl, rr) - | Type_open -> Type_open + type_kind = map_kind simple_copy decl.type_kind; } in cleanup_types (); @@ -1381,7 +1341,7 @@ let apply env params body args = type or module definition is overridden in the environnement. *) let previous_env = ref Env.empty -let string_of_kind = function Public -> "public" | Private -> "private" +(*let string_of_kind = function Public -> "public" | Private -> "private"*) let check_abbrev_env env = if env != !previous_env then begin (* prerr_endline "cleanup expansion cache"; *) @@ -1414,19 +1374,21 @@ let expand_abbrev_gen kind find_type_expansion env ty = {desc = Tconstr (path, args, abbrev); level = level} -> let lookup_abbrev = proper_abbrevs path args abbrev in begin match find_expans kind path !lookup_abbrev with - Some ty -> + Some ty' -> (* prerr_endline ("found a "^string_of_kind kind^" expansion for "^Path.name path);*) if level <> generic_level then begin try - update_level env level ty + update_level env level ty' with Unify _ -> (* XXX This should not happen. However, levels are not correctly restored after a typing error *) () end; - ty + let ty' = repr ty' in + assert (ty != ty'); + ty' | None -> let (params, body, lv) = try find_type_expansion path env with Not_found -> @@ -1456,8 +1418,8 @@ let expand_abbrev_gen kind find_type_expansion env ty = assert false (* Expand respecting privacy *) -let expand_abbrev ty = - expand_abbrev_gen Public Env.find_type_expansion ty +let expand_abbrev env ty = + expand_abbrev_gen Public Env.find_type_expansion env ty (* Expand once the head of a type *) let expand_head_once env ty = @@ -1606,57 +1568,12 @@ let generic_private_abbrev env path = | _ -> false with Not_found -> false -let is_contractive env ty = - match (repr ty).desc with - Tconstr (p, _, _) -> - in_pervasives p || - (try is_datatype (Env.find_type p env) with Not_found -> false) - | _ -> true - -(* Code moved to Typedecl - -(* The marks are already used by [expand_abbrev]... *) -let visited = ref [] - -let rec non_recursive_abbrev env ty0 ty = - let ty = repr ty in - if ty == repr ty0 then raise Recursive_abbrev; - if not (List.memq ty !visited) then begin - visited := ty :: !visited; - match ty.desc with - Tconstr(p, args, abbrev) -> - begin try - non_recursive_abbrev env ty0 (try_expand_once_opt env ty) - with Cannot_expand -> - if !Clflags.recursive_types && - (in_pervasives p || - try is_datatype (Env.find_type p env) with Not_found -> false) - then () - else iter_type_expr (non_recursive_abbrev env ty0) ty - end - | Tobject _ | Tvariant _ -> - () - | _ -> - if !Clflags.recursive_types then () else - iter_type_expr (non_recursive_abbrev env ty0) ty - end - -let correct_abbrev env path params ty = - check_abbrev_env env; - let ty0 = newgenvar () in - visited := []; - let abbrev = Mcons (Public, path, ty0, ty0, Mnil) in - simple_abbrevs := abbrev; +let is_contractive env p = try - non_recursive_abbrev env ty0 - (subst env generic_level Public (ref abbrev) None [] [] ty); - simple_abbrevs := Mnil; - visited := [] - with exn -> - simple_abbrevs := Mnil; - visited := []; - raise exn -*) + let decl = Env.find_type p env in + in_pervasives p && decl.type_manifest = None || is_datatype decl + with Not_found -> false + (*****************) (* Occur check *) @@ -1665,42 +1582,46 @@ let correct_abbrev env path params ty = exception Occur -let rec occur_rec env visited ty0 ty = +let rec occur_rec env allow_recursive visited ty0 = function + | {desc=Tlink ty} -> + occur_rec env allow_recursive visited ty0 ty + | ty -> if ty == ty0 then raise Occur; - let occur_ok = !Clflags.recursive_types && is_contractive env ty in match ty.desc with Tconstr(p, tl, abbrev) -> + if allow_recursive && is_contractive env p then () else begin try - if occur_ok || List.memq ty visited then raise Occur; - iter_type_expr (occur_rec env (ty::visited) ty0) ty + if TypeSet.mem ty visited then raise Occur; + let visited = TypeSet.add ty visited in + iter_type_expr (occur_rec env allow_recursive visited ty0) ty with Occur -> try let ty' = try_expand_head try_expand_once env ty in - (* Maybe we could simply make a recursive call here, - but it seems it could make the occur check loop - (see change in rev. 1.58) *) - if ty' == ty0 || List.memq ty' visited then raise Occur; - match ty'.desc with - Tobject _ | Tvariant _ -> () - | _ -> - if not (!Clflags.recursive_types && is_contractive env ty') then - iter_type_expr (occur_rec env (ty'::visited) ty0) ty' + (* This call used to be inlined, but there seems no reason for it. + Message was referring to change in rev. 1.58 of the CVS repo. *) + occur_rec env allow_recursive visited ty0 ty' with Cannot_expand -> - if not occur_ok then raise Occur + raise Occur end | Tobject _ | Tvariant _ -> () | _ -> - if not occur_ok then - iter_type_expr (occur_rec env visited ty0) ty + if allow_recursive || TypeSet.mem ty visited then () else begin + let visited = TypeSet.add ty visited in + iter_type_expr (occur_rec env allow_recursive visited ty0) ty + end let type_changed = ref false (* trace possible changes to the studied type *) let merge r b = if b then r := true let occur env ty0 ty = + let allow_recursive = !Clflags.recursive_types || !umode = Pattern in let old = !type_changed in try - while type_changed := false; occur_rec env [] ty0 ty; !type_changed + while + type_changed := false; + occur_rec env allow_recursive TypeSet.empty ty0 ty; + !type_changed do () (* prerr_endline "changed" *) done; merge type_changed old with exn -> @@ -1712,24 +1633,31 @@ let occur_in env ty0 t = (* Check that a local constraint is well-founded *) (* PR#6405: not needed since we allow recursion and work on normalized types *) -(* +(* PR#6992: we actually need it for contractiveness *) +(* This is a simplified version of occur, only for the rectypes case *) let rec local_non_recursive_abbrev visited env p ty = let ty = repr ty in - if not (List.memq ty !visited) then begin - visited := ty :: !visited; + if not (List.memq ty visited) then begin match ty.desc with Tconstr(p', args, abbrev) -> - if Path.same p p' then raise Recursive_abbrev; + if Path.same p p' then raise Occur; + if is_contractive env p' then () else + let visited = ty :: visited in begin try - local_non_recursive_abbrev visited env p (try_expand_once_opt env ty) - with Cannot_expand -> () + List.iter (local_non_recursive_abbrev visited env p) args + with Occur -> try + local_non_recursive_abbrev visited env p + (try_expand_head try_expand_once env ty) + with Cannot_expand -> + raise Occur end | _ -> () end -let local_non_recursive_abbrev env p = - local_non_recursive_abbrev (ref []) env p -*) +let local_non_recursive_abbrev env p ty = + try local_non_recursive_abbrev [] env p ty; true + with Occur -> false + (*****************************) (* Polymorphic Unification *) @@ -1956,6 +1884,7 @@ let reify env t = let newtype_level = get_newtype_level () in let create_fresh_constr lev name = let decl = new_declaration (Some (newtype_level, newtype_level)) None in + let name = match name with Some s -> "$'"^s | _ -> "$" in let name = get_new_abstract_name name in let (id, new_env) = Env.enter_type name decl !env in let t = newty2 lev (Tconstr (Path.Pident id,[],ref Mnil)) in @@ -1969,9 +1898,10 @@ let reify env t = visited := TypeSet.add ty !visited; match ty.desc with Tvar o -> - let name = match o with Some s -> s | _ -> "ex" in - let t = create_fresh_constr ty.level name in - link_type ty t + let t = create_fresh_constr ty.level o in + link_type ty t; + if ty.level < newtype_level then + raise (Unify [t, newvar2 ty.level]) | Tvariant r -> let r = row_repr r in if not (static_row r) then begin @@ -1979,11 +1909,12 @@ let reify env t = let m = r.row_more in match m.desc with Tvar o -> - let name = match o with Some s -> s | _ -> "ex" in - let t = create_fresh_constr m.level name in + let t = create_fresh_constr m.level o in let row = {r with row_fields=[]; row_fixed=true; row_more = t} in - link_type m (newty2 m.level (Tvariant row)) + link_type m (newty2 m.level (Tvariant row)); + if m.level < newtype_level then + raise (Unify [t, newvar2 m.level]) | _ -> assert false end; iter_row iterator r @@ -2007,6 +1938,13 @@ let non_aliasable p decl = (* in_pervasives p || (subsumed by in_current_module) *) in_current_module p && decl.type_newtype_level = None +(* PR#7113: -safe-string should be a global property *) +let compatible_paths p1 p2 = + let open Predef in + Path.same p1 p2 || + Path.same p1 path_bytes && Path.same p2 path_string || + Path.same p1 path_string && Path.same p2 path_bytes + (* Check for datatypes carefully; see PR#6348 *) let rec expands_to_datatype env ty = let ty = repr ty in @@ -2145,7 +2083,7 @@ and mcomp_type_decl type_pairs env p1 p2 tl1 tl2 = try let decl = Env.find_type p1 env in let decl' = Env.find_type p2 env in - if Path.same p1 p2 then begin + if compatible_paths p1 p2 then begin let inj = try List.map Variance.(mem Inj) (Env.find_type p1 env).type_variance with Not_found -> List.map (fun _ -> false) tl1 @@ -2182,7 +2120,12 @@ and mcomp_variant_description type_pairs env xs ys = match x, y with | c1 :: xs, c2 :: ys -> mcomp_type_option type_pairs env c1.cd_res c2.cd_res; - mcomp_list type_pairs env c1.cd_args c2.cd_args; + begin match c1.cd_args, c2.cd_args with + | Cstr_tuple l1, Cstr_tuple l2 -> mcomp_list type_pairs env l1 l2 + | Cstr_record l1, Cstr_record l2 -> + mcomp_record_description type_pairs env l1 l2 + | _ -> raise (Unify []) + end; if Ident.name c1.cd_id = Ident.name c2.cd_id then iter xs ys else raise (Unify []) @@ -2228,12 +2171,13 @@ let find_newtype_level env path = with Not_found -> assert false let add_gadt_equation env source destination = - let destination = duplicate_type destination in - let source_lev = find_newtype_level !env (Path.Pident source) in - let decl = new_declaration (Some source_lev) (Some destination) in - let newtype_level = get_newtype_level () in - env := Env.add_local_constraint source decl newtype_level !env; - cleanup_abbrev () + if local_non_recursive_abbrev !env (Path.Pident source) destination then + let destination = duplicate_type destination in + let source_lev = find_newtype_level !env (Path.Pident source) in + let decl = new_declaration (Some source_lev) (Some destination) in + let newtype_level = get_newtype_level () in + env := Env.add_local_constraint source decl newtype_level !env; + cleanup_abbrev () let unify_eq_set = TypePairs.create 11 @@ -2298,7 +2242,7 @@ let complete_type_list ?(allow_absent=false) env nl1 lv2 mty2 nl2 tl2 = (* raise Not_found rather than Unify if the module types are incompatible *) let unify_package env unify_list lv1 p1 n1 tl1 lv2 p2 n2 tl2 = let ntl2 = complete_type_list env n1 lv2 (Mty_ident p2) n2 tl2 - and ntl1 = complete_type_list env n2 lv2 (Mty_ident p1) n1 tl1 in + and ntl1 = complete_type_list env n2 lv1 (Mty_ident p1) n1 tl1 in unify_list (List.map snd ntl1) (List.map snd ntl2); if eq_package_path env p1 p2 || !package_subtype env p1 n1 tl1 p2 n2 tl2 @@ -2313,6 +2257,18 @@ let unify_eq env t1 t2 = try TypePairs.find unify_eq_set (order_type_pair t1 t2); true with Not_found -> false +let unify1_var env t1 t2 = + assert (is_Tvar t1); + occur env t1 t2; + occur_univar env t2; + let d1 = t1.desc in + link_type t1 t2; + try + update_level env t1.level t2 + with Unify _ as e -> + t1.desc <- d1; + raise e + let rec unify (env:Env.t ref) t1 t2 = (* First step: special cases (optimizations) *) if t1 == t2 then () else @@ -2329,15 +2285,9 @@ let rec unify (env:Env.t ref) t1 t2 = | (Tconstr _, Tvar _) when deep_occur t2 t1 -> unify2 env t1 t2 | (Tvar _, _) -> - occur !env t1 t2; - occur_univar !env t2; - link_type t1 t2; - update_level !env t1.level t2 + unify1_var !env t1 t2 | (_, Tvar _) -> - occur !env t2 t1; - occur_univar !env t1; - link_type t2 t1; - update_level !env t2.level t1 + unify1_var !env t2 t1 | (Tunivar _, Tunivar _) -> unify_univar t1 t2 !univar_pairs; update_level !env t1.level t2; @@ -2373,14 +2323,11 @@ let rec unify (env:Env.t ref) t1 t2 = and unify2 env t1 t2 = (* Second step: expansion of abbreviations *) - let rec expand_both t1'' t2'' = - let t1' = expand_head_unif !env t1 in - let t2' = expand_head_unif !env t2 in - (* Expansion may have changed the representative of the types... *) - if unify_eq !env t1' t1'' && unify_eq !env t2' t2'' then (t1',t2') else - expand_both t1' t2' - in - let t1', t2' = expand_both t1 t2 in + (* Expansion may change the representative of the types. *) + ignore (expand_head_unif !env t1); + ignore (expand_head_unif !env t2); + let t1' = expand_head_unif !env t1 in + let t2' = expand_head_unif !env t2 in let lv = min t1'.level t2'.level in update_level !env lv t2; update_level !env lv t1; @@ -2480,20 +2427,19 @@ and unify3 env t1 t1' t2 t2' = Tconstr ((Path.Pident p') as path',[],_)) when is_newtype !env path && is_newtype !env path' && !generate_equations -> - let source,destination = + let source, destination = if find_newtype_level !env path > find_newtype_level !env path' then p,t2' else p',t1' - in add_gadt_equation env source destination + in + add_gadt_equation env source destination | (Tconstr ((Path.Pident p) as path,[],_), _) when is_newtype !env path && !generate_equations -> reify env t2'; - (* local_non_recursive_abbrev !env (Path.Pident p) t2'; *) add_gadt_equation env p t2' | (_, Tconstr ((Path.Pident p) as path,[],_)) when is_newtype !env path && !generate_equations -> - reify env t1' ; - (* local_non_recursive_abbrev !env (Path.Pident p) t1'; *) + reify env t1'; add_gadt_equation env p t1' | (Tconstr (_,_,_), _) | (_, Tconstr (_,_,_)) when !umode = Pattern -> reify env t1'; @@ -2548,7 +2494,8 @@ and unify3 env t1 t1' t2 t2' = | (_, _) -> raise (Unify []) end; - (* XXX Commentaires + changer "create_recursion" *) + (* XXX Commentaires + changer "create_recursion" + ||| Comments + change "create_recursion" *) if create_recursion then match t2.desc with Tconstr (p, tl, abbrev) -> @@ -2623,9 +2570,6 @@ and unify_kind k1 k2 = | (Fpresent, Fpresent) -> () | _ -> assert false -and unify_pairs mode env tpl = - List.iter (fun (t1, t2) -> unify env t1 t2) tpl - and unify_row env row1 row2 = let row1 = row_repr row1 and row2 = row_repr row2 in let rm1 = row_more row1 and rm2 = row_more row2 in @@ -2736,6 +2680,19 @@ and unify_row_field env fixed1 fixed2 more l f1 f2 = if List.memq ty tl then remq tl tl' else ty :: remq tl tl' in let tl2' = remq tl2 tl1 and tl1' = remq tl1 tl2 in + (* PR#6744 *) + let split_univars = + List.partition + (fun ty -> try occur_univar !env ty; true with Unify _ -> false) in + let (tl1',tlu1) = split_univars tl1' + and (tl2',tlu2) = split_univars tl2' in + begin match tlu1, tlu2 with + [], [] -> () + | (tu1::tlu1), (tu2::_) -> + (* Attempt to merge all the types containing univars *) + List.iter (unify env tu1) (tlu1@tlu2) + | (tu::_, []) | ([], tu::_) -> occur_univar !env tu + end; (* Is this handling of levels really principal? *) List.iter (update_level !env (repr more).level) (tl1' @ tl2'); let e = ref None in @@ -2763,12 +2720,15 @@ and unify_row_field env fixed1 fixed2 more l f1 f2 = let unify env ty1 ty2 = + let snap = Btype.snapshot () in try unify env ty1 ty2 with Unify trace -> + undo_compress snap; raise (Unify (expand_trace !env trace)) | Recursive_abbrev -> + undo_compress snap; raise (Unification_recursive_abbrev (expand_trace !env [(ty1,ty2)])) let unify_gadt ~newtype_level:lev (env:Env.t ref) ty1 ty2 = @@ -2780,10 +2740,9 @@ let unify_gadt ~newtype_level:lev (env:Env.t ref) ty1 ty2 = newtype_level := None; TypePairs.clear unify_eq_set; with e -> + newtype_level := None; TypePairs.clear unify_eq_set; - match e with - Unify e -> raise (Unify e) - | e -> newtype_level := None; raise e + raise e let unify_var env t1 t2 = let t1 = repr t1 and t2 = repr t2 in @@ -2840,7 +2799,7 @@ let filter_arrow env t l = link_type t t'; (t1, t2) | Tarrow(l', t1, t2, _) - when l = l' || !Clflags.classic && l = "" && not (is_optional l') -> + when l = l' || !Clflags.classic && l = Nolabel && not (is_optional l') -> (t1, t2) | _ -> raise (Unify []) @@ -3178,11 +3137,6 @@ let matches env ty ty' = (* Equivalence between parameterized types *) (*********************************************) -let rec get_object_row ty = - match repr ty with - | {desc=Tfield (_, _, _, tl)} -> get_object_row tl - | ty -> ty - let expand_head_rigid env ty = let old = !rigid_variants in rigid_variants := true; @@ -3341,19 +3295,23 @@ and eqtype_row rename type_pairs subst env row1 row2 = | _ -> raise (Unify [])) pairs +(* Must empty univar_pairs first *) +let eqtype_list rename type_pairs subst env tl1 tl2 = + univar_pairs := []; + let snap = Btype.snapshot () in + try eqtype_list rename type_pairs subst env tl1 tl2; backtrack snap + with exn -> backtrack snap; raise exn + +let eqtype rename type_pairs subst env t1 t2 = + eqtype_list rename type_pairs subst env [t1] [t2] + (* Two modes: with or without renaming of variables *) let equal env rename tyl1 tyl2 = try - univar_pairs := []; eqtype_list rename (TypePairs.create 11) (ref []) env tyl1 tyl2; true with Unify _ -> false -(* Must empty univar_pairs first *) -let eqtype rename type_pairs subst env t1 t2 = - univar_pairs := []; - eqtype rename type_pairs subst env t1 t2 - (*************************) (* Class type matching *) @@ -3648,7 +3606,7 @@ let match_class_declarations env patt_params patt_type subj_params subj_type = (* Use moregeneral for class parameters, need to recheck everything to keeps relationships (PR#4824) *) let clty_params = - List.fold_right (fun ty cty -> Cty_arrow ("*",ty,cty)) in + List.fold_right (fun ty cty -> Cty_arrow (Labelled "*",ty,cty)) in match_class_types ~trace:false env (clty_params patt_params patt_type) (clty_params subj_params subj_type) @@ -3897,23 +3855,6 @@ let subtypes = TypePairs.create 17 let subtype_error env trace = raise (Subtype (expand_trace env (List.rev trace), [])) -(* check list inclusion, assuming lists are ordered *) -let rec included nl1 nl2 = - match nl1, nl2 with - (a::nl1', b::nl2') -> - if a = b then included nl1' nl2' else - a > b && included nl1 nl2' - | ([], _) -> true - | (_, []) -> false - -let rec extract_assoc nl1 nl2 tl2 = - match (nl1, nl2, tl2) with - (a::nl1', b::nl2, t::tl2) -> - if a = b then t :: extract_assoc nl1' nl2 tl2 - else extract_assoc nl1 nl2 tl2 - | ([], _, _) -> [] - | _ -> assert false - let rec subtype_rec env trace t1 t2 cstrs = let t1 = repr t1 in let t2 = repr t2 in @@ -3987,11 +3928,6 @@ let rec subtype_rec env trace t1 t2 cstrs = with Unify _ -> (trace, t1, t2, !univar_pairs)::cstrs end -(* | (Tpackage (p1, nl1, tl1), Tpackage (p2, nl2, tl2)) - when eq_package_path env p1 p2 && included nl2 nl1 -> - List.map2 (fun t1 t2 -> (trace, t1, t2, !univar_pairs)) - (extract_assoc nl2 nl1 tl1) tl2 - @ cstrs *) | (Tpackage (p1, nl1, tl1), Tpackage (p2, nl2, tl2)) -> begin try let ntl1 = complete_type_list env nl2 t1.level (Mty_ident p1) nl1 tl1 @@ -4166,6 +4102,40 @@ let cyclic_abbrev env id ty = false in check_cycle [] ty +(* Check for non-generalizable type variables *) +exception Non_closed0 +let visited = ref TypeSet.empty + +let rec closed_schema_rec env ty = + let ty = expand_head env ty in + if TypeSet.mem ty !visited then () else begin + visited := TypeSet.add ty !visited; + match ty.desc with + Tvar _ when ty.level <> generic_level -> + raise Non_closed0 + | Tfield(_, kind, t1, t2) -> + if field_kind_repr kind = Fpresent then + closed_schema_rec env t1; + closed_schema_rec env t2 + | Tvariant row -> + let row = row_repr row in + iter_row (closed_schema_rec env) row; + if not (static_row row) then closed_schema_rec env row.row_more + | _ -> + iter_type_expr (closed_schema_rec env) ty + end + +(* Return whether all variables of type [ty] are generic. *) +let closed_schema env ty = + visited := TypeSet.empty; + try + closed_schema_rec env ty; + visited := TypeSet.empty; + true + with Non_closed0 -> + visited := TypeSet.empty; + false + (* Normalize a type before printing, saving... *) (* Cannot use mark_type because deep_occur uses it too *) let rec normalize_type_rec env visited ty = @@ -4334,29 +4304,7 @@ let nondep_type_decl env mid id is_covariant decl = try let params = List.map (nondep_type_rec env mid) decl.type_params in let tk = - try match decl.type_kind with - Type_abstract -> - Type_abstract - | Type_variant cstrs -> - Type_variant - (List.map - (fun c -> - {c with - cd_args = List.map (nondep_type_rec env mid) c.cd_args; - cd_res = may_map (nondep_type_rec env mid) c.cd_res; - } - ) - cstrs) - | Type_record(lbls, rep) -> - Type_record - (List.map - (fun l -> - {l with ld_type = nondep_type_rec env mid l.ld_type} - ) - lbls, - rep) - | Type_open -> - Type_open + try map_kind (nondep_type_rec env mid) decl.type_kind with Not_found when is_covariant -> Type_abstract and tm = try match decl.type_manifest with @@ -4381,6 +4329,7 @@ let nondep_type_decl env mid id is_covariant decl = type_newtype_level = None; type_loc = decl.type_loc; type_attributes = decl.type_attributes; + type_immediate = decl.type_immediate; } with Not_found -> clear_hash (); @@ -4406,7 +4355,7 @@ let nondep_extension_constructor env mid ext = in ext.ext_type_path, type_params in - let args = List.map (nondep_type_rec env mid) ext.ext_args in + let args = map_type_expr_cstr_args (nondep_type_rec env mid) ext.ext_args in let ret_type = may_map (nondep_type_rec env mid) ext.ext_ret_type in clear_hash (); { ext_type_path = type_path; @@ -4501,3 +4450,35 @@ let rec collapse_conj env visited ty = let collapse_conj_params env params = List.iter (collapse_conj env []) params + +let same_constr env t1 t2 = + let t1 = expand_head env t1 in + let t2 = expand_head env t2 in + match t1.desc, t2.desc with + | Tconstr (p1, _, _), Tconstr (p2, _, _) -> Path.same p1 p2 + | _ -> false + +let () = + Env.same_constr := same_constr + +let maybe_pointer_type env typ = + match (repr typ).desc with + | Tconstr(p, args, abbrev) -> + begin try + let type_decl = Env.find_type p env in + not type_decl.type_immediate + with Not_found -> true + (* This can happen due to e.g. missing -I options, + causing some .cmi files to be unavailable. + Maybe we should emit a warning. *) + end + | Tvariant row -> + let row = Btype.row_repr row in + (* if all labels are devoid of arguments, not a pointer *) + not row.row_closed + || List.exists + (function + | _, (Rpresent (Some _) | Reither (false, _, _, _)) -> true + | _ -> false) + row.row_fields + | _ -> true diff --git a/typing/ctype.mli b/typing/ctype.mli index 36cb186f..6da7fa86 100644 --- a/typing/ctype.mli +++ b/typing/ctype.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Operations on core types *) @@ -37,6 +40,11 @@ val reset_global_level: unit -> unit val increase_global_level: unit -> int val restore_global_level: int -> unit (* This pair of functions is only used in Typetexp *) +type levels = + { current_level: int; nongen_level: int; global_level: int; + saved_level: (int * int) list; } +val save_levels: unit -> levels +val set_levels: levels -> unit val newty: type_desc -> type_expr val newvar: ?name:string -> unit -> type_expr @@ -85,8 +93,6 @@ val filter_row_fields: val generalize: type_expr -> unit (* Generalize in-place the given type *) -val iterative_generalization: int -> type_expr list -> type_expr list - (* Efficient repeated generalization of a type *) val generalize_expansive: Env.t -> type_expr -> unit (* Generalize the covariant part of a type, making contravariant branches non-generalizable *) @@ -110,6 +116,8 @@ val instance: ?partial:bool -> Env.t -> type_expr -> type_expr partial=true -> newty2 ty.level Tvar for non generic subterms *) val instance_def: type_expr -> type_expr (* use defaults *) +val generic_instance: ?partial:bool -> Env.t -> type_expr -> type_expr + (* Same as instance, but new nodes at generic_level *) val instance_list: Env.t -> type_expr list -> type_expr list (* Take an instance of a list of type schemes *) val instance_constructor: @@ -162,7 +170,7 @@ val unify_gadt: newtype_level:int -> Env.t ref -> type_expr -> type_expr -> unit val unify_var: Env.t -> type_expr -> type_expr -> unit (* Same as [unify], but allow free univars when first type is a variable. *) -val filter_arrow: Env.t -> type_expr -> label -> type_expr * type_expr +val filter_arrow: Env.t -> type_expr -> arg_label -> type_expr * type_expr (* A special case of unification (with l:'a -> 'b). *) val filter_method: Env.t -> string -> private_flag -> type_expr -> type_expr (* A special case of unification (with {m : 'a; 'b}). *) @@ -241,10 +249,10 @@ val nondep_cltype_declaration: (* Same for class type declarations. *) (*val correct_abbrev: Env.t -> Path.t -> type_expr list -> type_expr -> unit*) val cyclic_abbrev: Env.t -> Ident.t -> type_expr -> bool -val is_contractive: Env.t -> type_expr -> bool +val is_contractive: Env.t -> Path.t -> bool val normalize_type: Env.t -> type_expr -> unit -val closed_schema: type_expr -> bool +val closed_schema: Env.t -> type_expr -> bool (* Check whether the given type scheme contains no non-generic type variables *) @@ -271,6 +279,10 @@ val collapse_conj_params: Env.t -> type_expr list -> unit val get_current_level: unit -> int val wrap_trace_gadt_instances: Env.t -> ('a -> 'b) -> 'a -> 'b +val reset_reified_var_counter: unit -> unit + +val maybe_pointer_type : Env.t -> type_expr -> bool + (* True if type is possibly pointer, false if definitely not a pointer *) (* Stubs *) val package_subtype : diff --git a/typing/datarepr.ml b/typing/datarepr.ml index faeb48f0..1645dd9e 100644 --- a/typing/datarepr.ml +++ b/typing/datarepr.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compute constructor and label descriptions from type declarations, determining their representation. *) @@ -18,7 +21,7 @@ open Types open Btype (* Simplified version of Ctype.free_vars *) -let free_vars ty = +let free_vars ?(param=false) ty = let ret = ref TypeSet.empty in let rec loop ty = let ty = repr ty in @@ -30,7 +33,12 @@ let free_vars ty = | Tvariant row -> let row = row_repr row in iter_row loop row; - if not (static_row row) then loop row.row_more + if not (static_row row) then begin + match row.row_more.desc with + | Tvar _ when param -> ret := TypeSet.add ty !ret + | _ -> loop row.row_more + end + (* XXX: What about Tobject ? *) | _ -> iter_type_expr loop ty end @@ -39,11 +47,51 @@ let free_vars ty = unmark_type ty; !ret -let constructor_descrs ty_res cstrs priv = +let newgenconstr path tyl = newgenty (Tconstr (path, tyl, ref Mnil)) + +let constructor_args cd_args cd_res path rep = + let tyl = + match cd_args with + | Cstr_tuple l -> l + | Cstr_record l -> List.map (fun l -> l.ld_type) l + in + let existentials = + match cd_res with + | None -> [] + | Some type_ret -> + let arg_vars_set = free_vars (newgenty (Ttuple tyl)) in + let res_vars = free_vars type_ret in + TypeSet.elements (TypeSet.diff arg_vars_set res_vars) + in + match cd_args with + | Cstr_tuple l -> existentials, l, None + | Cstr_record lbls -> + let arg_vars_set = free_vars ~param:true (newgenty (Ttuple tyl)) in + let type_params = TypeSet.elements arg_vars_set in + let tdecl = + { + type_params; + type_arity = List.length type_params; + type_kind = Type_record (lbls, rep); + type_private = Public; + type_manifest = None; + type_variance = List.map (fun _ -> Variance.full) type_params; + type_newtype_level = None; + type_loc = Location.none; + type_attributes = []; + type_immediate = false; + } + in + existentials, + [ newgenconstr path type_params ], + Some tdecl + +let constructor_descrs ty_path decl cstrs = + let ty_res = newgenconstr ty_path decl.type_params in let num_consts = ref 0 and num_nonconsts = ref 0 and num_normal = ref 0 in List.iter (fun {cd_args; cd_res; _} -> - if cd_args = [] then incr num_consts else incr num_nonconsts; + if cd_args = Cstr_tuple [] then incr num_consts else incr num_nonconsts; if cd_res = None then incr num_normal) cstrs; let rec describe_constructors idx_const idx_nonconst = function @@ -56,32 +104,32 @@ let constructor_descrs ty_res cstrs priv = in let (tag, descr_rem) = match cd_args with - [] -> (Cstr_constant idx_const, + Cstr_tuple [] -> (Cstr_constant idx_const, describe_constructors (idx_const+1) idx_nonconst rem) | _ -> (Cstr_block idx_nonconst, describe_constructors idx_const (idx_nonconst+1) rem) in - let existentials = - match cd_res with - | None -> [] - | Some type_ret -> - let res_vars = free_vars type_ret in - let arg_vars = free_vars (newgenty (Ttuple cd_args)) in - TypeSet.elements (TypeSet.diff arg_vars res_vars) + + let cstr_name = Ident.name cd_id in + let existentials, cstr_args, cstr_inlined = + constructor_args cd_args cd_res + (Path.Pdot (ty_path, cstr_name, Path.nopos)) + (Record_inlined idx_nonconst) in let cstr = - { cstr_name = Ident.name cd_id; + { cstr_name; cstr_res = ty_res; cstr_existentials = existentials; - cstr_args = cd_args; - cstr_arity = List.length cd_args; + cstr_args; + cstr_arity = List.length cstr_args; cstr_tag = tag; cstr_consts = !num_consts; cstr_nonconsts = !num_nonconsts; cstr_normal = !num_normal; - cstr_private = priv; + cstr_private = decl.type_private; cstr_generalized = cd_res <> None; cstr_loc = cd_loc; cstr_attributes = cd_attributes; + cstr_inlined; } in (cd_id, cstr) :: descr_rem in describe_constructors 0 0 cstrs @@ -90,24 +138,18 @@ let extension_descr path_ext ext = let ty_res = match ext.ext_ret_type with Some type_ret -> type_ret - | None -> - newgenty (Tconstr(ext.ext_type_path, ext.ext_type_params, ref Mnil)) + | None -> newgenconstr ext.ext_type_path ext.ext_type_params in - let tag = Cstr_extension(path_ext, ext.ext_args = []) in - let existentials = - match ext.ext_ret_type with - | None -> [] - | Some type_ret -> - let ret_vars = free_vars type_ret in - let arg_vars = free_vars (newgenty (Ttuple ext.ext_args)) in - TypeSet.elements (TypeSet.diff arg_vars ret_vars) + let existentials, cstr_args, cstr_inlined = + constructor_args ext.ext_args ext.ext_ret_type + path_ext Record_extension in { cstr_name = Path.last path_ext; cstr_res = ty_res; cstr_existentials = existentials; - cstr_args = ext.ext_args; - cstr_arity = List.length ext.ext_args; - cstr_tag = tag; + cstr_args; + cstr_arity = List.length cstr_args; + cstr_tag = Cstr_extension(path_ext, cstr_args = []); cstr_consts = -1; cstr_nonconsts = -1; cstr_private = ext.ext_private; @@ -115,6 +157,7 @@ let extension_descr path_ext ext = cstr_generalized = ext.ext_ret_type <> None; cstr_loc = ext.ext_loc; cstr_attributes = ext.ext_attributes; + cstr_inlined; } let none = {desc = Ttuple []; level = -1; id = -1} @@ -153,7 +196,7 @@ exception Constr_not_found let rec find_constr tag num_const num_nonconst = function [] -> raise Constr_not_found - | {cd_args = []; _} as c :: rem -> + | {cd_args = Cstr_tuple []; _} as c :: rem -> if tag = Cstr_constant num_const then c else find_constr tag (num_const + 1) num_nonconst rem @@ -164,3 +207,15 @@ let rec find_constr tag num_const num_nonconst = function let find_constr_by_tag tag cstrlist = find_constr tag 0 0 cstrlist + +let constructors_of_type ty_path decl = + match decl.type_kind with + | Type_variant cstrs -> constructor_descrs ty_path decl cstrs + | Type_record _ | Type_abstract | Type_open -> [] + +let labels_of_type ty_path decl = + match decl.type_kind with + | Type_record(labels, rep) -> + label_descrs (newgenconstr ty_path decl.type_params) + labels rep decl.type_private + | Type_variant _ | Type_abstract | Type_open -> [] diff --git a/typing/datarepr.mli b/typing/datarepr.mli index 8e298deb..de8a8c28 100644 --- a/typing/datarepr.mli +++ b/typing/datarepr.mli @@ -1,30 +1,33 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Compute constructor and label descriptions from type declarations, determining their representation. *) -open Asttypes open Types -val constructor_descrs: - type_expr -> constructor_declaration list -> - private_flag -> (Ident.t * constructor_description) list val extension_descr: Path.t -> extension_constructor -> constructor_description -val label_descrs: - type_expr -> label_declaration list -> - record_representation -> private_flag -> - (Ident.t * label_description) list + +val labels_of_type: + Path.t -> type_declaration -> + (Ident.t * label_description) list +val constructors_of_type: + Path.t -> type_declaration -> + (Ident.t * constructor_description) list + exception Constr_not_found diff --git a/typing/env.ml b/typing/env.ml index b11be4d8..20e7a7ce 100644 --- a/typing/env.ml +++ b/typing/env.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Environment handling *) @@ -69,7 +72,6 @@ module EnvLazy : sig val force : ('a -> 'b) -> ('a,'b) t -> 'b val create : 'a -> ('a,'b) t - val is_val : ('a,'b) t -> bool val get_arg : ('a,'b) t -> 'a option end = struct @@ -94,15 +96,11 @@ end = struct x := Raise e; raise e - let is_val x = - match !x with Done _ -> true | _ -> false - let get_arg x = match !x with Thunk a -> Some a | _ -> None let create x = - let x = ref (Thunk x) in - x + ref (Thunk x) end @@ -127,25 +125,21 @@ module EnvTbl = let empty = Ident.empty let nothing = fun () -> () - let already_defined s tbl = - try ignore (Ident.find_name s tbl); true - with Not_found -> false + let already_defined wrap s tbl x = + wrap (try Some (fst (Ident.find_name s tbl), x) with Not_found -> None) - let add kind slot id x tbl ref_tbl = + let add slot wrap id x tbl ref_tbl = let slot = match slot with | None -> nothing | Some f -> (fun () -> let s = Ident.name id in - f kind s (already_defined s ref_tbl) + f s (already_defined wrap s ref_tbl x) ) in Ident.add id (x, slot) tbl - let add_dont_track id x tbl = - Ident.add id (x, nothing) tbl - let find_same_not_using id tbl = fst (Ident.find_same id tbl) @@ -190,7 +184,11 @@ type t = { } and module_components = - (t * Subst.t * Path.t * Types.module_type, module_components_repr) EnvLazy.t + { + deprecated: string option; + comps: (t * Subst.t * Path.t * Types.module_type, module_components_repr) + EnvLazy.t; + } and module_components_repr = Structure_comps of structure_components @@ -214,12 +212,37 @@ and functor_components = { fcomp_param: Ident.t; (* Formal parameter *) fcomp_arg: module_type option; (* Argument signature *) fcomp_res: module_type; (* Result signature *) - fcomp_env: t; (* Environment in which the result signature makes sense *) - fcomp_subst: Subst.t; (* Prefixing substitution for the result signature *) fcomp_cache: (Path.t, module_components) Hashtbl.t; (* For memoization *) fcomp_subst_cache: (Path.t, module_type) Hashtbl.t } +let same_constr = ref (fun _ _ _ -> assert false) + +(* Helper to decide whether to report an identifier shadowing + by some 'open'. For labels and constructors, we do not report + if the two elements are from the same re-exported declaration. + + Later, one could also interpret some attributes on value and + type declarations to silence the shadowing warnings. *) + +let check_shadowing env = function + | `Constructor (Some (c1, c2)) + when not (!same_constr env c1.cstr_res c2.cstr_res) -> + Some "constructor" + | `Label (Some (l1, l2)) + when not (!same_constr env l1.lbl_res l2.lbl_res) -> + Some "label" + | `Value (Some _) -> Some "value" + | `Type (Some _) -> Some "type" + | `Module (Some _) | `Component (Some _) -> Some "module" + | `Module_type (Some _) -> Some "module type" + | `Class (Some _) -> Some "class" + | `Class_type (Some _) -> Some "class type" + | `Constructor _ | `Label _ + | `Value None | `Type None | `Module None | `Module_type None + | `Class None | `Class_type None | `Component None -> + None + let subst_modtype_maker (subst, mty) = Subst.modtype subst mty let empty = { @@ -233,8 +256,13 @@ let empty = { functor_args = Ident.empty; } -let in_signature env = - {env with flags = env.flags lor in_signature_flag} +let in_signature b env = + let flags = + if b then env.flags lor in_signature_flag + else env.flags land (lnot in_signature_flag) + in + {env with flags} + let implicit_coercion env = {env with flags = env.flags lor implicit_coercion_flag} @@ -269,14 +297,15 @@ let diff env1 env2 = (* Forward declarations *) let components_of_module' = - ref ((fun env sub path mty -> assert false) : - t -> Subst.t -> Path.t -> module_type -> module_components) + ref ((fun ~deprecated env sub path mty -> assert false) : + deprecated:string option -> t -> Subst.t -> Path.t -> module_type -> + module_components) let components_of_module_maker' = ref ((fun (env, sub, path, mty) -> assert false) : t * Subst.t * Path.t * module_type -> module_components_repr) let components_of_functor_appl' = - ref ((fun f p1 p2 -> assert false) : - functor_components -> Path.t -> Path.t -> module_components) + ref ((fun f env p1 p2 -> assert false) : + functor_components -> t -> Path.t -> Path.t -> module_components) let check_modtype_inclusion = (* to be filled with Includemod.check_modtype_inclusion *) ref ((fun env mty1 path1 mty2 -> assert false) : @@ -289,6 +318,10 @@ let strengthen = let md md_type = {md_type; md_attributes=[]; md_loc=Location.none} +let get_components c = + EnvLazy.force !components_of_module_maker' c.comps + + (* The name of the compilation unit currently compiled. "" if outside a compilation unit. *) @@ -298,10 +331,9 @@ let current_unit = ref "" type pers_struct = { ps_name: string; - ps_sig: signature; + ps_sig: signature Lazy.t; ps_comps: module_components; ps_crcs: (string * Digest.t option) list; - mutable ps_crcs_checked: bool; ps_filename: string; ps_flags: pers_flags list } @@ -320,12 +352,17 @@ let imported_units = ref StringSet.empty let add_import s = imported_units := StringSet.add s !imported_units +let imported_opaque_units = ref StringSet.empty + +let add_imported_opaque s = + imported_opaque_units := StringSet.add s !imported_opaque_units + let clear_imports () = Consistbl.clear crc_units; - imported_units := StringSet.empty + imported_units := StringSet.empty; + imported_opaque_units := StringSet.empty let check_consistency ps = - if not ps.ps_crcs_checked then try List.iter (fun (name, crco) -> @@ -335,7 +372,6 @@ let check_consistency ps = add_import name; Consistbl.check crc_units name crc ps.ps_filename) ps.ps_crcs; - ps.ps_crcs_checked <- true; with Consistbl.Inconsistency(name, source, auth) -> error (Inconsistent_import(name, auth, source)) @@ -344,64 +380,114 @@ let check_consistency ps = let save_pers_struct crc ps = let modname = ps.ps_name in Hashtbl.add persistent_structures modname (Some ps); + List.iter + (function + | Rectypes -> () + | Deprecated _ -> () + | Opaque -> add_imported_opaque modname) + ps.ps_flags; Consistbl.set crc_units modname crc ps.ps_filename; add_import modname -let read_pers_struct modname filename = +let read_pers_struct check modname filename = + add_import modname; let cmi = read_cmi filename in let name = cmi.cmi_name in let sign = cmi.cmi_sign in let crcs = cmi.cmi_crcs in let flags = cmi.cmi_flags in + let deprecated = + List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None + flags + in let comps = - !components_of_module' empty Subst.identity + !components_of_module' ~deprecated empty Subst.identity (Pident(Ident.create_persistent name)) (Mty_signature sign) in let ps = { ps_name = name; - ps_sig = sign; + ps_sig = lazy (Subst.signature Subst.identity sign); ps_comps = comps; ps_crcs = crcs; ps_filename = filename; ps_flags = flags; - ps_crcs_checked = false; } in if ps.ps_name <> modname then error (Illegal_renaming(modname, ps.ps_name, filename)); - add_import name; List.iter - (function Rectypes -> - if not !Clflags.recursive_types then - error (Need_recursive_types(ps.ps_name, !current_unit))) + (function + | Rectypes -> + if not !Clflags.recursive_types then + error (Need_recursive_types(ps.ps_name, !current_unit)) + | Deprecated _ -> () + | Opaque -> add_imported_opaque modname) ps.ps_flags; + if check then check_consistency ps; Hashtbl.add persistent_structures modname (Some ps); ps -let find_pers_struct ?(check=true) name = +let find_pers_struct check name = if name = "*predef*" then raise Not_found; - let r = - try Some (Hashtbl.find persistent_structures name) - with Not_found -> None - in - let ps = - match r with - | Some None -> raise Not_found - | Some (Some sg) -> sg - | None -> - (* PR#6843: record the weak dependency ([add_import]) even if - the [find_in_path_uncap] call below fails to find the .cmi, - to help make builds more deterministic. *) - add_import name; - let filename = - try find_in_path_uncap !load_path (name ^ ".cmi") - with Not_found -> - Hashtbl.add persistent_structures name None; - raise Not_found - in - read_pers_struct name filename - in - if check then check_consistency ps; - ps + match Hashtbl.find persistent_structures name with + | Some ps -> ps + | None -> raise Not_found + | exception Not_found -> + let filename = + try + find_in_path_uncap !load_path (name ^ ".cmi") + with Not_found -> + Hashtbl.add persistent_structures name None; + raise Not_found + in + read_pers_struct check name filename + +(* Emits a warning if there is no valid cmi for name *) +let check_pers_struct name = + try + ignore (find_pers_struct false name) + with + | Not_found -> + let warn = Warnings.No_cmi_file(name, None) in + Location.prerr_warning Location.none warn + | Cmi_format.Error err -> + let msg = Format.asprintf "%a" Cmi_format.report_error err in + let warn = Warnings.No_cmi_file(name, Some msg) in + Location.prerr_warning Location.none warn + | Error err -> + let msg = + match err with + | Illegal_renaming(name, ps_name, filename) -> + Format.asprintf + " %a@ contains the compiled interface for @ \ + %s when %s was expected" + Location.print_filename filename ps_name name + | Inconsistent_import _ -> assert false + | Need_recursive_types(name, _) -> + Format.sprintf + "%s uses recursive types" + name + | Missing_module _ -> assert false + | Illegal_value_name _ -> assert false + in + let warn = Warnings.No_cmi_file(name, Some msg) in + Location.prerr_warning Location.none warn + +let read_pers_struct modname filename = + read_pers_struct true modname filename + +let find_pers_struct name = + find_pers_struct true name + +let check_pers_struct name = + if not (Hashtbl.mem persistent_structures name) then begin + (* PR#6843: record the weak dependency ([add_import]) regardless of + whether the check suceeds, to help make builds more + deterministic. *) + add_import name; + if (Warnings.is_active (Warnings.No_cmi_file("", None))) then + !add_delayed_check_forward + (fun () -> check_pers_struct name) + end let reset_cache () = current_unit := ""; @@ -446,9 +532,7 @@ let rec find_module_descr path env = else raise Not_found end | Pdot(p, s, pos) -> - begin match - EnvLazy.force !components_of_module_maker' (find_module_descr p env) - with + begin match get_components (find_module_descr p env) with Structure_comps c -> let (descr, pos) = Tbl.find s c.comp_components in descr @@ -456,11 +540,9 @@ let rec find_module_descr path env = raise Not_found end | Papply(p1, p2) -> - begin match - EnvLazy.force !components_of_module_maker' (find_module_descr p1 env) - with + begin match get_components (find_module_descr p1 env) with Functor_comps f -> - !components_of_functor_appl' f p1 p2 + !components_of_functor_appl' f env p1 p2 | Structure_comps c -> raise Not_found end @@ -471,9 +553,7 @@ let find proj1 proj2 path env = let (p, data) = EnvTbl.find_same id (proj1 env) in data | Pdot(p, s, pos) -> - begin match - EnvLazy.force !components_of_module_maker' (find_module_descr p env) - with + begin match get_components (find_module_descr p env) with Structure_comps c -> let (data, pos) = Tbl.find s (proj2 c) in data | Functor_comps f -> @@ -493,6 +573,51 @@ and find_class = and find_cltype = find (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes) +let type_of_cstr path = function + | {cstr_inlined = Some d; _} -> + (d, ([], List.map snd (Datarepr.labels_of_type path d))) + | _ -> + assert false + +let find_type_full path env = + match Path.constructor_typath path with + | Regular p -> find_type_full p env + | Cstr (ty_path, s) -> + let (_, (cstrs, _)) = + try find_type_full ty_path env + with Not_found -> assert false + in + let cstr = + try List.find (fun cstr -> cstr.cstr_name = s) cstrs + with Not_found -> assert false + in + type_of_cstr path cstr + | LocalExt id -> + let cstr = + try EnvTbl.find_same id env.constrs + with Not_found -> assert false + in + type_of_cstr path cstr + | Ext (mod_path, s) -> + let comps = + try find_module_descr mod_path env + with Not_found -> assert false + in + let comps = + match get_components comps with + | Structure_comps c -> c + | Functor_comps _ -> assert false + in + let exts = + List.filter + (function ({cstr_tag=Cstr_extension _}, _) -> true | _ -> false) + (try Tbl.find s comps.comp_constrs + with Not_found -> assert false) + in + match exts with + | [(cstr, _)] -> type_of_cstr path cstr + | _ -> assert false + let find_type p env = fst (find_type_full p env) let find_type_descrs p env = @@ -507,13 +632,11 @@ let find_module ~alias path env = with Not_found -> if Ident.persistent id && not (Ident.name id = !current_unit) then let ps = find_pers_struct (Ident.name id) in - md (Mty_signature(ps.ps_sig)) + md (Mty_signature(Lazy.force ps.ps_sig)) else raise Not_found end | Pdot(p, s, pos) -> - begin match - EnvLazy.force !components_of_module_maker' (find_module_descr p env) - with + begin match get_components (find_module_descr p env) with Structure_comps c -> let (data, pos) = Tbl.find s c.comp_modules in md (EnvLazy.force subst_modtype_maker data) @@ -522,11 +645,10 @@ let find_module ~alias path env = end | Papply(p1, p2) -> let desc1 = find_module_descr p1 env in - begin match EnvLazy.force !components_of_module_maker' desc1 with + begin match get_components desc1 with Functor_comps f -> md begin match f.fcomp_res with - | Mty_alias p -> - Mty_alias (Subst.module_path f.fcomp_subst p) + | Mty_alias p as mty-> mty | mty -> if alias then mty else try @@ -534,7 +656,7 @@ let find_module ~alias path env = with Not_found -> let mty = Subst.modtype - (Subst.add_module f.fcomp_param p2 f.fcomp_subst) + (Subst.add_module f.fcomp_param p2 Subst.identity) f.fcomp_res in Hashtbl.add f.fcomp_subst_cache p2 mty; mty @@ -639,7 +761,16 @@ let rec is_functor_arg path env = exception Recmodule -let rec lookup_module_descr lid env = +let report_deprecated ?loc p deprecated = + match loc, deprecated with + | Some loc, Some txt -> + let txt = if txt = "" then "" else "\n" ^ txt in + Location.prerr_warning loc + (Warnings.Deprecated (Printf.sprintf "module %s%s" + (Path.name p) txt)) + | _ -> () + +let rec lookup_module_descr_aux ?loc lid env = match lid with Lident s -> begin try @@ -650,8 +781,8 @@ let rec lookup_module_descr lid env = (Pident(Ident.create_persistent s), ps.ps_comps) end | Ldot(l, s) -> - let (p, descr) = lookup_module_descr l env in - begin match EnvLazy.force !components_of_module_maker' descr with + let (p, descr) = lookup_module_descr ?loc l env in + begin match get_components descr with Structure_comps c -> let (descr, pos) = Tbl.find s c.comp_components in (Pdot(p, s, pos), descr) @@ -659,53 +790,64 @@ let rec lookup_module_descr lid env = raise Not_found end | Lapply(l1, l2) -> - let (p1, desc1) = lookup_module_descr l1 env in - let p2 = lookup_module true l2 env in + let (p1, desc1) = lookup_module_descr ?loc l1 env in + let p2 = lookup_module ~load:true ?loc l2 env in let {md_type=mty2} = find_module p2 env in - begin match EnvLazy.force !components_of_module_maker' desc1 with + begin match get_components desc1 with Functor_comps f -> Misc.may (!check_modtype_inclusion env mty2 p2) f.fcomp_arg; - (Papply(p1, p2), !components_of_functor_appl' f p1 p2) + (Papply(p1, p2), !components_of_functor_appl' f env p1 p2) | Structure_comps c -> raise Not_found end -and lookup_module ~load lid env : Path.t = +and lookup_module_descr ?loc lid env = + let (p, comps) as res = lookup_module_descr_aux ?loc lid env in + report_deprecated ?loc p comps.deprecated; + res + +and lookup_module ~load ?loc lid env : Path.t = match lid with Lident s -> begin try - let (p, {md_type}) as r = EnvTbl.find_name s env.modules in + let (p, {md_type; md_attributes}) = EnvTbl.find_name s env.modules in begin match md_type with | Mty_ident (Path.Pident id) when Ident.name id = "#recmod#" -> (* see #5965 *) raise Recmodule | _ -> () end; + report_deprecated ?loc p + (Builtin_attributes.deprecated_of_attrs md_attributes); p with Not_found -> if s = !current_unit then raise Not_found; - if !Clflags.transparent_modules && not load then - try ignore (find_pers_struct ~check:false s) - with Not_found -> - Location.prerr_warning Location.none (Warnings.No_cmi_file s) - else ignore (find_pers_struct s); - Pident(Ident.create_persistent s) + let p = Pident(Ident.create_persistent s) in + if !Clflags.transparent_modules && not load then check_pers_struct s + else begin + let ps = find_pers_struct s in + report_deprecated ?loc p ps.ps_comps.deprecated + end; + p end | Ldot(l, s) -> - let (p, descr) = lookup_module_descr l env in - begin match EnvLazy.force !components_of_module_maker' descr with + let (p, descr) = lookup_module_descr ?loc l env in + begin match get_components descr with Structure_comps c -> let (data, pos) = Tbl.find s c.comp_modules in - Pdot(p, s, pos) + let (comps, _) = Tbl.find s c.comp_components in + let p = Pdot(p, s, pos) in + report_deprecated ?loc p comps.deprecated; + p | Functor_comps f -> raise Not_found end | Lapply(l1, l2) -> - let (p1, desc1) = lookup_module_descr l1 env in - let p2 = lookup_module true l2 env in + let (p1, desc1) = lookup_module_descr ?loc l1 env in + let p2 = lookup_module ~load:true ?loc l2 env in let {md_type=mty2} = find_module p2 env in let p = Papply(p1, p2) in - begin match EnvLazy.force !components_of_module_maker' desc1 with + begin match get_components desc1 with Functor_comps f -> Misc.may (!check_modtype_inclusion env mty2 p2) f.fcomp_arg; p @@ -713,13 +855,13 @@ and lookup_module ~load lid env : Path.t = raise Not_found end -let lookup proj1 proj2 lid env = +let lookup proj1 proj2 ?loc lid env = match lid with Lident s -> EnvTbl.find_name s (proj1 env) | Ldot(l, s) -> - let (p, desc) = lookup_module_descr l env in - begin match EnvLazy.force !components_of_module_maker' desc with + let (p, desc) = lookup_module_descr ?loc l env in + begin match get_components desc with Structure_comps c -> let (data, pos) = Tbl.find s (proj2 c) in (Pdot(p, s, pos), data) @@ -729,23 +871,7 @@ let lookup proj1 proj2 lid env = | Lapply(l1, l2) -> raise Not_found -let lookup_simple proj1 proj2 lid env = - match lid with - Lident s -> - EnvTbl.find_name s (proj1 env) - | Ldot(l, s) -> - let (p, desc) = lookup_module_descr l env in - begin match EnvLazy.force !components_of_module_maker' desc with - Structure_comps c -> - let (data, pos) = Tbl.find s (proj2 c) in - data - | Functor_comps f -> - raise Not_found - end - | Lapply(l1, l2) -> - raise Not_found - -let lookup_all_simple proj1 proj2 shadow lid env = +let lookup_all_simple proj1 proj2 shadow ?loc lid env = match lid with Lident s -> let xl = EnvTbl.find_all s (proj1 env) in @@ -758,8 +884,8 @@ let lookup_all_simple proj1 proj2 shadow lid env = in do_shadow xl | Ldot(l, s) -> - let (p, desc) = lookup_module_descr l env in - begin match EnvLazy.force !components_of_module_maker' desc with + let (p, desc) = lookup_module_descr ?loc l env in + begin match get_components desc with Structure_comps c -> let comps = try Tbl.find s (proj2 c) with Not_found -> [] @@ -799,6 +925,19 @@ and lookup_class = and lookup_cltype = lookup (fun env -> env.cltypes) (fun sc -> sc.comp_cltypes) +let update_value s f env = + try + let ((p, vd), slot) = Ident.find_name s env.values in + match p with + | Pident id -> + let vd2 = f vd in + {env with values = Ident.add id ((p, vd2), slot) env.values; + summary = Env_value(env.summary, id, vd2)} + | _ -> + env + with Not_found -> + env + let mark_value_used env name vd = if not (is_implicit_coercion env) then try Hashtbl.find value_declarations (name, vd.val_loc) () @@ -842,23 +981,16 @@ let set_type_used_callback name td callback = in Hashtbl.replace type_declarations key (fun () -> callback old) -let lookup_value lid env = - let (_, desc) as r = lookup_value lid env in +let lookup_value ?loc lid env = + let (_, desc) as r = lookup_value ?loc lid env in mark_value_used env (Longident.last lid) desc; r -let lookup_type lid env = - let (path, (decl, _)) = lookup_type lid env in +let lookup_type ?loc lid env = + let (path, (decl, _)) = lookup_type ?loc lid env in mark_type_used env (Longident.last lid) decl; (path, decl) -(* [path] must be the path to a type, not to a module ! *) -let path_subst_last path id = - match path with - Pident _ -> Pident id - | Pdot (p, name, pos) -> Pdot(p, Ident.name id, pos) - | Papply (p1, p2) -> assert false - let mark_type_path env path = try let decl = find_type path env in @@ -870,8 +1002,8 @@ let ty_path t = | {desc=Tconstr(path, _, _)} -> path | _ -> assert false -let lookup_constructor lid env = - match lookup_all_constructors lid env with +let lookup_constructor ?loc lid env = + match lookup_all_constructors ?loc lid env with [] -> raise Not_found | (desc, use) :: _ -> mark_type_path env (ty_path desc.cstr_res); @@ -882,9 +1014,9 @@ let is_lident = function Lident _ -> true | _ -> false -let lookup_all_constructors lid env = +let lookup_all_constructors ?loc lid env = try - let cstrs = lookup_all_constructors lid env in + let cstrs = lookup_all_constructors ?loc lid env in let wrap_use desc use () = mark_type_path env (ty_path desc.cstr_res); use () @@ -909,17 +1041,17 @@ let mark_constructor usage env name desc = let ty_name = Path.last ty_path in mark_constructor_used usage env ty_name ty_decl name -let lookup_label lid env = - match lookup_all_labels lid env with +let lookup_label ?loc lid env = + match lookup_all_labels ?loc lid env with [] -> raise Not_found | (desc, use) :: _ -> mark_type_path env (ty_path desc.lbl_res); use (); desc -let lookup_all_labels lid env = +let lookup_all_labels ?loc lid env = try - let lbls = lookup_all_labels lid env in + let lbls = lookup_all_labels ?loc lid env in let wrap_use desc use () = mark_type_path env (ty_path desc.lbl_res); use () @@ -928,16 +1060,16 @@ let lookup_all_labels lid env = with Not_found when is_lident lid -> [] -let lookup_class lid env = - let (_, desc) as r = lookup_class lid env in +let lookup_class ?loc lid env = + let (_, desc) as r = lookup_class ?loc lid env in (* special support for Typeclass.unbound_class *) - if Path.name desc.cty_path = "" then ignore (lookup_type lid env) + if Path.name desc.cty_path = "" then ignore (lookup_type ?loc lid env) else mark_type_path env desc.cty_path; r -let lookup_cltype lid env = - let (_, desc) as r = lookup_cltype lid env in - if Path.name desc.clty_path = "" then ignore (lookup_type lid env) +let lookup_cltype ?loc lid env = + let (_, desc) as r = lookup_cltype ?loc lid env in + if Path.name desc.clty_path = "" then ignore (lookup_type ?loc lid env) else mark_type_path env desc.clty_path; mark_type_path env desc.clty_path; r @@ -948,25 +1080,28 @@ let lookup_cltype lid env = type iter_cont = unit -> unit let iter_env_cont = ref [] -let rec scrape_alias_safe env mty = +let rec scrape_alias_for_visit env mty = match mty with - | Mty_alias (Pident id) when Ident.persistent id -> false + | Mty_alias (Pident id) + when Ident.persistent id + && not (Hashtbl.mem persistent_structures (Ident.name id)) -> false | Mty_alias path -> (* PR#6600: find_module may raise Not_found *) - scrape_alias_safe env (find_module path env).md_type + begin try scrape_alias_for_visit env (find_module path env).md_type + with Not_found -> false + end | _ -> true let iter_env proj1 proj2 f env () = Ident.iter (fun id (x,_) -> f (Pident id) x) (proj1 env); let rec iter_components path path' mcomps = let cont () = - let safe = - match EnvLazy.get_arg mcomps with - None -> true - | Some (env, sub, path, mty) -> - try scrape_alias_safe env mty with Not_found -> false + let visit = + match EnvLazy.get_arg mcomps.comps with + | None -> true + | Some (env, sub, path, mty) -> scrape_alias_for_visit env mty in - if not safe then () else - match EnvLazy.force !components_of_module_maker' mcomps with + if not visit then () else + match get_components mcomps with Structure_comps comps -> Tbl.iter (fun s (d, n) -> f (Pdot (path, s, n)) (Pdot (path', s, n), d)) @@ -1008,7 +1143,7 @@ let used_persistent () = !r let find_all_comps proj s (p,mcomps) = - match EnvLazy.force !components_of_module_maker' mcomps with + match get_components mcomps with Functor_comps _ -> [] | Structure_comps comps -> try let (c,n) = Tbl.find s (proj comps) in [Pdot(p,s,n), c] @@ -1103,7 +1238,7 @@ let rec scrape_alias env ?path mty = scrape_alias env (find_module path env).md_type ~path with Not_found -> (*Location.prerr_warning Location.none - (Warnings.No_cmi_file (Path.name path));*) + (Warnings.No_cmi_file (Path.name path));*) mty end | mty, Some path -> @@ -1112,28 +1247,6 @@ let rec scrape_alias env ?path mty = let scrape_alias env mty = scrape_alias env mty -(* Compute constructor descriptions *) - -let constructors_of_type ty_path decl = - let handle_variants cstrs = - Datarepr.constructor_descrs - (newgenty (Tconstr(ty_path, decl.type_params, ref Mnil))) - cstrs decl.type_private - in - match decl.type_kind with - | Type_variant cstrs -> handle_variants cstrs - | Type_record _ | Type_abstract | Type_open -> [] - -(* Compute label descriptions *) - -let labels_of_type ty_path decl = - match decl.type_kind with - Type_record(labels, rep) -> - Datarepr.label_descrs - (newgenty (Tconstr(ty_path, decl.type_params, ref Mnil))) - labels rep decl.type_private - | Type_variant _ | Type_abstract | Type_open -> [] - (* Given a signature and a root path, prefix all idents in the signature by the root path and build the corresponding substitution. *) @@ -1151,7 +1264,9 @@ let rec prefix_idents root pos sub = function (p::pl, final_sub) | Sig_typext(id, ext, _) :: rem -> let p = Pdot(root, Ident.name id, pos) in - let (pl, final_sub) = prefix_idents root (pos+1) sub rem in + (* we extend the substitution in case of an inlined record *) + let (pl, final_sub) = + prefix_idents root (pos+1) (Subst.add_type id p sub) rem in (p::pl, final_sub) | Sig_module(id, mty, _) :: rem -> let p = Pdot(root, Ident.name id, pos) in @@ -1165,12 +1280,15 @@ let rec prefix_idents root pos sub = function (Subst.add_modtype id (Mty_ident p) sub) rem in (p::pl, final_sub) | Sig_class(id, decl, _) :: rem -> + (* pretend this is a type, cf. PR#6650 *) let p = Pdot(root, Ident.name id, pos) in - let (pl, final_sub) = prefix_idents root (pos + 1) sub rem in + let (pl, final_sub) = + prefix_idents root (pos + 1) (Subst.add_type id p sub) rem in (p::pl, final_sub) | Sig_class_type(id, decl, _) :: rem -> let p = Pdot(root, Ident.name id, nopos) in - let (pl, final_sub) = prefix_idents root pos sub rem in + let (pl, final_sub) = + prefix_idents root pos (Subst.add_type id p sub) rem in (p::pl, final_sub) let subst_signature sub sg = @@ -1199,8 +1317,12 @@ 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) + let prefix_idents_and_subst root sub sg = - if sub = Subst.identity then + let sub = set_nongen_level sub root in + if sub = set_nongen_level Subst.identity root then let sgs = try Hashtbl.find prefixed_sg root @@ -1225,8 +1347,11 @@ let add_to_tbl id decl tbl = try Tbl.find id tbl with Not_found -> [] in Tbl.add id (decl :: decls) tbl -let rec components_of_module env sub path mty = - EnvLazy.create (env, sub, path, mty) +let rec components_of_module ~deprecated env sub path mty = + { + deprecated; + comps = EnvLazy.create (env, sub, path, mty) + } and components_of_module_maker (env, sub, path, mty) = (match scrape_alias env mty with @@ -1252,8 +1377,10 @@ and components_of_module_maker (env, sub, path, mty) = end | Sig_type(id, decl, _) -> let decl' = Subst.type_declaration sub decl in - let constructors = List.map snd (constructors_of_type path decl') in - let labels = List.map snd (labels_of_type path decl') in + let constructors = + List.map snd (Datarepr.constructors_of_type path decl') in + let labels = + List.map snd (Datarepr.labels_of_type path decl') in c.comp_types <- Tbl.add (Ident.name id) ((decl', (constructors, labels)), nopos) @@ -1280,7 +1407,10 @@ and components_of_module_maker (env, sub, path, mty) = let mty' = EnvLazy.create (sub, mty) in c.comp_modules <- Tbl.add (Ident.name id) (mty', !pos) c.comp_modules; - let comps = components_of_module !env sub path mty in + let deprecated = + Builtin_attributes.deprecated_of_attrs md.md_attributes + in + let comps = components_of_module ~deprecated !env sub path mty in c.comp_components <- Tbl.add (Ident.name id) (comps, !pos) c.comp_components; env := store_module None id (Pident id) md !env !env; @@ -1304,13 +1434,10 @@ and components_of_module_maker (env, sub, path, mty) = | Mty_functor(param, ty_arg, ty_res) -> Functor_comps { fcomp_param = param; - (* fcomp_arg must be prefixed eagerly, because it is interpreted - in the outer environment, not in env *) + (* 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 is prefixed lazily, because it is interpreted in env *) - fcomp_res = ty_res; - fcomp_env = env; - fcomp_subst = sub; + fcomp_res = Subst.modtype (set_nongen_level sub path) ty_res; fcomp_cache = Hashtbl.create 17; fcomp_subst_cache = Hashtbl.create 17 } | Mty_ident _ @@ -1355,7 +1482,8 @@ and store_value ?check slot id path decl env renv = check_value_name (Ident.name id) decl.val_loc; may (fun f -> check_usage decl.val_loc id f value_declarations) check; { env with - values = EnvTbl.add "value" slot id (path, decl) env.values renv.values; + values = EnvTbl.add slot (fun x -> `Value x) id (path, decl) + env.values renv.values; summary = Env_value(env.summary, id, decl) } and store_type ~check slot id path info env renv = @@ -1363,8 +1491,8 @@ and store_type ~check slot id path info env renv = if check then check_usage loc id (fun s -> Warnings.Unused_type_declaration s) type_declarations; - let constructors = constructors_of_type path info in - let labels = labels_of_type path info in + let constructors = Datarepr.constructors_of_type path info in + let labels = Datarepr.labels_of_type path info in let descrs = (List.map snd constructors, List.map snd labels) in if check && not loc.Location.loc_ghost && @@ -1391,16 +1519,18 @@ and store_type ~check slot id path info env renv = constrs = List.fold_right (fun (id, descr) constrs -> - EnvTbl.add "constructor" slot id descr constrs renv.constrs) + EnvTbl.add slot (fun x -> `Constructor x) id descr constrs + renv.constrs) constructors env.constrs; labels = List.fold_right (fun (id, descr) labels -> - EnvTbl.add "label" slot id descr labels renv.labels) + EnvTbl.add slot (fun x -> `Label x) id descr labels renv.labels) labels env.labels; - types = EnvTbl.add "type" slot id (path, (info, descrs)) env.types + types = + EnvTbl.add slot (fun x -> `Type x) id (path, (info, descrs)) env.types renv.types; summary = Env_type(env.summary, id, info) } @@ -1411,8 +1541,8 @@ and store_type_infos slot id path info env renv = keep track of type abbreviations (e.g. type t = float) in the computation of label representations. *) { env with - types = EnvTbl.add "type" slot id (path, (info,([],[]))) env.types - renv.types; + types = EnvTbl.add slot (fun x -> `Type x) id (path, (info,([],[]))) + env.types renv.types; summary = Env_type(env.summary, id, info) } and store_extension ~check slot id path ext env renv = @@ -1437,48 +1567,52 @@ and store_extension ~check slot id path ext env renv = end; end; { env with - constrs = EnvTbl.add "constructor" slot id + constrs = EnvTbl.add slot (fun x -> `Constructor x) id (Datarepr.extension_descr path ext) env.constrs renv.constrs; summary = Env_extension(env.summary, id, ext) } and store_module slot id path md env renv = + let deprecated = Builtin_attributes.deprecated_of_attrs md.md_attributes in { env with - modules = EnvTbl.add "module" slot id (path, md) env.modules renv.modules; + modules = EnvTbl.add slot (fun x -> `Module x) id (path, md) + env.modules renv.modules; components = - EnvTbl.add "module" slot id - (path, components_of_module env Subst.identity path md.md_type) - env.components renv.components; + EnvTbl.add slot (fun x -> `Component x) id + (path, components_of_module ~deprecated + env Subst.identity path md.md_type) + env.components renv.components; summary = Env_module(env.summary, id, md) } and store_modtype slot id path info env renv = { env with - modtypes = EnvTbl.add "module type" slot id (path, info) env.modtypes - renv.modtypes; + modtypes = EnvTbl.add slot (fun x -> `Module_type x) id (path, info) + env.modtypes renv.modtypes; summary = Env_modtype(env.summary, id, info) } and store_class slot id path desc env renv = { env with - classes = EnvTbl.add "class" slot id (path, desc) env.classes renv.classes; + classes = EnvTbl.add slot (fun x -> `Class x) id (path, desc) + env.classes renv.classes; summary = Env_class(env.summary, id, desc) } and store_cltype slot id path desc env renv = { env with - cltypes = EnvTbl.add "class type" slot id (path, desc) env.cltypes - renv.cltypes; + cltypes = EnvTbl.add slot (fun x -> `Class_type x) id (path, desc) + env.cltypes renv.cltypes; summary = Env_cltype(env.summary, id, desc) } (* Compute the components of a functor application in a path. *) -let components_of_functor_appl f p1 p2 = +let components_of_functor_appl f env p1 p2 = try Hashtbl.find f.fcomp_cache p2 with Not_found -> let p = Papply(p1, p2) in - let mty = - Subst.modtype (Subst.add_module f.fcomp_param p2 Subst.identity) - f.fcomp_res in - let comps = components_of_module f.fcomp_env f.fcomp_subst p mty in + let sub = Subst.add_module f.fcomp_param p2 Subst.identity in + let mty = Subst.modtype sub f.fcomp_res in + let comps = components_of_module ~deprecated:None (*???*) + env Subst.identity p mty in Hashtbl.add f.fcomp_cache p2 comps; comps @@ -1491,8 +1625,7 @@ let _ = (* Insertion of bindings by identifier *) -let add_functor_arg ?(arg=false) id env = - if not arg then env else +let add_functor_arg id env = {env with functor_args = Ident.add id () env.functor_args; summary = Env_functor_arg (env.summary, id)} @@ -1506,14 +1639,14 @@ let add_type ~check id info env = and add_extension ~check id ext env = store_extension ~check None id (Pident id) ext env env -and add_module_declaration ?arg id md env = +and add_module_declaration ?(arg=false) id md env = let path = (*match md.md_type with Mty_alias path -> normalize_path env path | _ ->*) Pident id in let env = store_module None id path md env env in - add_functor_arg ?arg id env + if arg then add_functor_arg id env else env and add_modtype id info env = store_modtype None id (Pident id) info env env @@ -1545,9 +1678,8 @@ let enter store_fun name data env = let enter_value ?check = enter (store_value ?check) and enter_type = enter (store_type ~check:true) and enter_extension = enter (store_extension ~check:true) -and enter_module_declaration ?arg name md env = - let id = Ident.create name in - (id, add_module_declaration ?arg id md env) +and enter_module_declaration ?arg id md env = + add_module_declaration ?arg id md env (* let (id, env) = enter store_module name md env in (id, add_functor_arg ?arg id env) *) and enter_modtype = enter store_modtype @@ -1555,7 +1687,8 @@ and enter_class = enter store_class and enter_cltype = enter store_cltype let enter_module ?arg s mty env = - enter_module_declaration ?arg s (md mty) env + let id = Ident.create s in + (id, enter_module_declaration ?arg id (md mty) env) (* Insertion of all components of a signature *) @@ -1564,7 +1697,7 @@ let add_item comp env = Sig_value(id, decl) -> add_value id decl env | Sig_type(id, decl, _) -> add_type ~check:false id decl env | Sig_typext(id, ext, _) -> add_extension ~check:false id ext env - | Sig_module(id, md, _) -> add_module_declaration id md env + | Sig_module(id, md, _) -> add_module_declaration id md env | Sig_modtype(id, decl) -> add_modtype id decl env | Sig_class(id, decl, _) -> add_class id decl env | Sig_class_type(id, decl, _) -> add_cltype id decl env @@ -1609,7 +1742,8 @@ let open_signature slot root sg env0 = let open_pers_signature name env = let ps = find_pers_struct name in - open_signature None (Pident(Ident.create_persistent name)) ps.ps_sig env + open_signature None (Pident(Ident.create_persistent name)) + (Lazy.force ps.ps_sig) env let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root sg env = if not toplevel && ovf = Asttypes.Fresh && not loc.Location.loc_ghost @@ -1624,16 +1758,18 @@ let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root sg env = Location.prerr_warning loc (Warnings.Unused_open (Path.name root)) ); let shadowed = ref [] in - let slot kind s b = - if b && not (List.mem (kind, s) !shadowed) then begin - shadowed := (kind, s) :: !shadowed; - let w = - match kind with - | "label" | "constructor" -> - Warnings.Open_shadow_label_constructor (kind, s) - | _ -> Warnings.Open_shadow_identifier (kind, s) - in - Location.prerr_warning loc w + let slot s b = + begin match check_shadowing env b with + | Some kind when not (List.mem (kind, s) !shadowed) -> + shadowed := (kind, s) :: !shadowed; + let w = + match kind with + | "label" | "constructor" -> + Warnings.Open_shadow_label_constructor (kind, s) + | _ -> Warnings.Open_shadow_identifier (kind, s) + in + Location.prerr_warning loc w + | _ -> () end; used := true in @@ -1645,8 +1781,7 @@ let open_signature ?(loc = Location.none) ?(toplevel = false) ovf root sg env = let read_signature modname filename = let ps = read_pers_struct modname filename in - check_consistency ps; - ps.ps_sig + Lazy.force ps.ps_sig (* Return the CRC of the interface of the given compilation unit *) @@ -1664,40 +1799,50 @@ let crc_of_unit name = (* Return the list of imported interfaces with their CRCs *) -let imports() = +let imports () = Consistbl.extract (StringSet.elements !imported_units) crc_units +(* Returns true if [s] is an opaque imported module *) +let is_imported_opaque s = + StringSet.mem s !imported_opaque_units + (* Save a signature to a file *) -let save_signature_with_imports sg modname filename imports = +let save_signature_with_imports ~deprecated sg modname filename imports = (*prerr_endline filename; List.iter (fun (name, crc) -> prerr_endline name) imports;*) Btype.cleanup_abbrev (); Subst.reset_for_saving (); let sg = Subst.signature (Subst.for_saving Subst.identity) sg in + let flags = + List.concat [ + if !Clflags.recursive_types then [Cmi_format.Rectypes] else []; + if !Clflags.opaque then [Cmi_format.Opaque] else []; + (match deprecated with Some s -> [Deprecated s] | None -> []); + ] + in let oc = open_out_bin filename in try let cmi = { cmi_name = modname; cmi_sign = sg; cmi_crcs = imports; - cmi_flags = if !Clflags.recursive_types then [Rectypes] else []; + cmi_flags = flags; } in let crc = output_cmi filename oc cmi in close_out oc; (* Enter signature in persistent table so that imported_unit() will also return its crc *) let comps = - components_of_module empty Subst.identity + components_of_module ~deprecated empty Subst.identity (Pident(Ident.create_persistent modname)) (Mty_signature sg) in let ps = { ps_name = modname; - ps_sig = sg; + ps_sig = lazy (Subst.signature Subst.identity sg); ps_comps = comps; ps_crcs = (cmi.cmi_name, Some crc) :: imports; ps_filename = filename; ps_flags = cmi.cmi_flags; - ps_crcs_checked = false; } in save_pers_struct crc ps; sg @@ -1706,8 +1851,8 @@ let save_signature_with_imports sg modname filename imports = remove_file filename; raise exn -let save_signature sg modname filename = - save_signature_with_imports sg modname filename (imports()) +let save_signature ~deprecated sg modname filename = + save_signature_with_imports ~deprecated sg modname filename (imports()) (* Folding on environments *) @@ -1719,7 +1864,7 @@ let find_all proj1 proj2 f lid env acc = (proj1 env) acc | Some l -> let p, desc = lookup_module_descr l env in - begin match EnvLazy.force components_of_module_maker desc with + begin match get_components desc with Structure_comps c -> Tbl.fold (fun s (data, pos) acc -> f s (Pdot (p, s, pos)) data acc) @@ -1736,7 +1881,7 @@ let find_all_simple_list proj1 proj2 f lid env acc = (proj1 env) acc | Some l -> let p, desc = lookup_module_descr l env in - begin match EnvLazy.force components_of_module_maker desc with + begin match get_components desc with Structure_comps c -> Tbl.fold (fun s comps acc -> @@ -1764,12 +1909,12 @@ let fold_modules f lid env acc = None -> acc | Some ps -> f name (Pident(Ident.create_persistent name)) - (md (Mty_signature ps.ps_sig)) acc) + (md (Mty_signature (Lazy.force ps.ps_sig))) acc) persistent_structures acc | Some l -> let p, desc = lookup_module_descr l env in - begin match EnvLazy.force components_of_module_maker desc with + begin match get_components desc with Structure_comps c -> Tbl.fold (fun s (data, pos) acc -> @@ -1840,10 +1985,10 @@ let env_of_only_summary env_from_summary env = open Format let report_error ppf = function - | Illegal_renaming(name, modname, filename) -> fprintf ppf + | Illegal_renaming(modname, ps_name, filename) -> fprintf ppf "Wrong file naming: %a@ contains the compiled interface for @ \ %s when %s was expected" - Location.print_filename filename name modname + Location.print_filename filename ps_name modname | Inconsistent_import(name, source1, source2) -> fprintf ppf "@[The files %a@ and %a@ \ make inconsistent assumptions@ over interface %s@]" diff --git a/typing/env.mli b/typing/env.mli index e894557e..8166db82 100644 --- a/typing/env.mli +++ b/typing/env.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Environment handling *) @@ -63,6 +66,7 @@ val find_type_expansion_opt: (* Find the manifest type information associated to a type for the sake of the compiler's type-based optimisations. *) val find_modtype_expansion: Path.t -> t -> module_type +val add_functor_arg: Ident.t -> t -> t val is_functor_arg: Path.t -> t -> bool val normalize_path: Location.t option -> t -> Path.t -> Path.t (* Normalize the path to a concrete value or module. @@ -81,18 +85,34 @@ val add_gadt_instance_chain: t -> int -> type_expr -> unit (* Lookup by long identifiers *) -val lookup_value: Longident.t -> t -> Path.t * value_description -val lookup_constructor: Longident.t -> t -> constructor_description +(* ?loc is used to report 'deprecated module' warnings *) + +val lookup_value: + ?loc:Location.t -> Longident.t -> t -> Path.t * value_description +val lookup_constructor: + ?loc:Location.t -> Longident.t -> t -> constructor_description val lookup_all_constructors: + ?loc:Location.t -> Longident.t -> t -> (constructor_description * (unit -> unit)) list -val lookup_label: Longident.t -> t -> label_description +val lookup_label: + ?loc:Location.t -> Longident.t -> t -> label_description val lookup_all_labels: + ?loc:Location.t -> Longident.t -> t -> (label_description * (unit -> unit)) list -val lookup_type: Longident.t -> t -> Path.t * type_declaration -val lookup_module: load:bool -> Longident.t -> t -> Path.t -val lookup_modtype: Longident.t -> t -> Path.t * modtype_declaration -val lookup_class: Longident.t -> t -> Path.t * class_declaration -val lookup_cltype: Longident.t -> t -> Path.t * class_type_declaration +val lookup_type: + ?loc:Location.t -> Longident.t -> t -> Path.t * type_declaration +val lookup_module: + load:bool -> ?loc:Location.t -> Longident.t -> t -> Path.t +val lookup_modtype: + ?loc:Location.t -> Longident.t -> t -> Path.t * modtype_declaration +val lookup_class: + ?loc:Location.t -> Longident.t -> t -> Path.t * class_declaration +val lookup_cltype: + ?loc:Location.t -> Longident.t -> t -> Path.t * class_type_declaration + +val update_value: + string -> (value_description -> value_description) -> t -> t + (* Used only in Typecore.duplicate_ident_types. *) exception Recmodule (* Raise by lookup_module when the identifier refers @@ -134,7 +154,7 @@ val enter_type: string -> type_declaration -> t -> Ident.t * t val enter_extension: string -> extension_constructor -> t -> Ident.t * t val enter_module: ?arg:bool -> string -> module_type -> t -> Ident.t * t val enter_module_declaration: - ?arg:bool -> string -> module_declaration -> t -> Ident.t * t + ?arg:bool -> Ident.t -> module_declaration -> t -> t val enter_modtype: string -> modtype_declaration -> t -> Ident.t * t val enter_class: string -> class_declaration -> t -> Ident.t * t val enter_cltype: string -> class_type_declaration -> t -> Ident.t * t @@ -153,10 +173,13 @@ val get_unit_name: unit -> string val read_signature: string -> string -> signature (* Arguments: module name, file name. Results: signature. *) -val save_signature: signature -> string -> string -> signature +val save_signature: + deprecated:string option -> signature -> string -> string -> signature (* Arguments: signature, module name, file name. *) val save_signature_with_imports: - signature -> string -> string -> (string * Digest.t option) list -> signature + deprecated:string option -> + signature -> string -> string -> (string * Digest.t option) list + -> signature (* Arguments: signature, module name, file name, imported units with their CRCs. *) @@ -168,6 +191,9 @@ val crc_of_unit: string -> Digest.t val imports: unit -> (string * Digest.t option) list +(* [is_imported_opaque md] returns true if [md] is an opaque imported module *) +val is_imported_opaque: string -> bool + (* Direct access to the table of imported compilation units with their CRC *) val crc_units: Consistbl.t @@ -212,9 +238,11 @@ val mark_constructor: val mark_extension_used: constructor_usage -> t -> extension_constructor -> string -> unit -val in_signature: t -> t +val in_signature: bool -> t -> t val implicit_coercion: t -> t +val is_in_signature: t -> bool + val set_value_used_callback: string -> value_description -> (unit -> unit) -> unit val set_type_used_callback: @@ -227,6 +255,8 @@ val check_modtype_inclusion: val add_delayed_check_forward: ((unit -> unit) -> unit) ref (* Forward declaration to break mutual recursion with Mtype. *) val strengthen: (t -> module_type -> Path.t -> module_type) ref +(* Forward declaration to break mutual recursion with Ctype. *) +val same_constr: (t -> type_expr -> type_expr -> bool) ref (** Folding over all identifiers (for analysis purpose) *) diff --git a/typing/envaux.ml b/typing/envaux.ml index 708da443..b83046c3 100644 --- a/typing/envaux.ml +++ b/typing/envaux.ml @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Misc open Types diff --git a/typing/envaux.mli b/typing/envaux.mli index b893c141..2869890a 100644 --- a/typing/envaux.mli +++ b/typing/envaux.mli @@ -1,15 +1,18 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* OCaml port by John Malecki and Xavier Leroy *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* OCaml port by John Malecki and Xavier Leroy *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format diff --git a/typing/ident.ml b/typing/ident.ml index db4ea699..951403fe 100644 --- a/typing/ident.ml +++ b/typing/ident.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) open Format @@ -38,8 +41,6 @@ let rename i = let name i = i.name -let stamp i = i.stamp - let unique_name i = i.name ^ "_" ^ string_of_int i.stamp let unique_toplevel_name i = i.name ^ "/" ^ string_of_int i.stamp @@ -54,6 +55,8 @@ let same i1 i2 = i1 = i2 then i1.stamp = i2.stamp else i2.stamp = 0 && i1.name = i2.name *) +let compare i1 i2 = Pervasives.compare i1 i2 + let binding_time i = i.stamp let current_time() = !currentstamp @@ -221,3 +224,26 @@ let make_key_generator () = let stamp = !c in decr c ; { id with name = key_name; stamp = stamp; } + +let compare x y = + let c = x.stamp - y.stamp in + if c <> 0 then c + else + let c = compare x.name y.name in + if c <> 0 then c + else + compare x.flags y.flags + +let output oc id = output_string oc (unique_name id) +let hash i = (Char.code i.name.[0]) lxor i.stamp + +let original_equal = equal +include Identifiable.Make (struct + type nonrec t = t + let compare = compare + let output = output + let print = print + let hash = hash + let equal = same +end) +let equal = original_equal diff --git a/typing/ident.mli b/typing/ident.mli index be226c2d..1c9b6e04 100644 --- a/typing/ident.mli +++ b/typing/ident.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Identifiers (unique names) *) @@ -30,12 +33,18 @@ val same: t -> t -> bool non-persistent and have been created by the same call to [new], or if they are both persistent and have the same name. *) +val compare: t -> t -> int + (* [compare x y] is 0 if [same x y] is true. *) +val hash: t -> int val hide: t -> t (* Return an identifier with same name as the given identifier, but stamp different from any stamp returned by new. When put in a 'a tbl, this identifier can only be looked up by name. *) +val compare : t -> t -> int +(* Compare identifiers by binding location *) + val make_global: t -> unit val global: t -> bool val is_predef_exn: t -> bool @@ -46,6 +55,7 @@ val set_current_time: int -> unit val reinit: unit -> unit val print: Format.formatter -> t -> unit +val output : out_channel -> t -> unit type 'a tbl (* Association tables from identifiers to type 'a. *) @@ -63,3 +73,5 @@ val iter: (t -> 'a -> unit) -> 'a tbl -> unit (* Idents for sharing keys *) val make_key_generator : unit -> (t -> t) + +include Identifiable.S with type t := t diff --git a/typing/includeclass.ml b/typing/includeclass.ml index 9e3564b1..92e06f1b 100644 --- a/typing/includeclass.ml +++ b/typing/includeclass.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1997 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1997 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. *) +(* *) +(**************************************************************************) (* Inclusion checks for the class language *) diff --git a/typing/includeclass.mli b/typing/includeclass.mli index 48c5c0ca..7483ee80 100644 --- a/typing/includeclass.mli +++ b/typing/includeclass.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1997 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1997 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. *) +(* *) +(**************************************************************************) (* Inclusion checks for the class language *) diff --git a/typing/includecore.ml b/typing/includecore.ml index 88fad1e5..a1bc3bdc 100644 --- a/typing/includecore.ml +++ b/typing/includecore.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Inclusion checks for the core language *) @@ -26,7 +29,10 @@ let value_descriptions env vd1 vd2 = match (vd1.val_kind, vd2.val_kind) with (Val_prim p1, Val_prim p2) -> if p1 = p2 then Tcoerce_none else raise Dont_match - | (Val_prim p, _) -> Tcoerce_primitive p + | (Val_prim p, _) -> + let pc = {pc_desc = p; pc_type = vd2.Types.val_type; + pc_env = env; pc_loc = vd1.Types.val_loc; } in + Tcoerce_primitive pc | (_, Val_prim p) -> raise Dont_match | (_, _) -> Tcoerce_none end else @@ -121,6 +127,7 @@ type type_mismatch = | Field_names of int * Ident.t * Ident.t | Field_missing of bool * Ident.t | Record_representation of bool + | Immediate let report_type_mismatch0 first second decl ppf err = let pr fmt = Format.fprintf ppf fmt in @@ -147,6 +154,7 @@ let report_type_mismatch0 first second decl ppf err = pr "Their internal representations differ:@ %s %s %s" (if b then second else first) decl "uses unboxed float representation" + | Immediate -> pr "%s is not an immediate type" first let report_type_mismatch first second decl ppf = List.iter @@ -154,7 +162,19 @@ let report_type_mismatch first second decl ppf = if err = Manifest then () else Format.fprintf ppf "@ %a." (report_type_mismatch0 first second decl) err) -let rec compare_variants env decl1 decl2 n cstrs1 cstrs2 = +let rec compare_constructor_arguments env cstr params1 params2 arg1 arg2 = + match arg1, arg2 with + | Types.Cstr_tuple arg1, Types.Cstr_tuple arg2 -> + if List.length arg1 <> List.length arg2 then [Field_arity cstr] + else if Misc.for_all2 + (fun ty1 ty2 -> Ctype.equal env true (ty1::params1) (ty2::params2)) + (arg1) (arg2) + then [] else [Field_type cstr] + | Types.Cstr_record l1, Types.Cstr_record l2 -> + compare_records env params1 params2 0 l1 l2 + | _ -> [Field_type cstr] + +and compare_variants env params1 params2 n cstrs1 cstrs2 = match cstrs1, cstrs2 with [], [] -> [] | [], c::_ -> [Field_missing (true, c.Types.cd_id)] @@ -163,42 +183,59 @@ let rec compare_variants env decl1 decl2 n cstrs1 cstrs2 = {Types.cd_id=cstr2; cd_args=arg2; cd_res=ret2}::rem2 -> if Ident.name cstr1 <> Ident.name cstr2 then [Field_names (n, cstr1, cstr2)] - else if List.length arg1 <> List.length arg2 then - [Field_arity cstr1] - else match ret1, ret2 with - | Some r1, Some r2 when not (Ctype.equal env true [r1] [r2]) -> - [Field_type cstr1] - | Some _, None | None, Some _ -> - [Field_type cstr1] - | _ -> - if Misc.for_all2 - (fun ty1 ty2 -> - Ctype.equal env true (ty1::decl1.type_params) - (ty2::decl2.type_params)) - (arg1) (arg2) - then - compare_variants env decl1 decl2 (n+1) rem1 rem2 - else [Field_type cstr1] + else + let r = + match ret1, ret2 with + | Some r1, Some r2 -> + if Ctype.equal env true [r1] [r2] then + compare_constructor_arguments env cstr1 [r1] [r2] arg1 arg2 + else [Field_type cstr1] + | Some _, None | None, Some _ -> + [Field_type cstr1] + | _ -> + compare_constructor_arguments env cstr1 + params1 params2 arg1 arg2 + in + if r <> [] then r + else compare_variants env params1 params2 (n+1) rem1 rem2 -let rec compare_records env decl1 decl2 n labels1 labels2 = +and compare_records env params1 params2 n labels1 labels2 = match labels1, labels2 with [], [] -> [] - | [], l::_ -> [Field_missing (true, l.ld_id)] - | l::_, [] -> [Field_missing (false, l.ld_id)] + | [], l::_ -> [Field_missing (true, l.Types.ld_id)] + | l::_, [] -> [Field_missing (false, l.Types.ld_id)] | {Types.ld_id=lab1; ld_mutable=mut1; ld_type=arg1}::rem1, {Types.ld_id=lab2; ld_mutable=mut2; ld_type=arg2}::rem2 -> if Ident.name lab1 <> Ident.name lab2 then [Field_names (n, lab1, lab2)] else if mut1 <> mut2 then [Field_mutable lab1] else - if Ctype.equal env true (arg1::decl1.type_params) - (arg2::decl2.type_params) - then compare_records env decl1 decl2 (n+1) rem1 rem2 + if Ctype.equal env true (arg1::params1) + (arg2::params2) + then compare_records env params1 params2 (n+1) rem1 rem2 else [Field_type lab1] let type_declarations ?(equality = false) env name decl1 id decl2 = if decl1.type_arity <> decl2.type_arity then [Arity] else if not (private_flags decl1 decl2) then [Privacy] else + let err = match (decl1.type_manifest, decl2.type_manifest) with + (_, None) -> + if Ctype.equal env true decl1.type_params decl2.type_params + then [] else [Constraint] + | (Some ty1, Some ty2) -> + if type_manifest env ty1 decl1.type_params ty2 decl2.type_params + decl2.type_private + then [] else [Manifest] + | (None, Some ty2) -> + let ty1 = + Btype.newgenty (Tconstr(Pident id, decl2.type_params, ref Mnil)) + in + if Ctype.equal env true decl1.type_params decl2.type_params then + if Ctype.equal env false [ty1] [ty2] then [] + else [Manifest] + else [Constraint] + in + if err <> [] then err else let err = match (decl1.type_kind, decl2.type_kind) with (_, Type_abstract) -> [] | (Type_variant cstrs1, Type_variant cstrs2) -> @@ -215,36 +252,28 @@ let type_declarations ?(equality = false) env name decl1 id decl2 = in mark cstrs1 usage name decl1; if equality then mark cstrs2 Env.Positive (Ident.name id) decl2; - compare_variants env decl1 decl2 1 cstrs1 cstrs2 + compare_variants env decl1.type_params decl2.type_params 1 cstrs1 cstrs2 | (Type_record(labels1,rep1), Type_record(labels2,rep2)) -> - let err = compare_records env decl1 decl2 1 labels1 labels2 in + let err = compare_records env decl1.type_params decl2.type_params + 1 labels1 labels2 in if err <> [] || rep1 = rep2 then err else [Record_representation (rep2 = Record_float)] | (Type_open, Type_open) -> [] | (_, _) -> [Kind] in if err <> [] then err else - let err = match (decl1.type_manifest, decl2.type_manifest) with - (_, None) -> - if Ctype.equal env true decl1.type_params decl2.type_params - then [] else [Constraint] - | (Some ty1, Some ty2) -> - if type_manifest env ty1 decl1.type_params ty2 decl2.type_params - decl2.type_private - then [] else [Manifest] - | (None, Some ty2) -> - let ty1 = - Btype.newgenty (Tconstr(Pident id, decl2.type_params, ref Mnil)) - in - if Ctype.equal env true decl1.type_params decl2.type_params then - if Ctype.equal env false [ty1] [ty2] then [] - else [Manifest] - else [Constraint] + let abstr = decl2.type_kind = Type_abstract && decl2.type_manifest = None in + (* If attempt to assign a non-immediate type (e.g. string) to a type that + * must be immediate, then we error *) + let err = + if abstr && + not decl1.type_immediate && + decl2.type_immediate then + [Immediate] + else [] in if err <> [] then err else - let abstr = - decl2.type_private = Private || - decl2.type_kind = Type_abstract && decl2.type_manifest = None in + let abstr = abstr || decl2.type_private = Private in let opn = decl2.type_kind = Type_open && decl2.type_manifest = None in let constrained ty = not (Btype.(is_Tvar (repr ty))) in if List.for_all2 @@ -278,17 +307,13 @@ let extension_constructors env id ext1 ext2 = (ty1 :: ext1.ext_type_params) (ty2 :: ext2.ext_type_params) then - if List.length ext1.ext_args = List.length ext2.ext_args then + if compare_constructor_arguments env (Ident.create "") + ext1.ext_type_params ext2.ext_type_params + ext1.ext_args ext2.ext_args = [] then if match ext1.ext_ret_type, ext2.ext_ret_type with Some r1, Some r2 when not (Ctype.equal env true [r1] [r2]) -> false | Some _, None | None, Some _ -> false - | _ -> - Misc.for_all2 - (fun ty1 ty2 -> - Ctype.equal env true - (ty1 :: ext1.ext_type_params) - (ty2 :: ext2.ext_type_params)) - ext1.ext_args ext2.ext_args + | _ -> true then match ext1.ext_private, ext2.ext_private with Private, Public -> false @@ -296,33 +321,3 @@ let extension_constructors env id ext1 ext2 = else false else false else false - -(* Inclusion between class types *) -let encode_val (mut, ty) rem = - begin match mut with - Asttypes.Mutable -> Predef.type_unit - | Asttypes.Immutable -> Btype.newgenvar () - end - ::ty::rem - -let meths meths1 meths2 = - Meths.fold - (fun nam t2 (ml1, ml2) -> - (begin try - Meths.find nam meths1 :: ml1 - with Not_found -> - ml1 - end, - t2 :: ml2)) - meths2 ([], []) - -let vars vars1 vars2 = - Vars.fold - (fun lab v2 (vl1, vl2) -> - (begin try - encode_val (Vars.find lab vars1) vl1 - with Not_found -> - vl1 - end, - encode_val v2 vl2)) - vars2 ([], []) diff --git a/typing/includecore.mli b/typing/includecore.mli index 0c8e9558..17278a4a 100644 --- a/typing/includecore.mli +++ b/typing/includecore.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Inclusion checks for the core language *) @@ -30,6 +33,7 @@ type type_mismatch = | Field_names of int * Ident.t * Ident.t | Field_missing of bool * Ident.t | Record_representation of bool + | Immediate val value_descriptions: Env.t -> value_description -> value_description -> module_coercion diff --git a/typing/includemod.ml b/typing/includemod.ml index 91f37d7c..6f9b2eeb 100644 --- a/typing/includemod.ml +++ b/typing/includemod.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Inclusion checks for the module language *) @@ -179,8 +182,9 @@ let rec print_coercion ppf c = pr "@[<2>functor@ (%a)@ (%a)@]" print_coercion inp print_coercion out - | Tcoerce_primitive pd -> - pr "prim %s" pd.Primitive.prim_name + | Tcoerce_primitive {pc_desc; pc_env = _; pc_type} -> + pr "prim %s@ (%a)" pc_desc.Primitive.prim_name + Printtyp.raw_type_expr pc_type | Tcoerce_alias (p, c) -> pr "@[<2>alias %a@ (%a)@]" Printtyp.path p @@ -279,7 +283,7 @@ and try_modtypes2 env cxt mty1 mty2 = and signatures env cxt subst sig1 sig2 = (* Environment used to check inclusion of components *) let new_env = - Env.add_signature sig1 (Env.in_signature env) in + Env.add_signature sig1 (Env.in_signature true env) in (* Keep ids for module aliases *) let (id_pos_list,_) = List.fold_left @@ -382,9 +386,11 @@ and signature_components old_env env cxt subst paired = extension_constructors env cxt subst id1 ext1 ext2; (pos, Tcoerce_none) :: comps_rec rem | (Sig_module(id1, mty1, _), Sig_module(id2, mty2, _), pos) :: rem -> + let p1 = Pident id1 in let cc = modtypes env (Module id1::cxt) subst - (Mtype.strengthen env mty1.md_type (Pident id1)) mty2.md_type in + (Mtype.strengthen (Env.add_functor_arg id1 env) mty1.md_type p1) + mty2.md_type in (pos, cc) :: comps_rec rem | (Sig_modtype(id1, info1), Sig_modtype(id2, info2), pos) :: rem -> modtype_infos env cxt subst id1 info1 info2; @@ -421,7 +427,10 @@ and check_modtype_equiv env cxt mty1 mty2 = modtypes env cxt Subst.identity mty2 mty1) with (Tcoerce_none, Tcoerce_none) -> () - | (_, _) -> raise(Error [cxt, env, Modtype_permutation]) + | (c1, c2) -> + (* Format.eprintf "@[c1 = %a@ c2 = %a@]@." + print_coercion c1 print_coercion c2; *) + raise(Error [cxt, env, Modtype_permutation]) (* Simplified inclusion check between module types (for Env) *) diff --git a/typing/includemod.mli b/typing/includemod.mli index 5bc3c336..72afe398 100644 --- a/typing/includemod.mli +++ b/typing/includemod.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Inclusion checks for the module language *) diff --git a/typing/mtype.ml b/typing/mtype.ml index 21d6b871..c1995dc3 100644 --- a/typing/mtype.ml +++ b/typing/mtype.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Operations on module types *) @@ -33,18 +36,23 @@ let freshen mty = let rec strengthen env mty p = match scrape env mty with Mty_signature sg -> - Mty_signature(strengthen_sig env sg p) + Mty_signature(strengthen_sig env sg p 0) | Mty_functor(param, arg, res) when !Clflags.applicative_functors && Ident.name param <> "*" -> Mty_functor(param, arg, strengthen env res (Papply(p, Pident param))) | mty -> mty -and strengthen_sig env sg p = +and strengthen_sig env sg p pos = match sg with [] -> [] | (Sig_value(id, desc) as sigelt) :: rem -> - sigelt :: strengthen_sig env rem p + let nextpos = match desc.val_kind with Val_prim _ -> pos | _ -> pos+1 in + sigelt :: strengthen_sig env rem p nextpos + | Sig_type(id, {type_kind=Type_abstract}, rs) :: + (Sig_type(id', {type_private=Private}, _) :: _ as rem) + when Ident.name id = Ident.name id' ^ "#row" -> + strengthen_sig env rem p pos | Sig_type(id, decl, rs) :: rem -> let newdecl = match decl.type_manifest, decl.type_private, decl.type_kind with @@ -59,13 +67,18 @@ and strengthen_sig env sg p = else { decl with type_manifest = manif } in - Sig_type(id, newdecl, rs) :: strengthen_sig env rem p + Sig_type(id, newdecl, rs) :: strengthen_sig env rem p pos | (Sig_typext(id, ext, es) as sigelt) :: rem -> - sigelt :: strengthen_sig env rem p + sigelt :: strengthen_sig env rem p (pos+1) | Sig_module(id, md, rs) :: rem -> - let str = strengthen_decl env md (Pdot(p, Ident.name id, nopos)) in + let str = + if Env.is_functor_arg p env then + strengthen_decl env md (Pdot(p, Ident.name id, pos)) + else + {md with md_type = Mty_alias (Pdot(p, Ident.name id, pos))} + in Sig_module(id, str, rs) - :: strengthen_sig (Env.add_module_declaration id md env) rem p + :: strengthen_sig (Env.add_module_declaration id md env) rem p (pos+1) (* Need to add the module in case it defines manifest module types *) | Sig_modtype(id, decl) :: rem -> let newdecl = @@ -76,12 +89,12 @@ and strengthen_sig env sg p = decl in Sig_modtype(id, newdecl) :: - strengthen_sig (Env.add_modtype id decl env) rem p + strengthen_sig (Env.add_modtype id decl env) rem p pos (* Need to add the module type in case it is manifest *) | (Sig_class(id, decl, rs) as sigelt) :: rem -> - sigelt :: strengthen_sig env rem p + sigelt :: strengthen_sig env rem p (pos+1) | (Sig_class_type(id, decl, rs) as sigelt) :: rem -> - sigelt :: strengthen_sig env rem p + sigelt :: strengthen_sig env rem p pos and strengthen_decl env md p = {md with md_type = strengthen env md.md_type p} @@ -258,7 +271,13 @@ and contains_type_sig env = List.iter (contains_type_item env) and contains_type_item env = function Sig_type (_,({type_manifest = None} | {type_kind = Type_abstract; type_private = Private}),_) - | Sig_modtype _ -> + | Sig_modtype _ + | Sig_typext (_, {ext_args = Cstr_record _}, _) -> + (* We consider that extension constructors with an inlined + record create a type (the inlined record), even though + it would be technically safe to ignore that considering + the current constraints which guarantee that this type + is kept local to expressions. *) raise Exit | Sig_module (_, {md_type = mty}, _) -> contains_type env mty @@ -282,7 +301,7 @@ module P = struct end module PathSet = Set.Make (P) module PathMap = Map.Make (P) -module IdentSet = Set.Make (struct type t = Ident.t let compare = compare end) +module IdentSet = Set.Make (Ident) let rec get_prefixes = function Pident _ -> PathSet.empty diff --git a/typing/mtype.mli b/typing/mtype.mli index 6e815fad..2aaafaef 100644 --- a/typing/mtype.mli +++ b/typing/mtype.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Operations on module types *) diff --git a/typing/oprint.ml b/typing/oprint.ml index 4f482325..5860c602 100644 --- a/typing/oprint.ml +++ b/typing/oprint.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) open Format open Outcometree @@ -99,7 +102,7 @@ let print_out_value ppf tree = | Oval_char c -> fprintf ppf "%C" c | Oval_string s -> begin try fprintf ppf "%S" s with - Invalid_argument "String.create" -> fprintf ppf "" + Invalid_argument _ (* "String.create" *)-> fprintf ppf "" end | Oval_list tl -> fprintf ppf "@[<1>[%a]@]" (print_tree_list print_tree_1 ";") tl @@ -224,7 +227,8 @@ and print_simple_out_type ppf = pp_print_char ppf ')'; pp_close_box ppf () | Otyp_abstract | Otyp_open - | Otyp_sum _ | Otyp_record _ | Otyp_manifest (_, _) -> () + | Otyp_sum _ | Otyp_manifest (_, _) -> () + | Otyp_record lbls -> print_record_decl ppf lbls | Otyp_module (p, n, tyl) -> fprintf ppf "@[<1>(module %s" p; let first = ref true in @@ -235,6 +239,11 @@ and print_simple_out_type ppf = ) n tyl; fprintf ppf ")@]" + | Otyp_attribute (t, attr) -> + fprintf ppf "@[<1>(%a [@@%s])@]" print_out_type t attr.oattr_name +and print_record_decl ppf lbls = + fprintf ppf "{%a@;<1 -2>}" + (print_list_init print_out_label (fun ppf -> fprintf ppf "@ ")) lbls and print_fields rest ppf = function [] -> @@ -279,6 +288,9 @@ and print_typargs ppf = pp_print_char ppf ')'; pp_close_box ppf (); pp_print_space ppf () +and print_out_label ppf (name, mut, arg) = + fprintf ppf "@[<2>%s%s :@ %a@];" (if mut then "mutable " else "") name + print_out_type arg let out_type = ref print_out_type @@ -343,19 +355,35 @@ let out_sig_item = ref (fun _ -> failwith "Oprint.out_sig_item") let out_signature = ref (fun _ -> failwith "Oprint.out_signature") let out_type_extension = ref (fun _ -> failwith "Oprint.out_type_extension") -let rec print_out_functor ppf = +let rec print_out_functor funct ppf = function Omty_functor (_, None, mty_res) -> - fprintf ppf "() %a" print_out_functor mty_res - | Omty_functor (name , Some mty_arg, mty_res) -> - fprintf ppf "(%s : %a) %a" name - print_out_module_type mty_arg print_out_functor mty_res - | m -> fprintf ppf "->@ %a" print_out_module_type m + if funct then fprintf ppf "() %a" (print_out_functor true) mty_res + else fprintf ppf "functor@ () %a" (print_out_functor true) mty_res + | Omty_functor (name, Some mty_arg, mty_res) -> begin + match name, funct with + | "_", true -> + fprintf ppf "->@ %a ->@ %a" + print_out_module_type mty_arg (print_out_functor false) mty_res + | "_", false -> + fprintf ppf "%a ->@ %a" + print_out_module_type mty_arg (print_out_functor false) mty_res + | name, true -> + fprintf ppf "(%s : %a) %a" name + print_out_module_type mty_arg (print_out_functor true) mty_res + | name, false -> + fprintf ppf "functor@ (%s : %a) %a" name + print_out_module_type mty_arg (print_out_functor true) mty_res + end + | m -> + if funct then fprintf ppf "->@ %a" print_out_module_type m + else print_out_module_type ppf m + and print_out_module_type ppf = function Omty_abstract -> () | Omty_functor _ as t -> - fprintf ppf "@[<2>functor@ %a@]" print_out_functor t + fprintf ppf "@[<2>%a@]" (print_out_functor false) t | Omty_ident id -> fprintf ppf "%a" print_ident id | Omty_signature sg -> fprintf ppf "@[sig@ %a@;<1 -2>end@]" !out_signature sg @@ -424,8 +452,8 @@ and print_out_sig_item ppf = | Orec_first -> "type" | Orec_next -> "and") ppf td - | Osig_value (name, ty, prims) -> - let kwd = if prims = [] then "val" else "external" in + | Osig_value vd -> + let kwd = if vd.oval_prims = [] then "val" else "external" in let pr_prims ppf = function [] -> () @@ -433,8 +461,12 @@ and print_out_sig_item ppf = fprintf ppf "@ = \"%s\"" s; List.iter (fun s -> fprintf ppf "@ \"%s\"" s) sl in - fprintf ppf "@[<2>%s %a :@ %a%a@]" kwd value_ident name !out_type - ty pr_prims prims + fprintf ppf "@[<2>%s %a :@ %a%a%a@]" kwd value_ident vd.oval_name + !out_type vd.oval_type pr_prims vd.oval_prims + (fun ppf -> List.iter (fun a -> fprintf ppf "@ [@@@@%s]" a.oattr_name)) + vd.oval_attributes + | Osig_ellipsis -> + fprintf ppf "..." and print_out_type_decl kwd ppf td = let print_constraints ppf = @@ -471,12 +503,15 @@ and print_out_type_decl kwd ppf td = Asttypes.Private -> fprintf ppf " private" | Asttypes.Public -> () in + let print_immediate ppf = + if td.otype_immediate then fprintf ppf " [%@%@immediate]" else () + in let print_out_tkind ppf = function | Otyp_abstract -> () | Otyp_record lbls -> - fprintf ppf " =%a {%a@;<1 -2>}" + fprintf ppf " =%a %a" print_private td.otype_private - (print_list_init print_out_label (fun ppf -> fprintf ppf "@ ")) lbls + print_record_decl lbls | Otyp_sum constrs -> fprintf ppf " =%a@;<1 2>%a" print_private td.otype_private @@ -488,10 +523,11 @@ and print_out_type_decl kwd ppf td = print_private td.otype_private !out_type ty in - fprintf ppf "@[<2>@[%t%a@]%t@]" + fprintf ppf "@[<2>@[%t%a@]%t%t@]" print_name_params print_out_tkind ty print_constraints + print_immediate and print_out_constr ppf (name, tyl,ret_type_opt) = match ret_type_opt with @@ -513,11 +549,6 @@ and print_out_constr ppf (name, tyl,ret_type_opt) = tyl print_simple_out_type ret_type end - -and print_out_label ppf (name, mut, arg) = - fprintf ppf "@[<2>%s%s :@ %a@];" (if mut then "mutable " else "") name - !out_type arg - and print_out_extension_constructor ppf ext = let print_extended_type ppf = let print_type_parameter ppf ty = diff --git a/typing/oprint.mli b/typing/oprint.mli index 1f9ec32b..7ce08a38 100644 --- a/typing/oprint.mli +++ b/typing/oprint.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2002 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 2002 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. *) +(* *) +(**************************************************************************) open Format open Outcometree diff --git a/typing/outcometree.mli b/typing/outcometree.mli index 18885e8d..7d4cb5b6 100644 --- a/typing/outcometree.mli +++ b/typing/outcometree.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 2001 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Daniel de Rauglaudre, projet Cristal, INRIA Rocquencourt *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) (* Module [Outcometree]: results displayed by the toplevel *) @@ -24,6 +27,9 @@ type out_ident = | Oide_dot of out_ident * string | Oide_ident of string +type out_attribute = + { oattr_name: string } + type out_value = | Oval_array of out_value list | Oval_char of char @@ -60,6 +66,7 @@ type out_type = bool * out_variant * bool * (string list) option | Otyp_poly of string list * out_type | Otyp_module of string * string list * out_type list + | Otyp_attribute of out_type * out_attribute and out_variant = | Ovar_fields of (string * bool * out_type list) list @@ -91,12 +98,14 @@ and out_sig_item = | Osig_modtype of string * out_module_type | Osig_module of string * out_module_type * out_rec_status | Osig_type of out_type_decl * out_rec_status - | Osig_value of string * out_type * string list + | Osig_value of out_val_decl + | Osig_ellipsis and out_type_decl = { otype_name: string; otype_params: (string * (bool * bool)) list; otype_type: out_type; otype_private: Asttypes.private_flag; + otype_immediate: bool; otype_cstrs: (out_type * out_type) list } and out_extension_constructor = { oext_name: string; @@ -110,6 +119,11 @@ and out_type_extension = otyext_params: string list; otyext_constructors: (string * out_type list * out_type option) list; otyext_private: Asttypes.private_flag } +and out_val_decl = + { oval_name: string; + oval_type: out_type; + oval_prims: string list; + oval_attributes: out_attribute list } and out_rec_status = | Orec_not | Orec_first diff --git a/typing/parmatch.ml b/typing/parmatch.ml index c2c7ceba..cc2a780f 100644 --- a/typing/parmatch.ml +++ b/typing/parmatch.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Detection of partial matches and unused match cases. *) @@ -621,18 +624,10 @@ let clean_env env = in loop env -let full_match ignore_generalized closing env = match env with +let full_match closing env = match env with | ({pat_desc = Tpat_construct(_,c,_);pat_type=typ},_) :: _ -> if c.cstr_consts < 0 then false (* extensions *) - else - if ignore_generalized then - (* remove generalized constructors; - those cases will be handled separately *) - let env = clean_env env in - List.length env = c.cstr_normal - else - List.length env = c.cstr_consts + c.cstr_nonconsts - + else List.length env = c.cstr_consts + c.cstr_nonconsts | ({pat_desc = Tpat_variant _} as p,_) :: _ -> let fields = List.map @@ -666,22 +661,6 @@ let full_match ignore_generalized closing env = match env with | ({pat_desc = Tpat_lazy(_)},_) :: _ -> true | _ -> fatal_error "Parmatch.full_match" -let full_match_gadt env = match env with - | ({pat_desc = Tpat_construct(_,c,_);pat_type=typ},_) :: _ -> - List.length env = c.cstr_consts + c.cstr_nonconsts - | _ -> true - -let extendable_match env = 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 - not - (Path.same path Predef.path_bool || - Path.same path Predef.path_list || - Path.same path Predef.path_option) -| _ -> false - - let should_extend ext env = match ext with | None -> false | Some ext -> match env with @@ -715,30 +694,57 @@ let complete_tags nconsts nconstrs tags = (* build a pattern from a constructor list *) let pat_of_constr ex_pat cstr = - {ex_pat with pat_desc = - Tpat_construct (mknoloc (Longident.Lident "?pat_of_constr?"), - cstr,omegas cstr.cstr_arity)} - -let rec pat_of_constrs ex_pat = function -| [] -> raise Empty -| [cstr] -> pat_of_constr ex_pat cstr -| cstr::rem -> - {ex_pat with - pat_desc= - Tpat_or - (pat_of_constr ex_pat cstr, - pat_of_constrs ex_pat rem, None)} + {ex_pat with pat_desc = + Tpat_construct (mknoloc (Longident.Lident "?pat_of_constr?"), + cstr, omegas cstr.cstr_arity)} + +let orify x y = make_pat (Tpat_or (x, y, None)) x.pat_type x.pat_env + +let rec orify_many = function +| [] -> assert false +| [x] -> x +| x :: xs -> orify x (orify_many xs) + +let pat_of_constrs ex_pat cstrs = + if cstrs = [] then raise Empty else + orify_many (List.map (pat_of_constr ex_pat) cstrs) + +let pats_of_type ?(always=false) env ty = + let ty' = Ctype.expand_head env ty in + match ty'.desc with + | Tconstr (path, _, _) -> + begin try match (Env.find_type path env).type_kind with + | Type_variant cl when always || List.length cl = 1 || + List.for_all (fun cd -> cd.Types.cd_res <> None) cl -> + let cstrs = fst (Env.find_type_descrs path env) in + List.map (pat_of_constr (make_pat Tpat_any ty env)) cstrs + | Type_record (ldl, _) -> + let labels = snd (Env.find_type_descrs path env) in + let fields = + List.map (fun ld -> + mknoloc (Longident.Lident "?pat_of_label?"), ld, omega) + labels + in + [make_pat (Tpat_record (fields, Closed)) ty env] + | _ -> [omega] + with Not_found -> [omega] + end + | Ttuple tl -> + [make_pat (Tpat_tuple (omegas (List.length tl))) ty env] + | _ -> [omega] let rec get_variant_constructors env ty = match (Ctype.repr ty).desc with | Tconstr (path,_,_) -> begin - match Env.find_type path env with + try match Env.find_type path env with | {type_kind=Type_variant _} -> fst (Env.find_type_descrs path env) | {type_manifest = Some _} -> get_variant_constructors env (Ctype.expand_head_once env (clean_copy ty)) | _ -> fatal_error "Parmatch.get_variant_constructors" + with Not_found -> + fatal_error "Parmatch.get_variant_constructors" end | _ -> fatal_error "Parmatch.get_variant_constructors" @@ -752,16 +758,25 @@ let rec map_filter f = (* Sends back a pattern that complements constructor tags all_tag *) let complete_constrs p all_tags = + let c = + match p.pat_desc with Tpat_construct (_, c, _) -> c | _ -> assert false in + let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in + let constrs = get_variant_constructors p.pat_env c.cstr_res in + let others = + List.filter (fun cnstr -> List.mem cnstr.cstr_tag not_tags) constrs in + let const, nonconst = + List.partition (fun cnstr -> cnstr.cstr_arity = 0) others in + const @ nonconst + +let build_other_constrs env p = match p.pat_desc with - | Tpat_construct (_,c,_) -> - let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in - let constrs = get_variant_constructors p.pat_env c.cstr_res in - map_filter - (fun cnstr -> - if List.mem cnstr.cstr_tag not_tags then Some cnstr else None) - constrs - | _ -> fatal_error "Parmatch.complete_constr" - + Tpat_construct (_, {cstr_tag=Cstr_constant _|Cstr_block _}, _) -> + let get_tag = function + | {pat_desc = Tpat_construct (_,c,_)} -> c.cstr_tag + | _ -> fatal_error "Parmatch.get_tag" in + let all_tags = List.map (fun (p,_) -> get_tag p) env in + pat_of_constrs p (complete_constrs p all_tags) + | _ -> extra_pat (* Auxiliary for build_other *) @@ -778,21 +793,17 @@ let build_other_constant proj make first next p env = in the first column of env *) -let build_other ext env = match env with +let build_other ext env = match env with | ({pat_desc = Tpat_construct (lid, ({cstr_tag=Cstr_extension _} as c),_)},_) :: _ -> let c = {c with cstr_name = "*extension*"} in make_pat (Tpat_construct(lid, c, [])) Ctype.none Env.empty -| ({pat_desc = Tpat_construct (_, _,_)} as p,_) :: _ -> +| ({pat_desc = Tpat_construct (_, cd,_)} as p,_) :: _ -> begin match ext with | Some ext when Path.same ext (get_type_path p.pat_type p.pat_env) -> extra_pat | _ -> - let get_tag = function - | {pat_desc = Tpat_construct (_,c,_)} -> c.cstr_tag - | _ -> fatal_error "Parmatch.get_tag" in - let all_tags = List.map (fun (p,_) -> get_tag p) env in - pat_of_constrs p (complete_constrs p all_tags) + build_other_constrs env p end | ({pat_desc = Tpat_variant (_,_,r)} as p,_) :: _ -> let tags = @@ -902,20 +913,6 @@ let build_other ext env = match env with | [] -> omega | _ -> omega -let build_other_gadt ext env = - match env with - | ({pat_desc = Tpat_construct _} as p,_) :: _ -> - let get_tag = function - | {pat_desc = Tpat_construct (_,c,_)} -> c.cstr_tag - | _ -> fatal_error "Parmatch.get_tag" in - let all_tags = List.map (fun (p,_) -> get_tag p) env in - let cnstrs = complete_constrs p all_tags in - let pats = List.map (pat_of_constr p) cnstrs in - (* List.iter (Format.eprintf "%a@." top_pretty) pats; - Format.eprintf "@.@."; *) - pats - | _ -> assert false - (* Core function : Is the last row of pattern matrix pss + qs satisfiable ? @@ -956,7 +953,7 @@ let rec satisfiable pss qs = match pss with (* first column of pss is made of variables only *) | [] -> satisfiable (filter_extra pss) qs | constrs -> - if full_match false false constrs then + if full_match false constrs then List.exists (fun (p,pss) -> not (is_absent_pat p) && @@ -970,6 +967,48 @@ let rec satisfiable pss qs = match pss with let q0 = discr_pat q pss in satisfiable (filter_one q0 pss) (simple_match_args q0 q @ qs) +(* Also return the remaining cases, to enable GADT handling *) +let rec satisfiables pss qs = match pss with +| [] -> if has_instances qs then [qs] else [] +| _ -> + match qs with + | [] -> [] + | {pat_desc = Tpat_or(q1,q2,_)}::qs -> + satisfiables pss (q1::qs) @ satisfiables pss (q2::qs) + | {pat_desc = Tpat_alias(q,_,_)}::qs -> + satisfiables pss (q::qs) + | {pat_desc = (Tpat_any | Tpat_var(_))}::qs -> + let q0 = discr_pat omega pss in + let wild p = + List.map (fun qs -> p::qs) (satisfiables (filter_extra pss) qs) in + begin match filter_all q0 pss with + (* first column of pss is made of variables only *) + | [] -> + wild omega + | (p,_)::_ as constrs -> + let for_constrs () = + List.flatten ( + List.map + (fun (p,pss) -> + if is_absent_pat p then [] else + List.map (set_args p) + (satisfiables pss (simple_match_args p omega @ qs))) + constrs ) + in + if full_match false constrs then for_constrs () else + match p.pat_desc with + Tpat_construct _ -> + (* activate this code for checking non-gadt constructors *) + wild (build_other_constrs constrs p) @ for_constrs () + | _ -> + wild omega + end + | {pat_desc=Tpat_variant (l,_,r)}::_ when is_absent l r -> [] + | q::qs -> + let q0 = discr_pat q pss in + List.map (set_args q0) + (satisfiables (filter_one q0 pss) (simple_match_args q0 q @ qs)) + (* Now another satisfiable function that additionally supplies an example of a matching value. @@ -981,15 +1020,6 @@ type 'a result = | Rnone (* No matching value *) | Rsome of 'a (* This matching value *) -let rec orify_many = - let orify x y = - make_pat (Tpat_or (x, y, None)) x.pat_type x.pat_env - in - function - | [] -> assert false - | [x] -> x - | x :: xs -> orify x (orify_many xs) - let rec try_many f = function | [] -> Rnone | (p,pss)::rest -> @@ -1008,6 +1038,7 @@ let rec try_many_gadt f = function | (p,pss)::rest -> rappend (f (p, pss)) (try_many_gadt f rest) +(* let rec exhaust ext pss n = match pss with | [] -> Rsome (omegas n) | []::_ -> Rnone @@ -1068,7 +1099,7 @@ let combinations f lst lst' = | x :: xs -> iter2 x lst' @ iter xs in iter lst - +*) (* let print_pat pat = let rec string_of_pat pat = @@ -1119,7 +1150,7 @@ let rec exhaust_gadt (ext:Path.t option) pss n = match pss with | r -> r in let before = try_many_gadt try_non_omega constrs in if - full_match_gadt constrs && not (should_extend ext constrs) + full_match false constrs && not (should_extend ext constrs) then before else @@ -1136,13 +1167,8 @@ let rec exhaust_gadt (ext:Path.t option) pss n = match pss with | Rnone -> before | Rsome r -> try - let missing_trailing = build_other_gadt ext constrs in - let dug = - combinations - (fun head tail -> head :: tail) - missing_trailing - r - in + let p = build_other ext constrs in + let dug = List.map (fun tail -> p :: tail) r in match before with | Rnone -> Rsome dug | Rsome x -> Rsome (x @ dug) @@ -1193,12 +1219,12 @@ let rec pressure_variants tdefs = function try_non_omega rem && ok | [] -> true in - if full_match true (tdefs=None) constrs then + if full_match (tdefs=None) constrs then try_non_omega constrs else if tdefs = None then pressure_variants None (filter_extra pss) else - let full = full_match true true constrs in + let full = full_match true constrs in let ok = if full then try_non_omega constrs else try_non_omega (filter_all q0 (mark_partial pss)) @@ -1237,6 +1263,7 @@ type answer = type 'a row = {no_ors : 'a list ; ors : 'a list ; active : 'a list} +(* let pretty_row {ors=ors ; no_ors=no_ors; active=active} = pretty_line ors ; prerr_string " *" ; pretty_line no_ors ; prerr_string " *" ; @@ -1250,6 +1277,7 @@ let pretty_rows rs = prerr_endline "") rs ; prerr_endline "end matrix" +*) (* Initial build *) let make_row ps = {ors=[] ; no_ors=[]; active=ps} @@ -1501,7 +1529,7 @@ let get_mins le ps = (* lub p q is a pattern that matches all values matched by p and q - may raise Empty, when p and q and not compatible + may raise Empty, when p and q are not compatible *) let rec lub p q = match p.pat_desc,q.pat_desc with @@ -1662,120 +1690,83 @@ let check_partial_all v casel = (* Exhaustiveness check *) (************************) - - let rec get_first f = - function - | [] -> None - | x :: xs -> - match f x with - | None -> get_first f xs - | x -> x - - (* conversion from Typedtree.pattern to Parsetree.pattern list *) module Conv = struct open Parsetree let mkpat desc = Ast_helper.Pat.mk desc - let rec select : 'a list list -> 'a list list = - function - | xs :: [] -> List.map (fun y -> [y]) xs - | (x::xs)::ys -> - List.map - (fun lst -> x :: lst) - (select ys) - @ - select (xs::ys) - | _ -> [] - let name_counter = ref 0 let fresh name = let current = !name_counter in name_counter := !name_counter + 1; "#$" ^ name ^ string_of_int current - let conv (typed: Typedtree.pattern) : - Parsetree.pattern list * - (string, Types.constructor_description) Hashtbl.t * - (string, Types.label_description) Hashtbl.t - = - let constrs = Hashtbl.create 0 in - let labels = Hashtbl.create 0 in + let conv typed = + let constrs = Hashtbl.create 7 in + let labels = Hashtbl.create 7 in let rec loop pat = match pat.pat_desc with - Tpat_or (a,b,_) -> - loop a @ loop b - | Tpat_any | Tpat_constant _ | Tpat_var _ -> - [mkpat Ppat_any] + Tpat_or (pa,pb,_) -> + mkpat (Ppat_or (loop pa, loop pb)) + | Tpat_any + | Tpat_var _ -> + mkpat Ppat_any + | Tpat_constant c -> + mkpat (Ppat_constant (Untypeast.constant c)) | Tpat_alias (p,_,_) -> loop p | Tpat_tuple lst -> - let results = select (List.map loop lst) in - List.map - (fun lst -> mkpat (Ppat_tuple lst)) - results - | Tpat_construct (cstr_lid, cstr,lst) -> + mkpat (Ppat_tuple (List.map loop lst)) + | Tpat_construct (cstr_lid, cstr, lst) -> let id = fresh cstr.cstr_name in let lid = { cstr_lid with txt = Longident.Lident id } in Hashtbl.add constrs id cstr; - let results = select (List.map loop lst) in - begin match lst with - [] -> - [mkpat (Ppat_construct(lid, None))] - | _ -> - List.map - (fun lst -> - let arg = - match lst with - [] -> assert false - | [x] -> Some x - | _ -> Some (mkpat (Ppat_tuple lst)) - in - mkpat (Ppat_construct(lid, arg))) - results - end + let arg = + match List.map loop lst with + | [] -> None + | [p] -> Some p + | lst -> Some (mkpat (Ppat_tuple lst)) + in + mkpat (Ppat_construct(lid, arg)) | Tpat_variant(label,p_opt,row_desc) -> - begin match p_opt with - | None -> - [mkpat (Ppat_variant(label, None))] - | Some p -> - let results = loop p in - List.map - (fun p -> - mkpat (Ppat_variant(label, Some p))) - results - end + let arg = Misc.may_map loop p_opt in + mkpat (Ppat_variant(label, arg)) | Tpat_record (subpatterns, _closed_flag) -> - let pats = - select - (List.map (fun (_,_,x) -> loop x) subpatterns) - in - let label_idents = + let fields = List.map - (fun (_,lbl,_) -> + (fun (_, lbl, p) -> let id = fresh lbl.lbl_name in Hashtbl.add labels id lbl; - Longident.Lident id) + (mknoloc (Longident.Lident id), loop p)) subpatterns in - List.map - (fun lst -> - let lst = List.map2 (fun lid pat -> - (mknoloc lid, pat) - ) label_idents lst in - mkpat (Ppat_record (lst, Open))) - pats + mkpat (Ppat_record (fields, Open)) | Tpat_array lst -> - let results = select (List.map loop lst) in - List.map (fun lst -> mkpat (Ppat_array lst)) results + mkpat (Ppat_array (List.map loop lst)) | Tpat_lazy p -> - let results = loop p in - List.map (fun p -> mkpat (Ppat_lazy p)) results + mkpat (Ppat_lazy (loop p)) in let ps = loop typed in (ps, constrs, labels) end +(* Whether the counter-example contains an extension pattern *) +let contains_extension pat = + let r = ref false in + let rec loop = function + {pat_desc=Tpat_construct(_, {cstr_name="*extension*"}, _)} -> + r := true + | p -> Typedtree.iter_pattern_desc loop p.pat_desc + in loop pat; !r + +(* Build an untyped or-pattern from its expected type *) +let ppat_of_type env ty = + match pats_of_type env ty with + [{pat_desc = Tpat_any}] -> + (Conv.mkpat Parsetree.Ppat_any, Hashtbl.create 0, Hashtbl.create 0) + | pats -> + Conv.conv (orify_many pats) + let do_check_partial ?pred exhaust loc casel pss = match pss with | [] -> (* @@ -1798,23 +1789,16 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with let v = match pred with | Some pred -> - let (patterns,constrs,labels) = Conv.conv u in -(* Hashtbl.iter (fun s (path, _) -> - Printf.fprintf stderr "CONV: %s -> %s \n%!" s (Path.name path)) - constrs - ; *) - get_first (pred constrs labels) patterns + if false then Some u else + let (pattern,constrs,labels) = Conv.conv u in + pred constrs labels pattern | None -> Some u in begin match v with None -> Total | Some v -> let errmsg = - match v.pat_desc with - Tpat_construct (_, {cstr_name="*extension*"}, _) -> - "_\nMatching over values of extensible variant types must include\n\ - a wild card pattern in order to be exhaustive." - | _ -> try + try let buf = Buffer.create 16 in let fmt = formatter_of_buffer buf in top_pretty fmt v; @@ -1827,7 +1811,13 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with is a pain in the top-level *) Buffer.add_string buf "\n(However, some guarded clause may match this value.)" - end ; + end; + if contains_extension v then + Buffer.add_string buf + "\nMatching over values of extensible variant types \ + (the *extension* above)\n\ + must include a wild card pattern in order to be exhaustive." + ; Buffer.contents buf with _ -> "" @@ -1839,8 +1829,10 @@ let do_check_partial ?pred exhaust loc casel pss = match pss with fatal_error "Parmatch.check_partial" end +(* let do_check_partial_normal loc casel pss = do_check_partial exhaust loc casel pss + *) let do_check_partial_gadt pred loc casel pss = do_check_partial ~pred exhaust_gadt loc casel pss @@ -1916,23 +1908,49 @@ let do_check_fragile_param exhaust loc casel pss = | Rsome _ -> ()) exts -let do_check_fragile_normal = do_check_fragile_param exhaust +(*let do_check_fragile_normal = do_check_fragile_param exhaust*) let do_check_fragile_gadt = do_check_fragile_param exhaust_gadt (********************************) (* Exported unused clause check *) (********************************) -let check_unused tdefs casel = - if Warnings.is_active Warnings.Unused_match then +let check_unused pred tdefs casel = + if Warnings.is_active Warnings.Unused_match + || List.exists (fun c -> c.c_rhs.exp_desc = Texp_unreachable) casel then let rec do_rec pref = function | [] -> () - | {c_lhs=q; c_guard} :: rem -> + | {c_lhs=q; c_guard; c_rhs} :: rem -> let qs = [q] in begin try let pss = get_mins le_pats (List.filter (compats qs) pref) in + (* First look for redundant or partially redundant patterns *) let r = every_satisfiables (make_rows pss) (make_row qs) in + let refute = (c_rhs.exp_desc = Texp_unreachable) in + (* Do not warn for unused [pat -> .] *) + if r = Unused && refute then () else + let r = + (* Do not refine if there are no other lines *) + let skip = + r = Unused || (not refute && pref = []) || + not(refute || Warnings.is_active Warnings.Unreachable_case) in + if skip then r else + (* Then look for empty patterns *) + let sfs = satisfiables pss qs in + if sfs = [] then Unused else + let sfs = + List.map (function [u] -> u | _ -> assert false) sfs in + let u = orify_many sfs in + (*Format.eprintf "%a@." pretty_val u;*) + let (pattern,constrs,labels) = Conv.conv u in + let pattern = {pattern with Parsetree.ppat_loc = q.pat_loc} in + match pred refute constrs labels pattern with + None when not refute -> + Location.prerr_warning q.pat_loc Warnings.Unreachable_case; + Used + | _ -> r + in match r with | Unused -> Location.prerr_warning @@ -2012,19 +2030,272 @@ let check_partial_param do_check_partial do_check_fragile loc casel = end else Partial -let check_partial = +(*let check_partial = check_partial_param do_check_partial_normal - do_check_fragile_normal + do_check_fragile_normal*) let check_partial_gadt pred loc casel = - (*ignores GADT constructors *) - let first_check = check_partial loc casel in - match first_check with - | Partial -> Partial - | Total -> - (* checks for missing GADT constructors *) - (* let casel = - match casel with [] -> [] | a :: l -> a :: l @ [a] in *) - check_partial_param (do_check_partial_gadt pred) - do_check_fragile_gadt loc casel + check_partial_param (do_check_partial_gadt pred) + do_check_fragile_gadt loc casel + + +(*************************************) +(* Ambiguous variable in or-patterns *) +(*************************************) + +(* Specification: ambiguous variables in or-patterns. + + The semantics of or-patterns in OCaml is specified with + a left-to-right bias: a value [v] matches the pattern [p | q] if it + matches [p] or [q], but if it matches both, the environment + captured by the match is the environment captured by [p], never the + one captured by [q]. + + While this property is generally well-understood, one specific case + where users expect a different semantics is when a pattern is + followed by a when-guard: [| p when g -> e]. Consider for example: + + | ((Const x, _) | (_, Const x)) when is_neutral x -> branch + + The semantics is clear: match the scrutinee against the pattern, if + it matches, test the guard, and if the guard passes, take the + branch. + + However, consider the input [(Const a, Const b)], where [a] fails + the test [is_neutral f], while [b] passes the test [is_neutral + b]. With the left-to-right semantics, the clause above is *not* + taken by its input: matching [(Const a, Const b)] against the + or-pattern succeeds in the left branch, it returns the environment + [x -> a], and then the guard [is_neutral a] is tested and fails, + the branch is not taken. Most users, however, intuitively expect + that any pair that has one side passing the test will take the + branch. They assume it is equivalent to the following: + + | (Const x, _) when is_neutral x -> branch + | (_, Const x) when is_neutral x -> branch + + while it is not. + + The code below is dedicated to finding these confusing cases: the + cases where a guard uses "ambiguous" variables, that are bound to + different parts of the scrutinees by different sides of + a or-pattern. In other words, it finds the cases where the + specified left-to-right semantics is not equivalent to + a non-deterministic semantics (any branch can be taken) relatively + to a specific guard. +*) + +module IdSet = Set.Make(Ident) + +let pattern_vars p = IdSet.of_list (Typedtree.pat_bound_idents p) + +(* Row for ambiguous variable search, + unseen is the traditional pattern row, + seen is a list of position bindings *) + +type amb_row = { unseen : pattern list ; seen : IdSet.t list; } + + +(* Push binding variables now *) + +let rec do_push r p ps seen k = match p.pat_desc with +| Tpat_alias (p,x,_) -> do_push (IdSet.add x r) p ps seen k +| Tpat_var (x,_) -> + (omega,{ unseen = ps; seen=IdSet.add x r::seen; })::k +| Tpat_or (p1,p2,_) -> + do_push r p1 ps seen (do_push r p2 ps seen k) +| _ -> + (p,{ unseen = ps; seen = r::seen; })::k + +let rec push_vars = function + | [] -> [] + | { unseen = [] }::_ -> assert false + | { unseen = p::ps; seen; }::rem -> + do_push IdSet.empty p ps seen (push_vars rem) + +let collect_stable = function + | [] -> assert false + | { seen=xss; _}::rem -> + let rec c_rec xss = function + | [] -> xss + | {seen=yss; _}::rem -> + let xss = List.map2 IdSet.inter xss yss in + c_rec xss rem in + let inters = c_rec xss rem in + List.fold_left IdSet.union IdSet.empty inters + + +(*********************************************) +(* Filtering utilities for our specific rows *) +(*********************************************) + +(* Take a pattern matrix as a list (rows) of lists (columns) of patterns + | p1, p2, .., pn + | q1, q2, .., qn + | r1, r2, .., rn + | ... + + We split this matrix into a list of sub-matrices, one for each head + constructor appearing in the leftmost column. For each row whose + left column starts with a head constructor, remove this head + column, prepend one column for each argument of the constructor, + and add the resulting row in the sub-matrix corresponding to this + head constructor. + + Rows whose left column is omega (the Any pattern _) may match any + head constructor, so they are added to all groups. + + The list of sub-matrices is represented as a list of pair + (head constructor, submatrix) +*) + +let filter_all = + (* the head constructor (as a pattern with omega arguments) of + a pattern *) + let discr_head pat = + match pat.pat_desc with + | Tpat_record (lbls, closed) -> + (* a partial record pattern { f1 = p1; f2 = p2; _ } + needs to be expanded, otherwise matching against this head + would drop the pattern arguments for non-mentioned fields *) + let lbls = all_record_args lbls in + normalize_pat { pat with pat_desc = Tpat_record (lbls, closed) } + | _ -> normalize_pat pat + in + + (* insert a row of head [p] and rest [r] into the right group *) + let rec insert p r env = match env with + | [] -> + (* if no group matched this row, it has a head constructor that + was never seen before; add a new sub-matrix for this head *) + let p0 = discr_head p in + [p0,[{ r with unseen = simple_match_args p0 p @ r.unseen }]] + | (q0,rs) as bd::env -> + if simple_match q0 p then begin + let r = { r with unseen = simple_match_args q0 p@r.unseen; } in + (q0,r::rs)::env + end + else bd::insert p r env in + + (* insert a row of head omega into all groups *) + let insert_omega r env = + List.map + (fun (q0,rs) -> + let r = + { r with unseen = simple_match_args q0 omega @ r.unseen; } in + (q0,r::rs)) + env + in + + let rec filter_rec env = function + | [] -> env + | ({pat_desc=(Tpat_var _|Tpat_alias _|Tpat_or _)},_)::_ -> assert false + | ({pat_desc=Tpat_any}, _)::rs -> filter_rec env rs + | (p,r)::rs -> filter_rec (insert p r env) rs in + + let rec filter_omega env = function + | [] -> env + | ({pat_desc=(Tpat_var _|Tpat_alias _|Tpat_or _)},_)::_ -> assert false + | ({pat_desc=Tpat_any},r)::rs -> filter_omega (insert_omega r env) rs + | _::rs -> filter_omega env rs in + + fun rs -> + (* first insert the rows with head constructors, + to get the definitive list of groups *) + let env = filter_rec [] rs in + (* then add the omega rows to all groups *) + filter_omega env rs + +(* Compute stable bindings *) + +let rec do_stable rs = match rs with +| [] -> assert false (* No empty matrix *) +| { unseen=[]; _ }::_ -> + collect_stable rs +| _ -> + let rs = push_vars rs in + match filter_all rs with + | [] -> + do_stable (List.map snd rs) + | (_,rs)::env -> + List.fold_left + (fun xs (_,rs) -> IdSet.inter xs (do_stable rs)) + (do_stable rs) env + +let stable p = do_stable [{unseen=[p]; seen=[];}] + + +(* All identifier paths that appear in an expression that occurs + as a clause right hand side or guard. + + The function is rather complex due to the compilation of + unpack patterns by introducing code in rhs expressions + and **guards**. + + For pattern (module M:S) -> e the code is + let module M_mod = unpack M .. in e + + Hence M is "free" in e iff M_mod is free in e. + + Not doing so will yield excessive warning in + (module (M:S) } ...) when true -> .... + as M is always present in + let module M_mod = unpack M .. in true +*) + +let all_rhs_idents exp = + let ids = ref IdSet.empty in + let module Iterator = TypedtreeIter.MakeIterator(struct + include TypedtreeIter.DefaultIteratorArgument + let enter_expression exp = match exp.exp_desc with + | Texp_ident (path, _lid, _descr) -> + List.iter + (fun id -> ids := IdSet.add id !ids) + (Path.heads path) + | _ -> () + +(* Very hackish, detect unpack pattern compilation + and perfom "indirect check for them" *) + let is_unpack exp = + List.exists + (fun (attr, _) -> attr.txt = "#modulepat") exp.exp_attributes + + let leave_expression exp = + if is_unpack exp then begin match exp.exp_desc with + | Texp_letmodule + (id_mod,_, + {mod_desc= + Tmod_unpack ({exp_desc=Texp_ident (Path.Pident id_exp,_,_)},_)}, + _) -> + assert (IdSet.mem id_exp !ids) ; + if not (IdSet.mem id_mod !ids) then begin + ids := IdSet.remove id_exp !ids + end + | _ -> assert false + end + end) in + Iterator.iter_expression exp; + !ids + +let check_ambiguous_bindings = + let open Warnings in + let warn0 = Ambiguous_pattern [] in + fun cases -> + if is_active warn0 then + List.iter + (fun case -> match case with + | { c_guard=None ; _} -> () + | { c_lhs=p; c_guard=Some g; _} -> + let all = + IdSet.inter (pattern_vars p) (all_rhs_idents g) in + if not (IdSet.is_empty all) then begin + let st = stable p in + let ambiguous = IdSet.diff all st in + if not (IdSet.is_empty ambiguous) then begin + let pps = IdSet.elements ambiguous |> List.map Ident.name in + let warn = Ambiguous_pattern pps in + Location.prerr_warning p.pat_loc warn + end + end) + cases diff --git a/typing/parmatch.mli b/typing/parmatch.mli index dfd955a8..e2122a68 100644 --- a/typing/parmatch.mli +++ b/typing/parmatch.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Detection of partial matches and unused match cases. *) open Asttypes @@ -51,6 +54,11 @@ val set_args_erase_mutable : pattern -> pattern list -> pattern list val pat_of_constr : pattern -> constructor_description -> pattern val complete_constrs : pattern -> constructor_tag list -> constructor_description list +val ppat_of_type : + Env.t -> type_expr -> + Parsetree.pattern * + (string, constructor_description) Hashtbl.t * + (string, label_description) Hashtbl.t val pressure_variants: Env.t -> pattern list -> unit val check_partial_gadt: @@ -58,8 +66,16 @@ val check_partial_gadt: (string, label_description) Hashtbl.t -> Parsetree.pattern -> pattern option) -> Location.t -> case list -> partial -val check_unused: Env.t -> case list -> unit +val check_unused: + (bool -> + (string, constructor_description) Hashtbl.t -> + (string, label_description) Hashtbl.t -> + Parsetree.pattern -> pattern option) -> + Env.t -> case list -> unit (* Irrefutability tests *) val irrefutable : pattern -> bool val fluid : pattern -> bool + +(* Ambiguous bindings *) +val check_ambiguous_bindings : case list -> unit diff --git a/typing/path.ml b/typing/path.ml index 260fc073..035f1222 100644 --- a/typing/path.ml +++ b/typing/path.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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 t = Pident of Ident.t @@ -48,7 +51,39 @@ let rec head = function | Pdot(p, s, pos) -> head p | Papply(p1, p2) -> assert false +let heads p = + let rec heads p acc = match p with + | Pident id -> id :: acc + | Pdot (p, _s, _pos) -> heads p acc + | Papply(p1, p2) -> + heads p1 (heads p2 acc) + in heads p [] + let rec last = function | Pident id -> Ident.name id | Pdot(_, s, _) -> s | Papply(_, p) -> last p + +let is_uident s = + assert (s <> ""); + match s.[0] with + | 'A'..'Z' -> true + | _ -> false + +type typath = + | Regular of t + | Ext of t * string + | LocalExt of Ident.t + | Cstr of t * string + +let constructor_typath = function + | Pident id when is_uident (Ident.name id) -> LocalExt id + | Pdot(ty_path, s, _) when is_uident s -> + if is_uident (last ty_path) then Ext (ty_path, s) + else Cstr (ty_path, s) + | p -> Regular p + +let is_constructor_typath p = + match constructor_typath p with + | Regular _ -> false + | _ -> true diff --git a/typing/path.mli b/typing/path.mli index c3f84130..7dac627c 100644 --- a/typing/path.mli +++ b/typing/path.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Access paths *) @@ -27,4 +30,15 @@ val name: ?paren:(string -> bool) -> t -> string (* [paren] tells whether a path suffix needs parentheses *) val head: t -> Ident.t +val heads: t -> Ident.t list + val last: t -> string + +type typath = + | Regular of t + | Ext of t * string + | LocalExt of Ident.t + | Cstr of t * string + +val constructor_typath: t -> typath +val is_constructor_typath: t -> bool diff --git a/typing/predef.ml b/typing/predef.ml index e9b9f7e5..db3d714c 100644 --- a/typing/predef.ml +++ b/typing/predef.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Predefined type constructors (with special typing rules in typecore) *) @@ -28,7 +31,7 @@ let ident_create_predef_exn = wrap Ident.create_predef_exn let ident_int = ident_create "int" and ident_char = ident_create "char" -and ident_string = ident_create "string" +and ident_bytes = ident_create "bytes" and ident_float = ident_create "float" and ident_bool = ident_create "bool" and ident_unit = ident_create "unit" @@ -40,11 +43,12 @@ and ident_nativeint = ident_create "nativeint" and ident_int32 = ident_create "int32" and ident_int64 = ident_create "int64" and ident_lazy_t = ident_create "lazy_t" -and ident_bytes = ident_create "bytes" +and ident_string = ident_create "string" +and ident_extension_constructor = ident_create "extension_constructor" let path_int = Pident ident_int and path_char = Pident ident_char -and path_string = Pident ident_string +and path_bytes = Pident ident_bytes and path_float = Pident ident_float and path_bool = Pident ident_bool and path_unit = Pident ident_unit @@ -56,11 +60,12 @@ and path_nativeint = Pident ident_nativeint and path_int32 = Pident ident_int32 and path_int64 = Pident ident_int64 and path_lazy_t = Pident ident_lazy_t -and path_bytes = Pident ident_bytes +and path_string = Pident ident_string +and path_extension_constructor = Pident ident_extension_constructor let type_int = newgenty (Tconstr(path_int, [], ref Mnil)) and type_char = newgenty (Tconstr(path_char, [], ref Mnil)) -and type_string = newgenty (Tconstr(path_string, [], ref Mnil)) +and type_bytes = newgenty (Tconstr(path_bytes, [], ref Mnil)) and type_float = newgenty (Tconstr(path_float, [], ref Mnil)) and type_bool = newgenty (Tconstr(path_bool, [], ref Mnil)) and type_unit = newgenty (Tconstr(path_unit, [], ref Mnil)) @@ -72,7 +77,9 @@ and type_nativeint = newgenty (Tconstr(path_nativeint, [], ref Mnil)) and type_int32 = newgenty (Tconstr(path_int32, [], ref Mnil)) and type_int64 = newgenty (Tconstr(path_int64, [], ref Mnil)) and type_lazy_t t = newgenty (Tconstr(path_lazy_t, [t], ref Mnil)) -and type_bytes = newgenty (Tconstr(path_bytes, [], ref Mnil)) +and type_string = newgenty (Tconstr(path_string, [], ref Mnil)) +and type_extension_constructor = + newgenty (Tconstr(path_extension_constructor, [], ref Mnil)) let ident_match_failure = ident_create_predef_exn "Match_failure" and ident_out_of_memory = ident_create_predef_exn "Out_of_memory" @@ -88,6 +95,21 @@ and ident_assert_failure = ident_create_predef_exn "Assert_failure" and ident_undefined_recursive_module = ident_create_predef_exn "Undefined_recursive_module" +let all_predef_exns = [ + ident_match_failure; + ident_out_of_memory; + ident_invalid_argument; + ident_failure; + ident_not_found; + ident_sys_error; + ident_end_of_file; + ident_division_by_zero; + ident_stack_overflow; + ident_sys_blocked_io; + ident_assert_failure; + ident_undefined_recursive_module; +] + let path_match_failure = Pident ident_match_failure and path_assert_failure = Pident ident_assert_failure and path_undefined_recursive_module = Pident ident_undefined_recursive_module @@ -102,12 +124,15 @@ let decl_abstr = type_variance = []; type_newtype_level = None; type_attributes = []; + type_immediate = false; } +let decl_abstr_imm = {decl_abstr with type_immediate = true} + let cstr id args = { cd_id = id; - cd_args = args; + cd_args = Cstr_tuple args; cd_res = None; cd_loc = Location.none; cd_attributes = []; @@ -123,10 +148,12 @@ and ident_some = ident_create "Some" let common_initial_env add_type add_extension empty_env = let decl_bool = {decl_abstr with - type_kind = Type_variant([cstr ident_false []; cstr ident_true []])} + type_kind = Type_variant([cstr ident_false []; cstr ident_true []]); + type_immediate = true} and decl_unit = {decl_abstr with - type_kind = Type_variant([cstr ident_void []])} + type_kind = Type_variant([cstr ident_void []]); + type_immediate = true} and decl_exn = {decl_abstr with type_kind = Type_open} @@ -163,11 +190,13 @@ let common_initial_env add_type add_extension empty_env = add_extension id { ext_type_path = path_exn; ext_type_params = []; - ext_args = l; + ext_args = Cstr_tuple l; ext_ret_type = None; ext_private = Asttypes.Public; ext_loc = Location.none; - ext_attributes = [] } + ext_attributes = [{Asttypes.txt="ocaml.warn_on_literal_pattern"; + loc=Location.none}, + Parsetree.PStr[]] } in add_extension ident_match_failure [newgenty (Ttuple[type_string; type_int; type_int])] ( @@ -196,9 +225,10 @@ let common_initial_env add_type add_extension empty_env = add_type ident_bool decl_bool ( add_type ident_float decl_abstr ( add_type ident_string decl_abstr ( - add_type ident_char decl_abstr ( - add_type ident_int decl_abstr ( - empty_env)))))))))))))))))))))))))) + add_type ident_char decl_abstr_imm ( + add_type ident_int decl_abstr_imm ( + add_type ident_extension_constructor decl_abstr ( + empty_env))))))))))))))))))))))))))) let build_initial_env add_type add_exception empty_env = let common = common_initial_env add_type add_exception empty_env in diff --git a/typing/predef.mli b/typing/predef.mli index 97236711..a7bf0634 100644 --- a/typing/predef.mli +++ b/typing/predef.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Predefined type constructors (with special typing rules in typecore) *) @@ -29,6 +32,7 @@ val type_nativeint: type_expr val type_int32: type_expr val type_int64: type_expr val type_lazy_t: type_expr -> type_expr +val type_extension_constructor:type_expr val path_int: Path.t val path_char: Path.t @@ -45,6 +49,7 @@ val path_nativeint: Path.t val path_int32: Path.t val path_int64: Path.t val path_lazy_t: Path.t +val path_extension_constructor: Path.t val path_match_failure: Path.t val path_assert_failure : Path.t @@ -63,3 +68,10 @@ val build_initial_env: val builtin_values: (string * Ident.t) list val builtin_idents: (string * Ident.t) list + +(** All predefined exceptions, exposed as [Ident.t] for flambda (for + building value approximations). + The [Ident.t] for division by zero is also exported explicitly + so flambda can generate code to raise it. *) +val ident_division_by_zero: Ident.t +val all_predef_exns : Ident.t list diff --git a/typing/primitive.ml b/typing/primitive.ml index 17abeb34..81a33397 100644 --- a/typing/primitive.ml +++ b/typing/primitive.ml @@ -1,57 +1,197 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Description of primitive functions *) open Misc +open Parsetree + +type boxed_integer = Pnativeint | Pint32 | Pint64 + +type native_repr = + | Same_as_ocaml_repr + | Unboxed_float + | Unboxed_integer of boxed_integer + | Untagged_int type description = { prim_name: string; (* Name of primitive or C function *) prim_arity: int; (* Number of arguments *) prim_alloc: bool; (* Does it allocates or raise? *) prim_native_name: string; (* Name of C function for the nat. code gen. *) - prim_native_float: bool } (* Does the above operate on unboxed floats? *) - -let parse_declaration arity decl = - match decl with - | name :: "noalloc" :: name2 :: "float" :: _ -> - {prim_name = name; prim_arity = arity; prim_alloc = false; - prim_native_name = name2; prim_native_float = true} - | name :: "noalloc" :: name2 :: _ -> - {prim_name = name; prim_arity = arity; prim_alloc = false; - prim_native_name = name2; prim_native_float = false} - | name :: name2 :: "float" :: _ -> - {prim_name = name; prim_arity = arity; prim_alloc = true; - prim_native_name = name2; prim_native_float = true} - | name :: "noalloc" :: _ -> - {prim_name = name; prim_arity = arity; prim_alloc = false; - prim_native_name = ""; prim_native_float = false} - | name :: name2 :: _ -> - {prim_name = name; prim_arity = arity; prim_alloc = true; - prim_native_name = name2; prim_native_float = false} - | name :: _ -> - {prim_name = name; prim_arity = arity; prim_alloc = true; - prim_native_name = ""; prim_native_float = false} - | [] -> - fatal_error "Primitive.parse_declaration" - -let description_list p = - let list = [p.prim_name] in - let list = if not p.prim_alloc then "noalloc" :: list else list in - let list = - if p.prim_native_name <> "" then p.prim_native_name :: list else list - in - let list = if p.prim_native_float then "float" :: list else list in - List.rev list + prim_native_repr_args: native_repr list; + prim_native_repr_res: native_repr } + +type error = + | Old_style_float_with_native_repr_attribute + | Old_style_noalloc_with_noalloc_attribute + | No_native_primitive_with_repr_attribute + +exception Error of Location.t * error + +let is_ocaml_repr = function + | Same_as_ocaml_repr -> true + | Unboxed_float + | Unboxed_integer _ + | Untagged_int -> false + +let is_unboxed = function + | Same_as_ocaml_repr + | Untagged_int -> false + | Unboxed_float + | Unboxed_integer _ -> true + +let is_untagged = function + | Untagged_int -> true + | Same_as_ocaml_repr + | Unboxed_float + | Unboxed_integer _ -> false + +let rec make_native_repr_args arity x = + if arity = 0 then + [] + else + x :: make_native_repr_args (arity - 1) x + +let simple ~name ~arity ~alloc = + {prim_name = name; + prim_arity = arity; + prim_alloc = alloc; + prim_native_name = ""; + prim_native_repr_args = make_native_repr_args arity Same_as_ocaml_repr; + prim_native_repr_res = Same_as_ocaml_repr} + +let make ~name ~alloc ~native_name ~native_repr_args ~native_repr_res = + {prim_name = name; + prim_arity = List.length native_repr_args; + prim_alloc = alloc; + prim_native_name = native_name; + prim_native_repr_args = native_repr_args; + prim_native_repr_res = native_repr_res} + +let parse_declaration valdecl ~native_repr_args ~native_repr_res = + let arity = List.length native_repr_args in + let name, native_name, old_style_noalloc, old_style_float = + match valdecl.pval_prim with + | name :: "noalloc" :: name2 :: "float" :: _ -> (name, name2, true, true) + | name :: "noalloc" :: name2 :: _ -> (name, name2, true, false) + | name :: name2 :: "float" :: _ -> (name, name2, false, true) + | name :: "noalloc" :: _ -> (name, "", true, false) + | name :: name2 :: _ -> (name, name2, false, false) + | name :: _ -> (name, "", false, false) + | [] -> + fatal_error "Primitive.parse_declaration" + in + let noalloc_attribute = + Attr_helper.has_no_payload_attribute ["noalloc"; "ocaml.noalloc"] + valdecl.pval_attributes + in + if old_style_float && + not (List.for_all is_ocaml_repr native_repr_args && + is_ocaml_repr native_repr_res) then + raise (Error (valdecl.pval_loc, + Old_style_float_with_native_repr_attribute)); + if old_style_noalloc && noalloc_attribute then + raise (Error (valdecl.pval_loc, + Old_style_noalloc_with_noalloc_attribute)); + (* The compiler used to assume "noalloc" with "float", we just make this + explicit now (GPR#167): *) + let old_style_noalloc = old_style_noalloc || old_style_float in + if old_style_float then + Location.prerr_warning valdecl.pval_loc + (Warnings.Deprecated "[@@unboxed] + [@@noalloc] should be used instead \ + of \"float\"") + else if old_style_noalloc then + Location.prerr_warning valdecl.pval_loc + (Warnings.Deprecated "[@@noalloc] should be used instead of \ + \"noalloc\""); + if native_name = "" && + not (List.for_all is_ocaml_repr native_repr_args && + is_ocaml_repr native_repr_res) then + raise (Error (valdecl.pval_loc, + No_native_primitive_with_repr_attribute)); + let noalloc = old_style_noalloc || noalloc_attribute in + let native_repr_args, native_repr_res = + if old_style_float then + (make_native_repr_args arity Unboxed_float, Unboxed_float) + else + (native_repr_args, native_repr_res) + in + {prim_name = name; + prim_arity = arity; + prim_alloc = not noalloc; + prim_native_name = native_name; + prim_native_repr_args = native_repr_args; + prim_native_repr_res = native_repr_res} + +open Outcometree + +let rec add_native_repr_attributes ty attrs = + match ty, attrs with + | Otyp_arrow (label, a, b), attr_opt :: rest -> + let b = add_native_repr_attributes b rest in + let a = + match attr_opt with + | None -> a + | Some attr -> Otyp_attribute (a, attr) + in + Otyp_arrow (label, a, b) + | _, [Some attr] -> Otyp_attribute (ty, attr) + | _ -> + assert (List.for_all (fun x -> x = None) attrs); + ty + +let oattr_unboxed = { oattr_name = "unboxed" } +let oattr_untagged = { oattr_name = "untagged" } +let oattr_noalloc = { oattr_name = "noalloc" } + +let print p osig_val_decl = + let prims = + if p.prim_native_name <> "" then + [p.prim_name; p.prim_native_name] + else + [p.prim_name] + in + let for_all f = + List.for_all f p.prim_native_repr_args && f p.prim_native_repr_res + in + let all_unboxed = for_all is_unboxed in + let all_untagged = for_all is_untagged in + let attrs = if p.prim_alloc then [] else [oattr_noalloc] in + let attrs = + if all_unboxed then + oattr_unboxed :: attrs + else if all_untagged then + oattr_untagged :: attrs + else + attrs + in + let attr_of_native_repr = function + | Same_as_ocaml_repr -> None + | Unboxed_float + | Unboxed_integer _ -> if all_unboxed then None else Some oattr_unboxed + | Untagged_int -> if all_untagged then None else Some oattr_untagged + in + let type_attrs = + List.map attr_of_native_repr p.prim_native_repr_args @ + [attr_of_native_repr p.prim_native_repr_res] + in + { osig_val_decl with + oval_prims = prims; + oval_type = add_native_repr_attributes osig_val_decl.oval_type type_attrs; + oval_attributes = attrs } let native_name p = if p.prim_native_name <> "" @@ -60,3 +200,25 @@ let native_name p = let byte_name p = p.prim_name + +let report_error ppf err = + match err with + | Old_style_float_with_native_repr_attribute -> + Format.fprintf ppf "Cannot use \"float\" in conjunction with \ + [%@unboxed]/[%@untagged]" + | Old_style_noalloc_with_noalloc_attribute -> + Format.fprintf ppf "Cannot use \"noalloc\" in conjunction with \ + [%@%@noalloc]" + | No_native_primitive_with_repr_attribute -> + Format.fprintf ppf + "The native code version of the primitive is mandatory when \ + attributes [%@untagged] or [%@unboxed] are present" + +let () = + Location.register_error_of_exn + (function + | Error (loc, err) -> + Some (Location.error_of_printer loc report_error err) + | _ -> + None + ) diff --git a/typing/primitive.mli b/typing/primitive.mli index 585dba0d..02ece7d9 100644 --- a/typing/primitive.mli +++ b/typing/primitive.mli @@ -1,27 +1,71 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Description of primitive functions *) -type description = +type boxed_integer = Pnativeint | Pint32 | Pint64 + +(* Representation of arguments/result for the native code version + of a primitive *) +type native_repr = + | Same_as_ocaml_repr + | Unboxed_float + | Unboxed_integer of boxed_integer + | Untagged_int + +type description = private { prim_name: string; (* Name of primitive or C function *) prim_arity: int; (* Number of arguments *) prim_alloc: bool; (* Does it allocates or raise? *) prim_native_name: string; (* Name of C function for the nat. code gen. *) - prim_native_float: bool } (* Does the above operate on unboxed floats? *) + prim_native_repr_args: native_repr list; + prim_native_repr_res: native_repr } + +(* Invariant [List.length d.prim_native_repr_args = d.prim_arity] *) + +val simple + : name:string + -> arity:int + -> alloc:bool + -> description -val parse_declaration: int -> string list -> description +val make + : name:string + -> alloc:bool + -> native_name:string + -> native_repr_args: native_repr list + -> native_repr_res: native_repr + -> description -val description_list: description -> string list +val parse_declaration + : Parsetree.value_description + -> native_repr_args:native_repr list + -> native_repr_res:native_repr + -> description + +val print + : description + -> Outcometree.out_val_decl + -> Outcometree.out_val_decl val native_name: description -> string val byte_name: description -> string + +type error = + | Old_style_float_with_native_repr_attribute + | Old_style_noalloc_with_noalloc_attribute + | No_native_primitive_with_repr_attribute + +exception Error of Location.t * error diff --git a/typing/printtyp.ml b/typing/printtyp.ml index 52fddd47..abd9cb80 100644 --- a/typing/printtyp.ml +++ b/typing/printtyp.ml @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt*) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy and Jerome Vouillon, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Printing functions *) @@ -122,6 +125,11 @@ let print_name ppf = function None -> fprintf ppf "None" | Some name -> fprintf ppf "\"%s\"" name +let string_of_label = function + Nolabel -> "" + | Labelled s -> s + | Optional s -> "?"^s + let visited = ref [] let rec raw_type ppf ty = let ty = safe_repr [] ty in @@ -134,8 +142,8 @@ and raw_type_list tl = raw_list raw_type tl and raw_type_desc ppf = function Tvar name -> fprintf ppf "Tvar %a" print_name name | Tarrow(l,t1,t2,c) -> - fprintf ppf "@[Tarrow(%s,@,%a,@,%a,@,%s)@]" - l raw_type t1 raw_type t2 + fprintf ppf "@[Tarrow(\"%s\",@,%a,@,%a,@,%s)@]" + (string_of_label l) raw_type t1 raw_type t2 (safe_commu_repr [] c) | Ttuple tl -> fprintf ppf "@[<1>Ttuple@,%a@]" raw_type_list tl @@ -272,10 +280,21 @@ let rec normalize_type_path ?(cache=false) env p = with Not_found -> (p, Id) +let penalty s = + if s <> "" && s.[0] = '_' then + 10 + else + try + for i = 0 to String.length s - 2 do + if s.[i] = '_' && s.[i + 1] = '_' then + raise Exit + done; + 1 + with Exit -> 10 + let rec path_size = function Pident id -> - (let s = Ident.name id in if s <> "" && s.[0] = '_' then 10 else 1), - -Ident.binding_time id + penalty (Ident.name id), -Ident.binding_time id | Pdot (p, _, _) -> let (l, b) = path_size p in (1+l, b) | Papply (p1, p2) -> @@ -355,7 +374,7 @@ let best_type_path p = let (p', s) = normalize_type_path !printing_env p in let get_path () = get_best_path (PathMap.find p' !printing_map) in while !printing_cont <> [] && - try ignore (get_path ()); false with Not_found -> true + try fst (path_size (get_path ())) > !printing_depth with Not_found -> true do printing_cont := List.map snd (Env.run_iter_cont !printing_cont); incr printing_depth; @@ -421,13 +440,6 @@ let remove_names tyl = let tyl = List.map repr tyl in names := List.filter (fun (ty,_) -> not (List.memq ty tyl)) !names - -let non_gen_mark sch ty = - if sch && is_Tvar ty && ty.level <> generic_level then "_" else "" - -let print_name_of_type sch ppf t = - fprintf ppf "'%s%s" (non_gen_mark sch t) (name_of_type t) - let visited_objects = ref ([] : type_expr list) let aliased = ref ([] : type_expr list) let delayed = ref ([] : type_expr list) @@ -534,8 +546,6 @@ let reset_and_mark_loops_list tyl = (* Disabled in classic mode when printing an unification error *) let print_labels = ref true -let print_label ppf l = - if !print_labels && l <> "" || is_optional l then fprintf ppf "%s:" l let rec tree_of_typexp sch ty = let ty = repr ty in @@ -551,7 +561,7 @@ let rec tree_of_typexp sch ty = | Tarrow(l, ty1, ty2, _) -> let pr_arrow l ty1 ty2 = let lab = - if !print_labels && l <> "" || is_optional l then l else "" + if !print_labels || is_optional l then string_of_label l else "" in let t1 = if is_optional l then @@ -656,10 +666,10 @@ and tree_of_row_field sch (l, f) = | Rpresent None | Reither(true, [], _, _) -> (l, false, []) | Rpresent(Some ty) -> (l, false, [tree_of_typexp sch ty]) | Reither(c, tyl, _, _) -> - if c (* contradiction: un constructeur constant qui a un argument *) + if c (* contradiction: constant constructor with an argument *) then (l, true, tree_of_typlist sch tyl) else (l, false, tree_of_typlist sch tyl) - | Rabsent -> (l, false, [] (* une erreur, en fait *)) + | Rabsent -> (l, false, [] (* actually, an error *)) and tree_of_typlist sch tyl = List.map (tree_of_typexp sch) tyl @@ -722,7 +732,7 @@ and type_scheme ppf ty = reset_and_mark_loops ty; typexp true 0 ppf ty let type_scheme_max ?(b_reset_names=true) ppf ty = if b_reset_names then reset_names () ; typexp true 0 ppf ty -(* Fin Maxence *) +(* End Maxence *) let tree_of_type_scheme ty = reset_and_mark_loops ty; tree_of_typexp true ty @@ -748,9 +758,9 @@ let filter_params tyl = [] tyl in List.rev params -let string_of_mutable = function - | Immutable -> "" - | Mutable -> "mutable " +let mark_loops_constructor_arguments = function + | Cstr_tuple l -> List.iter mark_loops l + | Cstr_record l -> List.iter (fun l -> mark_loops l.ld_type) l let rec tree_of_type_decl id decl = @@ -795,8 +805,8 @@ let rec tree_of_type_decl id decl = | Type_variant cstrs -> List.iter (fun c -> - List.iter mark_loops c.cd_args; - may mark_loops c.cd_res) + mark_loops_constructor_arguments c.cd_args; + may mark_loops c.cd_res) cstrs | Type_record(l, rep) -> List.iter (fun l -> mark_loops l.ld_type) l @@ -856,22 +866,31 @@ let rec tree_of_type_decl id decl = | Type_open -> tree_of_manifest Otyp_open, Public + in + let immediate = + List.exists (fun (loc, _) -> loc.txt = "immediate") decl.type_attributes in { otype_name = name; otype_params = args; otype_type = ty; otype_private = priv; + otype_immediate = immediate; otype_cstrs = constraints } +and tree_of_constructor_arguments = function + | Cstr_tuple l -> tree_of_typlist false l + | Cstr_record l -> [ Otyp_record (List.map tree_of_label l) ] + and tree_of_constructor cd = let name = Ident.name cd.cd_id in + let arg () = tree_of_constructor_arguments cd.cd_args in match cd.cd_res with - | None -> (name, tree_of_typlist false cd.cd_args, None) + | None -> (name, arg (), None) | Some res -> let nm = !names in names := []; let ret = tree_of_typexp false res in - let args = tree_of_typlist false cd.cd_args in + let args = arg () in names := nm; (name, args, Some ret) @@ -884,6 +903,10 @@ let tree_of_type_declaration id decl rs = let type_declaration id ppf decl = !Oprint.out_sig_item ppf (tree_of_type_declaration id decl Trec_first) +let constructor_arguments ppf a = + let tys = tree_of_constructor_arguments a in + !Oprint.out_type ppf (Otyp_tuple tys) + (* Print an extension declaration *) let tree_of_extension_constructor id ext es = @@ -893,7 +916,7 @@ let tree_of_extension_constructor id ext es = List.iter add_alias ty_params; List.iter mark_loops ty_params; List.iter check_name_of_type (List.map proxy ty_params); - List.iter mark_loops ext.ext_args; + mark_loops_constructor_arguments ext.ext_args; may mark_loops ext.ext_ret_type; let type_param = function @@ -906,12 +929,12 @@ let tree_of_extension_constructor id ext es = let name = Ident.name id in let args, ret = match ext.ext_ret_type with - | None -> (tree_of_typlist false ext.ext_args, None) + | None -> (tree_of_constructor_arguments ext.ext_args, None) | Some res -> let nm = !names in names := []; let ret = tree_of_typexp false res in - let args = tree_of_typlist false ext.ext_args in + let args = tree_of_constructor_arguments ext.ext_args in names := nm; (args, Some ret) in @@ -940,22 +963,24 @@ let tree_of_value_description id decl = (* Format.eprintf "@[%a@]@." raw_type_expr decl.val_type; *) let id = Ident.name id in let ty = tree_of_type_scheme decl.val_type in - let prims = + let vd = + { oval_name = id; + oval_type = ty; + oval_prims = []; + oval_attributes = [] } + in + let vd = match decl.val_kind with - | Val_prim p -> Primitive.description_list p - | _ -> [] + | Val_prim p -> Primitive.print p vd + | _ -> vd in - Osig_value (id, ty, prims) + Osig_value vd let value_description id ppf decl = !Oprint.out_sig_item ppf (tree_of_value_description id decl) (* Print a class type *) -let class_var sch ppf l (m, t) = - fprintf ppf - "@ @[<2>val %s%s :@ %a@]" (string_of_mutable m) l (typexp sch 0) t - let method_type (_, kind, ty) = match field_kind_repr kind, repr ty with Fpresent, {desc=Tpoly(ty, tyl)} -> (ty, tyl) @@ -1039,7 +1064,9 @@ let rec tree_of_class_type sch params = in Octy_signature (self_ty, List.rev csil) | Cty_arrow (l, ty, cty) -> - let lab = if !print_labels && l <> "" || is_optional l then l else "" in + let lab = + if !print_labels || is_optional l then string_of_label l else "" + in let ty = if is_optional l then match (repr ty).desc with @@ -1060,10 +1087,6 @@ let tree_of_class_param param variance = | _ -> "?"), if is_Tvar (repr param) then (true, true) else variance -let tree_of_class_params params = - let tyl = tree_of_typlist true params in - List.map (function Otyp_var (_, s) -> s | _ -> "?") tyl - let class_variance = List.map Variance.(fun v -> mem May_pos v, mem May_neg v) @@ -1145,6 +1168,7 @@ let dummy = type_private = Public; type_manifest = None; type_variance = []; type_newtype_level = None; type_loc = Location.none; type_attributes = []; + type_immediate = false; } let hide_rec_items = function @@ -1162,18 +1186,21 @@ let hide_rec_items = function ids !printing_env) | _ -> () -let rec tree_of_modtype = function +let rec tree_of_modtype ?(ellipsis=false) = function | Mty_ident p -> Omty_ident (tree_of_path p) | Mty_signature sg -> - Omty_signature (tree_of_signature sg) + Omty_signature (if ellipsis then [Osig_ellipsis] + else tree_of_signature sg) | Mty_functor(param, ty_arg, ty_res) -> let res = - match ty_arg with None -> tree_of_modtype ty_res + match ty_arg with None -> tree_of_modtype ~ellipsis ty_res | Some mty -> - wrap_env (Env.add_module ~arg:true param mty) tree_of_modtype ty_res + wrap_env (Env.add_module ~arg:true param mty) + (tree_of_modtype ~ellipsis) ty_res in - Omty_functor (Ident.name param, may_map tree_of_modtype ty_arg, res) + Omty_functor (Ident.name param, + may_map (tree_of_modtype ~ellipsis:false) ty_arg, res) | Mty_alias p -> Omty_alias (tree_of_path p) @@ -1182,38 +1209,42 @@ and tree_of_signature sg = and tree_of_signature_rec env' in_type_group = function [] -> [] - | item :: rem -> + | item :: rem as items -> let in_type_group = match in_type_group, item with true, Sig_type (_, _, Trec_next) -> true - | _, Sig_type (_, _, (Trec_not | Trec_first)) -> set_printing_env env'; true + | _, Sig_type (_, _, (Trec_not | Trec_first)) -> + set_printing_env env'; true | _ -> set_printing_env env'; false in let (sg, rem) = filter_rem_sig item rem in - let trees = - match item with - | Sig_value(id, decl) -> - [tree_of_value_description id decl] - | Sig_type(id, _, _) when is_row_name (Ident.name id) -> - [] - | Sig_type(id, decl, rs) -> - hide_rec_items (item :: rem); - [Osig_type(tree_of_type_decl id decl, tree_of_rec rs)] - | Sig_typext(id, ext, es) -> - [tree_of_extension_constructor id ext es] - | Sig_module(id, md, rs) -> - [Osig_module (Ident.name id, tree_of_modtype md.md_type, - tree_of_rec rs)] - | Sig_modtype(id, decl) -> - [tree_of_modtype_declaration id decl] - | Sig_class(id, decl, rs) -> - [tree_of_class_declaration id decl rs] - | Sig_class_type(id, decl, rs) -> - [tree_of_cltype_declaration id decl rs] - in + hide_rec_items items; + let trees = trees_of_sigitem item in let env' = Env.add_signature (item :: sg) env' in trees @ tree_of_signature_rec env' in_type_group rem +and trees_of_sigitem = function + | Sig_value(id, decl) -> + [tree_of_value_description id decl] + | Sig_type(id, _, _) when is_row_name (Ident.name id) -> + [] + | Sig_type(id, decl, rs) -> + [tree_of_type_declaration id decl rs] + | Sig_typext(id, ext, es) -> + [tree_of_extension_constructor id ext es] + | Sig_module(id, md, rs) -> + let ellipsis = + List.exists (function ({txt="..."}, Parsetree.PStr []) -> true + | _ -> false) + md.md_attributes in + [tree_of_module id md.md_type rs ~ellipsis] + | Sig_modtype(id, decl) -> + [tree_of_modtype_declaration id decl] + | Sig_class(id, decl, rs) -> + [tree_of_class_declaration id decl rs] + | Sig_class_type(id, decl, rs) -> + [tree_of_cltype_declaration id decl rs] + and tree_of_modtype_declaration id decl = let mty = match decl.mtd_type with @@ -1222,13 +1253,23 @@ and tree_of_modtype_declaration id decl = in Osig_modtype (Ident.name id, mty) -let tree_of_module id mty rs = - Osig_module (Ident.name id, tree_of_modtype mty, tree_of_rec rs) +and tree_of_module id ?ellipsis mty rs = + Osig_module (Ident.name id, tree_of_modtype ?ellipsis mty, tree_of_rec rs) let modtype ppf mty = !Oprint.out_module_type ppf (tree_of_modtype mty) let modtype_declaration id ppf decl = !Oprint.out_sig_item ppf (tree_of_modtype_declaration id decl) +(* For the toplevel: merge with tree_of_signature? *) +let rec print_items showval env = function + | [] -> [] + | item :: rem as items -> + let (sg, rem) = filter_rem_sig item rem in + hide_rec_items items; + let trees = trees_of_sigitem item in + List.map (fun d -> (d, showval env item)) trees @ + print_items showval env rem + (* Print a signature body (used by -i when compiling a .ml) *) let print_signature ppf tree = @@ -1257,7 +1298,9 @@ let same_path t t' = false let type_expansion t ppf t' = - if same_path t t' then type_expr ppf t else + if same_path t t' + then begin add_delayed (proxy t); type_expr ppf t end + else let t' = if proxy t == proxy t' then unalias t' else t' in fprintf ppf "@[<2>%a@ =@ %a@]" type_expr t type_expr t' @@ -1364,7 +1407,9 @@ let explanation unif t3 t4 ppf = fprintf ppf "@,@[This instance of %a is ambiguous:@ %s@]" type_expr t' "it would escape the scope of its equation" - | Tfield (lab, _, _, _), _ + | Tfield (lab, _, _, _), _ when lab = dummy_method -> + fprintf ppf + "@,Self type cannot be unified with a closed object type" | _, Tfield (lab, _, _, _) when lab = dummy_method -> fprintf ppf "@,Self type cannot be unified with a closed object type" @@ -1386,11 +1431,11 @@ let explanation unif t3 t4 ppf = row1.row_fields, row1.row_closed, row2.row_fields, row2.row_closed with | [], true, [], true -> fprintf ppf "@,These two variant types have no intersection" - | [], true, fields, _ -> + | [], true, (_::_ as fields), _ -> fprintf ppf "@,@[The first variant type does not allow tag(s)@ @[%a@]@]" print_tags fields - | fields, _, [], true -> + | (_::_ as fields), _, [], true -> fprintf ppf "@,@[The second variant type does not allow tag(s)@ @[%a@]@]" print_tags fields @@ -1400,6 +1445,20 @@ let explanation unif t3 t4 ppf = end | _ -> () + +let warn_on_missing_def env ppf t = + match t.desc with + | Tconstr (p,_,_) -> + begin + try + ignore(Env.find_type p env : Types.type_declaration) + with Not_found -> + fprintf ppf + "@,@[%a is abstract because no corresponding cmi file was found \ + in path.@]" path p + end + | _ -> () + let explanation unif mis ppf = match mis with None -> () @@ -1429,7 +1488,7 @@ let rec trace_same_names = function type_same_name t1 t2; type_same_name t1' t2'; trace_same_names rem | _ -> () -let unification_error unif tr txt1 ppf txt2 = +let unification_error env unif tr txt1 ppf txt2 = reset (); trace_same_names tr; let tr = List.map (fun (t, t') -> (t, hide_variant_name t')) tr in @@ -1453,6 +1512,11 @@ let unification_error unif tr txt1 ppf txt2 = txt2 (type_expansion t2) t2' (trace false "is not compatible with type") tr (explanation unif mis); + if env <> Env.empty + then begin + warn_on_missing_def env ppf t1; + warn_on_missing_def env ppf t2 + end; print_labels := true with exn -> print_labels := true; @@ -1460,7 +1524,7 @@ let unification_error unif tr txt1 ppf txt2 = let report_unification_error ppf env ?(unif=true) tr txt1 txt2 = - wrap_printing_env env (fun () -> unification_error unif tr txt1 ppf txt2) + wrap_printing_env env (fun () -> unification_error env unif tr txt1 ppf txt2) ;; let trace fst keep_last txt ppf tr = diff --git a/typing/printtyp.mli b/typing/printtyp.mli index b58b854c..8fd027ec 100644 --- a/typing/printtyp.mli +++ b/typing/printtyp.mli @@ -1,14 +1,17 @@ -(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) -(* *) -(* Copyright 1996 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. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 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. *) +(* *) +(**************************************************************************) (* Printing functions *) @@ -22,6 +25,7 @@ val tree_of_path: Path.t -> out_ident val path: formatter -> Path.t -> unit val string_of_path: Path.t -> string val raw_type_expr: formatter -> type_expr -> unit +val string_of_label: Asttypes.arg_label -> string val wrap_printing_env: Env.t -> (unit -> 'a) -> 'a (* Call the function using the environment for type path shortening *) @@ -32,6 +36,7 @@ val mark_loops: type_expr -> unit val reset_and_mark_loops: type_expr -> unit val reset_and_mark_loops_list: type_expr list -> unit val type_expr: formatter -> type_expr -> unit +val constructor_arguments: formatter -> constructor_arguments -> unit val tree_of_type_scheme: type_expr -> out_type val type_sch : formatter -> type_expr -> unit val type_scheme: formatter -> type_expr -> unit @@ -39,7 +44,7 @@ val type_scheme: formatter -> type_expr -> unit val reset_names: unit -> unit val type_scheme_max: ?b_reset_names: bool -> formatter -> type_expr -> unit -(* Fin Maxence *) +(* End Maxence *) val tree_of_value_description: Ident.t -> value_description -> out_sig_item val value_description: Ident.t -> formatter -> value_description -> unit val tree_of_type_declaration: @@ -49,7 +54,8 @@ val tree_of_extension_constructor: Ident.t -> extension_constructor -> ext_status -> out_sig_item val extension_constructor: Ident.t -> formatter -> extension_constructor -> unit -val tree_of_module: Ident.t -> module_type -> rec_status -> out_sig_item +val tree_of_module: + Ident.t -> ?ellipsis:bool -> module_type -> rec_status -> out_sig_item val modtype: formatter -> module_type -> unit val signature: formatter -> signature -> unit val tree_of_modtype_declaration: @@ -80,4 +86,5 @@ val report_ambiguous_type_error: (formatter -> unit) -> (formatter -> unit) -> (formatter -> unit) -> unit (* for toploop *) -val hide_rec_items: signature_item list -> unit +val print_items: (Env.t -> signature_item -> 'a option) -> + Env.t -> signature_item list -> (out_sig_item * 'a option) list diff --git a/typing/printtyped.ml b/typing/printtyped.ml index 0e97e586..a0cf6282 100644 --- a/typing/printtyped.ml +++ b/typing/printtyped.ml @@ -1,14 +1,17 @@ -2(***********************************************************************) -(* *) -(* OCaml *) -(* *) -(* Fabrice Le Fessant, INRIA Saclay *) -(* *) -(* Copyright 1999 Institut National de Recherche en Informatique et *) -(* en Automatique. All rights reserved. This file is distributed *) -(* under the terms of the Q Tublic License version 1.0. *) -(* *) -(***********************************************************************) +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Fabrice Le Fessant, INRIA Saclay *) +(* *) +(* 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. *) +(* *) +(**************************************************************************) open Asttypes;; open Format;; @@ -36,7 +39,6 @@ let rec fmt_longident_aux f x = fprintf f "%a(%a)" fmt_longident_aux y fmt_longident_aux z; ;; -let fmt_longident_noloc f x = fprintf f "\"%a\"" fmt_longident_aux x;; let fmt_longident f x = fprintf f "\"%a\"" fmt_longident_aux x.txt;; let fmt_ident = Ident.print @@ -50,7 +52,6 @@ let rec fmt_path_aux f x = ;; let fmt_path f x = fprintf f "\"%a\"" fmt_path_aux x;; -let fmt_path_loc f x = fprintf f "\"%a\"" fmt_path_aux x.txt;; let fmt_constant f x = match x with @@ -129,12 +130,12 @@ let option i f ppf x = ;; let longident i ppf li = line i ppf "%a\n" fmt_longident li;; -let path i ppf li = line i ppf "%a\n" fmt_path li;; -let ident i ppf li = line i ppf "%a\n" fmt_ident li;; let string i ppf s = line i ppf "\"%s\"\n" s;; -let string_loc i ppf s = line i ppf "\"%s\"\n" s.txt;; -let bool i ppf x = line i ppf "%s\n" (string_of_bool x);; -let label i ppf x = line i ppf "label=\"%s\"\n" x;; +let arg_label i ppf = function + | Nolabel -> line i ppf "Nolabel\n" + | Optional s -> line i ppf "Optional \"%s\"\n" s + | Labelled s -> line i ppf "Labelled \"%s\"\n" s +;; let attributes i ppf l = let i = i + 1 in @@ -150,25 +151,25 @@ let rec core_type i ppf x = attributes i ppf x.ctyp_attributes; let i = i+1 in match x.ctyp_desc with - | Ttyp_any -> line i ppf "Ptyp_any\n"; - | Ttyp_var (s) -> line i ppf "Ptyp_var %s\n" s; + | Ttyp_any -> line i ppf "Ttyp_any\n"; + | Ttyp_var (s) -> line i ppf "Ttyp_var %s\n" s; | Ttyp_arrow (l, ct1, ct2) -> - line i ppf "Ptyp_arrow\n"; - string i ppf l; + line i ppf "Ttyp_arrow\n"; + arg_label i ppf l; core_type i ppf ct1; core_type i ppf ct2; | Ttyp_tuple l -> - line i ppf "Ptyp_tuple\n"; + line i ppf "Ttyp_tuple\n"; list i core_type ppf l; | Ttyp_constr (li, _, l) -> - line i ppf "Ptyp_constr %a\n" fmt_path li; + line i ppf "Ttyp_constr %a\n" fmt_path li; list i core_type ppf l; | Ttyp_variant (l, closed, low) -> - line i ppf "Ptyp_variant closed=%a\n" fmt_closed_flag closed; + line i ppf "Ttyp_variant closed=%a\n" fmt_closed_flag closed; list i label_x_bool_x_core_type_list ppf l; option i (fun i -> list i string) ppf low | Ttyp_object (l, c) -> - line i ppf "Ptyp_object %a\n" fmt_closed_flag c; + line i ppf "Ttyp_object %a\n" fmt_closed_flag c; let i = i + 1 in List.iter (fun (s, attrs, t) -> @@ -178,17 +179,17 @@ let rec core_type i ppf x = ) l | Ttyp_class (li, _, l) -> - line i ppf "Ptyp_class %a\n" fmt_path li; + line i ppf "Ttyp_class %a\n" fmt_path li; list i core_type ppf l; | Ttyp_alias (ct, s) -> - line i ppf "Ptyp_alias \"%s\"\n" s; + line i ppf "Ttyp_alias \"%s\"\n" s; core_type i ppf ct; | Ttyp_poly (sl, ct) -> - line i ppf "Ptyp_poly%a\n" + line i ppf "Ttyp_poly%a\n" (fun ppf -> List.iter (fun x -> fprintf ppf " '%s" x)) sl; core_type i ppf ct; | Ttyp_package { pack_path = s; pack_fields = l } -> - line i ppf "Ptyp_package %a\n" fmt_path s; + line i ppf "Ttyp_package %a\n" fmt_path s; list i package_with ppf l; and package_with i ppf (s, t) = @@ -215,166 +216,172 @@ and pattern i ppf x = pattern i ppf { x with pat_extra = rem } | [] -> match x.pat_desc with - | Tpat_any -> line i ppf "Ppat_any\n"; - | Tpat_var (s,_) -> line i ppf "Ppat_var \"%a\"\n" fmt_ident s; + | Tpat_any -> line i ppf "Tpat_any\n"; + | Tpat_var (s,_) -> line i ppf "Tpat_var \"%a\"\n" fmt_ident s; | Tpat_alias (p, s,_) -> - line i ppf "Ppat_alias \"%a\"\n" fmt_ident s; + line i ppf "Tpat_alias \"%a\"\n" fmt_ident s; pattern i ppf p; - | Tpat_constant (c) -> line i ppf "Ppat_constant %a\n" fmt_constant c; + | Tpat_constant (c) -> line i ppf "Tpat_constant %a\n" fmt_constant c; | Tpat_tuple (l) -> - line i ppf "Ppat_tuple\n"; + line i ppf "Tpat_tuple\n"; list i pattern ppf l; | Tpat_construct (li, _, po) -> - line i ppf "Ppat_construct %a\n" fmt_longident li; + line i ppf "Tpat_construct %a\n" fmt_longident li; list i pattern ppf po; | Tpat_variant (l, po, _) -> - line i ppf "Ppat_variant \"%s\"\n" l; + line i ppf "Tpat_variant \"%s\"\n" l; option i pattern ppf po; | Tpat_record (l, c) -> - line i ppf "Ppat_record\n"; + line i ppf "Tpat_record\n"; list i longident_x_pattern ppf l; | Tpat_array (l) -> - line i ppf "Ppat_array\n"; + line i ppf "Tpat_array\n"; list i pattern ppf l; | Tpat_or (p1, p2, _) -> - line i ppf "Ppat_or\n"; + line i ppf "Tpat_or\n"; pattern i ppf p1; pattern i ppf p2; | Tpat_lazy p -> - line i ppf "Ppat_lazy\n"; + line i ppf "Tpat_lazy\n"; pattern i ppf p; and expression_extra i ppf x attrs = match x with | Texp_constraint ct -> - line i ppf "Pexp_constraint\n"; + line i ppf "Texp_constraint\n"; attributes i ppf attrs; core_type i ppf ct; | Texp_coerce (cto1, cto2) -> - line i ppf "Pexp_constraint\n"; + line i ppf "Texp_coerce\n"; attributes i ppf attrs; option i core_type ppf cto1; core_type i ppf cto2; | Texp_open (ovf, m, _, _) -> - line i ppf "Pexp_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m; + line i ppf "Texp_open %a \"%a\"\n" fmt_override_flag ovf fmt_path m; attributes i ppf attrs; | Texp_poly cto -> - line i ppf "Pexp_poly\n"; + line i ppf "Texp_poly\n"; attributes i ppf attrs; option i core_type ppf cto; | Texp_newtype s -> - line i ppf "Pexp_newtype \"%s\"\n" s; + line i ppf "Texp_newtype \"%s\"\n" s; attributes i ppf attrs; and expression i ppf x = line i ppf "expression %a\n" fmt_location x.exp_loc; attributes i ppf x.exp_attributes; let i = - List.fold_left (fun i (extra,_,attrs) -> expression_extra i ppf extra attrs; i+1) + List.fold_left (fun i (extra,_,attrs) -> + expression_extra i ppf extra attrs; i+1) (i+1) x.exp_extra in match x.exp_desc with - | Texp_ident (li,_,_) -> line i ppf "Pexp_ident %a\n" fmt_path li; - | Texp_instvar (_, li,_) -> line i ppf "Pexp_instvar %a\n" fmt_path li; - | Texp_constant (c) -> line i ppf "Pexp_constant %a\n" fmt_constant c; + | Texp_ident (li,_,_) -> line i ppf "Texp_ident %a\n" fmt_path li; + | Texp_instvar (_, li,_) -> line i ppf "Texp_instvar %a\n" fmt_path li; + | Texp_constant (c) -> line i ppf "Texp_constant %a\n" fmt_constant c; | Texp_let (rf, l, e) -> - line i ppf "Pexp_let %a\n" fmt_rec_flag rf; + 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) -> - line i ppf "Pexp_function \"%s\"\n" p; -(* option i expression ppf eo; *) + line i ppf "Texp_function\n"; + arg_label i ppf p; list i case ppf l; | Texp_apply (e, l) -> - line i ppf "Pexp_apply\n"; + line i ppf "Texp_apply\n"; expression i ppf e; list i label_x_expression ppf l; | Texp_match (e, l1, l2, partial) -> - line i ppf "Pexp_match\n"; + line i ppf "Texp_match\n"; expression i ppf e; list i case ppf l1; list i case ppf l2; | Texp_try (e, l) -> - line i ppf "Pexp_try\n"; + line i ppf "Texp_try\n"; expression i ppf e; list i case ppf l; | Texp_tuple (l) -> - line i ppf "Pexp_tuple\n"; + line i ppf "Texp_tuple\n"; list i expression ppf l; | Texp_construct (li, _, eo) -> - line i ppf "Pexp_construct %a\n" fmt_longident li; + line i ppf "Texp_construct %a\n" fmt_longident li; list i expression ppf eo; | Texp_variant (l, eo) -> - line i ppf "Pexp_variant \"%s\"\n" l; + line i ppf "Texp_variant \"%s\"\n" l; option i expression ppf eo; | Texp_record (l, eo) -> - line i ppf "Pexp_record\n"; + line i ppf "Texp_record\n"; list i longident_x_expression ppf l; option i expression ppf eo; | Texp_field (e, li, _) -> - line i ppf "Pexp_field\n"; + line i ppf "Texp_field\n"; expression i ppf e; longident i ppf li; | Texp_setfield (e1, li, _, e2) -> - line i ppf "Pexp_setfield\n"; + line i ppf "Texp_setfield\n"; expression i ppf e1; longident i ppf li; expression i ppf e2; | Texp_array (l) -> - line i ppf "Pexp_array\n"; + line i ppf "Texp_array\n"; list i expression ppf l; | Texp_ifthenelse (e1, e2, eo) -> - line i ppf "Pexp_ifthenelse\n"; + line i ppf "Texp_ifthenelse\n"; expression i ppf e1; expression i ppf e2; option i expression ppf eo; | Texp_sequence (e1, e2) -> - line i ppf "Pexp_sequence\n"; + line i ppf "Texp_sequence\n"; expression i ppf e1; expression i ppf e2; | Texp_while (e1, e2) -> - line i ppf "Pexp_while\n"; + line i ppf "Texp_while\n"; expression i ppf e1; expression i ppf e2; | Texp_for (s, _, e1, e2, df, e3) -> - line i ppf "Pexp_for \"%a\" %a\n" fmt_ident s fmt_direction_flag df; + line i ppf "Texp_for \"%a\" %a\n" fmt_ident s fmt_direction_flag df; expression i ppf e1; expression i ppf e2; expression i ppf e3; | Texp_send (e, Tmeth_name s, eo) -> - line i ppf "Pexp_send \"%s\"\n" s; + line i ppf "Texp_send \"%s\"\n" s; expression i ppf e; option i expression ppf eo | Texp_send (e, Tmeth_val s, eo) -> - line i ppf "Pexp_send \"%a\"\n" fmt_ident s; + line i ppf "Texp_send \"%a\"\n" fmt_ident s; expression i ppf e; option i expression ppf eo - | Texp_new (li, _, _) -> line i ppf "Pexp_new %a\n" fmt_path li; + | Texp_new (li, _, _) -> line i ppf "Texp_new %a\n" fmt_path li; | Texp_setinstvar (_, s, _, e) -> - line i ppf "Pexp_setinstvar \"%a\"\n" fmt_path s; + line i ppf "Texp_setinstvar \"%a\"\n" fmt_path s; expression i ppf e; | Texp_override (_, l) -> - line i ppf "Pexp_override\n"; + line i ppf "Texp_override\n"; list i string_x_expression ppf l; | Texp_letmodule (s, _, me, e) -> - line i ppf "Pexp_letmodule \"%a\"\n" fmt_ident s; + line i ppf "Texp_letmodule \"%a\"\n" fmt_ident s; module_expr i ppf me; expression i ppf e; | Texp_assert (e) -> - line i ppf "Pexp_assert"; + line i ppf "Texp_assert"; expression i ppf e; | Texp_lazy (e) -> - line i ppf "Pexp_lazy"; + line i ppf "Texp_lazy"; expression i ppf e; | Texp_object (s, _) -> - line i ppf "Pexp_object"; + line i ppf "Texp_object"; class_structure i ppf s | Texp_pack me -> - line i ppf "Pexp_pack"; + line i ppf "Texp_pack"; module_expr i ppf me + | Texp_unreachable -> + line i ppf "Texp_unreachable" + | Texp_extension_constructor (li, _) -> + line i ppf "Texp_extension_constructor %a" fmt_longident li and value_description i ppf x = - line i ppf "value_description %a %a\n" fmt_ident x.val_id fmt_location x.val_loc; + line i ppf "value_description %a %a\n" fmt_ident x.val_id fmt_location + x.val_loc; attributes i ppf x.val_attributes; core_type (i+1) ppf x.val_desc; list (i+1) string ppf x.val_prim; @@ -382,7 +389,8 @@ and value_description i ppf x = and type_parameter i ppf (x, _variance) = core_type i ppf x and type_declaration i ppf x = - line i ppf "type_declaration %a %a\n" fmt_ident x.typ_id fmt_location x.typ_loc; + line i ppf "type_declaration %a %a\n" fmt_ident x.typ_id fmt_location + x.typ_loc; attributes i ppf x.typ_attributes; let i = i+1 in line i ppf "ptype_params =\n"; @@ -398,15 +406,15 @@ and type_declaration i ppf x = and type_kind i ppf x = match x with | Ttype_abstract -> - line i ppf "Ptype_abstract\n" + line i ppf "Ttype_abstract\n" | Ttype_variant l -> - line i ppf "Ptype_variant\n"; + line i ppf "Ttype_variant\n"; list (i+1) constructor_decl ppf l; | Ttype_record l -> - line i ppf "Ptype_record\n"; + line i ppf "Ttype_record\n"; list (i+1) label_decl ppf l; | Ttype_open -> - line i ppf "Ptype_open\n" + line i ppf "Ttype_open\n" and type_extension i ppf x = line i ppf "type_extension\n"; @@ -430,11 +438,11 @@ and extension_constructor i ppf x = and extension_constructor_kind i ppf x = match x with Text_decl(a, r) -> - line i ppf "Pext_decl\n"; - list (i+1) core_type ppf a; + line i ppf "Text_decl\n"; + constructor_arguments (i+1) ppf a; option (i+1) core_type ppf r; | Text_rebind(p, _) -> - line i ppf "Pext_rebind\n"; + line i ppf "Text_rebind\n"; line (i+1) ppf "%a\n" fmt_path p; and class_type i ppf x = @@ -443,13 +451,14 @@ and class_type i ppf x = let i = i+1 in match x.cltyp_desc with | Tcty_constr (li, _, l) -> - line i ppf "Pcty_constr %a\n" fmt_path li; + line i ppf "Tcty_constr %a\n" fmt_path li; list i core_type ppf l; | Tcty_signature (cs) -> - line i ppf "Pcty_signature\n"; + line i ppf "Tcty_signature\n"; class_signature i ppf cs; | Tcty_arrow (l, co, cl) -> - line i ppf "Pcty_arrow \"%s\"\n" l; + line i ppf "Tcty_arrow\n"; + arg_label i ppf l; core_type i ppf co; class_type i ppf cl; @@ -464,21 +473,22 @@ and class_type_field i ppf x = attributes i ppf x.ctf_attributes; match x.ctf_desc with | Tctf_inherit (ct) -> - line i ppf "Pctf_inherit\n"; + line i ppf "Tctf_inherit\n"; class_type i ppf ct; | Tctf_val (s, mf, vf, ct) -> - line i ppf "Pctf_val \"%s\" %a %a\n" s fmt_mutable_flag mf + line i ppf "Tctf_val \"%s\" %a %a\n" s fmt_mutable_flag mf fmt_virtual_flag vf; core_type (i+1) ppf ct; | Tctf_method (s, pf, vf, ct) -> - line i ppf "Pctf_method \"%s\" %a %a\n" s fmt_private_flag pf fmt_virtual_flag vf; + line i ppf "Tctf_method \"%s\" %a %a\n" s fmt_private_flag pf + fmt_virtual_flag vf; core_type (i+1) ppf ct; | Tctf_constraint (ct1, ct2) -> - line i ppf "Pctf_constraint\n"; + line i ppf "Tctf_constraint\n"; core_type (i+1) ppf ct1; core_type (i+1) ppf ct2; | Tctf_attribute (s, arg) -> - line i ppf "Pctf_attribute \"%s\"\n" s.txt; + line i ppf "Tctf_attribute \"%s\"\n" s.txt; Printast.payload i ppf arg and class_description i ppf x = @@ -508,27 +518,27 @@ and class_expr i ppf x = let i = i+1 in match x.cl_desc with | Tcl_ident (li, _, l) -> - line i ppf "Pcl_constr %a\n" fmt_path li; + line i ppf "Tcl_ident %a\n" fmt_path li; list i core_type ppf l; | Tcl_structure (cs) -> - line i ppf "Pcl_structure\n"; + line i ppf "Tcl_structure\n"; class_structure i ppf cs; | Tcl_fun (l, p, _, ce, _) -> - line i ppf "Pcl_fun\n"; - label i ppf l; + line i ppf "Tcl_fun\n"; + arg_label i ppf l; pattern i ppf p; class_expr i ppf ce | Tcl_apply (ce, l) -> - line i ppf "Pcl_apply\n"; + line i ppf "Tcl_apply\n"; class_expr i ppf ce; list i label_x_expression ppf l; | Tcl_let (rf, l1, l2, ce) -> - line i ppf "Pcl_let %a\n" fmt_rec_flag rf; + line i ppf "Tcl_let %a\n" fmt_rec_flag rf; list i value_binding ppf l1; list i ident_x_loc_x_expression_def ppf l2; class_expr i ppf ce; | Tcl_constraint (ce, Some ct, _, _, _) -> - line i ppf "Pcl_constraint\n"; + line i ppf "Tcl_constraint\n"; class_expr i ppf ce; class_type i ppf ct | Tcl_constraint (ce, None, _, _, _) -> class_expr i ppf ce @@ -544,24 +554,24 @@ and class_field i ppf x = attributes i ppf x.cf_attributes; match x.cf_desc with | Tcf_inherit (ovf, ce, so, _, _) -> - line i ppf "Pcf_inherit %a\n" fmt_override_flag ovf; + line i ppf "Tcf_inherit %a\n" fmt_override_flag ovf; class_expr (i+1) ppf ce; option (i+1) string ppf so; | Tcf_val (s, mf, _, k, _) -> - line i ppf "Pcf_val \"%s\" %a\n" s.txt fmt_mutable_flag mf; + line i ppf "Tcf_val \"%s\" %a\n" s.txt fmt_mutable_flag mf; class_field_kind (i+1) ppf k | Tcf_method (s, pf, k) -> - line i ppf "Pcf_method \"%s\" %a\n" s.txt fmt_private_flag pf; + line i ppf "Tcf_method \"%s\" %a\n" s.txt fmt_private_flag pf; class_field_kind (i+1) ppf k | Tcf_constraint (ct1, ct2) -> - line i ppf "Pcf_constraint\n"; + line i ppf "Tcf_constraint\n"; core_type (i+1) ppf ct1; core_type (i+1) ppf ct2; | Tcf_initializer (e) -> - line i ppf "Pcf_initializer\n"; + line i ppf "Tcf_initializer\n"; expression (i+1) ppf e; | Tcf_attribute (s, arg) -> - line i ppf "Pcf_attribute \"%s\"\n" s.txt; + line i ppf "Tcf_attribute \"%s\"\n" s.txt; Printast.payload i ppf arg and class_field_kind i ppf = function @@ -587,21 +597,21 @@ and module_type i ppf x = attributes i ppf x.mty_attributes; let i = i+1 in match x.mty_desc with - | Tmty_ident (li,_) -> line i ppf "Pmty_ident %a\n" fmt_path li; - | Tmty_alias (li,_) -> line i ppf "Pmty_alias %a\n" fmt_path li; + | Tmty_ident (li,_) -> line i ppf "Tmty_ident %a\n" fmt_path li; + | Tmty_alias (li,_) -> line i ppf "Tmty_alias %a\n" fmt_path li; | Tmty_signature (s) -> - line i ppf "Pmty_signature\n"; + line i ppf "Tmty_signature\n"; signature i ppf s; | Tmty_functor (s, _, mt1, mt2) -> - line i ppf "Pmty_functor \"%a\"\n" fmt_ident s; + line i ppf "Tmty_functor \"%a\"\n" fmt_ident s; Misc.may (module_type i ppf) mt1; module_type i ppf mt2; | Tmty_with (mt, l) -> - line i ppf "Pmty_with\n"; + line i ppf "Tmty_with\n"; module_type i ppf mt; list i longident_x_with_constraint ppf l; | Tmty_typeof m -> - line i ppf "Pmty_typeof\n"; + line i ppf "Tmty_typeof\n"; module_expr i ppf m; and signature i ppf x = list i signature_item ppf x.sig_items @@ -611,45 +621,45 @@ and signature_item i ppf x = let i = i+1 in match x.sig_desc with | Tsig_value vd -> - line i ppf "Psig_value\n"; + line i ppf "Tsig_value\n"; value_description i ppf vd; - | Tsig_type l -> - line i ppf "Psig_type\n"; + | Tsig_type (rf, l) -> + line i ppf "Tsig_type %a\n" fmt_rec_flag rf; list i type_declaration ppf l; | Tsig_typext e -> - line i ppf "Psig_typext\n"; + line i ppf "Tsig_typext\n"; type_extension i ppf e; | Tsig_exception ext -> - line i ppf "Psig_exception\n"; + line i ppf "Tsig_exception\n"; extension_constructor i ppf ext | Tsig_module md -> - line i ppf "Psig_module \"%a\"\n" fmt_ident md.md_id; + line i ppf "Tsig_module \"%a\"\n" fmt_ident md.md_id; attributes i ppf md.md_attributes; module_type i ppf md.md_type | Tsig_recmodule decls -> - line i ppf "Psig_recmodule\n"; + line i ppf "Tsig_recmodule\n"; list i module_declaration ppf decls; | Tsig_modtype x -> - line i ppf "Psig_modtype \"%a\"\n" fmt_ident x.mtd_id; + line i ppf "Tsig_modtype \"%a\"\n" fmt_ident x.mtd_id; attributes i ppf x.mtd_attributes; modtype_declaration i ppf x.mtd_type | Tsig_open od -> - line i ppf "Psig_open %a %a\n" + line i ppf "Tsig_open %a %a\n" fmt_override_flag od.open_override fmt_path od.open_path; attributes i ppf od.open_attributes | Tsig_include incl -> - line i ppf "Psig_include\n"; + line i ppf "Tsig_include\n"; attributes i ppf incl.incl_attributes; module_type i ppf incl.incl_mod | Tsig_class (l) -> - line i ppf "Psig_class\n"; + line i ppf "Tsig_class\n"; list i class_description ppf l; | Tsig_class_type (l) -> - line i ppf "Psig_class_type\n"; + line i ppf "Tsig_class_type\n"; list i class_type_declaration ppf l; | Tsig_attribute (s, arg) -> - line i ppf "Psig_attribute \"%s\"\n" s.txt; + line i ppf "Tsig_attribute \"%s\"\n" s.txt; Printast.payload i ppf arg and module_declaration i ppf md = @@ -669,38 +679,38 @@ and modtype_declaration i ppf = function and with_constraint i ppf x = match x with | Twith_type (td) -> - line i ppf "Pwith_type\n"; + line i ppf "Twith_type\n"; type_declaration (i+1) ppf td; | Twith_typesubst (td) -> - line i ppf "Pwith_typesubst\n"; + line i ppf "Twith_typesubst\n"; type_declaration (i+1) ppf td; - | Twith_module (li,_) -> line i ppf "Pwith_module %a\n" fmt_path li; - | Twith_modsubst (li,_) -> line i ppf "Pwith_modsubst %a\n" fmt_path li; + | Twith_module (li,_) -> line i ppf "Twith_module %a\n" fmt_path li; + | Twith_modsubst (li,_) -> line i ppf "Twith_modsubst %a\n" fmt_path li; and module_expr i ppf x = line i ppf "module_expr %a\n" fmt_location x.mod_loc; attributes i ppf x.mod_attributes; let i = i+1 in match x.mod_desc with - | Tmod_ident (li,_) -> line i ppf "Pmod_ident %a\n" fmt_path li; + | Tmod_ident (li,_) -> line i ppf "Tmod_ident %a\n" fmt_path li; | Tmod_structure (s) -> - line i ppf "Pmod_structure\n"; + line i ppf "Tmod_structure\n"; structure i ppf s; | Tmod_functor (s, _, mt, me) -> - line i ppf "Pmod_functor \"%a\"\n" fmt_ident s; + line i ppf "Tmod_functor \"%a\"\n" fmt_ident s; Misc.may (module_type i ppf) mt; module_expr i ppf me; | Tmod_apply (me1, me2, _) -> - line i ppf "Pmod_apply\n"; + line i ppf "Tmod_apply\n"; module_expr i ppf me1; module_expr i ppf me2; | Tmod_constraint (me, _, Tmodtype_explicit mt, _) -> - line i ppf "Pmod_constraint\n"; + line i ppf "Tmod_constraint\n"; module_expr i ppf me; module_type i ppf mt; | Tmod_constraint (me, _, Tmodtype_implicit, _) -> module_expr i ppf me | Tmod_unpack (e, _) -> - line i ppf "Pmod_unpack\n"; + line i ppf "Tmod_unpack\n"; expression i ppf e; and structure i ppf x = list i structure_item ppf x.str_items @@ -710,62 +720,53 @@ and structure_item i ppf x = let i = i+1 in match x.str_desc with | Tstr_eval (e, attrs) -> - line i ppf "Pstr_eval\n"; + line i ppf "Tstr_eval\n"; attributes i ppf attrs; expression i ppf e; | Tstr_value (rf, l) -> - line i ppf "Pstr_value %a\n" fmt_rec_flag rf; + line i ppf "Tstr_value %a\n" fmt_rec_flag rf; list i value_binding ppf l; | Tstr_primitive vd -> - line i ppf "Pstr_primitive\n"; + line i ppf "Tstr_primitive\n"; value_description i ppf vd; - | Tstr_type l -> - line i ppf "Pstr_type\n"; + | Tstr_type (rf, l) -> + line i ppf "Tstr_type %a\n" fmt_rec_flag rf; list i type_declaration ppf l; | Tstr_typext te -> - line i ppf "Pstr_typext\n"; + line i ppf "Tstr_typext\n"; type_extension i ppf te | Tstr_exception ext -> - line i ppf "Pstr_exception\n"; + line i ppf "Tstr_exception\n"; extension_constructor i ppf ext; | Tstr_module x -> - line i ppf "Pstr_module\n"; + line i ppf "Tstr_module\n"; module_binding i ppf x | Tstr_recmodule bindings -> - line i ppf "Pstr_recmodule\n"; + line i ppf "Tstr_recmodule\n"; list i module_binding ppf bindings | Tstr_modtype x -> - line i ppf "Pstr_modtype \"%a\"\n" fmt_ident x.mtd_id; + line i ppf "Tstr_modtype \"%a\"\n" fmt_ident x.mtd_id; attributes i ppf x.mtd_attributes; modtype_declaration i ppf x.mtd_type | Tstr_open od -> - line i ppf "Pstr_open %a %a\n" + line i ppf "Tstr_open %a %a\n" fmt_override_flag od.open_override fmt_path od.open_path; attributes i ppf od.open_attributes | Tstr_class (l) -> - line i ppf "Pstr_class\n"; - list i class_declaration ppf (List.map (fun (cl, _,_) -> cl) l); + line i ppf "Tstr_class\n"; + list i class_declaration ppf (List.map (fun (cl, _) -> cl) l); | Tstr_class_type (l) -> - line i ppf "Pstr_class_type\n"; + line i ppf "Tstr_class_type\n"; list i class_type_declaration ppf (List.map (fun (_, _, cl) -> cl) l); | Tstr_include incl -> - line i ppf "Pstr_include"; + line i ppf "Tstr_include"; attributes i ppf incl.incl_attributes; module_expr i ppf incl.incl_mod; | Tstr_attribute (s, arg) -> - line i ppf "Pstr_attribute \"%s\"\n" s.txt; + line i ppf "Tstr_attribute \"%s\"\n" s.txt; Printast.payload i ppf arg -and string_x_module_type i ppf (s, _, mty) = - ident i ppf s; - module_type (i+1) ppf mty; - -and string_x_modtype_x_module i ppf (s, _, mty, modl) = - ident i ppf s; - module_type (i+1) ppf mty; - module_expr (i+1) ppf modl; - and longident_x_with_constraint i ppf (li, _, wc) = line i ppf "%a\n" fmt_path li; with_constraint (i+1) ppf wc; @@ -775,14 +776,20 @@ and core_type_x_core_type_x_location i ppf (ct1, ct2, l) = core_type (i+1) ppf ct1; core_type (i+1) ppf ct2; -and constructor_decl i ppf {cd_id; cd_name = _; cd_args; cd_res; cd_loc; cd_attributes} = +and constructor_decl i ppf {cd_id; cd_name = _; cd_args; cd_res; cd_loc; + cd_attributes} = line i ppf "%a\n" fmt_location cd_loc; line (i+1) ppf "%a\n" fmt_ident cd_id; attributes i ppf cd_attributes; - list (i+1) core_type ppf cd_args; + constructor_arguments (i+1) ppf cd_args; option (i+1) core_type ppf cd_res -and label_decl i ppf {ld_id; ld_name = _; ld_mutable; ld_type; ld_loc; ld_attributes} = +and constructor_arguments i ppf = function + | Cstr_tuple l -> list i core_type ppf l + | Cstr_record l -> list i label_decl ppf l + +and label_decl i ppf {ld_id; ld_name = _; ld_mutable; ld_type; ld_loc; + ld_attributes} = line i ppf "%a\n" fmt_location ld_loc; attributes i ppf ld_attributes; line (i+1) ppf "%a\n" fmt_mutable_flag ld_mutable; @@ -816,8 +823,9 @@ and longident_x_expression i ppf (li, _, e) = line i ppf "%a\n" fmt_longident li; expression (i+1) ppf e; -and label_x_expression i ppf (l, e, _) = - line i ppf "
  • OJIa8I$+*xmdC3`qS8iQ}^<* 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